Instantiating in-line parsers

Once an application-specific parser class has been written, and its parser grammar made available as a runtime resource, an instance of it needs to be created. This is done by creating a parser factory, which causes the grammar to be parsed as part of its creation. The parser factory is then used by invoking its CreateInstance method to create a parser instance.

Creating factories from grammar descriptions

Before any instance of an in-line parser can be created, a parser factorymust be constructed using its input grammar description, and by using a pre-existing application-specific parser class that implements any non-inline action and guard functions required by the parser. The details for the parser factory constructor and its parameters are given below:


public ParserFactory<TParser>.ParserFactory
(
    TextReader input,
    TextWriter tabOut,
    bool compressParser,
    bool supportErrorRecovery,
    bool generalisedParser,
    TextWriter sourceOutput = null
);

The constructor reads a character string that contains the input grammar description in ParseLR grammar format, and creates a template of a state machine driven parser that is capable of parsing that grammar. This state machine is compiled to a dynamic assembly, and loaded into the current application, all from within the constructor.

ARGUMENT DESCRIPTION
TParser This generic type parameter should be substituted with the class name for the application-specific parser class that is expected by the input grammar. This parser class is described elsewhere, but basically should provide any named action and guard functions needed by the grammar description, and not written as inline code directly in the grammar.
input The text stream containing the grammar description. The parser will be constructed from this grammar description. Note that any references to DLLs needed by the inline actions or guards written in the grammar will need to be included in the options section of the grammar.
tabOut An output text stream to which a tabular document describing the states, transitions and productions the parser works from will be written. If this parameter is null, no output tabular document is generated.
compressParser Set this parameter to true to turn on Pager's algorithm for compressing the size of the parsing tables. With this flag set to false, the parser generator creates a full LR(1) parser. Since Pager's algorithm does not remove any functionality from the parser, and does not restrict the range of unambiguous grammars that can be parsed, unlike the LALR(1) algorithm, there is little reason to not set this flag to true.
supportErrorRecovery When set to true, this enables the parser features that allow popping the parser state stack and discarding input tokens until a resynchronisation point in the grammar is reached. When set to false, the first unacceptable input parser token will cause the parser to halt the parsing before all the input tokens have been consumed. Only enable this flag if you are using the error keyword in your input grammar, as it degrades parser performance slightly to enable support for error recovery.
generalisedParser When set to true, this enables the parser to ignore shift/reduce and reduce/reduce conflicts in the grammar. This is necessary when building a generalised LR parser rather than one with a single lookahead token to resolve rule ambiguity.
sourceOutput An output text stream to which the autogenerated source code for the parser grammar will be written. If this optional parameter is left out, or set to null, no source code will be written out for you. Useful if trying to debug an inline parser.

If successful, the ParserFactory<TParser> will have been created, and will therefore become the runtime factory for creating instances of the parser. If unsuccessful, an ArgumentException is thrown, whose Message property is set to the combined error messages from the parser generation process.

Instantiating parser objects

The ParserFactory<TParser>.CreateInstance() method allows a new parser instance of type TParser to be created. Remember that the ParseLR library is designed with workflow engines in mind. The construction of a parser factory is an expensive runtime operation. Creation of parser instances however is extremely fast. Hence a scenario in which many parser instances might be created, as in workflow applications for example, is directly supported by this parser factory design.

The method is described below:


public static TParser CreateInstance();

When this method is invoked, it uses the parser state machine structure from the parser factory to create a new instance of a parser that can parse input tokens conforming to the grammar.

The new parser inherits from the factory the state machine structure and hence the compression flag value and the error handling value. It does not inherit anything else. Hence the new parser has initially no output error or debug stream, and begins life with no input token stream connected.