Skip to content

moxar/arithmetic

Repository files navigation

Arithmetic parser

Godoc license

This library parses and solves a mathematical expression.

It uses a Shunting-Yard algorithm (aka Reverse-Polish notation).

Usual mathematic constants and functions are defined in this package (see doc). Additional can be defined using the functions RegisterVariable and RegisterFunction.

Getting started

	package main

	import(
		"fmt"
		
		"github.com/moxar/arithmetic"
	)

	func main() {
		
		v, err := arithmetic.Parse("2+3")
		if err != nil {
			// ...
		}
		
		fmt.Println(v) // print 5
	}

This snippet is a very simple usage example of the arithmetic package.

Built-in

The following operators, variables and functions are supported by the package. Note that the inputs of the Parse method are not case sensitive.

Operators

The package supports the following operators:

* +  (sum)
* -  (difference)
* /  (quotient)
* x  (product)
* %  (modulo). Note: modulo requires both operand to be integer
* >  (greater)
* >= (greater or equal)
* == (equal)
* <= (lower or equal)
* <  (lower)
* != (different)
* && (and). Note: "and" is an alias to "&&"
* || (or). Note: "or" is an alias to "||"
* !  (not). Note: "not" is an alias to "!"

Variables

The package supports the following variables from the math package:

* e
* pi
* phi

* sqrt2
* sqrte
* sqrtpi
* sqrtphi

* ln2
* ln2e
* ln10
* log10e

Additionnaly, it supports the boolean true and false.

Functions

The package supports the following functions:

* max(a, b, c...). Note: Max only supports float, but can use any number of arguments.
* min(a, b, c...). Note: Min only supports float, but can use any number of arguments.
* mean(a, b, c...). Note: Mean only supports float, but can use any number of arguments.
* if(condition, success, failure).

Extension

The package can be extended. You can add variable, functions or expression to be automaticaly recognized by the parser. The extension is made possible by the RegisterXXX functions, which works in a similar way than the sql drivers. The functions will panic if there is a conflict between the name of the newly defined variable/function and an existing one.

Variable

A variable is a mapping from a string to a value. In this example, when the parser detects "dayInYear", it converts it to 365.

	package main
	
	import "github.com/moxar/arithmetic"

	func init() {
		arithmetic.RegisterVariable("dayInYear", 365)
	}
	
	func main() {
		
		v, err := arithmetic.Parse("dayInYear * 2")
		if err != nil {
			// ...
		}
		
		fmt.Println(v) 
		
		// Output: 730
	}

Function

A function is a mapping from a string to a function that returns a value. In this example, when the parser detects "contains", it checks if the second argument is contained within the first one.

	package main
	
	import (
		"fmt"
	
		"github.com/moxar/arithmetic"
	)

	func init() {

		// Register a new function, that increments the value by one.
		arithmetic.RegisterFunction("increment", func(args ...interface{}) (interface{}, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("increment requires one argument, %d provided", len(args))
			}

			f, ok := arithmetic.ToFloat(args[0])
			if !ok {
				return nil, fmt.Errorf("increment requires integer argument, %v (%T) provided", args[0], args[0])
			}

			return int(f) + 1, nil
		})
	}
	
	func main() {

		v, err := Parse("increment(2)")
		if err != nil {
			// ...
		}

		fmt.Println(v)
		// Output: 3
	}

Expression

An expression is a function that transforms an input to a value. The boolean tells whether the input could be transformed or not. Because the expressions are tested in an undefined order, you have to ensure there is no overlap between them.

	package main
	
	import (
		"fmt"
		"strings"
	
		"github.com/moxar/arithmetic"
	)

	func init() {
		arithmetic.RegisterExpression(foo)
	}
	
	func foo(input string) (interface{}, bool) {
		if len(input) == 0 {
			return nil, false
		}

		if input[0] != 'f' {
			return nil, false
		}
		

		for i, r := range input {
		
			if r != 'o' {
				return nil, false
			}
		}

		return true, true
	})
	
	func main() {

		v, err := arithmetic.Parse("fooOOoOoooOOOooOo && true")
		if err != nil {
			// ...
		}

		fmt.Println(v) 
		// Output: true
	}

Disclaimer

This lib is still at early development stages. The API is most likely susceptible to change.

About

Extensible arithmetic parsing lib for go

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages