Отрицание может происходить внутри правил лексера и парсера .
Внутри правил лексера вы можете отрицать символы, а внутри правил парсера вы можете отрицать токены (правила лексера). Но и правила лексера, и правила синтаксического анализатора могут отменять только одиночные символы или одиночные токены соответственно.
Пара примеров:
Правила лексера
Чтобы соответствовать одному или нескольким символам, кроме строчных букв 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) ;
Как и в случае с правилами лексеров, вы не можете отменить более одного токена. Для этого вам необходимо:
P
: A ~B
| ~A .
;
Обратите внимание, что символ .
(DOT) в правилах синтаксического анализа не соответствует любому символу, как в правилах лексера. В правилах синтаксического анализа он соответствует любому токену (A
, B
, C
, D
или E
, в данном случае).
Обратите внимание, что вы не можете отрицать правила парсера. Следующее незаконно:
p : ~a ;
a : A ;