Closed WenhaoWu closed 3 years ago
To my understanding, it never actually goes to the second parser (ba
) in the choice list, when the first parser (ab
) sees the input (b1:b2, a1:a2
) is only partially valid, it terminates the whole parsing process and returns failure, without trying the second parser.
Your conclusion in https://github.com/petitparser/dart-petitparser/issues/114#issuecomment-879791030 is correct. PEGs like PetitParser use ordered-choices, once a choice is picked it never backtracks and tries any of the other choices.
I would write it as follows:
Parser arguments() =>
(ref0(a) & ref0(b)) |
(ref0(a)) |
(ref0(b) & ref0(a)) |
(ref0(b)) |
epsilon();
Important is that the longer variations are before the shorter ones (prefixes of other parsers need to come last).
Probably simpler would be to write it more forgiving and then validate the names either in a second step or using the new predicate operator (not on pub.dev yet).
Parser arguments() => ref0(argument).separatedBy(ref1(token, ','));
Parser argument() => ref0(id) & ref1(token, ':') & ref0(id);
Ok thanks to reply. In reality we have unknown number of predefined optional named parameters, so listing all possible combination might not be ideal. I think we can proceed now with more forgiving grammar and then later validate in parsers case by case. Thanks again 👍
Given the below testing grammar trying to accept the optional named parameter with any oder :
However, the test case fails when providing both optional named parameter in reverse order:
It fails at
expect('test(b1:b2, a1:a2)', accept(stmGrammar));
All other tests seem to be ok. Shouldn't I put optional within choice parsers?
P.s. Big thanks to this awesome library and the great effort that has been put into it :)