forked from bvwells/go-patterns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterpreter.go
118 lines (101 loc) · 2.78 KB
/
interpreter.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package behavioral
import (
"strings"
)
// Expression represents an expression to evaluate.
type Expression interface {
Interpret(variables map[string]Expression) int
}
// Integer represents an integer number.
type Integer struct {
integer int
}
// Interpret returns the integer representation of the number.
func (n *Integer) Interpret(variables map[string]Expression) int {
return n.integer
}
// Plus represents the addition operation.
type Plus struct {
leftOperand Expression
rightOperand Expression
}
// Interpret interprets by adding the left and right variables.
func (p *Plus) Interpret(variables map[string]Expression) int {
return p.leftOperand.Interpret(variables) + p.rightOperand.Interpret(variables)
}
// Minus represents the subtraction operation.
type Minus struct {
leftOperand Expression
rightOperand Expression
}
// Interpret interprets by subtracting the right from left variables.
func (m *Minus) Interpret(variables map[string]Expression) int {
return m.leftOperand.Interpret(variables) - m.rightOperand.Interpret(variables)
}
// Variable represents a variable.
type Variable struct {
name string
}
// Interpret looks up the variable value and returns it, if not found returns zero.
func (v *Variable) Interpret(variables map[string]Expression) int {
value, found := variables[v.name]
if !found {
return 0
}
return value.Interpret(variables)
}
// Evaluator evaluates the expression.
type Evaluator struct {
syntaxTree Expression
}
// NewEvaluator creates a new Evaluator.
func NewEvaluator(expression string) *Evaluator {
expressionStack := new(Stack)
for _, token := range strings.Split(expression, " ") {
switch token {
case "+":
right := expressionStack.Pop().(Expression)
left := expressionStack.Pop().(Expression)
subExpression := &Plus{left, right}
expressionStack.Push(subExpression)
case "-":
right := expressionStack.Pop().(Expression)
left := expressionStack.Pop().(Expression)
subExpression := &Minus{left, right}
expressionStack.Push(subExpression)
default:
expressionStack.Push(&Variable{token})
}
}
syntaxTree := expressionStack.Pop().(Expression)
return &Evaluator{syntaxTree}
}
// Interpret interprets the expression syntax tree.
func (e *Evaluator) Interpret(context map[string]Expression) int {
return e.syntaxTree.Interpret(context)
}
// Node represents a node in the stack.
type Node struct {
value interface{}
next *Node
}
// Stack represents a stack with push and pop operations.
type Stack struct {
top *Node
size int
}
// Push pushes a new value into the stack.
func (s *Stack) Push(value interface{}) {
s.top = &Node{value, s.top}
s.size++
}
// Pop pops a value out the stack.
func (s *Stack) Pop() interface{} {
if s.size == 0 {
return nil
}
value := s.top.value
s.top = s.top.next
s.size--
return value
}