Отрицание внутри правил лексера и парсера

Как можно использовать метасимвол отрицания ~ в правилах ANTLR lexer- и parser?

Ответы

Ответ 1

Отрицание может происходить внутри правил lexer и parser.

Внутри правил lexer вы можете отрицать символы, а внутри правил парсера вы можете сбрасывать токены (правила lexer). Но оба правила lexer- и parser могут только отрицать либо одиночные символы, либо одиночные токены соответственно.

Несколько примеров:

правила lexer

Чтобы соответствовать одному или нескольким символам, кроме строчных букв ascii, вы можете:

NO_LOWERCASE : ~('a'..'z')+ ;

(отрицание-meta- char, ~ имеет более высокий приоритет, чем +, поэтому приведенное выше правило равно (~('a'..'z'))+)

Обратите внимание, что 'a'..'z' соответствует одному символу (и может быть отменено), но следующее правило недействительно:

ANY_EXCEPT_AB : ~('ab') ;

Потому что 'ab' (очевидно) соответствует 2 символам, его нельзя отменить. Чтобы сопоставить токен, состоящий из 2 символов, но не 'ab', вам нужно будет сделать следующее:

ANY_EXCEPT_AB 
  :  'a' ~'b' // any two chars starting with 'a' followed by any other than 'b'
  |  ~'a' .   // other than 'a' followed by any char
  ;

правила анализатора

Внутри правил парсера ~ отменяет определенный токен или более одного токена. Например, вы определили следующие маркеры:

A : 'A';
B : 'B';
C : 'C';
D : 'D';
E : 'E';

Если вы хотите совместить любой токен, кроме A, выполните следующие действия:

p : ~A ;

И если вы хотите совместить любой токен, кроме B и D, вы можете сделать:

p : ~(B | D) ;

Однако, если вы хотите сопоставить любые два токена, кроме A, за которыми следует B, вы не можете сделать:

p : ~(A B) ;

Как и в случае с правилами lexer, вы не можете отрицать больше, чем один токен. Чтобы выполнить вышеизложенное, вам нужно сделать:

P
  :  A ~B
  |  ~A .
  ; 

Обратите внимание, что . (DOT) char в правилах анализатора не соответствует любому символу, как и внутри правил lexer. Внутри правил парсера он соответствует любому токену (A, B, C, D или E, в этом случае).

Обратите внимание, что вы не можете отменить правила парсера. Недопустимо следующее:

p : ~a ;
a : A  ;