-
Notifications
You must be signed in to change notification settings - Fork 0
/
eval.go
79 lines (69 loc) · 1.42 KB
/
eval.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package main
import (
"errors"
"math"
"strconv"
)
type evaluator func(*astNode) (any, error)
func eval(ast *astNode) (any, error) {
return ast.evalr(ast)
}
func evalNumber(ast *astNode) (any, error) {
return strconv.ParseFloat(string(ast.token.val), 64)
}
func evalUnary(ast *astNode) (any, error) {
right, err := eval(ast.right)
if err != nil {
return nil, err
}
switch ast.token.tokenType {
case Minus:
return -right.(float64), nil
case Not:
return !right.(bool), nil
}
return nil, nil
}
func evalInfix(ast *astNode) (any, error) {
var left, right any
left, err := eval(ast.left)
if err != nil {
return nil, err
}
right, err = eval(ast.right)
if err != nil {
return 0, nil
}
leftF := left.(float64)
rightF := right.(float64)
switch ast.token.tokenType {
case Minus:
return leftF - rightF, nil
case Plus:
return leftF + rightF, nil
case Asterisk:
return leftF * rightF, nil
case Slash:
if rightF == 0 {
return 0, errors.New("divided by zero")
}
return leftF / rightF, nil
case Mod:
return float64(int64(leftF) % int64(rightF)), nil
case RaisePower:
return math.Pow(leftF, rightF), nil
case LT:
return leftF < rightF, nil
case GT:
return leftF > rightF, nil
case LTEQ:
return leftF <= rightF, nil
case GTEQ:
return leftF >= rightF, nil
case Eq:
return leftF == rightF, nil
case NotEq:
return leftF != rightF, nil
}
return nil, nil // Need to take care of this
}