我的解析器快要工作了:) (仍然让Spirit功能集(和编译时)以及非常欢迎的社区在堆栈溢出时感到惊讶)
在线尝试的小样本: http://coliru.stacked-crooked.com/a/1c1bf88909dce7e3
所以我学会了使用更多的lexeme-rules并尝试防止no_skip- 我的规则较小,因此更易于阅读,但现在我坚持使用 将lexeme-rules和skipping-rules结合起来似乎是不可能的(编译时出现错误,并警告说无法将其投射到Skipper)
我的问题是订阅中用逗号分隔的列表 不会跳过表达式周围的空格
解析:
"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跳过程序,但不能编译
我应该在expression_list的identifier_chains的前面和后面添加空格符吗?
感觉就像写一个正则表达式:(
expression_list = *qi::blank >> identifier_chain >> *(*qi::blank >> qi::char_(',') >> *qi::blank >> identifier_chain >> *qi::blank);
它可以工作,但是我已经读到,这最终将使我进入一个更大的解析器(处理所有由我自己跳过的空间)
任何建议
btw:任何想法,如果用'.'
包围indentifier_chain中的qi::char_('.')
,为什么我不能编译
identifier_chain = identifier >> *(('.' >> identifier) | subscription);
更新:
我已经按照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_(']');
但由于不可转换的船长,仍会出现编译错误:http://coliru.stacked-crooked.com/a/adcf665742b055dd
我还尝试将identifer_chain更改为
identifier_chain = identifier >> *(('.' >> identifier) | qi::skip(qi::blank)[subscription]);
但我仍然无法编译示例
答案 0 :(得分:1)
我先前链接的答案描述了所有组合(如果我没记错的话):Boost spirit skipper issues
简而言之:
任何声明了船长的规则(因此rule<It, Skipper[, Attr()]>
或rule<It, Attr(), Skipper>
)都必须使用兼容的船长(可以分配为Skipper
类型的表达式)调用
任何不声明船长的规则(格式为rule<It[, Attr()]>
)将隐式表现为 lexeme ,这意味着不会跳过任何输入字符。
就是这样。较微妙的结果是给出了两个规则:
rule<It, blank_type> a;
rule<It> b; // b is implicitly lexeme
您可以从b
调用a
:
a = "test" >> b;
但是,当您希望从a
调用b
时,您会发现必须提供船长:
b = "oops" >> a; // DOES NOT COMPILE
b = "okay" >> qi::skip(qi::blank) [ a ];
这几乎就是所有内容。关于Qi中的船长和词素,还有其他一些指令,请再次参见上面链接的答案。
我应该在expression_list的identifier_chains的前面和后面添加空格符吗?
如果您仔细查看Parse a '.' chained identifier list, with qi::lexeme and prevent space skipping的答案示例,您会发现它已经 已经正确地进行了跳过,因为我使用了phrase_parse
:>
" a.b " OK: ( "a" "b" )
----
"a . b" Failed
Remaining unparsed: "a . b"
----
您也可以将整个内容包装在“外部”规则中:
rule<std::string::const_iterator> main_rule =
qi::skip(qi::blank) [ identifier_chain ];
这是相同的,但是允许用户调用parse
而不指定船长。