Reputation: 1268
I'm having function with arguments grammar like below lexer and parser:
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);
But in parser is accepting function with arguments or function with argument as function(nested function). I am using visitor pattern for validation. But now if I pass function with no arguments it is throwing error. How to accept function with zero argument in the above parser?
Example For Working input:
FUNCTION.toString(String)
Example For Not Working input:
FUNCTION.getTimestamp()
Upvotes: 2
Views: 1483
Reputation: 370112
function : FUNCTION '.' NAME '(' (function | argument (',' argument)*) ')';
First of all the function |
here is really odd. At the face of it, it would mean that you can call a function with only a single function call as its argument or with arbitrarily many argument
s. But since argument
itself already contains function
as an alternative, it's simply redundant. So let's simplify the rule by removing that part:
function : FUNCTION '.' NAME '(' (argument (',' argument)*) ')';
So why does this not match function calls without arguments? Because the argument
before the comma is not optional. The ',' argument
part has a *
applied to it, so it can appear any number of times - including zero. But the first argument
doesn't have any modifiers, so it needs to be there.
So how can we change that? Given that I just identified the problem as the first argument not being optional, one's first thought might be to just make the argument
optional by adding a ?
directly after it (i.e. argument? (',' argument)*
), but that would also allow constructions such as FUNCTION.f(,X)
, which you presumably don't want to allow.
Instead you should apply ?
to the whole list of arguments, like this:
(argument (',' argument)*)?
That way it can match either "an argument followed by zero or more instances of 'comma followed by argument'" or nothing.
Upvotes: 4