2015-09-16 2 views
3

Могу ли я генерировать правила динамически в parboiled2 parser? Вариант использования заключается в том, что у меня есть куча уже определенных правил, но я хочу добавить больше и не компилировать каждый раз, когда добавляю правило.Динамически создавать правила parboiled2

+0

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

+0

'добавить и не компилировать каждый раз, когда я добавляю правило, почему рекомпиляция касается вас? –

ответ

2

Если вы хотите генерировать правила во время выполнения (как вы делали в Parboiled1), это невозможно. Parboiled 2 использует marco exressions, поэтому вы не можете генерировать правила во время выполнения. Все происходит на этапе компиляции.

Если у вас есть ряд определенных правил и вы хотите составить их в произвольном порядке, даже если некоторые из них отсутствуют. Возможно. Я сделал это.

Есть два известных варианта, как можно достичь этого:

Первый вариант (я не пробовал еще) называется DynamicRuleDispatch вы можете найти его в documentation и смотреть на это испытание here.

Второй вариант заключается в отправке отправки вручную (как и я).

  1. Вы должны создать кучу правил, которые могут комбинироваться динамически. Эти правила должны иметь тип Rule0. Они не должны влиять на стек значений. Добавьте побочный эффект к этим правилам после оценки правила. Операция побочного эффекта должна сохранять захваченные данные где-то внутри вашего синтаксического анализатора. Вы должны использовать capture + ~ + run сверток для достижения этой цели, смотрите на примере ниже:

    Защиту RuleWithSideEffect = норма { захвата (EmailAddress) ~ пробег {адрес: String => saveItSomewhere (адрес) } ~ ВЗ

  2. Вам необходимо создать какое-то изменяемое состояние внутри вашего синтаксического анализатора. Сохраняйте место, где вы можете сохранить результаты синтаксического анализа. Это может быть hashmap. Этот Hashmap должен хранить все возможные правила и их значения. Вы не можете использовать стек значений, потому что вы не будете определять количество согласованных правил. Будьте внимательны при сохранении изменчивого состояния. Он должен быть очищен после каждого вызова.

  3. Для выравнивания правил вам нужен формат выравнивания правил. Например:

    класс Parser (вход: ParserInput, формат: String) расширяет Parser ....

Затем вам нужно разобрать строку формата и получить маркеры формата. Используйте шаблон соответствия для отправки списка соответствующих токенов формата в поля Rule0 dispatchRule ниже. А затем сопоставьте список токенов строк с правилами.

Если у вас есть список правил, которые необходимо выполнить следующие операции:

// concatenates two rules. Must be inside rule block 
def concatRules(f: Rule0, s: Rule0): Rule0 = rule { 
    f ~ s 
} 

val rootRule = 
    stringTokens map dispatchRule reduce concatRules 

def RootRule: Rule0 = rule { mainRule ~ EOI } 

def dispatchRule(token: String): Rule0 = match token { 
    case "DATE" => DateParser.DateRule 
    .... 
} 

Вы можете разобрать generater журнал доступа при наличии LogFormat в парсер конструктора. Итак, вам нужна модель данных для выравнивания правил.

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