阅读和观看此演示文稿:http:
//boost-spirit.com/home/2011/06/12/ast-construction-with-the-universal-tree/
我发现了这个陈述 - 基本上我们建议不要使用语义动作.
我必须承认,我已经感受到了类似的东西:具有语义行为的语法实际上看起来有点难看.而且,当我需要扩展/改变它们时,它完全采用语义动作进行了大量的"微观管理".在演示文稿中演示的具有属性语法的方法似乎更加优雅和有前途.
所以我想问:这是一个"官方"观点吗?我应该学习如何使用属性语法并更详细地避免语义动作吗?如果是这样 - 我想=要求一些基本的(甚至是微不足道的)例子,展示这样的方法 - LISP解释器太复杂了我不能咀嚼......
这在理论上取决于任务吗?
它是否可以实际完成,并且生成的解析器是否可以使用足够的性能和输出(例如,LLVM IR或GCC的gimple)来集成到竞争编译器中?
标准ascii::space_type船长当然不会跳过我的评论.文档提到你可以制作自己的跳过解析器但是没有实际如何做的例子.
我只需要一个示例代码或任何东西,我现在谷歌搜索了2个小时.
请不要指出我的例子,一些无效的链接已经过时,处理Spirit 1.6.
我正在研究编译器,我想提高它的性能.我发现大约50%的时间花在解析源文件上.由于源文件非常小,之后我做了很多转换,在我看来它是可以完善的.
我的解析器是一个带有词法分析器(带有lexer :: pos_iterator)的Boost Spirit解析器,我有一个中等大小的语法.我正在将源解析为AST.
我的问题是我不知道解析过程中花费的时间最多:AST节点,词法分析器,解析器规则或内存的副本.
我不认为这是I/O问题,因为我正在使用SSD并且我在开始时完全读取文件然后仅使用内存版本.
我尝试使用分析器,但是花费时间的方法是Boost的一些方法,其名称长达数百个字符,我不知道它们到底做了什么......
那么,是否有一种首选方法来对Boost Spirit Parser及其语法进行基准测试?或者是否有一些规则可用于验证某些特定点的效率?
谢谢
感兴趣的人的来源:
c++ benchmarking boost-spirit boost-spirit-qi boost-spirit-lex
我想知道Boost.Spirit.Qi中是否有一种方法可以在运行时动态组合任意数量的规则.Boost.Spirit的内部工作方式对我来说仍然有点神秘,但由于规则被实现为对象似乎是可行的.我的动机是让我的语法的某些部分容易扩展.
考虑以下人为的例子:
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
typedef std::string::const_iterator iterator_t;
template<typename Expr>
inline bool parse_full(const std::string& input, const Expr& expr)
{
iterator_t first(input.begin()), last(input.end());
bool result = qi::phrase_parse(first, last, expr, boost::spirit::ascii::space);
return first == input.end() && result;
}
void no_op() {}
int main(int argc, char *argv[])
{
int attr = -1;
// "Static" version - Works fine!
/*
qi::rule<iterator_t, void(int&)> grammar;
qi::rule<iterator_t, void(int&)> ruleA = qi::char_('a')[qi::_r1 = px::val(0)];
qi::rule<iterator_t, void(int&)> ruleB = qi::char_('b')[qi::_r1 = px::val(1)];
qi::rule<iterator_t, void(int&)> …Run Code Online (Sandbox Code Playgroud) 一般情况:我无法弄清楚为什么我的Spirit语法/语义动作没有编译.
有时,编译器会抱怨分配或类型不兼容,我不知道什么是错的.问题出现在两个主要方面:
编译器错误不是完全易处理的,文档是错误的,或者我误解了它.
无论如何,有没有办法确切地找出Spirit传入我的语义行为的方式?
struct mybase { int a,b; };
struct myderived : mybase { int c,d; };
BOOST_FUSION_ADAPT_STRUCT(mybase, (int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived, (int,a)(int,b)(int,c)(int,d));
auto base_expr = int_ >> int_; // avoids assigning to struct attribute
rule<decltype(f), mybase() , space_type> base_ = int_ >> int_;
rule<decltype(f), myderived(), space_type> derived_ = base_ >> int_ >> int_;
myderived data;
bool ok = phrase_parse(f,l,derived_,space,data);
Run Code Online (Sandbox Code Playgroud)
此代码无法编译,存在大量难以理解的错误.
(松散地改编自精神总表上的帖子)
我有一个很大的问题.我有一个公共库,在我的项目中使用.这个图书馆密集使用boost.spirit和boost.fusion.不幸的是,图书馆约.700Mb大小.使用了所有的重要boost.spirit代码,它运行良好.可以采取哪些措施来减少其输出尺寸?是否有一个工具可以帮助确定哪些模板实例化浪费了大部分空间?
起初,我决定将所有精神感知代码移动到cpp文件.其次,我将尝试不同的编译器标志来优化大小.我不知道还能做什么.
更新(详细信息)
我正在使用GNU工具链.巨大的库实际上是一个静态库.使用这个700Mb库的可执行文件大小为200Mb.至少有一半的代码是*.h文件.一些boost.spirit语法(非常模板重的东西)也位于*.h文件中.
干杯!
以下几个教程(例如http://boost-spirit.com/home/articles/qi-example/nabialek-trick/)我想使用Nabialek技巧来获得动态解析器.解析已经工作正常,但我没有得到运输的属性.像/sf/answers/637698071/这样的解释表明,属性应该是可能的,但不是参数.
这只是一个将字符串和数字解析为结构的小例子.这只是为了展示我的问题; 此方法应在稍后的大型系统中使用,其中真正需要动态解析器.
问题:如何使用Nabialek技巧传输属性?
我不是精神专家,所以请耐心等待.我正在使用gcc 4.8.1并提升1.54.
#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
//------------------------------------------------------------------------------
// Data structure
struct myline {
myline()
: _n(0), _s("") {
}
myline(int n, std::string s)
: _n(n), _s(s) {
}
void set(int n, std::string s) {
_n = n;
_s = s;
}
int _n;
std::string _s;
};
BOOST_FUSION_ADAPT_STRUCT(::myline, (int, _n) (std::string, _s))
//------------------------------------------------------------------------------
// Parser grammar
template<typename It, typename …Run Code Online (Sandbox Code Playgroud) 我试图在Boost.Spirit中编写一个shell语言解析器.但是,我不清楚有关rules 语义的一些基本问题.
综观文档,有成员r.alias()及r.copy()的rule.IIUC,这些成员应分别返回对规则的引用和规则内容的副本.但是,我没有明确说明当我在另一个规则的定义中使用该规则时会发生什么.从我的实验中,我发现相互递归规则可以通过以下方式定义:
rule<Iter> r1, r2;
r1 = ... >> r2 >> ...;
r2 = ... >> r1 >> ...;
Run Code Online (Sandbox Code Playgroud)
这表明规则是通过解析器表达式中的引用来获取的.问题是,当变量超出范围时它会做什么,例如:
rule<Iter> r1;
{
rule<Iter> r2;
r1 = ... >> r2 >> ...;
r2 = ... >> r1 >> ...;
}
... // use r1
Run Code Online (Sandbox Code Playgroud)
在同一个注释中,将从包含类型规则工作的rvalue的解析表达式中分配规则(r.copy()也将是类型的右值rule,不是吗)?例如.
rule<Iter> f() { return char_('a') << char_('b'); }
rule<Iter> r1 = ... << f();
Run Code Online (Sandbox Code Playgroud)
任何人都可以启发我rule的副本和引用的详细语义,并可能纠正这篇文章中的任何误解吗?
boost-spirit ×10
c++ ×10
parsing ×3
boost ×2
benchmarking ×1
c++11 ×1
runtime ×1
templates ×1
tmp ×1