Подтвердить что ты не робот

ANTLR: Как объясняется поведение этой грамматики, которая распознает суффиксы Java-кода?

Неделю назад я начал следующий проект: грамматику, которая распознает суффиксы 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 -> '{' '}'?

4b9b3361

Ответ 1

Я думаю, что вы обнаружите, что он не отступает так, как вы ожидаете. Причина в том, что он находит {}, а затем ожидает увидеть v2_181, который он не находит. потому что он не отступает, он не находит альтернативы, которую вы хотите. Альтернативой является просто сделать опцию v2_181 опциональной, тогда вам не потребуется обратный отсчет. Что-то вроде ниже:

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
    ;