Может ли ANTLR различать правила лексера на основе следующего символа? - PullRequest
0 голосов
/ 06 апреля 2011

Для разбора тестового файла я бы хотел, чтобы идентификаторы начинались с цифры.

мое правило:

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

Однако мне также нужно сопоставить числа в этом файле. Мое правило для этого:

INT :   '0'..'9'+
;

Очевидно, что Antlr не позволит мне сделать это, поскольку INT никогда не будет совпадать.

Есть ли способ разрешить это? В частности, я хотел бы сопоставить INTEGER, за которым следует идентификатор без пробелов, как просто идентификатор, и создать токен INT, только если за ним следует пробел.

Например:

3BOB -> [ID with text "3BOB"]
3 BOB -> [INT with text "3"] [ID with text "BOB"]

Ответы [ 2 ]

2 голосов
/ 04 мая 2011

Просто измените порядок, в котором определены токены ID и INT.

grammar qqq;

// Parser's rules.

root:
    (integer|identifier)+
;

integer:
    INT {System.out.println("INT with text '"+$INT.text+"'.");}
;

identifier:
    ID {System.out.println("ID with text '"+$ID.text+"'.");}
;

// Lexer's tokens.

INT:    '0'..'9'+
;

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

WS:    ' ' {skip();}
;

UNPREDICTED_TOKEN
:
    ~(' ') {System.out.println("Unpredicted token.");}
;

Порядок, в котором токены определены в грамматике, имеет значение: в случае, если строку можно отнести к нескольким токенам, она присваиваетсяк тому, который определен первым.В вашем случае, если вы хотите, чтобы целое число «123» относилось к INT, когда оно все еще соответствует ID - сначала укажите определение INT.

Соответствие токена Antlr является жадным, поэтому оно не остановится на «123» в«123BOB», но будет продолжаться до тех пор, пока ни один из токенов не совпадет со строкой и не возьмет последний соответствующий токен.Таким образом, ваши идентификаторы теперь могут начинаться с цифр.

Замечание о порядке токенов также можно найти в этой статье Марка Фолькмана .

1 голос
/ 06 мая 2011

Следующие незначительные изменения в ваших правилах должны помочь:

ID  :   ('0'..'9')* // optional numbers
        ('a'..'z' | 'A'..'Z' | '_' |  '&' | '/' | '-' | '.') // followed by mandatory character which is not a number
        ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')* // followed by more stuff (including numbers)
;

INT :   '0'..'9'+ // a number
;

Вы просто разрешаете своим идентификаторам начинаться с необязательного числа и делаете обязательными следующие символы.

...