C ++升压齐递归规则建设 [英] C++ Boost qi recursive rule construction
问题描述
[看来我的解释和期望都不清楚可言,所以我加了precision上,我想如何使用该功能在帖子的末尾]
我目前正在使用升压齐语法。我有一个循环建设一个规则,因为我需要从一个向量的元素构建它。具有简单类型我已经重新编写它,它看起来像:
的#include<串GT;使用升压1.43.0 //
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ qi_eps.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>命名空间BQI =的boost ::精神::补气;类型定义为const char *迭代器;//功能,你可以找到[这里] [1]
模板< typename的P>无效test_phrase_parser(字符常量*输入,P&const的放大器; P,布尔full_match = TRUE);诠释的main()
{
//我的工作规则类型:
BQI ::规则<迭代器,标准::字符串()> myLoopBuiltRule;
的std ::矢量<标准::字符串>伏;
的std ::矢量<标准::字符串> ::为const_iterator IV; v.push_back(ABC);
v.push_back(DEF);
v.push_back(GHI);
v.push_back(JKL); myLoopBuiltRule =(BQI :: EPS!);
为(ⅳ= v.begin();!四= v.end();四++)
{
myLoopBuiltRule =
myLoopBuiltRule.copy()[BQI :: _ VAL = BQI :: _ 1]
| BQI ::字符串(* IV)BQI :: _ VAL = BQI :: _ 1]
;
}
调试(myLoopBuiltRule); 个char [] =ABC; test_phrase_parser(S,myLoopBuiltRule);
}
(貌似的这里不希望被相应超级链接所取代,所以这里是要找到函数test_phrase_parser()地址:的http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference/basics.html)
全部是最好的世界上最好的......直到我有一个参数传递给此规则。这是新规则类型:
//我不-了工作的规则类型:
BQI ::规则<迭代器,标准::字符串(INT *)> myLoopBuiltRule;
为int *类型,例如只的目的,我真正的指针adressing一个更复杂的类...但还是一个单纯的指针。
我改变了我的'for'循环据此,即:
为(IV = v.begin(!); IV = v.end(); 4 ++)
{
myLoopBuiltRule =
myLoopBuiltRule.copy()(BQI :: _ R1)BQI :: _ VAL = BQI :: _ 1]
| BQI ::字符串(* IV)BQI :: _ VAL = BQI :: _ 1]
;
}
我不得不添加新的规则,因为test_phrase_parser()不能猜出哪个值被赋予INT指针:
BQI ::规则<&迭代器GT; myInitialRule;
和改变一切遵循for循环:
myInitialRule = myLoopBuiltRule(为(int *)NULL);调试(myLoopBuiltRule);个char [] =ABC;test_phrase_parser(S,myInitialRule);
然后,一切都崩溃:
<$p$p><$c$c>/home/sylvain.darras/software/repository/software/external/include/boost/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:199:错误:调用'assertion_failed(不匹配的函数MPL _ ::失败************(升压::精神::齐::规则&LT;迭代器,T1,T2,T3,T4计算值: :运算符=(const的Expr的&安培;)然后我疯了,想:
myLoopBuiltRule =
myLoopBuiltRule.copy(BQI :: _ R1)BQI :: _ VAL = BQI :: _ 1]
| BQI ::字符串(* IV)BQI :: _ VAL = BQI :: _ 1]
- >
错误:调用'的boost ::精神::齐::规则&LT没有匹配的功能;为const char *,标准::字符串(INT *),提振::融合: :unused_type,提振::融合:: unused_type,提振::融合:: unused_type&GT; ::复制(常量的boost ::凤::演员&LT;的boost ::精神::属性&LT; 1 GT;&GT;&安培;)
然后我生气的说:
myLoopBuiltRule =
myLoopBuiltRule(BQI :: _ R1)BQI :: _ VAL = BQI :: _ 1]
| BQI ::字符串(* IV)BQI :: _ VAL = BQI :: _ 1]
哪个编译,因为它是完全语法正确,但辉煌堆栈溢出堂妹得开心,很好,递归调用自身死亡...
然后,我失去了我的头脑和类型的:
myLoopBuiltRule =
JF jhsgf jshdg fjsdgh fjsg jhsdg景洪sjfg jsgh DF
其中,因为你可能期望,未能进行编译。
您想象,写上述新型之前,我检查了在网络上,但没有找到复制相关的任何事情()和参数传递的同时。有没有人已经经历这个问题?我错过了什么?
请放心,任何帮助将是真的真的AP preciated。
PS:十分感谢hkaiser谁拥有,不知道它,回答了很多我的提振::气问题,通过谷歌(但此一)
更多信息:
我的解析器的目的是读取写在一个给定的语言L.我的帖子的目的是传播我的上下文(即文件:变量定义,尤其是常数值,这样我就可以计算出前pressions )。
变量类型我处理数量虽小,但它必将成长,所以我把这些类型的容器类。我可以对这些托管类型循环。
所以,让我们考虑,我想才达到什么伪算法:
LTypeList myTypes;
LTypeList ::为const_iterator iTypes;BQI ::规则&LT;迭代器,LTYPE(LContext *)&GT; myLoopBuiltRule;myLoopBuiltRule =(BQI :: EPS!);
为(iTypes = myTypes.begin();!iTypes = myTypes.end(); iTypes ++)
{
myLoopBuiltRule =
myLoopBuiltRule.copy()(BQI :: _ R1)BQI :: _ VAL = BQI :: _ 1]
| iTypes-&GT; getRule()(BQI :: _ R1)BQI :: _ VAL = BQI :: _ 1]
}
此初始化期间完成的,然后用与不同LContext *重用myLoopBuiltRule,解析多种类型。而且,由于几种L类型可以有边界,这是整前pressions,而这些整数前pressions可以表现出常量,我(想我)需要我的继承属性,各地把我LContext,并能计算前pression值。
希望我已经在我的意图已经清晰。
注意我只是伸出我多带几个信息链接的答案。在这种特殊情况下,我有一种预感,你可以的只是的逃脱了Nabialek招和有相应的替代的继承属性的 齐::当地人&LT;&GT;
的代替。如果我有足够的时间,我可能会在以后工作了示范。
注意事项,expositioning问题
请注意,有抄袭原前pression树木和精神解析器前pressions特别是当问题 - 它的将会的创建悬空的引用作为内部不应该住过去含全前pressions的结束。见BOOST_SPIRIT_AUTO在零到60 MPH 2秒!
另请参阅这些答案也涉及自己与建筑/动态(在运行时)组成的规则:
- Generating从另一种解析器前pressions 一个可变参数列表精神解析器前pressions
- Can提振精神的规则进行参数演示如何从一个函数返回使用规则
的boost ::原:: deepcopy的
(如BOOST_SPIRIT_AUTO做,实际上)
Nabialek计谋
在一般情况下,我已经很强烈建议的对的在运行时合并规则。相反,如果你正在寻找在运行时添加替代品的规则,你总是可以使用齐::符号&LT;&GT;
来代替。诀窍是的存储在符号表的规则的,并使用气懒::
来调用规则。特别是,这是被称为 Nabialek把戏。
我有一个玩具的命令行参数解析器这里演示了如何使用这个成语来匹配运行时定义的一组命令行参数:
气懒::
的局限性,下一步是什么?
不幸的是,气懒::
不支持的继承参数的参见例如
您可能会更好编写自定义分析器组件,如下记载:
我会尽量找一些时间来解决,通过补气::当地人更高版本。
替换继承参数的样本[It seems my explanations and expectations are not clear at all, so I added precision on how I'd like to use the feature at the end of the post]
I'm currently working on grammars using boost qi. I had a loop construction for a rule cause I needed to build it from the elements of a vector. I have re-written it with simple types, and it looks like:
#include <string>
// using boost 1.43.0
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_eps.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace bqi = boost::spirit::qi;
typedef const char* Iterator;
// function that you can find [here][1]
template<typename P> void test_phrase_parser(char const* input, P const& p, bool full_match = true);
int main()
{
// my working rule type:
bqi::rule<Iterator, std::string()> myLoopBuiltRule;
std::vector<std::string> v;
std::vector<std::string>::const_iterator iv;
v.push_back("abc");
v.push_back("def");
v.push_back("ghi");
v.push_back("jkl");
myLoopBuiltRule = (! bqi::eps);
for(iv = v.begin() ; iv != v.end() ; iv++)
{
myLoopBuiltRule =
myLoopBuiltRule.copy() [ bqi::_val = bqi::_1 ]
| bqi::string(*iv) [ bqi::_val = bqi::_1 ]
;
}
debug(myLoopBuiltRule);
char s[] = " abc ";
test_phrase_parser(s, myLoopBuiltRule);
}
(Looks like here does not want to be replaced by corresponding hyperlink, so here is the address to find function test_phrase_parser(): http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference/basics.html)
All was for the best in the best of all worlds... until I had to pass an argument to this rule. Here is the new rule type:
// my not-anymore-working rule type:
bqi::rule<Iterator, std::string(int*)> myLoopBuiltRule;
'int*' type is for example purpose only, my real pointer is adressing a much more complex class... but still a mere pointer.
I changed my 'for' loop accordingly, i.e.:
for(iv = v.begin() ; iv != v.end() ; iv++)
{
myLoopBuiltRule =
myLoopBuiltRule.copy()(bqi::_r1) [ bqi::_val = bqi::_1 ]
| bqi::string(*iv) [ bqi::_val = bqi::_1 ]
;
}
I had to add a new rule because test_phrase_parser() cannot guess which value is to be given to the int pointer:
bqi::rule<Iterator> myInitialRule;
And change everything that followed the for loop:
myInitialRule = myLoopBuiltRule((int*)NULL);
debug(myLoopBuiltRule);
char s[] = " abc ";
test_phrase_parser(s, myInitialRule);
Then everything crashed:
/home/sylvain.darras/software/repository/software/external/include/boost/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:199: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&)
Then I got crazy and tried:
myLoopBuiltRule =
myLoopBuiltRule.copy(bqi::_r1) [ bqi::_val = bqi::_1 ]
| bqi::string(*iv) [ bqi::_val = bqi::_1 ]
-->
error: no matching function for call to ‘boost::spirit::qi::rule<const char*, std::string(int*), boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>::copy(const boost::phoenix::actor<boost::spirit::attribute<1> >&)’
Then I got mad and wrote:
myLoopBuiltRule =
myLoopBuiltRule(bqi::_r1) [ bqi::_val = bqi::_1 ]
| bqi::string(*iv) [ bqi::_val = bqi::_1 ]
Which compiles since it is perfectly syntactically correct, but which magnificently stack overflows coz it happily, nicely, recursively, calls itself to death...
Then I lost my mind and typed:
myLoopBuiltRule =
jf jhsgf jshdg fjsdgh fjsg jhsdg jhg sjfg jsgh df
Which, as you probably expect, has failed to compile.
You imagine that before writing the above novel, I checked out on the web, but didn't find out anything related to copy() and argument passing in the same time. Has anyone already experienced this problem ? Have I missed something ?
Be assured that any help will be really really appreciated.
PS: Great thanks to hkaiser who has, without knowing it, answered a lot of my boost::qi problems through google (but this one).
Further information:
The purpose of my parser is to read files written in a given language L. The purpose of my post is to propagate my "context" (i.e.: variable definitions and especially constant values, so I can compute expressions).
The number of variable types I handle is small, but it's bound to grow, so I keep these types in a container class. I can loop on these managed types.
So, let's consider a pseudo-algorithm of what I would like to achive:
LTypeList myTypes;
LTypeList::const_iterator iTypes;
bqi::rule<Iterator, LType(LContext*)> myLoopBuiltRule;
myLoopBuiltRule = (! bqi::eps);
for(iTypes = myTypes.begin() ; iTypes != myTypes.end() ; iTypes++)
{
myLoopBuiltRule =
myLoopBuiltRule.copy()(bqi::_r1) [ bqi::_val = bqi::_1 ]
| iTypes->getRule()(bqi::_r1) [ bqi::_val = bqi::_1 ]
}
This is done during initialization and then myLoopBuiltRule is used and reused with different LContext*, parsing multiple types. And since some L types can have bounds, which are integer expressions, and that these integer expressions can exhibit constants, I (think that I) need my inherited attribute to take my LContext around and be able to compute expression value.
Hope I've been clearer in my intentions.
Note I just extended my answer with a few more informational links. In this particular case I have a hunch that you could just get away with the Nabialek trick and replacing the inherited attribute with a corresponding qi::locals<>
instead. If I have enough time, I might work out a demonstration later.
Caveats, expositioning the problem
Please be advised that there are issues when copying proto expression trees and spirit parser expressions in particular - it will create dangling references as the internals are not supposed to live past the end of the containing full expressions. See BOOST_SPIRIT_AUTO on Zero to 60 MPH in 2 seconds!
Also see these answers which also concerns themselves with building/composing rules on the fly (at runtime):
- Generating Spirit parser expressions from a variadic list of alternative parser expressions
- Can Boost Spirit Rules be parameterized which demonstrates how to return rules from a function using
boost::proto::deepcopy
(like BOOST_SPIRIT_AUTO does, actually)
Nabialek Trick
In general, I'd very strongly advise against combining rules at runtime. Instead, if you're looking to 'add alternatives' to a rule at runtime, you can always use qi::symbols<>
instead. The trick is to store a rule in the symbol-table and use qi::lazy
to call the rule. In particular, this is known as the Nabialek Trick.
I have a toy command-line arguments parser here that demonstrates how you could use this idiom to match a runtime-defined set of command line arguments:
Limitations of qi::lazy
, what's next?
Unfortunately, qi::lazy
does not support inherited arguments see e.g.
You might be better off writing a custom parser component, as documented here:
I'll try to find some time to work out a sample that replaces inherited arguments by qi::locals later.
这篇关于C ++升压齐递归规则建设的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!