Если я определю токен VALUE
перед конкретными значениями, то правило data_stmt
сработает, но address_stmt
не найдет жизнеспособных альтернатив, поскольку десятичное или шестнадцатеричное число будет соответствовать VALUE
раньше.
Вс другой стороны, если я определю VALUE
после всех определенных значений, то address_stmt
будет работать, но data_stmt
завершится неудачно, потому что любой конкретный маркер значения будет соответствовать до VALUE
.
Можно ли как-то решить эту проблему путем перестановки грамматики?
Возможно, есть способ с предикатами, но я еще недостаточно изучил их.
Возможным решением было бы использование всех определенных токенов и избавление от VALUE
в целом, но это сделало бы грамматику слишком многословной и менее изящной.
Я также мог бы определить address_stmt
, чтобы использовать любые VALUE
итогда разрешите только шестнадцатеричные и десятичные числа в коде Слушателя, но я бы лучше решил это в грамматике, если это возможно.
Пример источника:
address $0108
data $0E08, $0A00
Грамматика:
grammar so;
program: ( statement EOL )* EOF ;
statement:
address_stmt |
data_stmt |
;
address_stmt: ADDRESS_KWD (DECIMAL_NUMBER | HEX_NUMBER) ;
data_stmt: DATA_KWD VALUE (',' VALUE)* ;
ADDRESS_KWD: [aA][dD][dD][rR][eE][sS][sS] ;
DATA_KWD : [dD][aA][tT][aA] ;
VALUE: DECIMAL_NUMBER | HEX_NUMBER | BINARY_NUMBER | STRING ;
DECIMAL_NUMBER: [0-9]+ ;
HEX_NUMBER: '$' [0-9a-fA-F]+ ;
BINARY_NUMBER: '%' [01]+ ;
STRING: '"' [^"]+ '"' ; // very basic string definition
/* VALUE: DECIMAL_NUMBER | HEX_NUMBER | BINARY_NUMBER | STRING ; */
WHITESPACE: [ \t]+ -> skip;
EOL: '\r'? '\n';