Кажущийся недетерминизм в анализе ANTLR

#parsing #antlr

#синтаксический анализ #antlr

Вопрос:

Если у меня есть грамматика ANTLR следующим образом:

 grammar Test;
options {
  language = Java;
}

rule : (foo | bar);


foo : FOO ',' FOO;   
bar : BAR; 

FOO: ('0'..'9') ;
BAR: ('a'..'z' | 'A'..'Z' | '0'..'9' | ' ') ;
WHITESPACE: (' ' | 't')  { $channel=HIDDEN; };
  

И я использую тестовую строку:


12abc3

это (я полагаю) BAR токен, который удовлетворяет bar правилу и анализируется как таковой. Браво.

Однако, если у меня есть эта строка:

 12
  

Я получаю line 1:2 mismatched input '' expecting ','

Это кажется довольно недетерминированным, хотя я уверен, что это не так. Я понимаю, что у меня уже проблемы с наличием двух токенов: FOO и BAR , которые принимают цифры. Но если анализатор собирается добиться успеха или потерпеть неудачу, он должен добиться успеха или потерпеть неудачу последовательно. Другими словами, в первом случае первым символом является 1 и, по-видимому, вычисляется как член BAR токена, и, таким образом, анализатор направляется по успешному пути. Во втором случае тот ЖЕ самый первый символ вычисляется как FOO токен, и, таким образом, путь обречен на неудачу, несмотря на то, что строка МОГЛА быть успешно bar проанализирована. Почему несоответствие? Или я упускаю что-то более фундаментальное в ANTLR и / или синтаксическом анализе?

Ответ №1:

ANTLR не определяет тип токена, пока не увидит первый символ для следующего токена (или EOF). ANTLR также попытается найти самое длинное совпадение, вот почему вы видите ’12abc3′ как BAR, а не как FOO BAR. Во втором случае ANTLR будет использовать FOO для ’12’, потому что он указан первым в грамматике.

Основы ANTLR

Лексеры ANTLR

Ответ №2:

В дополнение к ответу Adam, вы должны понимать, что лексер и анализатор, хотя и определены в одной и той же грамматике, создаются в разное время. Сначала источник входных данных маркируется, и когда это произошло, только тогда анализатор работает с этими маркерами. Токены не создаются, пока анализатор просматривает источник (поток символов), чтобы обеспечить полное совпадение (т.Е. обозначить "12" как BAR ). Тот факт, что "12" обозначается как FOO , заключается в том, что FOO оно предшествует BAR правилу и поэтому имеет более высокий приоритет в случае равного длинного совпадения.

Короче говоря: грамматики ANTLR не привязками.