Как да създадем правило, което съдържа няколко срещания на един и същ токен?

Работя с 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 правило, което налага, че и двете VARNAMEs са равни:

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

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

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). Някой да е имал такъв проблем с C#? - 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