The code consists of four classes in order to evaluate a string of a real or complex math expression, reducing the expression to one real or complex number. The math expression may or may not include variables.

## Introduction

In many situations, there may be a `string`

containing a math expression, such as "`1+2*5`

" or "`(3+i)(3-i)`

", and there is the need to do the math and calculate the result. Also, in case of a formula like "`0.5*x+4`

", we may need to calculate the result for several different values of `x`

. In those situations, the complex parser presented here may help.

The classes here are a small part -but improved- of my all free and downloadable CAS calculator http://xrjunque.nom.es. One of the goals is that these classes do not rely on other 'external' classes as happens in the CAS calculator.

## The Five Classes

- Class
`Global10`

contains global values like number of decimals, imaginary character (`i`

or `j`

) or `CultureInfo`

. - Class
`Msg10`

just contains a few messages to handle possible errors. - Class
`Rational`

gives a bit more of accuracy in the operations. - Class
`Complex`

class does the complex math. - Class
`parseComplex`

is in charge of dividing the input string into tokens and call accordingly to classes `Complex`

or `Msg10`

. Class `Complex`

makes use of class `Rational`

for its Real and Imaginary members. The 'tokenizing' job is done by a Regex pattern.

## Tokens

The tokens groups are:

mode <mode>
numbers <num>
operators <op>
logical operators <lop>
functions <fn>
constants <cnt>
variables <var>
any other character <any>
besides end of tokens <end> formed by an escape character Chr(27).

The pattern looks like:

(?i)(?<mode>(&dec(?<dec>\d{1,2})|&(rad|deg|grad|[hobdij])))(?-i)
(?<numop>(?<num>((\d{1,3}((\,\d{3})+(?!\d))(\.[0-9]+)?)|
[\d]{1}[\.\dA-Fa-f]*)([eE](\s*)[-+]?[0-9]+)?)|
(?<op>[-+*/\^]))|\(|\)|
(?i)(?<fn>logtwo|logten|acosh|acoth|acsch|asech|asinh|atanh|
floor|round|norm|conj|coth|csch|sech|acos|acot|acsc|asec|asin|atan|cosh|sign|sinh|
sqrt|tanh|abs|cos|cot|csc|exp|log|sec|sin|sqr|tan|ln|re|im)(?![a-zA-Z_]+)|
(?<lop>\<\<|\>\>|nand|mod|and|nor|xor|not|or|%|!)(?![a-zA-Z_]+)|
(?<cnt>e|(?i)pi)(?![a-zA-Z_]+)|
(?<vars>[_a-zA-Z]\w*)+|(?<end>\e)+|
(?<any>[^\s←\,\.])+|(?<any>\,|\.)+
</dec>

Pattern for numbers, depending on the `Globalization.CultureInfo`

setting, may swap the dot (`NumberFormat.NumberDecimalSeparator`

) and the comma (`NumberFormat.NumberGroupSeparator`

).

Mode makes possible to enter numbers in hexadecimal, decimal, octal or binary base; along with setting the number of decimals and the imaginary character.

## Using the Code

The are two possible ways of instantiation:

Dim eP As New ParseComplex
eP.CultureInfo = New Globalization.CultureInfo("fr-FR")
...
Dim eP As New ParseComplex(New Globalization.CultureInfo("es-AR"))
...

By default, `CultureInfo`

is set to "`en-US`

".

Evaluation is done by calling one of the two `Evaluate()`

methods.

First method:

Dim cplx As Complex = eP.Evaluate("(3+5*i)*(3-i*5)")

First method with variables, set in a `Dictionay(Of String, Complex)`

:

eP.vars.Add("x", Complex.one)
eP.vars.Add("y", New Complex(-1, 2))
Dim cplx As Complex = eP.Evaluate("(3+x*i)*(y-i*5)")

Once the `string`

has been parsed, it is possible to call the overloaded second method:

eP.vars.Item("x") = New Complex(3)
Dim cplx As Complex = eP.Evaluate(eP.vars)

Variables names start with a letter or underscore (`_`

), can contain letters, numbers or underscore and can be any length.

Of course, you may call the `Complex`

class directly, if you don't need the parser.

The default numeric base is decimal. To change to another base write `&h`

(hexadecimal), `&o`

(octal) or `&b`

(binary). Appending `&d`

will restore to decimal base.

In a similar way, `°`

, `&grad`

will accept angles in degrees or in gradians. To restore to default radians, enter `&rad`

.

To change default imaginary `i`

to `j`

, write `&j`

and to turn back to the default character, write `&i`

.

For instance, entering `&culture it-IT`

will change the current `CultureInfo`

to `it-IT`

. So inputs and ouputs will be in mented culture.

An example of possible modificators is the following:

Dim cplx As Complex = eP.Evaluate("&culture fr-FR &dec2 &h 0f + &j &d 0,2+0,3*j"
Console.WriteLine(cplx.tostring)

## The Output

You may call `Complex.ToString()`

or `ToStringComplex( numDecimals As Int32, sImg As String, cultureInfo As Globalization.CultureInfo) As String`

:

cplx.ToStringComplex(4, eP.Imaginary, eP.CultureInfo)

## Detail Version

If the word `detail`

is found, code will output operation steps. For example:

Dim cP As New ParseComplex
Dim cplx As Complex = cP.Evaluate("detail (2+i*3)*(1+i)")
Console.WriteLine(cP.GetDetail)

## Basic Principles

The parsing method is a recursive-descent parsing: Parsing Expressions by Recursive Descent.

Evaluation method `E`

calls `T`

for any addition or substraction, but `T`

calls first `F`

for any multiplication or substraction, and `F`

calls first P for any power possible power operation. `P`

calls first `v`

to get next token. If there is a "`(`

" token, `v`

calls recursively to `T`

.

E --> T {( "+" | "-" ) T}
T --> F {( "*" | "/" ) F}
F --> P ["^" F]
P --> v | "(" E ")" | "-" T

## Step by Step Walk-throughs

The algorithm presented here englobes `T `

and `F`

in a single method. Besides, method `v`

operates logical operators, '%' and `mod`

any possible function like `cos()`

, `csc()`

and so on.

While writing this article, I found some glitches. If you find any further error, please let me know.

## History

- 25
^{th} March, 2022: Initial version

This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.