# Math Parser for Go

bcParserGo is a Math Parser Library for Go. bcParserGo evaluates mathematical expressions given as strings at runtime. bcParserGo compiles with Golang 1.5 and later versions. It can be used on Linux, Mac OS and Windows.
This Math parser comes as an easy to use, simple Go API. bcParserGo has predefined functions. Users can create custom functions/variables. Constant expressions are eliminated for repeated tasks. Analytic operators that bcParserGo supports are +, -, /, *, ^. Logical operators supported are =(equals), & (and), |(or), !(not), <>(not equals), <=(less than or equals), >=(greater than or equals) The expression can contain parenthesis. Functions are in the form of: f(x, y, z,…). Function parameters are not calculated until they are actually needed. This makes it easier to avoid division by zero or overflow errors when used along with IF() function. List of predefined functions is available in the documentation. Go source code is included.
An example of a simple expression is : LN(X)+SIN(10/2-5)
When parsed, this expression will be represented as: since the SIN(10/2-5) is in fact SIN(0) which is a constant and is 0.
Thus, in a loop, if you change the value of X and ask for the value of the expression, it will be evaluated quite fast since SIN(10/2-5) is not dependent on X.
You can create your own variables as needed. CreateDefaultFuncs() can be used to define default mathematical functions listed in the documentation. You can create your own functions as needed. IF logic is implemented through a predefined IF(A,B,C) function. Similar logical functions can be created as needed.

## bcParserGo Documentation

bcParserGo – Go Math Parser documentation is generated by the godoc tool from the source code. You can find other examples here as well. If you have questions, please post it using the comment form below this page.

## Example of User Defined Variable in Math Parser

This is a small code snippet that shows how to define and use user defined variables in bcParserGo.

```  var parser MathParser = mathparser.NewMathParser()
parser.CreateDefaultFuncs()
parser.SetExpression("SIN( X / Y  )+MYVARIABLE")
parser.SetVariable("X", 4)
parser.SetVariable("Y", 5)
parser.SetVariable("MYVARIABLE", 6)
fmt.Println("Value: ", parser.Value())
```

### Undefined Variables in the Expression

Sometimes it is not possible to predefine all possible variables that a user can use in an expression. In that case, bcParserGo allows you to set an implementation of VariableResolver interface to provide values for variables that were not previously defined:

```/**
*  VariableResolver is implemented by the user and used in
*  func (*MathParser) SetVariableResolver(VariableResolver) to enable the
*  Math Parser allow variables that are not defined before parse time.
*  If set, the parser allows undefined variables at parse time.
* VariableResolver will be used to return the values of variables
*  at evaluation time. This is typically needed when the problem domain
*  is too large to define all possible variables ahead of time.
*  When VariableResolver is set, parser will tolerate undefined variables
*  at parse time and it will invoke the given VariableResolver
*  to retrieve variable values at evaluation time.
*/
type VariableResolver func(parser MathParser, varName string) float64
```

Here is an example of using VariableResolver:

```func myVariableResolver(
p mathparser.MathParser, varName string) float64 {
if (varName == "A") {
return 5
}
panic("Variable " + varName + " is not defined.")
}
func main() {
p := mathparser.NewMathParser()
p.SetVariableResolver(myVariableResolver)
p.SetExpression("A+3")
fmt.Println("Value: ", p.Value())
};
```

## Example of User Defined Function in bcParserGo

Below is an example that demonstrates the use of user defined functions in bcParserGo.

```  type CircleArea struct{} // implements Function interface
func (f *CircleArea) Run(p []mathparser.Parameter) float64 {
r := p.Value()
return math.Pi * math.Pow(r, 2)
}
func (f *CircleArea) NumberOfParams() int {
return 1 // CircleArea function takes 1 parameter, the radius
}
func main() {
p := mathparser.NewMathParser()
p.CreateFunc("CIRCLEAREA", new(CircleArea))
p.SetExpression("CIRCLEAREA(3)+5")
fmt.Println("Value: ", p.Value())
}
}
```

## Sample Calculator Program

We don’t have a trial version of the library because it comes as source code. But we have a very simple calculator example that you can run to type expressions and view their results. You can download the command line binary for Linux, Mac OS X and Windows, 64 bit: Calculator for Mac OS X
Calculator for Linux
Calculator for Windows
When you run it, the command line calculator looks like this: The source code for this calculator is as follows:

```package main
import (
"bestcode/mathparser"
"flag"
"fmt"
"os"
"strconv"
)
// Returns values for previously undefined variables. In this example we don't rely on it
// for values; but we simply set it to turn off strict parsing to allow undefined variables
// at parse time. Then we ask the parser what those vars are, and then we explicitly set
// values for them. That is why this function never gets called.
func cmdLineVariableResolver(p mathparser.MathParser, varName string) float64 {
panic(fmt.Sprintf("VariableResolver should never get called in this case, "+
"but it got called for variable name %s", varName))
}
// This program asks for a mathematical expression to be entered on the command line.
func main() {
p := mathparser.NewMathParser()
p.CreateDefaultFuncs()
flag.Usage = func() {
fmt.Println("Default functions you can use:")
for _, funcName := range p.Functions() {
fmt.Println(funcName)
}
}
flag.Parse(); // Help -h
var expression string
for true {
fmt.Println("Input an expression such as x+sin(y) and press ENTER.")
fmt.Scan(&expression)
fmt.Println()
p.SetExpression(expression)
// We set variable resolver just to allow undefined variables
// in this case, so that Parse can succeed. We will set variable
// values later.
p.SetVariableResolver(cmdLineVariableResolver)
err := p.Parse()
if err == nil {
break
} else {
fmt.Println(err.Error())
}
}
vars, err := p.VariablesUsed()
if err != nil {
// Should never happen
fmt.Println("Error: ", err.Error())
os.Exit(1)
}
for _, variable := range vars {
var str string
AGAIN:
fmt.Println("Input ", variable, " value and press ENTER.")
fmt.Scan(&str)
val, err := strconv.ParseFloat(str, 64)
if err != nil {
fmt.Println(str, "is not a valid float64")
goto AGAIN
}
p.SetVariable(variable, val)
}
fmt.Println("-------------------------------------------------------")
val, err := p.Value()
if err != nil {
// Should never happen
fmt.Println("Error: ", err.Error())
os.Exit(1)
}
fmt.Println("Result of ", p.Expression(), " is: ", val)
fmt.Println("-------------------------------------------------------")
fmt.Println("Done.")
fmt.Println("Type exit and press ENTER to exit.")
fmt.Scan(&expression)
}
```