Как выбрать правило лексера / парсера при реализации - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть грамматика для анализа разнородного SQL кода.

Проблема:

- иногда я хочу, чтобы она обрабатывала вложенные комментарии (например: Microsoft SQL) :

COMMENT: '/*' (COMMENT|.)*? ('*/' | EOF) -> channel(HIDDEN);

- иногда я хочу, чтобы он не обрабатывал их (например: Oracle):

COMMENT: '/*' .*? '*/' -> channel(HIDDEN);

Я не хочу:

  • сделать две разные грамматики

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

Лучшим решением было бы иметь аргумент, передаваемый лексеру / парсеру, чтобы выбрать, какую "реализацию COMMENT" использовать.

Я могу сделать это ? Если да, то как, если нет, есть ли удовлетворительное решение моей проблемы?

Спасибо!

1 Ответ

2 голосов
/ 06 февраля 2020

Вы можете достичь этого, используя предикат semanti c в своем лексере. Вам нужно будет (1) отделить лексер и парсер друг от друга. (2) Создайте базовый класс для лексера с логическим полем, свойством или методом, для которого вы можете установить значение true, если хотите, чтобы лексер разрешил вложенные комментарии, или false, чтобы запретить. Ради приведенного ниже кода предположим, что вы добавили "bool nested = false;" в базовый класс лексера. (3) В вашей лексерской грамматике создайте одно правило COMMENT, как показано ниже. (4) После создания лексера присвойте «вложенному» полю значение true, если вы хотите, чтобы вложенные комментарии были распознаны.

COMMENT
   : (
      {nested}? '/*' (COMMENT|.)*? ('*/' | EOF)
      | '/*' .*? '*/') -> channel(HIDDEN)
   ;
...