Проблема с пробелами в скрытом канале - PullRequest
2 голосов
/ 18 июля 2009

У меня есть следующая грамматика 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 в этом примере для упрощения, но поддерживаются другие виды комментариев.

Ответы [ 2 ]

6 голосов
/ 19 июля 2009

Вам необходимо создать общий идентификатор токена. Так как лексер создает самый длинный токен, который он может, он будет видеть ввод «hiworld» как одно слово, так как он длиннее, чем «hi» или «world» сами по себе. Такое правило может выглядеть так:

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

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

0 голосов
/ 18 июля 2009

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

doc:      intro planet;
failure : 'hiworld' { false }?;
intro   : 'hi';
planet  : 'world';
// rest of grammar omitted
...