Calculator Example - RopleyIT/GLRParser GitHub Wiki
This example implements a desktop calculator. The user enters an arithmetic
expression into the text box on the calculator window, either by typing it, or
by using the calculator buttons. When pressing the '=' button, the expression is
passed to an instance of an expression parser written as a ParseLR
grammar. The parser computes the result while parsing the expression, and
displays this result in the same text box as the expression was entered.
This sample demonstrates the use of an offline parser, with reduction actions
built into the grammar directly. The grammar will be found in the file
Calculator.g
and is converted to a C# source file using ParseLR.exe
.
An example of the output source file is to be found in
Calculator.designer.cs
. Its application-specific part of the parser class
is to be found in Calculator.cs
. This class has a static method
called Calculate
that converts a parsable expression into a
calculated result. If there is a grammar fault in the parsable expression, the
parser's own detailed error messages are made available through the static
Error
property, and the Calculate
method returns the simple
string "Error"
.
The sample code for the application is divided into three projects.
CalculatorDemo
contains the actual parser-driven calculator
implementation as described above. CalculatorDemoApp
is the Blazor-hosted
application that provides a GUI onto the calculator. The third project, is
an example of a unit-testing project that exercises the CalculatorDemo
class library. This unit-testing project is designed to use the Microsoft test
libraries, as found in Visual Studio.
Notice too that the example demonstrates the use of strongly typed terminal and non-terminal tokens. Numbers are returned as type double in the grammar, and consequently the non-terminal expression nodes in the constructed expression trees are also typed to be double floating point.
The example also contains an alternative implementation that uses a GLR
parser to parse an arithmetic expression. The GLR version of the grammar, along
with inline source code for a GLR merge function, will be found in
GLRCalculator.g
. The implementation of the parser class is in
GLRCalculator.cs
. The merge function's role is to deal with operator
precedence in this example. Multiple candidate parse trees are built for
arithmetic expressions, but the merge function ensures it selects the tree that
uses the correct operator precedence.
To toggle between LR(1) and GLR parsing, there are two radio button options for selecting the appropriate kind of parser. Once an expression has been entered and calculated (the '=' key has been pressed to compute the result), the full debug output from the parser can be seen in a tall text area to the right of the calculator. For the GLR parser, this text area also shows the state of the various stacks and expression trees after each input token shift, and reduction. Part way through the parse, the multiple expression stacks can be seen. Similarly the calls to the merge function are clearly identified, with the subsequent reduction in the number of candidate parser stacks.
The source code and grammar files for the projects in this
example are included in the CalculatorExample
folder.