Как сделать правило, которое содержит несколько вхождений одного и того же токена?

Я работаю с ANTLR4, чтобы разобрать простой язык сценариев.

Этот язык использует следующий синтаксис для FOR циклов:

FOR [I] = 1 to [N]
   instructions
NEXT [I]

Чтобы быть правильным, цикл FOR должен иметь точно такой же токен после ключевого слова FOR и после ключевого слова NEXT.

Например, это правильно:

FOR I = 1 TO 10
NEXT I

Хотя это неверно:

FOR I = 1 TO 10
NEXT J

Пока у меня есть правило, которое выглядит так:

forloop
    : FOR VARNAME EQUAL INT TO INT instructions NEXT VARNAME
    ;

Со следующими связанными правилами лексера (я удалил постоянные ключевые слова, такие как FOR : 'FOR';):

fragment ALPHA : [a-zA-Z_];
fragment ALPHANUM : [a-zA-Z_0-9];
fragment DIGIT : [0-9];
VARNAME : ALPHA ALPHANUM*;
INT : DIGIT+;

Однако это правило будет интерпретировать как правильный второй пример, который на самом деле неверен.

Как я могу сказать ANTLR4, что второй VARNAME должен быть таким же, как первый в правиле?


person Benlitz    schedule 27.04.2014    source источник


Ответы (1)


Вы можете добавить предикат в конце вашего forloop правила, обеспечивающего равенство обоих VARNAME:

forloop
    : FOR a=VARNAME EQUAL INT TO INT instructions NEXT b=VARNAME
      {$a.getText().equals($b.getText())}?
    ;

Но (IMO) лучший способ - позволить синтаксическому анализатору просто принимать неравные VARNAME и проверять их после завершения синтаксического анализа (в каком-то прослушивателе проверки, который просматривает дерево синтаксического анализа).

person Bart Kiers    schedule 27.04.2014
comment
Спасибо! Если подумать, я думаю, что вы правы, но все равно хорошо знать, как добавлять такие предикаты :) - person Benlitz; 28.04.2014
comment
На самом деле я использую C #, поэтому преобразовал предикат в код C #: {$a.Text == $b.Text}?. К сожалению, у меня есть следующая ошибка: error AC0066: attribute 'Text' isn't a valid property in '$a.Text'. Однако, если я прервусь с отладчиком (используя простой предикат, который компилируется), свойство Text кажется доступным и правильно определенным (из интерфейса IToken). Кто-нибудь испытывал такую ​​проблему с С #? - person Benlitz; 28.04.2014
comment
@Benlitz, а разве нет $a.GetText() метода? - person Bart Kiers; 28.04.2014
comment
На самом деле мне пришлось использовать $a.text в нижнем регистре, хотя свойство C # - Text. От автора antlr4cs, это также будет работать с java (см. github.com/tunnelvisionlabs/antlr4cs / issues / 47). - person Benlitz; 29.04.2014