package main import ( "fmt" "math/big" ) type Op int const ( OpInvalid Op = iota OpAdd OpSub OpMul OpDiv OpExp ) type Expr interface { Eval() *big.Int } type NumExpr struct { N *big.Int } func (n *NumExpr) Eval() *big.Int { return n.N } type NopExpr struct { } func (e *NopExpr) Eval() *big.Int { return &big.Int{} } type OpExpr struct { Op Op L Expr R Expr } func (o *OpExpr) Eval() *big.Int { l := o.L.Eval() r := o.R.Eval() n := new(big.Int) switch o.Op { case OpAdd: n.Add(l, r) case OpSub: n.Sub(l, r) case OpMul: n.Mul(l, r) case OpDiv: n.Div(l, r) case OpExp: n.Exp(l, r, nil) } return n } func Parse(d []byte) (e Expr, err error) { sc := newScanner(d) t, d := sc.Scan() switch t { case NUM: s := string(d) n, ok := big.NewInt(0).SetString(s, 10) if !ok { return nil, fmt.Errorf("invalid number %s at %d", s, sc.Pos()) } l := &NumExpr{N: n} var op Op t, d = sc.Scan() switch t { case EOF: return l, nil case ADD: op = OpAdd case SUB: op = OpSub case MUL: op = OpMul case DIV: op = OpDiv case EXP: op = OpExp default: return nil, fmt.Errorf("expected operator at %d", sc.Pos()) } t, d = sc.Scan() if t != NUM { return nil, fmt.Errorf("expected number at %d", sc.Pos()) } s = string(d) n2, ok := big.NewInt(0).SetString(s, 10) if !ok { return nil, fmt.Errorf("invalid nummber %s at %d", s, sc.Pos()) } r := &NumExpr{N: n2} return &OpExpr{Op: op, L: l, R: r}, nil case EOF: return &NopExpr{}, nil } return nil, fmt.Errorf("invalid token %s at index %d", t, sc.Pos()) }