如何使用ANTLR匹配函数的空参数?
问题描述
需要使用ANTLR识别函数的空参数,支持任意位置的参数为空,同时非空参数前后可包含空白字符,示例如下:
f(x,y,) parse args --> {x,y,empty} f(x,,z) parse args --> {x,empty,z} f(x, ,z) parse args --> {x,empty,z} f( x , y, ) parse args --> {x,y,empty}
测试代码如下:
Lexer代码
// DELETE THIS CONTENT IF YOU PUT COMBINED GRAMMAR IN Parser TAB lexer grammar ExprLexer; AND : 'and' ; OR : 'or' ; NOT : 'not' ; EQ : '=' ; COMMA : ',' ; SEMI : ';' ; LPAREN : '(' ; RPAREN : ')' ; LCURLY : '{' ; RCURLY : '}' ; INT : [0-9]+ ; ID: [a-zA-Z_][a-zA-Z_0-9]* ; WS: [ \t\n\r\f]+ -> skip ;
Parser代码
parser grammar ExprParser; options { tokenVocab=ExprLexer; } program : stat EOF | def EOF ; stat: ID '=' expr ';' | expr ';' ; def : ID '(' ID (',' ID)* ')' '{' stat* '}' ; expr: ID | INT | WS* | func | 'not' expr | expr 'and' expr | expr 'or' expr ; func : ID '(' expr (',' expr)* ')' ;
测试输入
f(x,y,) { a = 3; x and y; }
错误信息
1:8 mismatched input '{' expecting {'and', 'or', ';'}
问题分析与解决方案
错误原因
- 原
def规则的参数部分ID (',' ID)*仅能匹配非空的ID参数,无法处理末尾带逗号的空参数场景(如f(x,y,)的第三个空参数)。 expr规则中包含WS*,而Lexer已经配置了WS -> skip,这会导致解析歧义——空的空白被视为合法expr,进而让Parser错误地将f(x,y,)当作函数调用表达式,后续的{不符合表达式的后续语法要求(预期and/or/;),因此报错。
修改后的Parser代码
parser grammar ExprParser; options { tokenVocab=ExprLexer; } program : stat EOF | def EOF ; stat: ID '=' expr ';' | expr ';' ; // 函数定义:支持空参数的参数列表 def : ID '(' paramList ')' '{' stat* '}' ; paramList : param (',' param)* ; param : ID? ; // 单个参数可以是空(ID可选) expr: ID | INT | func | 'not' expr | expr 'and' expr | expr 'or' expr ; // 函数调用:同样支持空参数的参数列表 func : ID '(' exprList ')' ; exprList : expr? (',' expr?)* ; // 每个调用参数都可以是空
说明
- 新增
paramList和param规则,通过ID?允许单个参数为空,配合param (',' param)*实现任意位置的空参数支持(包括开头、中间、结尾)。 - 删除
expr规则中的WS*,避免空白导致的解析歧义。 - 函数调用的
exprList规则也采用expr? (',' expr?)*,确保函数调用场景同样支持空参数。
内容的提问来源于stack exchange,提问作者doc
相关产品推荐
相关产品推荐

