Неделю назад я начал следующий проект: грамматику, которая распознает суффиксы Java-кода.
Я использовал официальную грамматику ANTLR
для Java (Java.g4
) в качестве базовой линии и начал добавлять некоторые правила. Однако эти новые правила также ввели левую рекурсию, с которой мне также пришлось иметь дело.
После нескольких дней работы у меня был следующий код. Когда я начал тестировать, я заметил что-то необычное, которое я до сих пор не могу объяснить. Когда вводится вход { }
, парсер говорит мне no viable alternative at input '<EOF>'
, но когда я переключаю порядок терминалов в правой части правила s2
, особенно если мы изменим правую сторону от v2_1 | v2_2 | v2_3 ...
до v2_36 | v2_1 | v2_2 ...
(терминал v2_36
перемещается в первую позицию), последовательность { }
принимается.
Мои первые мысли заключались в том, что ANTLR
не отступает, потому что я заметил, что с входом { }
первая версия анализатора начинает следовать правилу v2_3
и просто сообщает, что ничего не найдено и не пытается рассмотрите другие варианты (что я думаю, но, возможно, это не так), как v2_36
, которые дают именно положительный ответ.
Но после некоторого исследования я узнал, что ANTLR
действительно отступает, но только если все остальное терпит неудачу. По крайней мере, это верно для v3.3 (читайте в официальной статье ANTLR
), но я думаю, что это также верно для v4
. Теперь я немного смущен. Проведя так много часов в этом проекте, я почувствовал бы себя ужасно, если не заработаю. Может кто-то дает какой-то совет или что-то еще? Было бы очень благодарно, спасибо.
ИЗМЕНИТЬ
Удалось решить проблему с помощью
grammar Java;
@parser::members {String ruleName; }
start : compilationUnitSuf EOF;
compilationUnitSuf
: {ruleName = "typeDeclarationSuf"; } s2
;
s2: '{' '}' v2_81 | '{' '}';
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}';
t173: '}' | '{'*;
LBRACKET: '{';
RBRACKET: '}';
WS : [ \t\r\n\u000C]+ -> skip
;
Итак, почему алгоритм прогнозирования предлагает мне следовать s2 -> v'{' '}' v2_81 -> ...
вместо s2 -> '{' '}'
?