如何结合跳过和不跳过(lexeme)规则? [英] How to combine skipping and non-skipping (lexeme) rules?

查看:72
本文介绍了如何结合跳过和不跳过(lexeme)规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的解析器快要工作了:)(仍然让Spirit功能集(和编译时)以及非常欢迎的社区在堆栈溢出时感到惊讶)

my parser is nearly working :) (still amazed by Spirit feature set (and compiletimes) and the very welcoming community here on stack overflow)

在线尝试的小样本: http://coliru.stacked-crooked.com/a/1c1bf88909dce7e3

所以我学会了使用更多的lexeme-rules并尝试防止no_skip-我的规则较小,因此更易于阅读,但现在我坚持使用将lexeme-rules和skipping-rules结合起来似乎是不可能的(编译时错误,并带有警告,提示无法将其转换为Skipper)

so i've learned to use more lexeme-rules and try to prevent no_skip - my rules are smaller and better to read as a result but now i stuck with combining lexeme-rules and skipping-rules what seems to be not possible (compiletime error with warning about not castable to Skipper)

我的问题是订阅中用逗号分隔的列表不会跳过表达式周围的空格

my problem is the comma seperated list in subscriptions which does not skip spaces around expressions

解析:

"a.b[a,b]"

失败:

"a.b[ a , b ]"

这些是我的规则:

qi::rule<std::string::const_iterator, std::string()> identifier_chain;

qi::rule<std::string::const_iterator, std::string()>
    expression_list = identifier_chain >> *(qi::char_(',') >> identifier_chain);

qi::rule < std::string::const_iterator, std::string() >
    subscription = qi::char_('[') >> expression_list >> qi::char_(']');

qi::rule<std::string::const_iterator, std::string()>
    identifier = qi::ascii::alpha >> *(qi::ascii::alnum | '_');

identifier_chain = identifier >> *(('.' >> identifier) | subscription);

如您所见,所有规则都是"lexeme",我认为订阅规则应为ascii :: space_type跳过程序,但不能编译

as you can see all rules are "lexeme" and i think the subscription rule should be a ascii::space_type skipper but that does not compile

我应该在expression_list的identifier_chains的前面和后面添加空格符吗?

should i add space eaters in the front and back of identifier_chains in the expression_list?

感觉就像写一个正则表达式:(

feels like writing an regex :(

expression_list = *qi::blank >> identifier_chain >> *(*qi::blank >> qi::char_(',') >> *qi::blank >> identifier_chain >> *qi::blank);

它可以工作,但是我已经读到,这最终将使我进入更大的解析器(处理所有由我自己跳过的空间)

it works but i've read that this will get me to an much bigger parser in the end (handling all the space skipping by myself)

任何建议

顺便说一句:任何想法为什么我用 qi :: char _('.')

btw: any idea why i can't compile if surrounding the '.' in the indentifier_chain with qi::char_('.')

identifier_chain = identifier >> *(('.' >> identifier) | subscription);

更新:

我已经按照sehe的建议更新了我的表情列表

i've updated my expression list as suggested by sehe

qi::rule<std::string::const_iterator, spirit::ascii::blank_type, std::string()>
expression_list = identifier_chain >> *(qi::char_(',') >> identifier_chain);

qi::rule < std::string::const_iterator, std::string() >
subscription = qi::char_('[') >> qi::skip(qi::blank)[expression_list] >> qi::char_(']');

但由于无法强制转换的Skipper仍然出现编译错误: http://coliru.stacked-crooked.com/a/adcf665742b055dd

but still get compile error due to non castable Skipper: http://coliru.stacked-crooked.com/a/adcf665742b055dd

我还尝试将identifer_chain更改为

i also tried changed the identifer_chain to

identifier_chain = identifier >> *(('.' >> identifier) | qi::skip(qi::blank)[subscription]);

但我仍然无法编译示例

推荐答案

我先前链接的答案描述了所有组合(如果我没记错的话):

The answer I linked to earlier describes all the combinations (if I remember correctly): Boost spirit skipper issues

简而言之:

  • 任何声明船长的规则(因此 rule< It,Skipper [,Attr()]> rule< It,Attr(),Skipper> )必须使用兼容的跨接程序(可以指定为 Skipper 类型的表达式)调用.

  • any rule that declares a skipper (so rule<It, Skipper[, Attr()]> or rule<It, Attr(), Skipper>) MUST be invoked with a compatible skipper (an expression that can be assigned to the type of Skipper).

任何不声明船长的规则(其格式为 rule< It [,Attr()]> )将隐含地表现为 lexeme ,表示不会跳过任何输入字符.

any rule that does NOT declare a skipper (so of the form rule<It[, Attr()]>) will implicitly behave like a lexeme, meaning no input characters are skipped.

就是这样.较微妙的结果是给出了两个规则:

That's it. The slightly subtler ramifications are that given two rules:

rule<It, blank_type> a;
rule<It> b; // b is implicitly lexeme

可以 a 调用 b :

a = "test" >> b;

但是,当您希望从 b 调用 a 时,您会发现必须提供船长:

But when you wish to invoke a from b you will find that you have to provide the skipper:

b = "oops" >> a; // DOES NOT COMPILE
b = "okay" >> qi::skip(qi::blank) [ a ];

这几乎就是所有内容.关于Qi中的船长和词素,还有其他一些指令,请再次参见上面链接的答案.

That's almost all there is to it. There are a few more directives around skippers and lexemes in Qi, see again the answer linked above.

我应该在expression_list的identifier_chains的前面和后面添加空格符吗?

should i add space eaters in the front and back of identifier_chains in the expression_list?

如果您在此处仔细查看答案示例,您可以看到它已经已经正确地进行了跳前和跳后,因为我使用了 phrase_parse :

If you look closely at the answer example here Parse a '.' chained identifier list, with qi::lexeme and prevent space skipping, you can see that it already does pre- and post skipping correctly, because I used phrase_parse:

" a.b " OK: ( "a" "b" ) 
----
"a . b" Failed
Remaining unparsed: "a . b"
----

您也可以将整个内容包装在外部"规则中:

You COULD also wrap the whole thing in an "outer" rule:

rule<std::string::const_iterator> main_rule = 
     qi::skip(qi::blank) [ identifier_chain ];

相同,但是允许用户调用 parse 而不指定船长.

That's just the same but allows users to call parse without specifying the skipper.

这篇关于如何结合跳过和不跳过(lexeme)规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆