问题在第23行: qi :: rule< std :: string :: iterator,qi :: blank_type,utree()>标识符链=标识符>>*('.'>>标识符); 我不能在规则周围使用qi :: lexeme,我会得到一个无法转换为Skipper的编译错误但是如果我将完整的标识符规则复制到identifier_chain规则中就可以使用 qi :: rule< std :: string :: iterator,qi :: blank_type,utree()>identifer_chain= qi :: lexeme [qi :: ascii :: alpha>>*(qi :: ascii :: alnum |'_')>>*('.'>> qi :: ascii :: alpha>> *(qi :: ascii :: alnum |'_'))]]; 但是这似乎非常多余,我认为在解析器增长时,复制将使我将来陷入困境关于如何使用lexeme或其他方式保持我的."的任何想法.连接无空格从而使订阅结束和成员链接紧密相连 ].a. 那是我的解析器中唯一不希望空间跳过的地方,剩下的地方可以减少解析器代码的完美表现 thx以获取任何帮助/提示解决方案这是船长的工作方式(请参见助推器问题)您的规则声明了船长: qi :: rule< std :: string :: iterator,qi :: blank_type,utree()>identifier_chain; 因此,为了禁止它,您可以用lexeme包围,但是您也可以从声明中删除船长.标识符规则实际上也是如此,因为它也完全包裹在 lexeme [] 中.建议的最小修补程序: 在Coliru上直播 #include< iostream>#include< iomanip>#include< string>#include< boost/spirit/include/qi.hpp>#include< boost/spirit/include/support_utree.hpp>命名空间qi = boost :: spirit :: qi;使用boost :: spirit :: utree;int main(){自动测试= std :: vector< std :: string> {一个OK"a.b",//好的"a.b",//好的"a.b",//错误"a.b.c"//错误};for(std :: string const str:tests){自动迭代= str.begin(),end = str.end();qi :: rule< std :: string :: const_iterator,utree()>标识符= qi :: ascii :: alpha>>*(qi :: ascii :: alnum |'_'),identifier_chain =标识符>>*('.'>>标识符);utree ut;bool r = qi :: phrase_parse(iter,end,identifier_chain>> qi :: eoi,qi :: blank,ut);std :: cout<<std :: quoted(str)<<";如果(r){std :: cout<<确定:"<<ut<<"\ n";} 别的 {std :: cout<<失败\ n";}如果(iter!= end){std :: cout<<未解析的内容:"<<std :: quoted(std :: string(iter,end))<<"\ n";}std :: cout<<"---- \ n";}返回0;} 打印: "a" OK:("a")-"a.b" OK:("a""b")-"a.b" OK:("a""b")-"a.b"失败剩余的未分析内容:"a.b"-"a.b.c"失败剩余的未分析内容:"a.b.c"- im currently working on a Spirit based Expression Parser that should allow in the end (far far in the future) expressions like"a*b*c""10+20*x.y.z""a.b.c[ a.b ][ e.c( d.e()*4 )].e.f( (a.b+23)*d, -23*b.e(a.b.c) ).x.y"wild mix of member accesses, array subscriptions, function calling and expressions[] -> subscription() -> function call or expression bracket. member chainingcurrently im fighting with the space skipping on member-chaining"a . b . c"is not valid in my world - but gets parsed due to space skipping featuretry online my reduced sample: https://wandbox.org/permlink/o5kcYtUQEfKZqJgwProblem is line 23:qi::rule<std::string::iterator, qi::blank_type, utree()> identifier_chain = identifier >> *('.' >> identifier);i can't use an qi::lexeme around the rule, i'll get an not castable to Skipper compile errorbut it works if i copy my complete identifier rule into the identifier_chain ruleqi::rule<std::string::iterator, qi::blank_type, utree()> identifer_chain = qi::lexeme[qi::ascii::alpha >> *(qi::ascii::alnum | '_') >> *('.' >> qi::ascii::alpha >> *(qi::ascii::alnum | '_'))];but that seems very redundant and i think that copying will get me into trouble in the future when the parser is growingany idea how to use the lexeme or something else to keep my '.' connects free of whitespacesso that subscription ends and member-chaining are strongly connected].aa.bthat is the only place in my parser where space skipping is not wanted for the rest its perfect to reduce the parser codethx for any help/hints 解决方案 This is how the skippers work (see Boost spirit skipper issues)Your rule declares the skipper:qi::rule<std::string::iterator, qi::blank_type, utree()> identifier_chain;So to inhibit it you could surround with a lexeme, but you might just as well just drop the skipper from the declaration. The same actually goes for the the identifier rule, since it is also completely wrapped in lexeme[].Suggested minimal fix:Live On Coliru#include <iostream>#include <iomanip>#include <string>#include <boost/spirit/include/qi.hpp>#include <boost/spirit/include/support_utree.hpp>namespace qi = boost::spirit::qi;using boost::spirit::utree;int main() { auto tests = std::vector<std::string>{ "a", // ok "a.b", // ok " a.b ", // ok "a . b", // error "a . b. c" // error }; for (std::string const str : tests) { auto iter = str.begin(), end = str.end(); qi::rule<std::string::const_iterator, utree()> identifier = qi::ascii::alpha >> *(qi::ascii::alnum | '_'), identifier_chain = identifier >> *('.' >> identifier); utree ut; bool r = qi::phrase_parse(iter, end, identifier_chain >> qi::eoi, qi::blank, ut); std::cout << std::quoted(str) << " "; if (r) { std::cout << "OK: " << ut << "\n"; } else { std::cout << "Failed\n"; } if (iter!=end) { std::cout << "Remaining unparsed: " << std::quoted(std::string(iter,end)) << "\n"; } std::cout << "----\n"; } return 0;}Prints:"a" OK: ( "a" ) ----"a.b" OK: ( "a" "b" ) ----" a.b " OK: ( "a" "b" ) ----"a . b" FailedRemaining unparsed: "a . b"----"a . b. c" FailedRemaining unparsed: "a . b. c"---- 这篇关于解析一个“."链接的标识符列表,带有qi :: lexeme并防止空间跳过的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-23 05:41