package calc import ( "fmt" . "github.com/vektah/goparsify" ) var ( value Parser sumOp = Chars("+-", 1, 1) prodOp = Chars("/*", 1, 1) groupExpr = Map(Seq("(", sum, ")"), func(n Result) Result { return Result{Result: n.Child[1].Result} }) number = Map(NumberLit(), func(n Result) Result { switch i := n.Result.(type) { case int64: return Result{Result: float64(i)} case float64: return Result{Result: i} default: panic(fmt.Errorf("unknown value %#v", i)) } }) sum = Map(Seq(prod, Some(Seq(sumOp, prod))), func(n Result) Result { i := n.Child[0].Result.(float64) for _, op := range n.Child[1].Child { switch op.Child[0].Token { case "+": i += op.Child[1].Result.(float64) case "-": i -= op.Child[1].Result.(float64) } } return Result{Result: i} }) prod = Map(Seq(&value, Some(Seq(prodOp, &value))), func(n Result) Result { i := n.Child[0].Result.(float64) for _, op := range n.Child[1].Child { switch op.Child[0].Token { case "/": i /= op.Child[1].Result.(float64) case "*": i *= op.Child[1].Result.(float64) } } return Result{Result: i} }) y = Maybe(sum) ) func init() { value = Any(number, groupExpr) } func Calc(input string) (float64, error) { result, err := Run(y, input) if err != nil { return 0, err } return result.(float64), nil }