在boost :: spirit语法中翻转子规则的顺序会导致segfault [英] Flipping the order of subrules inside a rule in a boost::spirit grammar results in segfault

查看:100
本文介绍了在boost :: spirit语法中翻转子规则的顺序会导致segfault的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

警告;而我试图将代码缩短到最低限度.我仍然需要包括很多内容,以确保提供所需的信息.

Warning; while I tried to shorten the code down, to a minimum. I still had to include quite a bit, to ensure that the required information was present.

此代码,编译文件并运行会导致语法错误;

This code, compiles files, and runs resulting in a syntax error;

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*();

All of these rules, return a 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)

所使用的词法分析器定义为;

The lexer definitions used are defined as;

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}")

我的输入是一个简单的字符串;

My input, is a simple string;

package a.D;

标记的词汇;

Keywords : package
Identifier : a
Delimiters : .
Identifier : D
Delimiters : ;

在第一个示例(首先是simple_name)的地方,语法错误为;

Where the first example (with simple_name first), throws a syntax error as;

Syntax Error at line 1:
package a.D;
          ^^

最后一个示例只是抛出了一个段错误,错误已在前面发布.

And the last example simply throws an segfault, with the error posted previously.

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

Clearly the second example is what I want, as it should try to match the complex expression, before the simple one.

有人看到代码为什么崩溃,或者我将如何解决吗? -还应该在代码审查中吗?

Does anyone see why the code crashes, or how I would go about figuring out? - Also should this be at code review?

推荐答案

问题是您有左递归语法,并且不能与Boost.Spirit一起使用. 基本上,您拥有的是:

The problem is that you have a left recursive grammar and that cannot be used with Boost.Spirit. What you have is basically:

name = identifier | name >> dot >> identifier;

您可以在此处,以便在您遇到类似以下情况时删除左递归:

As you can see here, in order to remove the left recursion when you have something like:

A = A >> alpha | beta;

您需要创建2个新的规则":

You need to create 2 new "rules":

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是:

If you look closely at name_tail you can see that it literally means: either nothing or dot >> identifier followed by either nothing or dot >> identifier and so on. That means that name_tail is:

name_tail = *(dot >> identifier);

所以最终您的name规则将是:

So finally your name rule would be:

name = identifier >> *(dot >> identifier);

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

All of this is correct, but there is a very good chance that it will not work with your attributes.

这篇关于在boost :: spirit语法中翻转子规则的顺序会导致segfault的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆