The GeneralisedParser class

Differences between LR(1) and GLR parsers

The parser tables used by LR(1) and GLR parsers are the same, except for two small differences. First, when constructing a set of parser tables for an LR(1) parser, the parser generator tries to identify places where shift-reduce and reduce-reduce conflicts occur, and will fail to produce a set of parser tables (and hence a parser) if these conflicts are encountered. This is not the case when constructing a GLR parser, as the GLR parsing algorithm merely clones the parser stacks when a conflict is encountered.

Second, there is a property in the IParser interface (implemented by both the Parser class and the GeneralisedParser class) called ParserType. This readonly string property is set to "LR1" for a regular lookahead parser, and to "GLR" for a generalised parser.

Writing offline GLR parsers

Using ParseLR to create source code for an offline GLR parser is virtually the same as for an LR(1) parser, which is described elsewhere. The primary difference is that the application-specific parser class should have GeneralisedParser as its base class rather than Parser. Since these two base classes both implement the IParser interface, and the methods and properties of that interface are all you need to use from your parser, there is very little you have to do when writing your parser class.

The only thing you will need to be aware of is that you may have to write merge action functions to resolve those places in the grammar where two separate valid parses merge on a reduction to the same non-terminal. You can find out how to write these merge functions here.

Writing inline GLR parsers

Writing inline GLR parsers similarly is very much like writing inline LR(1) parser classes. The main difference is that you must derive your application-specific parser class from the GeneralisedParser base class rather than the Parser base class. In addition, when you construct the parser factory object using new, you must make sure the generalisedParser parameter to the constructor is set to true. This will automatically ensure that the right kind of parser is created and used at runtime to handle the input token or event streams, and will turn off shift-reduce and reduce-reduce conflict rejection when building the parser tables. The ParserFactory<MyParser>CreateInstance method is then used to create each instance of a generalised parser.