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 invoking a method of a static parser factory class, which
causes the grammar to be parsed as part of its initialisation. The application
can thereafter invoke the CreateInstance
method of the parser factory class to create each parser instance.
Before any instance of an in-line parser can be created, a parser factory must be initialised from its input grammar description, and from 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 initialisation method and its parameters are given below:
public static void ParserFactory<TParser>.InitializeFromGrammar
(
TextReader input,
TextWriter tabOut,
bool compressParser,
bool supportErrorRecovery,
bool generalisedParser,
TextWriter sourceOutput = null
);
The method reads a character stream 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 within the method.
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>
class will have been
initialised, and will therefore become the static 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.
The static 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 initialisation 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.
Parser objects have an ErrorLevel
property that can be set to one of
the levels NONE, ERROR, WARN, VERBOSE, or DEBUG. These levels are members of the
MessageLevel enumeration. Later levels in the list include all messages that are
rendered by the earlier (lower) levels. NONE forces the parser to remain silent,
even in the presence of errors. ERROR reports errors, but skips warnings. WARN
includes non-fatal warnings in the output, while VERBOSE describes all the
shifts and reductions executed by the parser, albeit in a more succinct form than
DEBUG. The DEBUG level is always used on the parser's DebugStream if this is
not null. The default level if not otherwise set is WARN. See the example below:
MyParser p = ParserFactory<MyParser>.CreateInstance();
p.ErrorLevel = MessageLevel.VERBOSE;