ANTLR: ошибка лексера или парсера? - PullRequest
1 голос
/ 26 декабря 2011

Я написал простой лексер в ANTLR, и грамматика для ID выглядит примерно так:

ID  :   (('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*|'_'('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*);

(цифры не допускаются в начале)

при создании кода (в Java) и проверил ввод:

3a

Я ожидал ошибку, но вход был распознан как "INT ID", как я могу исправить грамматику, чтобы она сообщала об ошибке? (только с правилами лексера))

Спасибо за внимание

1 Ответ

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

Обратите внимание, что ваше правило может быть переписано в:

ID
 : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '0'..'9' |'_')*
 ;    

или с fragments (правила, которые не производят токены, но используются только другими правилами лексера):

ID
 : (Letter | '_') (Letter| Digit |'_')*
 ;

fragment Letter
 : 'a'..'z'
 | 'A'..'Z'
 ;

fragment Digit
 : '0'..'9'
 ;

Но если ввод, такой как "3a", распознается вашим лексером и выдает токены INT и ID, то вам не следует ничего менять.Проблема с таким вводом, вероятно, возникнет в ваших правилах синтаксического анализа, потому что это семантически неверно.

Если вы действительно хотите, чтобы лексер мог обрабатывать такие вещи, вы можете сделать что-то вроде этого:1013 *

INT
 : Digit+ (Letter {/* throw an exception */})?
 ;

И если вы хотите, чтобы литералы INT могли заканчиваться f или L, то вам сначала нужно проверить содержимое Letter, и если это не "f" или "L", вы бросаете исключение.

...