2

Предупреждение; в то время как я пытался сократить код до минимума. Я все еще должен был включить совсем немного, чтобы обеспечить наличие необходимой информации.Перевертывание порядка субрулей внутри правила в boost :: spirit grammar приводит к segfault

Этот код компилирует файлы и запускает, что приводит к синтаксической ошибке;

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) 

Используемые определения lexer определяются как;

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; 

Какие лексики для жетонов;

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

Где первый пример (с первым именем simple_name), генерирует синтаксическую ошибку как;

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

И последний пример просто выбрасывает segfault с ранее отправленной ошибкой.

Очевидно, что второй пример - это то, что я хочу, поскольку он должен попытаться совместить сложное выражение перед простым.

Кто-нибудь видит, почему происходит сбой кода, или как я буду разбираться? - Также должно ли это быть в обзоре кода?

+0

Вы оставили рекурсию, имя зависит от квалифицированного имени, которое зависит от имени и т. Д. – llonesmiz

+0

Это незаконно? - Также, если это так, как я могу получить тот же эффект, вот как я могу его реорганизовать? – Skeen

ответ

2

Проблема в том, что у вас есть 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); 

Все это правильно, но есть очень хороший шанс, что он не будет работать с атрибутами.

+0

Тогда я исправлю свои атрибуты! Также спасибо большое :) – Skeen

+0

Умм, у меня есть вопрос на самом деле, так как кажется, что существует детерминированный способ удаления левой рекурсии, есть ли конкретная причина, почему boost :: spirit не просто «просто» препроцессу грамматики, чтобы его устранить. - Это невозможно, невозможно или просто функция, которую никто не реализовал? – Skeen

+0

Не знаю, я на самом деле пытался реализовать именно это, без успеха. Я думаю, что это будет что-то действительно круто. Могли ли вы изменить свои семантические действия, чтобы приспособиться к этому, или я должен попытаться что-то сделать? – llonesmiz

 Смежные вопросы

  • Нет связанных вопросов^_^