Самореферентные PPCompositeParsers PetitParser

У меня есть грамматика языка программирования, которую я хотел бы разбить на несколько подклассов PPCompositeParser (например, один класс будет обрабатывать инструкции, другой класс будет обрабатывать выражения, другой класс с обработкой структуры программы). Я хочу сделать это, чтобы избежать большого класса с десятками переменных экземпляра.

Моя проблема заключается в том, что эти подпрограммы имеют циклическую зависимость: структурная грамматика ссылается на правило 'Statement' грамматики оператора, которое ссылается на правило 'expression' грамматики выражения, которое ссылается на 'subroutineName' грамматики структуры (закрытие цикла зависимости). Я попробовал простой подход, чтобы, например, иметь метод #subroutineName в грамматике выражения, который выглядит следующим образом:

MyExpressionGrammar>>subroutineName
  ^ N2TJStructureParser newStartingAt: #subroutineName

но это не удается при инициализации из-за бесконечной рекурсии (очевидно).

Чтобы решить эту проблему, я создал PPDeferedParser:

PPParser subclass: #PPDeferedParser
    instanceVariableNames: 'creationBlock'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'PetitParser-Tools'

PPDeferedParser>>parseOn: aStream
    ^ creationBlock value parseOn: aStream

что делает предыдущее имя #subroutineName следующим образом:

MyExpressionGrammar>>subroutineName
  ^ PPDederedParser creationBlock: [N2TJStructureParser newStartingAt: #subroutineName]

Кажется, это работает, но мне интересно, есть ли другое решение.

1 ответ

Решение

В настоящее время разделение составного парсера на несколько PPCompositeParser подклассы напрямую не поддерживаются PetitParser.

Имейте в виду, что если вы используете браузер PetitParser, вам не нужно беспокоиться о переменных экземпляра, они автоматически управляются для вас. Кроме того, вам не обязательно нужна переменная экземпляра для каждого производства. Например, терминалы могут быть в методах, которые вы вызываете напрямую.

Ваше решение, конечно, тоже работает, но оно не так уж и приятно, потому что требует от вас внимательного отношения к тому, как вы хотите соединить свои грамматики. Также в вашей реализации вы должны лениво кэшировать результаты, так как в противном случае ваш код будет создавать новые составные парсеры при разборе. Это очень дорого.

Все это в стороне, конечно, можно было бы улучшить PPCompositeParser поддерживать зависимости между несколькими подклассами, например, путем объявления зависимых других анализаторов, которые конструктор должен подготовить, инициализировать и в конечном итоге разрешить.

Другие вопросы по тегам