4 ms·
One thing that I like about PEG (among many) is that it's fairly easy to create useful error messages from them. My approach has been to introduce a type of cu
by pacaro 7y ago
One thing that I like about PEG (among many) is that it's fairly easy to create useful error messages from them.
My approach has been to introduce a type of cut operator, such that if you backtrack past a cut operator then it's information is stored, then if the parsee can't proceed it can examine the stored errors and produce hopefully sensible error messages.
For example, if I have a simple rule for an expression
exp = atom (op exp)*
And I insert a cut between the op and the atom...
exp = atom (op <cut> exp)*
Then that cut (which can be appropriately annotated with human readable error information) will be returned if there is a binary exp with no rhs
- colanderman 7y agoI used this exact same technique for the most recent PEG-based parser I wrote too. Works really well, and integrates well with Prolog (which I was using).
- mamcx 7y agoWait... what is a "cut"? A minimal sample that show how it help with the error messages?
- drothlis 7y agoCut means "if you matched this far, don't consider other options even if the current option fails to parse". With this grammar: expr: expr '+' term | term And this input: 5 + It will first consider the first alternative (expr '+' term) but will fail to match that branch because it's missing the "term" after the "+". That's fine because there's another alternative to try (term). That alternative doesn't match either, and you'll get the error message from the last alternative that it tried (probably something like "unexpected +"). But with this grammar: expr: expr '+' <cut> term | term Then with the same input ("5 +") it will consider the first alternative, fail to match, and then fail immediately with the error message from that first alternative (something like "missing term after +").
- mamcx 7y agoyeah, I get the purposed point of a "cut" but how I put one? Exist a basic sample? (ie: Using a peg parser how define what is a "cut"???) expr: expr '+' API_call_here? term | term
- pacaro 7y agoHmm, if you're using a peg parser that doesn't directly support this you can emulate it by choosing between the rhs of the cut and a production that will always match so expr : atom (op <cut> expr)* Would be replaced with expr : atom (op (expr / cut))* cut : "XXX"? or perhaps simpler expr : atom (op expr?)* Either way when you process the expr rule there will be an empty match where the rhs should be, and an appropriate error can be generated
- pacaro 7y agoDrothlis comment describes it well, but to perhaps explain where the term comes from, Prolog has a related concept and calls it the cut operator
- aidenn0 7y agoAny suggestions for discriminating between a partial parse and an error parse? For example a REPL in which on newline if the parse can never be correct versus a parse that could be made correct with more input.
- victorNicollet 7y agoThis has always struck me as significant effort invested in making a bad user experience only slight less bad: the REPL overloads the meaning of "enter" to mean both "insert a new line" and "execute command", and then attempts to guess what the user meant by tweaking the grammar of the language. Why not distinguish between "insert a new line" and "execute command" as two distinct inputs, and eliminate all ambiguity ?
- pacaro 7y agoI haven't used it for that, but I have used it to absorb errors and continue. The error just gets placed into the AST and then a later phase can report on (potentially) many errors, rather than just stopping at the first. YMMV