Antlr условно переписывает - PullRequest
2 голосов
/ 16 декабря 2011

У меня есть следующее правило грамматики Antlr:

expression1
  : e=expression2 (BINOR^ e2=expression2)*
  ;

Однако, если у меня есть '3 | 1 | 2 | 6', это приводит к плоскому дереву с 3, 1, 2, 6 всеми дочерними элементами узла BINOR. Что я действительно хочу, так это иметь возможность сопоставления с шаблоном на

expression2
or
^(BINOR expression2 expression2)

Как я могу изменить перезапись так, чтобы это были 2 шаблона?

EDIT:

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

expression1
  : e=expression2 (BINOR e2=expression2)*
            ->  {$BINOR != null}?   ^(BINOR $e $e2*)
            -> $e

Но когда я делаю это с '1 | 2 | 3', результирующее дерево имеет только один узел BINOR с двумя дочерними элементами, которые равны 1 и 3, поэтому 2 отсутствует.

Большое спасибо

1 Ответ

1 голос
/ 16 декабря 2011

Вы были близки, это будет работать:

expression1
@init{boolean or = false;}
 : e=expression2 (BINOR {or=true;} expression2)* -> {or}? ^(BINOR expression2+)
                                                 ->       $e
 ;

Но это предпочтительнее, так как он не использует какой-либо пользовательский код:

grammar T;

options {
  output=AST;
}

expression1
 : (e=expression2 -> $e) ((BINOR expression2)+ -> ^(BINOR expression2+))?
 ;

expression2
 : NUMBER
 ;

NUMBER
 : '0'..'9'+
 ;

BINOR
 : '|'
 ;

Парсер, сгенерированный из приведенной выше грамматики, будет анализировать входные данные "3|1|2|6" в AST:

enter image description here

и ввод "3" в AST:

enter image description here

Но ваша оригинальная попытка:

expression1
  : e=expression2 (BINOR^ e2=expression2)*
  ;

не создает плоское дерево (при условии, что у вас есть output=AST; в ваших настройках). Он генерирует следующий AST для "3|1|2|6":

enter image description here

Если вы «видите» плоское дерево, я думаю, вы используете интерпретатор в ANTLRWorks, который показывает не AST, а дерево разбора вашего разбора. Интерпретатор также довольно глючит (не обрабатывает предикаты и не оценивает пользовательский код), поэтому лучше его не использовать. Вместо этого используйте отладчик ANTLRWorks, который работает как шарм (изображения из моего ответа взяты из отладчика)!

...