Как получить хорошее сообщение об ошибке для отсутствующих токенов в ANTLR 4? - PullRequest
0 голосов
/ 15 ноября 2018

Я написал грамматику ANTLR 4 для языка программирования в стиле C и пытаюсь улучшить сообщения об ошибках для отсутствующих разделителей, таких как пропущенная запятая или отсутствующая закрывающая скобка в списке аргументов функции.

Я думал, что механизм вставки одиночного токена в ANTLR точно обнаружит отсутствующие токены, но вместо этого я часто получаю ошибку «альтернатива не жизнеспособна».Вот пример:

root
  : expr+ EOF
  ;

expr
  : '(' expr ')'
  | '(' ')' '->' expr
  | ID
  ;

ID: [a-zA-Z0-9$_]+;

Whitespace
  : [ \t\r\n\f]+ -> skip
  ;

Синтаксический ввод ( -> foo приводит к:

line 1:2 no viable alternative at input '(->'

Вместо этого я хотел бы видеть missing ')'.Каков рекомендуемый способ достижения этого?

Единственное работающее решение, которое я нашел на сегодняшний день, это сделать все разделители необязательными в грамматике и действовать в зависимости от их отсутствия у посетителя.Однако это похоже на обходной путь и имеет существенные недостатки, которых я бы предпочел избежать.

1 Ответ

0 голосов
/ 16 ноября 2018

Первое, на что нужно обратить внимание, это то, что вы получите почти то же сообщение об ошибке, что и вы, если удалите правило '(' expr ')':

expr
  : '(' ')' '->' expr
  | ID
  ;

Сообщение об ошибке:

line 1:2 missing ')' at '->'
line 1:4 mismatched input '<EOF>' expecting {'(', ID}

Я полагаю, что вы получаете ошибки, такие как «несоответствующий ввод X, ожидая Y» и «пропущенный X» для грамматик LL (1) и no viable alternative, когда требуется предварительный просмотр в текущей позиции или что-то в этом роде.

Так что спомните, что мы можем попытаться переписать вашу грамматику на LL (1):

expr
  : '(' ( expr ')' | ')' '->' expr )
  | ID
  ;

Тогда появится сообщение об ошибке:

line 1:2 mismatched input '->' expecting {'(', ')', ID}

Это очень близко к тому, что вы хотите.

...