Разрешение конфликта токенов в antlr

У меня есть токен ИЛИ:'ИЛИ'; который я использую для оценки логического выражения ( a == b OR a == c). У меня есть другое правило для анализа аббревиатуры состояния, которая находится в списке символов AZ, AK, OR, GA... Я обнаружил, что antlr имеет ошибку в списке состояний, полагая, что ИЛИ должен быть токеном or, а не

stateName   
    : CHAR CHAR (','|EOF) ->^(STATE CHAR+)
    ;   

как мне решить эту двусмысленность?

вот некоторые из правил, которые я пытаюсь разобрать

  • THEN STATE_LICENSE AL,AK,AS,AZ,AR,CT,DE,DC,FM,FL,GA,GU,HI,ID,IL,IN,IA,KS,KY,LA,ME,MH,MD,MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, MP, OH, OK, ИЛИ, PW, PA
  • ЕСЛИ 1198 == "x" ИЛИ 1190 != "x", ТО ОТКЛЮЧИТЬ 800
  • IF 801 >= "1000000" THEN DISPLAY_ERROR "Это+слишком+дорого.+Иди+и+получи+дешевле+один+!!!"

Вот грамматика, которую я использую

grammar PointFieldRule;


options 
{
//language = 'CSharp3'; 
output=AST; 
ASTLabelType=CommonTree;
} 
tokens{
STATE;

}


rule : ifExpression?  actionExpression EOF!
;
ifExpression 
    :'IF'! logicalConditionExpression
    ;

logicalConditionExpression
    : booleanAndConditionExpression ( BigOR^ booleanAndConditionExpression)*
    ;


booleanAndConditionExpression
    : logicalCondition ( BigAND^ logicalCondition )*
    ;

BigAND : 'and'|'AND';

logicalCondition
    : booleanAndCondition ( OR^ booleanAndCondition )*
    ;

OR:'||';

booleanAndCondition
    : evalCondition ( AND^ evalCondition)*
    ;

AND: '&&';

evalCondition 
    : FieldID OPERATOR^ (FieldID|STRING)
    ;

 actionExpression 
    : 'THEN'! (actionMessage | fieldAction | stateAction )  
    ;

actionMessage 
    : ('DISPLAY_WARNING' | 'DISPLAY_ERROR')^ STRING
    ;

fieldAction 
    : ('DISABLE' | 'REQUIRED')^ FieldID ( ','! FieldID )* 
    ;


stateAction
    : 'STATE_LICENSE'^ stateName+ //(','! stateName)*
    ;

FieldID
    :'0'..'9'+;

 /* item : FIELD 
    | CHAR CHAR
    ;
*/
//class csharpTestLexer extends Lexer; 

stateName   
    : CHAR CHAR (','|EOF) ->^(STATE CHAR+)
    ;   
CHAR:  ('a'..'z'|'A'..'Z')
    ;

WS : (' ' 
| '\t' 
| '\n' 
| '\r') 
{ $channel = HIDDEN; } 
//{ $channel = Hidden; } 
; 



OPERATOR 
    :   '=='
    | '!='
    |    '<='
    |    '>='
    |    '<'
    |    '>'
    | 'TD'
    | 'FD'
    | 'PD'
    | 'TY'
    | 'LY'
    | 'TM'
    | 'LM'
    | '+(DELTA%)>'
    | '-(DELTA%)>'
    | '+(DELTA)>'
    | '-(DELTA)>'
    | 'LIKE'
    ;


STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;


fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

//fragment
BigOR: 'or'|'OR';

person Aaron Fischer    schedule 18.07.2012    source источник


Ответы (1)


Лексер создает токены независимо от парсера. Таким образом, не имеет значения, может ли синтаксический анализатор "потребоваться" два токена CHAR в данной точке, если лексер "видит" текст "OR", он всегда будет создавать токен BigOR. Вы ничего не можете с этим поделать.

В вашем случае вы можете просто позволить stateName соответствовать двум токенам CHAR или одному токену OR следующим образом:

stateName   
 : name (','|EOF) ->^(STATE name)
 ;   

name
 : CHAR CHAR
 | BigOR
 ;

Анализ ввода "THEN STATE_LICENSE AL,OR,PA" приведет к следующему AST:

введите здесь описание изображения

Обратите внимание, что OR — это один токен, в отличие от других, тип которых CHAR и символы которых разделены. Если вы хотите, чтобы ваш узел OR вел себя так же, сделайте что-то вроде этого:

name
 : CHAR CHAR
 | BigOR     -> CHAR[""+$BigOR.text.charAt(0)] CHAR[""+$BigOR.text.charAt(1)]
 ;

в результате чего:

введите здесь описание изображения

Или, если вы хотите, чтобы два отдельных символа были объединены, выполните:

name
 : (CHAR CHAR | BigOR) -> CHAR[$text]
 ;

в результате чего:

введите здесь описание изображения

person Bart Kiers    schedule 18.07.2012