Recursive descent expression parser in Go
go get -u github.com/svstanev/goexp
package main
import (
"fmt"
"math"
"github.com/svstanev/goexp"
"github.com/svstanev/goexp/types"
)
func main() {
context := goexp.NewEvalContext(nil)
context.AddName("x", types.Integer(1))
context.AddName("y", types.Integer(3))
context.AddName("z", types.Integer(5))
context.AddMethod("max", func(args ...types.Integer) (interface{}, error) {
var res int64 = math.MinInt64
for _, value := range args {
n := int64(value)
if n > res {
res = n
}
}
return types.Integer(res), nil
})
res, err := goexp.EvalString("max(x, y, z)", context)
if err != nil {
panic(err)
}
fmt.Println(res)
}
expression -> logical_or
logical_or -> logical_and (("||") logical_and)*;
logical_and -> logical_not (("&&") logical_not)*;
logical_not -> "!"? equality;
equality -> comparison (("==" | "!=") comparison)*;
comparison -> addition (("<" | "<=" | ">" | ">=") addition)*;
addition -> multiplication (("+" | "-") multiplication)*;
multiplication -> negate (("*" | "/" | "%") negate)*;
power -> negate ("**" negate)*;
negate -> "-"? call;
call -> primary (("(" arguments? ")") | ("." IDENTIFIER))*;
primary -> "false" | "true" | "nil" | IDENTIFIER | NUMBER | STRING | "(" expression ")";
arguments -> expression ("," expression)*;
IDENTIFIER -> ALPHA (ALPHA | DIGIT)*;
NUMBER -> DIGIT* ("." DIGIT*)?;
STRING -> "'" <any char except "'">* "'"
| '"' <any char except '"'>* '"';
DIGIT -> '0'...'9'
ALPHA -> 'a'...'z'|'A'...'Z'|'_'