ANTLR4: обработка пробелов

Я видел много грамматик ANTLR, которые используют обработку пробелов следующим образом:

WS: [ \n\t\r]+ -> skip;
// or
WS: [ \n\t\r]+ -> channel(HIDDEN);

Таким образом, пробелы выбрасываются, соответственно отправляются на скрытый канал.

С такой грамматикой:

grammar Not;

start:      expression;
expression: NOT expression
          | (TRUE | FALSE);

NOT:    'not';
TRUE:   'true';
FALSE:  'false';
WS: [ \n\t\r]+ -> skip;

действительные входы "не истинны" или "не являются ложными", но также "nottrue", что не является желаемым результатом. Изменение грамматики на:

grammar Not;

start:      expression;

expression: NOT WS+ expression
          | (TRUE | FALSE);

NOT:    'not';

TRUE:   'true';
FALSE:  'false';

WS: [ \n\t\r];

устраняет проблему, но я не хочу обрабатывать пробелы вручную в каждом правиле.

Как правило, я хочу иметь пробел между каждым токеном с некоторыми исключениями (например, "! true" не требует пробела между ними). ​​

Есть ли простой способ сделать это?

Ответ 1

Добавить правило IDENTIFIER lexer для обработки слов, которые не являются ключевыми словами.

IDENTIFIER : [a-zA-Z]+;

Теперь текст nottrue - это единственный тег IDENTIFIER, который ваш парсер не будет принимать вместо отдельных ключевых слов в not true.

Убедитесь, что IDENTIFIER определяется после других ключевых слов. Лексер найдет, что оба NOT и IDENTIFIER соответствуют тексту NOT, и назначат тип токена первой, которая появляется в грамматике.