Как мой лексер ANTLR может соответствовать токену, составленному из символов, которые являются подмножеством токена другого вида? - PullRequest
5 голосов
/ 01 февраля 2010

У меня есть, на мой взгляд, простой вопрос ANTLR. У меня есть два типа токенов: ident и special_ident. Я хочу, чтобы мои special_ident соответствовали одной букве, за которой следовала одна цифра. Я хочу, чтобы шаблон ident соответствовал одной букве, за которой может следовать любое количество букв или цифр. Моя (неправильная) грамматика ниже:

expr 
    : special_ident
    | ident
    ;

special_ident : LETTER DIGIT;
ident         : LETTER (LETTER | DIGIT)*;

LETTER : 'A'..'Z';
DIGIT  : '0'..'9';

Когда я пытаюсь проверить эту грамматику, я получаю это предупреждение:

Решение может соответствовать вводу, такому как «ЦИФРА ПИСЬМА», используя несколько альтернатив: 1, 2. В результате альтернатива (ы) 2 были отключены для этого ввода

Я понимаю, что моя грамматика неоднозначна и что ввод, такой как A1, может соответствовать либо ident, либо special_ident. Я действительно хочу, чтобы special_ident использовался в самом узком случае.

Вот несколько примеров ввода и того, что бы я хотел, чтобы оно совпадало:

A      : ident
A1     : special_ident
A1A    : ident
A12    : ident
AA1    : ident

Как я могу сформировать мою грамматику так, чтобы я правильно идентифицировал мои два типа идентификаторов?

Ответы [ 2 ]

3 голосов
/ 01 февраля 2010

Кажется, у вас есть 3 случая:

  • A
  • AN
  • A(A|N)(A|N)+

Вы можете классифицировать средний как special_ident, а два других как ident; Кажется, что должен сделать свое дело.

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

long_ident    : LETTER (LETTER | DIGIT) (LETTER | DIGIT)+
special_ident : LETTER DIGIT;
ident         : LETTER | long_ident;
2 голосов
/ 01 февраля 2010

Продолжая мысль Карла, я думаю, у вас есть четыре разных случая:

  1. A
  2. Звездочкой 1006 *
  3. AA (A | N) *
  4. (Л | Н) +

Только опция 2 должна быть токеном special_ident, а остальные три должны быть тождественными. Все токены можно идентифицировать только по синтаксису. Вот быстрая грамматика, которую я смог протестировать в ANTLRWorks, и она, кажется, работает правильно для меня. Я думаю, что у Карла может быть одна ошибка при попытке проверить АА, но получить 99% - это огромная выгода, так что это лишь незначительная модификация его быстрой мысли.

prog 
    :    (expr WS)+ EOF;

expr 
    : special_ident {System.out.println("Found special_ident:" + $special_ident.text + "\n");}
    | ident {System.out.println("Found ident:" + $ident.text + "\n");}
    ;

special_ident : LETTER DIGIT;

ident         : LETTER 
    |LETTER DIGIT (LETTER|DIGIT)+
    |LETTER LETTER (LETTER|DIGIT)*;

LETTER : 'A'..'Z';
DIGIT  : '0'..'9';
WS 
    :   (' '|'\t'|'\n'|'\r')+;
...