Ответ 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 ;