Вопрос

У меня есть следующая грамматика ANTLR:

grammar MyGrammar;

doc :   intro planet;
intro   :   'hi';
planet  :   'world';
MLCOMMENT 
    :   '/*' ( options {greedy=false;} : . )* '*/' { $channel = HIDDEN; };
WHITESPACE : ( 
    (' ' | '\t' | '\f')+
  |
    // handle newlines
    ( '\r\n'  // DOS/Windows
      | '\r'    // Macintosh
      | '\n'    // Unix
    )
    )
 { $channel = HIDDEN; };

В интерпретаторе Antlrworks 1.2.3 входные данные hi world,hi/**/world а также hi /*A*/ world работа, как и ожидалось.

Однако вход hiworld, который не должен работа, также принимается. Как мне сделать hiworld потерпеть неудачу? Как привести хотя бы один пробел (или комментарий) между «Привет» и «Миром»?

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

Это было полезно?

Решение

Вам нужно создать токен общего идентификатора. Поскольку Lexer строит самый длинный токен, который он может, он будет рассматривать ввод «Hiworld» как одно слово, так как он сам дольше, чем «HI» или «World». Такое правило может выглядеть как:

ID : ('a'..'z' | 'A'..'Z')+;

Например, именно так аналогичники для языков программирования отделяют ключевое слово «do» от «Double» (тип ключевого слова, начинается с «do») или «Do Do» (имя переменной).

Другие советы

Один из способов сделать строку hiworld Неудача в том, чтобы использовать подтверждающий семантический предикат, который гарантированно не удастся, следующим образом:

doc:      intro planet;
failure : 'hiworld' { false }?;
intro   : 'hi';
planet  : 'world';
// rest of grammar omitted
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top