func TestEval(t *testing.T) { addTree := ast.New() addTree.AddChildren([]ast.Node{ &ast.Number{ Value: "2", }, &ast.Operator{ Class: ast.OpAdd, }, &ast.Number{ Value: "3", }, }) subTree := ast.New() subTree.AddChildren([]ast.Node{ &ast.Number{ Value: "5", }, &ast.Operator{ Class: ast.OpSubtract, }, &ast.Number{ Value: "3", }, }) testCases := []struct { tree ast.Node expected *big.Rat }{ { tree: &ast.Number{ Value: "42", }, expected: big.NewRat(42, 1), }, { tree: addTree, expected: big.NewRat(5, 1), }, { tree: subTree, expected: big.NewRat(2, 1), }, } for i, tc := range testCases { tcInfo := fmt.Sprintf("test case: %d\ninput:\n%s\n", i, tc.tree.Format(0)) actual, err := Eval(tc.tree) require.NoError(t, err) assert.Exactly(t, tc.expected, actual, "\nexpected: %0.3f\ngot: %0.3f\n%s", ratFloat(tc.expected), ratFloat(actual), tcInfo) } }
func justNumber(value string) ast.Node { base := ast.New() base.AddChild(&ast.Number{ Value: value, }) return base }
// E'2 -> "(" E ")" func ep2(buf *token.Buffer, tree ast.Node) (newTree ast.Node, err error) { origPos := buf.Pos() defer func() { if err != nil { buf.MustSeek(origPos) } }() newTree = tree.Copy() expr := ast.New() newTree.AddChild(expr) if err := termOpenParen(buf); err != nil { return nil, err } if buf.Pos() >= buf.Len() { return nil, io.EOF } eTree, err := e(buf, tree.Copy()) if err != nil { return nil, err } expr.AddChildren(eTree.Children()) if buf.Pos() >= buf.Len() { return nil, io.EOF } if err := termCloseParen(buf); err != nil { return nil, err } return newTree, nil }
func Parse(tokens []token.Token) (ast.Node, error) { buf := token.NewBuffer(tokens) root := ast.New() tree, err := e(buf, root) if err != nil { if err == io.EOF { return nil, errors.New("Unexpected end of input") } return nil, err } return tree, nil }
func operation(a string, opClass ast.OpClass, b string) ast.Node { base := ast.New() base.AddChildren([]ast.Node{ &ast.Number{ Value: a, }, &ast.Operator{ Class: opClass, }, &ast.Number{ Value: b, }, }) return base }