parsingpegll-grammarpegjs

PEGjs grammar star (*) not matching as expected


I have this lexeme:

a().length()

And this PEGjs grammar:

start = func_call

func_call = header "(" ")"

header = "a" suffix*

suffix = "(" ")" ("." "length")

In the grammar, I'm parsing a function call. This currently parses, as you can try online in the PEGjs playground.

Input parsed successfully.

However, if I add an asterisk to the end of the suffix production, like so:

suffix = "(" ")" ("." "length")*

Then the input fails to parse:

Line 1, column 13: Expected "(" or "." but end of input found.

I don't understand why. From the documentation:

expression * Match zero or more repetitions of the expression and return their match results in an array. The matching is greedy

This should be a greedy match of "." "length" which should match one time. But instead it fails to match at all. Is this related to the nested use of * in header?


Solution

  • * matches zero or more repetitions of its operand, as you say.

    So when you write

    suffix = "(" ")" ("." "length")*
    

    You are saying that a suffix is () followed by zero or more repetitions of .length. Thus it could be (), which has zero repetitions.

    Thus, suffix* (in header) can match ().length() as two repetitions of suffix, first ().length, and then (). That would be the greedy match, which is PEG's modus operandi.

    But after that, there is no () left to be matched by func_call. Hence the parse error.