diff options
author | Adam Scarr <adam@vektah.net> | 2017-08-08 23:11:47 +1000 |
---|---|---|
committer | Adam Scarr <adam@vektah.net> | 2017-08-08 23:11:47 +1000 |
commit | acd48fdfa4653dbeffd41f6b773ae4552e6c55bc (patch) | |
tree | c65e965b0bf88ccd28f657f11c36b7e73d3eaea2 /calc/calc.go | |
parent | ef04f70d750e8e447e096ac7ffb49d8831008a9c (diff) |
Add readme and calc example
Diffstat (limited to 'calc/calc.go')
-rw-r--r-- | calc/calc.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/calc/calc.go b/calc/calc.go new file mode 100644 index 0000000..d24dcea --- /dev/null +++ b/calc/calc.go @@ -0,0 +1,80 @@ +package calc + +import ( + "errors" + "fmt" + + . "github.com/vektah/goparsify" +) + +var ( + value Parser + + sumOp = Chars("+-", 1, 1) + prodOp = Chars("/*", 1, 1) + + groupExpr = Map(And("(", sum, ")"), func(n Node) Node { + return Node{Result: n.Child[1].Result} + }) + + number = Map(NumberLit(), func(n Node) Node { + switch i := n.Result.(type) { + case int64: + return Node{Result: float64(i)} + case float64: + return Node{Result: i} + default: + panic(fmt.Errorf("unknown value %#v", i)) + } + }) + + sum = Map(And(prod, Kleene(And(sumOp, prod))), func(n Node) Node { + 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 Node{Result: i} + }) + + prod = Map(And(&value, Kleene(And(prodOp, &value))), func(n Node) Node { + 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 Node{Result: i} + }) + + Y = Maybe(sum) +) + +func init() { + value = Any(number, groupExpr) +} + +func Calc(input string) (float64, error) { + result, remaining, err := ParseString(Y, input) + + if err != nil { + return 0, err + } + + if remaining != "" { + return result.(float64), errors.New("left unparsed: " + remaining) + } + + return result.(float64), nil +} |