How to find parsing error with ParseKit framework

objective-c, parsekit

Solution

Developer of ParseKit here.

There are two features in ParseKit which can be used to help provide user-readable hints describing parse errors encountered in input.

- `-[PKParser bestMatchFor:]`

- The `PKTrack` class

It sounds like you're aware of the `-bestMatchFor:` method even if it's not doing what you expect in this case.

I think the `PKTrack` class will be more helpful here. As described in Metsker's book, `PKTrack` is exactly like `PKSequence` except that its subparsers are required, and an error is thrown (with a helpful error message) when all of its subparsers are not matched.

So here's a grammar for your example input:

@start         = '(' expr ')' | expr;
expr           = ('+' | '-') term term;
term           = '(' expr ')' | Word;

Any productions listed contiguously are a Sequence -- but could instead be a Track.

The benefit of changing these Sequences to be Tracks is that an `NSException` will be thrown with a human-readable parse error message if the input doesn't match. The downside is that you must now wrap all usages of your factory-generated parser in a try/catch block to catch these Track exceptions.

The problem currently (or before now, at least) is that the `PKParserFactory` never produced a parser using Tracks. Instead, it would always use Sequences.

So I've just added a new option in head of trunk at Google Code (you'll need to udpate).

#define USE_TRACK 0

in

PKParserFactory.m

It's `0` by default. If you change this define to `1`, Tracks will be used instead of Sequences. So given the grammar above and invalid input like this:

(+ a - b c))

and this client code:

NSString *g = // fetch grammar above
PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
NSString *s = @"(+ a - b c))";

@try {
    PKAssembly *res = [p parse:s];
    NSLog(@"res %@", res);
}
@catch (NSException *exception) {
    NSLog(@"Parse Error:%@", exception);
}

you will get a nice-ish human-readable error:

Parse Error:

After : ( + a
Expected : Alternation (term)
Found : -

Hope that helps.

Problem

I was wondering if there were a way to get back how far into an assembly a PKParser has parsed before encountering a syntax error. reference: http://parsekit.com/ I'm using a grammar that basically describes a prefix notation expression language. For example: given your standard prefix notation expression grammar and a string "(+ a - b c))" I'd like to retrieve that [(,+,a] where matched, so I can give the user some idea of where to look to fix their error, but the completeMatchFor and bestMatchFor don't return anything I can use to find this info. Ideally I'd like to say that a '(' was expected, but it's not necessary for a grammar as simple as what I'm using. From the book mentioned as the user manual, it seemed as if I would need to create a custom parser for this, but I was hoping that maybe I'd simply missed something in the framework. Thoughts?

Original source