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";
}
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
