## Introduction

In Math Tutor Part 1, I showed you a program created for a math student I know to study mathematical functions. Four pre-defined math functions were provided. In this Part 2, you can define your own math functions, and they will be evaluated by a Recursive Descent Parser, or RDP.

## Changes from Part 1

Before we get into the RDP, here are some of the changes from Part 1:

- Created
`MathUtilLib`

and moved *MathFunction.cs*, *ExtensionMethods.cs* and *Options.cs* to it. - Options now allows you to set the precision of the text box and numeric up-down controls, and the increment value of the numeric up-down controls.
- Added logging that utilizes the Windows Event Log; you will need admin access to your machine to use it. If you don't have admin access or don't want to use the Windows Event Log, you can modify
*Logger.cs* in `MathUtilLib`

to do something simple, like write logging info to a text file. - Created
`RDPLib`

containing the RDP and a unit test project (more on this below). - Changed the settings saving. Some reviewers thought using
`%userprofile%\appdata`

was too "Windows-centric." So, for simplicity and flexibility, the settings are saved in a text file. So now you can simply save and retrieve your settings from a regular text file using File->Save and File->Open. See the *HelpFile.html* available via the Menu Strip's Help->Instructions for details. - Modified the UI giving the ability to Edit functions, and to Define new functions.

## The Recursive Descent Parser (RDP)

For this Part 2 of the Math Tutor, I've utilized Herb Shildt's Recursive Descent Parser. Mr. Shildt's books on C and C++ introduced me to the concept several years ago, and I've modified it to be able to recognize constants and math functions like cosine and sine.

An *expression parser* evaluates an algebraic expression like: **1 + 2 * 3**

. The precedence is defined by rules known as the grammar. Thus, in the expression **1 + 2 * 3**

, the 2 is multiplied by 3 first, then the 1 is added, giving 7. If we use parentheses, we can force the addition to happen first, so **(1 + 2) * 3**

evaluates to `9`

. In these expressions, each component is called a *token* and is a `string`

that contains at least a single character. In the above expressions, the digits `1`

, `2`

, and `3`

are `TokenType NUMBER`

, the +, - and parentheses are `TokenType DELIMITER`

. The magic of the RDP is in *RecursiveDescentParser.cs*. At first, the code may seem a little daunting. But creating your own Test Methods (methods annotated with `[TestMethod]`

) in the `RDPUnitTestProject`

and stepping through them with the debugger is an effective way to learn how the RDP works.

The math functions (sqrt, sin, cos, etc.) are defined in *Functions.cs*; the constants (pi, e, G) are defined in *Constants.cs*. The net result of all this somewhat complex code is that you can type an expression directly into the function parameter text box like this: **sqrt(3 * pi / 2)**

, and the RDP will arrive at the right answer, namely `2.171`

. The RDP is not only used to evaluate expressions in the text box controls, it is also used to evaluate functions you define. Associated with each user defined function are four parameters called `A`

, `B`

, `C`

and `D`

. You set values of the parameters with the *function parameter controls*. So when you define your own function, you can include any of the parameters. For example, the pre-defined linear function is **A * x + B**

where `x`

is the value on the x axis. You can label the controls, so for the linear function, the controls associated with `A`

are labeled "`Slope`

", the controls associated with `B`

are labeled "`Y-intercept`

". Moving the track bar ("slider"), clicking the numeric up-down control, or typing a value into the text box will change the value of the respective parameter, causing the slope or y-intercept of the line to change accordingly.

## Editing Functions

As with Math Tutor Part 1, there are four pre-defined math functions. However, in this Part 2, you can edit the formula and labels, and set the initial values of the parameters. See the *HelpFile.html* available via the Menu Strip's Help->Instructions for details.

## Defining Your Own Functions

You can also define your own functions. See the *HelpFile.html* available via the Menu Strip's Help->Instructions for details. In brief, select Function->Manage from the Men2u Strip to display the Math Function Detail dialog, then click "**Add New Function**". After entering the name, formula, labels and initial values, clicking Save, then Close, the new `MathFunction`

will be added to the list of math functions, and the new `MathFunctionUserControl`

will be added to the `FlowLayoutPanel`

.

## Using the Code

Download and open the *MathTutor.sln* solution with Visual Studio. It consists of five projects:

`ControlLib`

- a library that contains a .NET User Control `MathTutor`

- the main forms of the solution `MathUtilLib`

- a utility library that contains, among other things, the `MathFunction`

class `RDPLib`

- the Recursive Descent Parser (RDP) `RDPUnitTestProject`

- a Visual Studio Unit Test Project for the RDP

Build the solution by pressing F6.

The primary class is still `MathFunction`

, but it differs from the previous version in that it has an instance of the RDP instead of `MyFunc`

:

public class MathFunction
{
RecursiveDescentParser parser = new RecursiveDescentParser();
public String Name { get; set; }
public String Formula { get; set; }
...
}

## Conclusion

With a little imagination, you can create some extraordinary functions. Here's one I came up with while I was testing the project: `A * cos(x - B) + sqrt(abs(sin (C * x)))`

. Start the parameter `C`

, "`sin freq`

", at `1.0`

, then click the "**Start Timer**" button and watch what happens.

## History