An offline parser is created using the ParseLR.exe
command line
tool to create source code for a parser. This source file is then added to the
project in which the parser is needed, and compiled to make the executable with
an embedded parser. Because of this, there are some differences in how the
parser class source code is written relative to an inline parser.
In an offline parser, the parser class source code is written as a two-part
inheritance hierarchy. For some parser whose class name is MyParser
, the
file MyParser.cs
is written by the developer
wishing to use a parser, and MyParser.Designer.cs
is generated from the ParseLR
command line tool. MyParser.cs
is the
base class
that contains the application-specific methods, properties and fields that you
wish to implement on a one per parser instance basis. MyParser.Designer.cs
is the derived class, created from the input grammar specification by the ParseLR.exe
application. Note that your parser class should be inherited from the
Parsing.Parser
base class, and references to the
parsing assemblies added to the project. The
auto-generated derived class in MyParser.Designer.cs
is generated
to inherit from your MyParser
class.
In an offline parser, rather than having references out to action functions
made in the grammar, it is more conventional to write the actual C# action code
inline at the end of each grammar production. The ParseLR.exe
application converts these inline code fragments into action functions
automatically, and places them in the parser class as member functions. These
action functions are to be found in the MyParser.Designer.cs
half
of the class. Guard functions can also be written in the same way, if you wish.
Once generated, the source code for the offline parser should be added to the
same project as the application-specific parser class. Hence both
MyParser.designer.cs
and MyParser.cs
will end up
in the same compiled assembly. This is necessary for the parser factory to
be able to find the parser class when an instance is to be constructed.
An example of the non auto-generated part of the parser class is given below:
// References will have been added to the project for Parsing.dll and
// ParserGenerator.dll. Suitable using statements appear here:
using Parsing;
using ParserGenerator;
namespace MyApplication
{
public class MyParser : Parser
{
// Example of a guard function.
// Note that this, like action functions,
// could have been written in the grammar
// under the definition of PluralNoun
// in the guards section of the grammar.
public bool PluralNoun(object arg)
{
return arg.ToString().EndsWith("s");
}
}
}
The default (parameterless) constructor for your offline parser will be called automatically from
the auto-generated derived class in the
MyParser.Designer.cs
file. Hence your parser class should either
provide a default constructor, or no constructor at all. Initialisation should
be handled by property assignment or a hand-crafted initialiser function called
once the parser instance has been constructed.
To create an instance of the parser for an offline generated and compiled
parser, you will invoke the static CreateInstance()
method
of the parser factory.
// References will have been added to the project for Parsing.dll and
// ParserGenerator.dll. Suitable using statements appear here:
using Parsing;
using ParserGenerator;
namespace MyApplication
{
public class MyParser : Parser
{
// Example of a guard function.
// Note that no action functions are
// written here, as they are captured
// from inline code in the grammar
// description.
public bool PluralNoun(object arg)
{
return arg.ToString().EndsWith("s");
}
}
... Client code creating a parser instance ...
MyParser myParser =
ParserFactory<MyParser>.CreateInstance();
... Use the parser to parse input ...
}