首页 > 解决方案 > ANTLR4 语法 - 字段和扩展表达式中的“点”问题

问题描述

我有以下 ANTLR4 语法

grammar ExpressionGrammar;

parse: (expr)
     ;

expr: MIN expr
    | expr ( MUL | DIV ) expr
    | expr ( ADD | MIN ) expr
    | NUM
    | function
    | '(' expr ')'
    ;

function : ID '(' arguments? ')';

arguments: expr ( ',' expr)*;

/* Tokens */

MUL : '*';
DIV : '/';
MIN : '-';
ADD : '+';
OPEN_PAR : '(' ;
CLOSE_PAR : ')' ;

NUM : '0' | [1-9][0-9]*;
ID : [a-zA-Z_] [a-zA-Z]*;
COMMENT: '//' ~[\r\n]* -> skip;
WS: [ \t\n]+ -> skip;

我有一个这样的输入表达式:-

(Fields.V1)*(Fields.V2) + (Constants.Value1)*(Constants.Value2)

ANTLR 解析器从上面的语法生成以下文本:-

(FieldsV1)*(FieldsV2)+(Constants<missing ')'> 

如您所见,文本中缺少 Fields.V1 和 Fields.V2 中的“点”,并且还有一个 <missing ')' 错误节点。我相信我应该以某种方式让 ANTLR 了解表达式也可以包含带有点运算符的字段。

最重要的一个问题:-

 (Var1)(Var2)    

对于上述情况,ANTLR 不会给我报错,表达式不应该是 (Var1)(Var2) - 它应该总是有运算符 (var1)*(var2) 或 (var1)+(var2) 等。解析器错误树没有产生这个错误。应如何修改语法以确保即使考虑到这种情况。

标签: antlrantlr4

解决方案


要识别IDs like Fields.V1,请将 Lexer 规则更改为ID如下所示:

fragment ID_NODE: [a-zA-Z_][a-zA-Z0-9]*;
ID: ID_NODE ('.' ID_NODE)*;

请注意,由于 ID 的每个“节点”都遵循相同的规则,因此我将其设为可用于构成 ID 规则的词法分析器片段。我还添加0-9到片段的第二部分,因为您似乎希望在IDs中允许数字

然后该ID规则使用该片段来构建允许在ID.

您也没有添加ID为有效的expr替代品

要处理 中的错误条件检测(Var1)(Var2),您需要 Mike 的建议将 EOF Lexer 规则添加到parse解析器规则的末尾。如果没有EOF,ANTLR 将在到达可识别的 expr ( (Var1)) 末尾时立即停止解析。上面写着“然后EOF你需要找到一个EOF”,所以 ANTLR 将继续解析到(Var2)并给你错误。

处理您的两个示例的修订版:

grammar ExpressionGrammar;

parse: expr EOF;

expr:
    MIN expr
    | expr ( MUL | DIV) expr
    | expr ( ADD | MIN) expr
    | NUM
    | ID
    | function
    | '(' expr ')';

function: ID '(' arguments? ')';

arguments: expr ( ',' expr)*;

/* Tokens */

MUL: '*';
DIV: '/';
MIN: '-';
ADD: '+';
OPEN_PAR: '(';
CLOSE_PAR: ')';

NUM: '0' | [1-9][0-9]*;
fragment ID_NODE: [a-zA-Z_][a-zA-Z0-9]*;
ID: ID_NODE ('.' ID_NODE)*;
COMMENT: '//' ~[\r\n]* -> skip;
WS: [ \t\n]+ -> skip;

(现在我已经阅读了评论,这几乎只是应用评论中的建议)


推荐阅读