在boost::spirit语法中翻转规则内子规则的顺序会导致segfault

在boost::spirit语法中翻转规则内子规则的顺序会导致segfault,boost,segmentation-fault,boost-spirit,boost-spirit-qi,boost-spirit-lex,Boost,Segmentation Fault,Boost Spirit,Boost Spirit Qi,Boost Spirit Lex,警告;我试图把代码缩短到最低限度。我仍然必须包括相当多的信息,以确保提供所需的信息 此代码、编译文件和运行导致语法错误 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:

警告;我试图把代码缩短到最低限度。我仍然必须包括相当多的信息,以确保提供所需的信息

此代码、编译文件和运行导致语法错误

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 ...

所有这些规则,返回一个
Ast::name*()

其中模式
{JAVA\u LETTER}
{JAVA\u LETTER\u或\u DIGIT}
定义为:

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)
lex::token_def<std::string> identifier = "{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;
对代币进行词法转换

Keywords : package
Identifier : a
Delimiters : .
Identifier : D
Delimiters : ;
其中第一个示例(首先是simple_name)抛出语法错误,如下所示:

Syntax Error at line 1:
package a.D;
          ^^
最后一个示例只是抛出一个segfault,前面已经发布了错误

显然,第二个示例是我想要的,因为它应该在简单表达式之前尝试匹配复杂表达式

有人知道为什么代码会崩溃吗,或者我会怎么去弄清楚?
-这也应该在代码审查时进行吗?

问题是您有一个不能与Boost.Spirit一起使用的。 你所拥有的基本上是:

name = identifier | name >> dot >> identifier;
如您所见,为了在如下情况下删除左递归:

A = A >> alpha | beta;
您需要创建两个新的“规则”:

就你而言:

A := name
alpha := dot >> identifier
beta := identifier
所以你的“规则”是:

name = identifier >> name_tail;
name_tail = eps | dot >> identifier >> A_tail;
name = identifier >> *(dot >> identifier);
如果你仔细观察
name\u tail
,你会发现它的字面意思是:要么没有,要么
dot>>identifier
,后面跟着要么没有,要么
dot>>identifier
等等。这意味着
name\u tail
是:

name_tail = *(dot >> identifier);
因此,最后您的
名称
规则是:

name = identifier >> name_tail;
name_tail = eps | dot >> identifier >> A_tail;
name = identifier >> *(dot >> identifier);

所有这些都是正确的,但它很有可能不适用于您的属性。

您离开了递归,名称取决于限定名称,而限定名称取决于名称等等。这是非法的吗?-如果是这样的话,我如何才能获得同样的效果,那就是我如何重构它?嗯,我有一个问题,实际上,似乎有一种确定性的方法可以消除左递归,那么boost::spirit不“简单地”预处理语法以消除它有什么具体的原因吗这是不可能的,不可行的,还是仅仅是一个没有人实现的特性?不知道,我实际上已经尝试实现了,但没有成功。我想这会是一件很酷的事情。你能改变你的语义动作来适应它吗?或者我应该试着做点什么吗?@Skeen它不能,因为你可以有违反关联性法则的自定义解析器(更不用说语义动作了)。当然,“他们”可以允许使用特征,但让人类进行思考要容易得多:/通常,我认为精神上不存在任何表达式转换(除了可能隐含的
char\uu
类的减法)Qi@Skeen他指的是后者,就像。
A := name
alpha := dot >> identifier
beta := identifier
name = identifier >> name_tail;
name_tail = eps | dot >> identifier >> A_tail;
name_tail = *(dot >> identifier);
name = identifier >> *(dot >> identifier);