c# - 解决 antlr 中的 token 冲突

标签 c# antlr antlr3 antlrworks

我有一个 Token OR:'OR';我用于评估 bool 表达式(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,OR,PW,PA
  • IF 1198 == "x"OR 1190 != "x"THEN DISABLE 800
  • IF 801 >= "1000000"THEN DISPLAY_ERROR "它+太+贵了。+Go+and+get+cheaper+one+!!!"

这是我使用的语法

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';

最佳答案

词法分析器独立于解析器创建标记。因此,解析器是否可能在给定点“需要”两个 CHAR 标记并不重要,如果词法分析器“看到”文本 “OR”,它将始终创建一个 BigOR token 。您对此无能为力。

在您的情况下,您可以简单地让 stateName 匹配两个 CHAR 标记,或像这样的单个 OR 标记:

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

name
 : CHAR CHAR
 | BigOR
 ;

解析输入 "THEN STATE_LICENSE AL,OR,PA" 将产生以下 AST:

enter image description here

请注意,OR 是一个单独的标记,与其他标记不同,其类型为 CHAR 并且字符分开。如果您希望您的 OR 节点也表现得像那样,请执行以下操作:

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

导致:

enter image description here

或者,如果您希望连接两个单独的字符,请执行以下操作:

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

导致:

enter image description here

关于c# - 解决 antlr 中的 token 冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11548819/

相关文章:

c# - 如何在每次输入退出或取消时中断表单流?

antlr - 带有 ANTLR 文本属性的 NullPointerException

antlr - antlr4语法中 "~"运算符的意义

antlr3 - 从 ANTLR4 解析器获取 First 和 Follow 元数据

eclipse - Eclipse 不自动生成解析器和词法分析器文件

javascript - C# 创建 websocket - onmessage 函数不起作用

c# - SwitchToThread 与 sleep (1)

c# - Linq to SQL、InsertOnSubmit 与 InsertAllOnSubmit 性能对比?

java - 如何从ANTLR语法中收集 'returns'

antlr - 如何获取 Antlr 解析器规则以从默认和隐藏 channel 读取