我的函数具有参数语法,如下面的词法分析器和解析器:
MyFunctionsLexer.g4
lexer grammar MyFunctionsLexer;
FUNCTION: 'FUNCTION';
NAME: [A-Za-z0-9]+;
DOT: '.';
COMMA: ',';
L_BRACKET: '(';
R_BRACKET: ')';
WS : [ \t\r\n]+ -> skip;
MyFunctionsParser.g4
parser grammar MyFunctionsParser;
options { tokenVocab=MyFunctionsLexer; }
functions : function* EOF;
function : FUNCTION '.' NAME '(' (function | argument (',' argument)*) ')';
argument: (NAME | function);
但是在解析器中接受带参数的函数或带参数的函数作为函数(嵌套函数)。我正在使用访客模式进行验证。但现在如果我传递不带参数的函数,它就会抛出错误。如何在上面的解析器中接受带有零参数的函数?
工作输入示例:
FUNCTION.toString(String)
输入无效的示例:
FUNCTION.getTimestamp()
最佳答案
function : FUNCTION '.' NAME '(' (function | argument (',' argument)*) ')';
首先,这里的function |
确实很奇怪。从表面上看,这意味着您可以仅使用单个函数调用作为参数或使用任意多个参数来调用函数。但由于 argument
本身已经包含 function
作为替代方案,因此它是多余的。因此,让我们通过删除该部分来简化规则:
function : FUNCTION '.' NAME '(' (argument (',' argument)*) ')';
那么为什么这与不带参数的函数调用不匹配呢?因为逗号之前的argument
不是可选的。 ',' 参数
部分应用了 *
,因此它可以出现任意次数 - 包括零次。但第一个参数
没有任何修饰符,因此它需要存在。
那么我们该如何改变呢?鉴于我刚刚将问题确定为第一个参数不是可选的,人们的第一个想法可能是通过直接在其后面添加 ?
来使 argument
成为可选(即 argument? (',' argument)*
),但这也将允许诸如 FUNCTION.f(,X)
之类的构造,您可能不希望允许这种构造。
相反,您应该将 ?
应用于整个参数列表,如下所示:
(argument (',' argument)*)?
这样它就可以匹配“一个参数后跟零个或多个‘逗号后跟参数’的实例”,或者什么也不匹配。
关于java - 如何在 Antlr4 中为零参数函数编写语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59011569/