Чтобы справиться с большим временем компиляции и повторным использованием грамматик, я разбил свою грамматику на несколько суб-грамматик, которые вызываются последовательно. Одна из них (назовем ее: грамматика SETUP) предлагает некоторую конфигурацию анализатора (через синтаксический анализатор символов), поэтому более поздние подграмматики логически зависят от этой грамматики (опять же через другие синтаксические анализаторы символов). Таким образом, после синтаксического анализа SETUP необходимо изменить синтаксические анализаторы следующих подграмматик.
Мой вопрос: как подойти к этому эффективно, сохранив при этом слабую связь между подграмматиками?
В настоящее время я вижу только две возможности:
- Обработчик on_success грамматики SETUP, который мог бы выполнять эту работу, но это внесло бы некоторую связь.
- После НАСТРОЙКИ проанализируйте все в строку, создайте новый синтаксический анализатор (из измененных символов) и проанализируйте эту строку на втором этапе. Это оставило бы некоторые накладные расходы.
Я бы хотел иметь обработчик on_before_parse, который может быть реализован любой грамматикой, которая должна выполнять некоторую работу перед каждым синтаксическим анализом. С моей точки зрения, это привело бы к меньшему связыванию, и некоторая настройка парсера могла бы пригодиться и в других ситуациях. Возможно ли что-то подобное?
Обновление:
Извините за отрывочность, это не было моим намерением.
Задача состоит в том, чтобы проанализировать вход I с некоторыми ключевыми словами, такими как #task1
и #task2
. Но будут случаи, когда эти ключевые слова должны быть разными, например $$task1
и $$task2
.
Итак, проанализированный файл будет начинаться с
setup {
#task1=$$task1
#task2=$$task2
}
realwork {
...
}
Некоторые наброски кода: Дан основной парсер, состоящий из нескольких (как минимум двух) парсеров.
template<typename Iterator>
struct MainParser: qi::grammar<Iterator, Skipper<Iterator>> {
MainParser() : MainParser::base_type(start) {
start = setup >> realwork;
}
Setup<Iterator> setup;
RealWork<Iterator> realwork;
qi::rule<Iterator, Skipper<Iterator> > start;
}
Setup
и RealWork
сами являются парсерами (мои вспомогательные парсеры сверху). Во время настройки некоторые ключевые слова грамматики могут быть изменены, поэтому в части настройки есть правило qi::symbols<char, keywords>
. Вначале эти символы будут содержать #task1
и #task2
. После анализа первой части файла они содержат $$task1
и $$task2
.
Поскольку ключевые слова изменились и RealWork
нужно проанализировать I, ему необходимо знать о новых ключевых словах. Поэтому мне нужно перенести символы с Setup
на RealWork
во время обработки файла.
Я вижу два подхода:
- Сообщите
Setup
оRealWork
и перенесите символы изSetup
вRealWork
вqi::on_success
обработчикеSetup
. (плохо, сцепление) Переключитесь на два шага анализа.
start
изMainParser
будет выглядеть какstart = setup >> unparsed_rest
и будет второй парсер после
MainParser
. Схематично:SymbolTable Table; string Unparsed_Rest; MainParser.parse(Input, (Unparsed_Rest, Table)); RealWordParser.setupFromAlteredSymbolTable(Table); RealWorkParser.parse(Unparsed_Rest);
Накладные расходы на несколько шагов синтаксического анализа.
Итак, до сих пор атрибуты не используются. Просто измените синтаксический анализатор во время синтаксического анализа для обработки нескольких типов входных файлов.
Надеюсь, что такой обработчик qi::on_before_parse
, как qi::on_success
. По идее, этот обработчик будет запускаться каждый раз, когда синтаксический анализатор начинает синтаксический анализ ввода. Теоретически просто перехват в начале разбора, как у нас есть перехваты on_success
и on_error
.