c – Boost.Spirit语法问题
我试图解析terminfo定义文本文件.我是Boost.Spirit的新手.我从简单的语法开始,只解析注释行,空行和终端定义.正如语法中的代码注释所示,取消注释[_val = _1]定义会中断编译.为什么?我可以修理吗?
如果我忽略实际的terminfo文件,我希望下面的代码解析这种文本: # comment line first definition line second third line # another comment line 码: #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/qi_eol.hpp> #include <boost/spirit/include/qi_eoi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/spirit/include/phoenix_object.hpp> #include <vector> #include <iostream> #include <string> namespace termcxx { namespace parser { namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace px = boost::phoenix; //using qi::double_; using ascii::space; //using px::ref; using px::construct; //using qi::eps; //using qi::lit; using qi::_val; using qi::_1; using ascii::char_; using qi::eol; using qi::eoi; struct context { int dummy; context () = default; context (context const &) = default; context (std::vector<char> a) { } context (std::vector<char> a,std::vector<char> b) { } }; } } BOOST_FUSION_ADAPT_STRUCT( termcxx::parser::context,(int,dummy)) namespace termcxx { namespace parser { template <typename Iterator> struct parser : qi::grammar<Iterator,context()> { qi::rule<Iterator,std::vector<char> > comment_line = (*space >> '#' >> *(char_ - eol) >> (eol | eoi))[_val = _1] ; qi::rule<Iterator,std::vector<char> > empty_line = (*space >> (eol | eoi))[_val = _1] ; qi::rule<Iterator,std::vector<char> > def_first_line = (+(char_ - eol) >> (eol | eoi))[_val = _1] ; qi::rule<Iterator,std::vector<char> > def_subsequent_line = (+space >> +(char_ - eol) >> (eol | eoi))[_val = _1] ; qi::rule<Iterator,std::vector<char> > definition = (def_first_line >> *def_subsequent_line)//[_val = _1] // Uncommenting the [_val = _1] breaks compilation. Why? ; qi::rule<Iterator,context()> start = (*(comment_line | empty_line | definition))[_val = construct<context> ()] ; parser() : parser::base_type(start) { } }; template struct parser<std::string::iterator>; } // namespace parser } // namespace termcxx 解决方法
为什么你坚持指定[_val = _1]?这是多余的,因为默认属性传播就是这样做的.事实上它很疼,见下文
接下来,(def_first_line>> * def_subsequent_line)的属性类型(显然)与std :: vector< char>不兼容.也许你可以 >只使用默认属性传播(具有足够的智能来继续追加) 也, >你可以替换std :: vector< char>当依赖于自动属性传播时,使用std :: string 更新 还有一些问题: >您拼错了大多数规则的属性类型(missing()): qi::rule<Iterator,std::string()> comment_line; qi::rule<Iterator,std::string()> empty_line; qi::rule<Iterator,std::string()> def_first_line; qi::rule<Iterator,std::string()> def_subsequent_line; qi::rule<Iterator,std::string()> definition; >在eoi处匹配的empty_line在输入结束时导致无限循环 def_first_line = graph >> +(char_ - eol) >> (eol|eoi); >使用qi :: space也会吃掉行尾!请改用qi :: blank empty_line = *blank >> eol; comment_line = *blank >> '#' >> *(char_ - eol) >> (eol|eoi); def_first_line = graph >> +(char_ - eol) >> (eol|eoi); def_subsequent_line = +blank >> +(char_ - eol) >> (eol|eoi); definition = (def_first_line >> *def_subsequent_line); start = ( *(comment_line | empty_line | definition) ) [ _val = px::construct<context>() ] ; 在与Spirit合作时,这种简单的习惯将为您节省数小时的工作和理智. 这是一个带有输出的固定版本Live On Coliru: <start> <try># comment linennfirs</try> <comment_line> <try># comment linennfirs</try> <success>nfirst definition li</success> <attributes>[[,c,o,m,e,n,t,l,i,e]]</attributes> </comment_line> <comment_line> <try>nfirst definition li</try> <fail/> </comment_line> <empty_line> <try>nfirst definition li</try> <success>first definition lin</success> <attributes>[[]]</attributes> </empty_line> <comment_line> <try>first definition lin</try> <fail/> </comment_line> <empty_line> <try>first definition lin</try> <fail/> </empty_line> <definition> <try>first definition lin</try> <def_first_line> <try>first definition lin</try> <success> second n third li</success> <attributes>[[f,r,s,d,f,e]]</attributes> </def_first_line> <def_subsequent_line> <try> second n third li</try> <success> third linenn# anot</success> <attributes>[[f,]]</attributes> </def_subsequent_line> <def_subsequent_line> <try> third linenn# anot</try> <success>n# another comment l</success> <attributes>[[f,h,e]]</attributes> </def_subsequent_line> <def_subsequent_line> <try>n# another comment l</try> <fail/> </def_subsequent_line> <success>n# another comment l</success> <attributes>[[f,e]]</attributes> </definition> <comment_line> <try>n# another comment l</try> <fail/> </comment_line> <empty_line> <try>n# another comment l</try> <success># another comment li</success> <attributes>[[]]</attributes> </empty_line> <comment_line> <try># another comment li</try> <success></success> <attributes>[[,a,!]]</attributes> </comment_line> <comment_line> <try></try> <fail/> </comment_line> <empty_line> <try></try> <fail/> </empty_line> <definition> <try></try> <def_first_line> <try></try> <fail/> </def_first_line> <fail/> </definition> <success></success> <attributes>[]</attributes> </start> Success 完整代码供参考: #define BOOST_SPIRIT_DEBUG #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <vector> #include <iostream> #include <string> namespace qi = boost::spirit::qi; namespace termcxx { namespace parser { namespace ascii = boost::spirit::ascii; namespace px = boost::phoenix; //using qi::double_; using ascii::blank; //using px::ref; using px::construct; //using qi::eps; //using qi::lit; using qi::_val; using qi::_1; using ascii::char_; using ascii::graph; using qi::eol; using qi::eoi; struct context { int dummy; context () = default; context (context const &) = default; context (std::vector<char> a) { } context (std::vector<char> a,std::vector<char> b) { } }; } } BOOST_FUSION_ADAPT_STRUCT(termcxx::parser::context,dummy)) namespace termcxx { namespace parser { template <typename Iterator> struct parser : qi::grammar<Iterator,context()> { parser() : parser::base_type(start) { empty_line = *blank >> eol; comment_line = *blank >> '#' >> *(char_ - eol) >> (eol|eoi); def_first_line = graph >> +(char_ - eol) >> (eol|eoi); def_subsequent_line = +blank >> +(char_ - eol) >> (eol|eoi); definition = (def_first_line >> *def_subsequent_line); start = ( *(comment_line | empty_line | definition) ) [ _val = px::construct<context>() ] ; BOOST_SPIRIT_DEBUG_NODES((start)(def_first_line)(def_subsequent_line)(definition)(empty_line)(comment_line)) } private: qi::rule<Iterator,context()> start; qi::rule<Iterator,std::string()> comment_line; qi::rule<Iterator,std::string()> empty_line; qi::rule<Iterator,std::string()> def_first_line; qi::rule<Iterator,std::string()> def_subsequent_line; qi::rule<Iterator,std::string()> definition; }; } } int main() { using It = boost::spirit::istream_iterator; termcxx::parser::parser<It> g; It f(std::cin >> std::noskipws),l; termcxx::parser::context data; if (qi::parse(f,g,data)) std::cout << "Successn"; else std::cout << "Failuren"; if (f != l) std::cout << "Remaining input: '" << std::string(f,l) << "'n"; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |