警告;虽然我试图将代码缩短到最少。我仍然需要包含相当多的内容,以确保提供所需的信息。
此代码编译文件并运行,导致语法错误;
name = simple_name [ qi::_val = qi::_1 ]
| qualified_name [ qi::_val = qi::_1 ]
;
同时;
name = qualified_name [ qi::_val = qi::_1 ]
| simple_name [ qi::_val = qi::_1 ]
;
导致SIGSEGV
,段错误;
boost::detail::function::function_obj_invoker4<boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::reference<boost::spirit::qi::rule<boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<__gnu_cxx::__normal_iterator<char*, std::string>, boost::mpl::vector<std::string, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, mpl_::bool_<false>, unsigned long>, boost::spirit::lex::lexertl::detail::data, __gnu_cxx::__normal_iterator<char*, std::string>, mpl_::bool_<true>, mpl_::bool_<false> > >, Ast::name* (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::phoenix::actor<boost::proto::exprns_::expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >,0l>,boost::phoenix::actor<boost::spirit::argument<0> > >, 2l> > >,boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::reference<boost::spirit::qi::rule<boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<__gnu_cxx::__normal_iterator<char*, std::string>,boost::mpl::vector<std::string, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, mpl_::bool_<false>,unsigned long>, boost::spirit::lex::lexertl::detail::data, __gnu_cxx::__normal_iterator<char*,std::string>, mpl_::bool_<true>, mpl_::bool_<false> > >, Ast::name* (), ... more to come ...
哪里;
simple_name = (tok.identifier) [ qi::_val = build_simple_name_(qi::_1) ];
并且;
qualified_name = (name >> qi::raw_token(DOT) >> tok.identifier) [ qi::_val = build_qualified_name_(qi::_1, qi::_2) ] ;
所有这些规则,返回一个 Ast::name*()
;
qi::rule<Iterator, Ast::name*()> name;
qi::rule<Iterator, Ast::name*()> simple_name;
qi::rule<Iterator, Ast::name*()> qualified_name;
辅助函数定义为;
Ast::name* build_simple_name(std::string str)
{
return (new Ast::name_simple(Ast::identifier(str)));
}
BOOST_PHOENIX_ADAPT_FUNCTION(Ast::name*, build_simple_name_, build_simple_name, 1)
并且;
Ast::name* build_qualified_name(Ast::name* name, std::string str)
{
std::list<Ast::identifier> qualified_name = Ast::name_to_identifier_list(name);
qualified_name.push_back(Ast::identifier(str));
return (new Ast::name_qualified(qualified_name));
}
BOOST_PHOENIX_ADAPT_FUNCTION(Ast::name*, build_qualified_name_, build_qualified_name, 2)
使用的词法分析器定义定义为:
lex::token_def<std::string> identifier = "{JAVA_LETTER}{JAVA_LETTER_OR_DIGIT}*";
并且;
('.', DOT)
其中模式 {JAVA_LETTER}
和 {JAVA_LETTER_OR_DIGIT}
定义为:
("DIGIT", "[0-9]")
("LATIN1_LETTER", "[A-Z]|[a-z]")
("JAVA_LETTER", "{LATIN1_LETTER}|$|_")
("JAVA_LETTER_OR_DIGIT", "{JAVA_LETTER}|{DIGIT}")
我的输入是一个简单的字符串;
package a.D;
token 的词法;
Keywords : package
Identifier : a
Delimiters : .
Identifier : D
Delimiters : ;
第一个示例(首先是 simple_name)抛出语法错误:
Syntax Error at line 1:
package a.D;
^^
最后一个示例只是抛出一个段错误,错误已在前面发布。
显然,第二个示例是我想要的,因为它应该在简单表达式之前尝试匹配复杂表达式。
有谁知道代码崩溃的原因,或者我将如何解决? - 这也应该在代码审查中进行吗?
最佳答案
问题是你有一个left recursive grammar并且不能与 Boost.Spirit 一起使用。 你所拥有的基本上是:
name = identifier | name >> dot >> identifier;
如您所见here ,以便在遇到以下情况时删除左递归:
A = A >> alpha | beta;
您需要创建 2 条新的“规则”:
A = beta >> A_tail;
A_tail = eps | alpha >> A_tail;
就您而言:
A := name
alpha := dot >> identifier
beta := identifier
所以你的“规则”是:
name = identifier >> name_tail;
name_tail = eps | dot >> identifier >> A_tail;
如果你仔细观察name_tail
你可以看到它的字面意思是:要么什么都没有,要么 dot >> identifier
后面要么什么也不做,要么 dot >> identifier
等等。这意味着name_tail
是:
name_tail = *(dot >> identifier);
最后你的name
规则是:
name = identifier >> *(dot >> identifier);
所有这些都是正确的,但很有可能它不适用于您的属性。
关于boost - 在 boost::spirit 语法中翻转规则内的子规则顺序会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18611990/