Допустим, внутри вашего a
правила все ACCEPTED_SYMBOLS
символы действительны, но внутри правила b
=
недействительно.
Вы можете сделать это, используя предикат , например:
a
: ACCEPTED_SYMBOLS
;
b
: t=ACCEPTED_SYMBOLS {!$t.text.equals("=")}?
;
ACCEPTED_SYMBOLS
: '~' | '!' | '@' | '#' | '$' | '%' | '^' | '-' | '+' | '=' |
'\\' | ':' | '"' | '\'' | '<' | '>' | ',' | '.' | '?' | '/'
;
Обратите внимание, что в грамматике ANTLR необходимо экранировать только одинарные кавычки и обратную косую черту внутри буквенной строки.
Или без предиката:
a
: any
;
b
: SYMBOLS
;
any
: SYMBOLS
| EQ
;
SYMBOLS
: '~' | '!' | '@' | '#' | '$' | '%' | '^' | '-' | '+' |
'\\' | ':' | '"' | '\'' | '<' | '>' | ',' | '.' | '?' | '/'
;
EQ
: '='
;
EDIT
Обратите внимание, что вы не можете определить правила в следующем порядке:
ACCEPTED_SYMBOLS: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' | '=' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
ACCEPTED_SYMBOLS_EXCEPT_EQUAL: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
ANTLR выдаст ошибку, что токен ACCEPTED_SYMBOLS_EXCEPT_EQUAL
никогда не может быть создан, поскольку предыдущие правила уже будут соответствовать всему, что ACCEPTED_SYMBOLS_EXCEPT_EQUAL
может соответствовать.
И если вы измените правила:
ACCEPTED_SYMBOLS_EXCEPT_EQUAL: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
ACCEPTED_SYMBOLS: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' | '=' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
тогда правило ACCEPTED_SYMBOLS
может совпадать только с '='
. Все остальные персонажи будут маркированы как ACCEPTED_SYMBOLS_EXCEPT_EQUAL
токены.
Вы должны понимать, что лексер работает независимо от парсера: он просто создает токены, следуя правилам лексера сверху вниз, пытаясь найти максимально возможное совпадение, и ему все равно, что парсер в это время пытается чтобы соответствовать.