如何在 Antlr4 中为零参数函数编写语法

How to write grammar in Antlr4 for function with zero arguments

我正在使用如下词法分析器和解析器的参数语法函数:

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 来调用一个函数。但是由于 argument 本身已经包含 function 作为替代,它只是多余的。因此,让我们通过删除该部分来简化规则:

function : FUNCTION '.' NAME '(' (argument (',' argument)*) ')';

那为什么这不匹配没有参数的函数调用呢?因为逗号前的 argument 不是可选的。 ',' argument 部分应用了 *,因此它可以出现任意次数 - 包括零次。但是第一个 argument 没有任何修饰符,所以它需要在那里。

那么我们该如何改变呢?鉴于我只是将问题确定为第一个参数不是可选的,人们的第一个想法可能是通过直接在其后添加 ?(即 argument? (',' argument)*)来使 argument 可选,但这也将允许诸如 FUNCTION.f(,X) 之类的结构,您可能不想允许这种结构。

相反,您应该将 ? 应用于整个参数列表,如下所示:

(argument (',' argument)*)?

这样它既可以匹配 "an argument followed by zero or more instances of 'comma followed by argument'" 也可以不匹配。