ANTLR4 语法 - 字段和扩展表达式中 "dot" 的问题
ANTLR4 Grammar - Issue with "dot" in fields and extended expressions
我有以下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 中的“点”,并且还有一个
除此之外的一个问题:-
(Var1)(Var2)
ANTLR 不会为上述场景抛出错误,表达式不应该是 (Var1)(Var2) -- 它应该始终包含运算符 (var1)*(var2) 或 (var1)+(var2)等解析器错误树不生成此错误。应该如何修改语法以确保考虑到这种情况。
要识别像 Fields.V1
这样的 ID
,请将 ID
的 Lexer 规则更改为如下内容:
fragment ID_NODE: [a-zA-Z_][a-zA-Z0-9]*;
ID: ID_NODE ('.' ID_NODE)*;
注意,因为 ID 的每个“节点”都遵循相同的规则,所以我将它作为一个词法分析器片段,我可以用它来编写 ID 规则。我还在片段的第二部分添加了 0-9
,因为您似乎希望在 ID
s
中允许数字
然后 ID
规则使用片段构建 Lexer 规则,允许 ID
.
中的点
您也没有将 ID
添加为有效的 expr
替代项
要处理 (Var1)(Var2)
中错误条件的检测,您需要 Mike 的建议将 EOF Lexer 规则添加到 parse
解析器规则的末尾。如果没有 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;
(现在我已经通读了评论,这几乎只是在应用评论中的建议)
我有以下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 中的“点”,并且还有一个 除此之外的一个问题:- ANTLR 不会为上述场景抛出错误,表达式不应该是 (Var1)(Var2) -- 它应该始终包含运算符 (var1)*(var2) 或 (var1)+(var2)等解析器错误树不生成此错误。应该如何修改语法以确保考虑到这种情况。 (Var1)(Var2)
要识别像 Fields.V1
这样的 ID
,请将 ID
的 Lexer 规则更改为如下内容:
fragment ID_NODE: [a-zA-Z_][a-zA-Z0-9]*;
ID: ID_NODE ('.' ID_NODE)*;
注意,因为 ID 的每个“节点”都遵循相同的规则,所以我将它作为一个词法分析器片段,我可以用它来编写 ID 规则。我还在片段的第二部分添加了 0-9
,因为您似乎希望在 ID
s
然后 ID
规则使用片段构建 Lexer 规则,允许 ID
.
您也没有将 ID
添加为有效的 expr
替代项
要处理 (Var1)(Var2)
中错误条件的检测,您需要 Mike 的建议将 EOF Lexer 规则添加到 parse
解析器规则的末尾。如果没有 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;
(现在我已经通读了评论,这几乎只是在应用评论中的建议)