Внутренние ошибки Boost :: Spirit кода при разборе составной грамматики
Я пытаюсь использовать Дух для разбора выражений видаModule1.Module2.value
(любое количество разделенных точками заглавных идентификаторов, затем точка, а затем строчный идентификатор в стиле OCaml). Мое текущее определение парсера выглядит так:
using namespace boost::spirit::qi;
template <typename Iter=std::string::iterator>
struct value_path : grammar<Iter, boost::tuple<std::vector<std::string>, std::string>()> {
value_path() :
value_path::base_type(start)
{
start = -(module_path<Iter>() >> '.') >> value_name<Iter>();
}
rule<Iter, boost::tuple<std::vector<std::string>, std::string>()> start;
};
гдеmodule_path
а такжеvalue_name
аналогичные шаблонные структуры, наследующие отqi::grammar
с однимstart
поле, которому назначено некоторое правило Духа, возможно, с использованием других пользовательских грамматик (например,value_name
зависит отlowercase_ident
а такжеoperator_name
которые определяются аналогично) в конструкторе.
При попыткеparse_phrase()
с этой грамматикой программа segfaults где-то во внутренностях Духа (согласно GDB). Эквивалентное определение, где конструкторvalue_path
выглядит следующим образом (я в основном развернул все пользовательские грамматики, от которых это зависит, оставив только встроенные анализаторы Spirit, и попытался сделать его читабельным, что задним числом было глупым поручением):
start =
-((raw[upper >> *(alnum | char_('_') | char_('\''))] % '.') >> '.')
>> lexeme[((lower | char_('_')) >> *(alnum | char_('_') | char_('\'')))
| char_('(') >>
( ( (char_('!') >> *char_("-+!$%&*./:<=>?@^|~")
| (char_("~?") >> +char_("-+!$%&*./:<=>?@^|~"))
| ( (char_("-+=<>@^|&*/$%") >> *char_("-+!$%&*./:<=>?@^|~"))
| string("mod")
| string("lor")
| string("lsl")
| string("lsr")
| string("asr")
| string("or")
| string("-.")
| string("!=")
| string("||")
| string("&&")
| string(":=")
| char_("*+=<>&-")
)
) >> char_(')')
)
)
];
не выполняет segfault и, кажется, работает правильно, однако я бы предпочел избежать чего-то такого многословного и нечитаемого в моем коде. Это также не расширяемо вообще.
До сих пор я пробовал различные комбинации.alias()
, а также сохранениеvalue_name<Iter>()
, module_path<Iter>()
и все промежуточные грамматики по цепочке зависимостей в свои поля. Ни один из тех не работал. Как я могу сохранить высокий уровень абстракции первого примера? Есть ли стандартный способ составления грамматик в Духе, который не сталкивается с проблемами?