c – Spirit qi解析为嵌套函数的抽象语法树
我正在尝试使用boost的精神qi解析器创建一个解析器.它正在解析包含三种类型值的字符串.常量,变量或函数.这些函数可以嵌套在一起.测试串是f(a,b)= f(g(z,x),g(x,h(x)),c),其中a-e是常数,f-r是函数,s-z是变量.我成功创建了一个可以正确解析表达式的规则.当我将解析规则的函数更改为
grammar时,出现了麻烦.我可以解决几个错误.我几乎得到语法来解析表达式并将其转换为我创建的抽象语法树.但是我得到了关于boost库中包含的文件的错误,我无法弄清楚它来自哪里因为我不理解编译器消息.我按照网站上的示例,使用员工示例将数据从解析器放到结构中:
http://www.boost.org/doc/libs/1_41_0/libs/spirit/example/qi/employee.cpp
main.cpp中 #include "Parser.h" #include "Term.h" #include <boost/spirit/include/qi.hpp> #include <string> #include <iostream> #include <list> using std::string; using std::cout; using std::endl; int main() { cout << "Unification Algorithm" << endl << endl; string phrase = "f(a,b) = f(g(z,c)"; string::const_iterator itr = phrase.begin(); string::const_iterator last = phrase.end(); cout << phrase << endl; // Parser grammar Parser<string::const_iterator> g; // Output data Expression expression; if (phrase_parse(itr,last,g,boost::spirit::ascii::space,expression)) { cout << "Expression parsed." << endl; } else { cout << "Could not parse expression." << endl; } } Parser.h #ifndef _Parser_h_ #define _Parser_h_ #include "Term.h" #include <boost/spirit/include/qi.hpp> #include <vector> namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; template <typename Iterator> struct Parser : qi::grammar<Iterator,Expression(),ascii::space_type> { Parser() : Parser::base_type(expression) { using qi::char_; const_char = char_("a-eA-E"); fn_char = char_("f-rF-R"); var_char = char_("s-zS-Z"); basic_fn = fn_char >> char_('(') >> (const_char | var_char) % char_(',') >> char_(')'); first_fn_wrapper = fn_char >> char_('(') >> (basic_fn | const_char | var_char) % char_(',') >> char_(')'); nested_fn = fn_char >> char_('(') >> (first_fn_wrapper | const_char | var_char) % char_(',') >> char_(')'); expression = nested_fn >> char_("=") >> nested_fn; } // Constant character a - e qi::rule<Iterator,T_Cons,ascii::space_type> const_char; // Function character f - r qi::rule<Iterator,char(),ascii::space_type> fn_char; // Variable character s - z qi::rule<Iterator,T_Var,ascii::space_type> var_char; // Allows for basic function parsing eg. f(x,y,z) qi::rule<Iterator,T_Fn,ascii::space_type> basic_fn; // Allows for single nested functions eg. f(g(x),ascii::space_type> first_fn_wrapper; // Allows for fully nested functions eg. f(g(x,h(y)),z) and so on qi::rule<Iterator,ascii::space_type> nested_fn; // Full rule for a nested function expression qi::rule<Iterator,Expression,ascii::space_type> expression; }; #endif // _Parser_h_ Term.h #ifndef _Term_h_ #define _Term_h_ #include <boost/fusion/include/adapt_struct.hpp> #include <vector> struct Term { char name; }; BOOST_FUSION_ADAPT_STRUCT(Term,(char,name)) struct T_Cons : Term { }; BOOST_FUSION_ADAPT_STRUCT(T_Cons,name)) struct T_Var : Term { }; BOOST_FUSION_ADAPT_STRUCT(T_Var,name)) struct T_Fn : Term { std::vector<Term> * params; T_Fn() { params = new std::vector<Term>(); } ~T_Fn() { delete params; } }; BOOST_FUSION_ADAPT_STRUCT(T_Fn,(std::vector<Term>*,params)) struct Expression { Term lh_term; Term rh_term; }; BOOST_FUSION_ADAPT_STRUCT(Expression,name) (Term,lh_term) (Term,rh_term)) #endif // _Term_h_ 我无法链接编译器的整个错误消息,因为它非常长,但这里是最后几个.这些是它给出的编译错误: boost_1_46_0boostmplassert.hpp|360|error: no matching function for call to 'assertion_failed(mpl_::failed************ (boost::spirit::qi::grammar<Iterator,T1,T2,T3,T4>::grammar(const boost::spirit::qi::rule<Iterator_,T1_,T2_,T3_,T4_>&,const string&) [with Iterator_ = __gnu_cxx::__normal_iterator<const char*,std::basic_string<char> >; T1_ = Expression; T2_ = boost::proto::exprns_::expr<boost::proto::tag::terminal,boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,boost::spirit::char_encoding::asci| boost_1_46_0boostprotoextends.hpp|540|error: use of deleted function 'boost::proto::exprns_::expr<boost::proto::tag::terminal,boost::proto::argsns_::term<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,std::basic_string<char> >,boost::proto::exprns_::expr<boost::proto::tag::terminal,boost::spirit::char_encoding::ascii> >,0l>,boost::spirit::unused_type,boost::spirit::unused_type> > >,0l>:| boost_1_46_0boostprotodetailexpr0.hpp|165|error: no matching function for call to 'boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,boost::spirit::unused_type> >::reference()'| 解决方法
与往常一样,断言消息导致了问题: // If you see the assertion below failing then the start rule // passed to the constructor of the grammar is not compatible with // the grammar (i.e. it uses different template parameters). BOOST_SPIRIT_ASSERT_MSG( (is_same<start_type,rule<Iterator_,T4_> >::value),incompatible_start_rule,(rule<Iterator_,T4_>)); 所以它告诉你应该将语法与开始规则相匹配:你有 struct Parser : qi::grammar<Iterator,ascii::space_type> 但 qi::rule<Iterator,ascii::space_type> expression; 显然你忘记了括号: qi::rule<Iterator,ascii::space_type> expression; 使用通用库时的准则: 其中一些“规则”通常适用,但没有. 2与Boost Spirit特别相关: >宝贝步骤;从小开始(空,均匀) UPDATE 这是一个非常简化的语法.如前所述,在之前的“精神第一规则”中,从AST开始,完全匹配语法: namespace ast { namespace tag { struct constant; struct variable; struct function; } template <typename Tag> struct Identifier { char name; }; using Constant = Identifier<tag::constant>; using Variable = Identifier<tag::variable>; using Function = Identifier<tag::function>; struct FunctionCall; using Expression = boost::make_recursive_variant< Constant,Variable,boost::recursive_wrapper<FunctionCall> >::type; struct FunctionCall { Function function; std::vector<Expression> params; }; struct Equation { Expression lhs,rhs; }; } 当然,这可能更简单,因为所有标识符都只是char,你可以动态切换(impression). 现在,语法必须遵循. 1.保持简单2.仔细格式化3.直接匹配ast,4.添加调试宏: template <typename It,typename Skipper = ascii::space_type> struct Parser : qi::grammar<It,ast::Equation(),Skipper> { Parser() : Parser::base_type(equation_) { using namespace qi; constant_ = qi::eps >> char_("a-eA-E"); function_ = qi::eps >> char_("f-rF-R"); variable_ = qi::eps >> char_("s-zS-Z"); function_call = function_ >> '(' >> -(expression_ % ',') >> ')'; expression_ = constant_ | variable_ | function_call; equation_ = expression_ >> '=' >> expression_; BOOST_SPIRIT_DEBUG_NODES((constant_)(function_)(variable_)(function_call)(expression_)(equation_)) } qi::rule<It,ast::Constant()> constant_; qi::rule<It,ast::Function()> function_; qi::rule<It,ast::Variable()> variable_; qi::rule<It,ast::FunctionCall(),Skipper> function_call; qi::rule<It,ast::Expression(),Skipper> expression_; qi::rule<It,Skipper> equation_; };
完整计划 Live On Coliru //#define BOOST_SPIRIT_DEBUG #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace ast { namespace tag { struct constant; struct variable; struct function; } template <typename Tag> struct Identifier { char name; }; using Constant = Identifier<tag::constant>; using Variable = Identifier<tag::variable>; using Function = Identifier<tag::function>; struct FunctionCall; using Expression = boost::make_recursive_variant< Constant,rhs; }; } BOOST_FUSION_ADAPT_STRUCT(ast::Constant,name)) BOOST_FUSION_ADAPT_STRUCT(ast::Variable,name)) BOOST_FUSION_ADAPT_STRUCT(ast::Function,name)) BOOST_FUSION_ADAPT_STRUCT(ast::FunctionCall,(ast::Function,function)(std::vector<ast::Expression>,params)) BOOST_FUSION_ADAPT_STRUCT(ast::Equation,(ast::Expression,lhs)(ast::Expression,rhs)) namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; template <typename It,typename Skipper = ascii::space_type> struct Parser : qi::grammar<It,Skipper> equation_; }; int main() { std::cout << "Unification Algorithmnn"; std::string const phrase = "f(a,c)"; using It = std::string::const_iterator; It itr = phrase.begin(),last = phrase.end(); std::cout << phrase << std::endl; Parser<It> g; ast::Equation parsed; if (phrase_parse(itr,ascii::space,parsed)) { std::cout << "Expression parsed.n"; } else { std::cout << "Could not parse equation.n"; } if (itr != last) { std::cout << "Remaining unparsed input: '" << std::string(itr,last) << "'n"; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |