ANTLR4语法-使用“发布”;点“;在字段和扩展表达式中

ANTLR4语法-使用“发布”;点“;在字段和扩展表达式中,antlr,antlr4,Antlr,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 ( ',' exp

我有下面的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 ')'> 

对于上述场景,ANTLR不会抛出错误,表达式不应该是(Var1)(Var2)——它应该始终具有运算符(Var1)*(Var2)或(Var1)+(Var2)等。解析器错误树不会生成此错误。应如何修改语法以确保考虑到这种情况。

要识别
ID
s,如
字段。V1
,请将
ID
的词法规则更改为类似以下内容:

fragment ID_NODE: [a-zA-Z_][a-zA-Z0-9]*;
ID: ID_NODE ('.' ID_NODE)*;
请注意,由于ID的每个“节点”都遵循相同的规则,因此我将其作为一个lexer片段,可以用来编写ID规则。我还向片段的第二部分添加了
0-9
,因为您似乎希望在
ID
s中允许数字

然后
ID
规则使用片段构建Lexer规则,该规则允许
ID
中的点

您也没有将
ID
添加为有效的
expr
备选方案

要处理
(Var1)(Var2)
中错误条件的检测,需要Mike的建议,将EOF Lexer规则添加到
解析
解析器规则的末尾。如果没有
EOF
,ANTLR将在到达可识别表达式的末尾时停止解析(
(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;

(现在我已经通读了注释,这几乎只是应用注释中的建议)

首先将
EOF
添加到
parse
规则中(并删除不必要的括号).我不确定你期望发生什么:我在你的lexer中没有看到任何规则与
..@BartKiers匹配,这是对的。我想知道应该在哪里添加匹配项。因为我的解析器实际上不应该分割“点”。它应该是一个整体“Fields.V1”@MikeLischke-EOF-您是指第一个解析:(expr)吗?您想让我将其更改为expr EOF?“它应该作为一个整体”Fields.V1“,然后您应该编辑
ID
规则,使其也包括
。但我很困惑:这是你自己的语法,还是你在什么地方找到的?我得到的印象是你在盲目地尝试,而没有真正理解ANTLR。也许退一步,从基本的ANTLR教程开始?
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;