This repository has been archived by the owner on Mar 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser_test.go
183 lines (169 loc) · 3.89 KB
/
parser_test.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package arnoldc
import (
"os"
"testing"
)
func TestParser(t *testing.T) {
src := `
IT'S SHOWTIME
HEY CHRISTMAS TREE myVar
YOU SET US UP 10
TALK TO THE HAND "hello world"
GET TO THE CHOPPER a
HERE IS MY INVITATION 4
GET UP b
YOU'RE FIRED 2
ENOUGH TALK
GET TO THE CHOPPER a
HERE IS MY INVITATION b
GET UP 5
LET OFF SOME STEAM BENNET c
ENOUGH TALK
BECAUSE I'M GOING TO SAY PLEASE @I LIED
TALK TO THE HAND "false is true?!"
BULLSHIT
TALK TO THE HAND "false is not true"
YOU HAVE NO RESPECT FOR LOGIC
YOU HAVE BEEN TERMINATED
LISTEN TO ME VERY CAREFULLY hello
TALK TO THE HAND "hello"
HASTA LA VISTA, BABY
LISTEN TO ME VERY CAREFULLY double
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE number
GIVE THESE PEOPLE AIR
GET TO THE CHOPPER result
HERE IS MY INVITATION double
YOU'RE FIRED 2
ENOUGH TALK
I'LL BE BACK result
HASTA LA VISTA, BABY
`
f, err := fileFromString(src)
if err != nil {
t.Fatal(err)
}
defer func(f *os.File) {
f.Close()
os.Remove(f.Name())
}(f)
p := ArnoldC{input: f}
program, err := p.Parse()
if err != nil {
t.Fatalf("error parsing: %v", err)
}
expect := Program{
Main: Method{
Statements: []Statement{
Expression{
Instruction: DECLARE,
Args: []Value{VariableValue{"myVar"}, IntegerValue{10}},
},
Expression{
Instruction: PRINT,
Args: []Value{StringValue{"hello world"}},
},
Block{
Instruction: ASSIGNMENT,
Args: []Value{VariableValue{"a"}},
Statements: []Statement{
Expression{
Instruction: FIRST_OPERAND,
Args: []Value{IntegerValue{4}},
},
Expression{
Instruction: ADD,
Args: []Value{VariableValue{"b"}},
},
Expression{
Instruction: MULTIPLY,
Args: []Value{IntegerValue{2}},
},
},
},
Block{
Instruction: ASSIGNMENT,
Args: []Value{VariableValue{"a"}},
Statements: []Statement{
Expression{
Instruction: FIRST_OPERAND,
Args: []Value{VariableValue{"b"}},
},
Expression{
Instruction: ADD,
Args: []Value{IntegerValue{5}},
},
Expression{
Instruction: GREATER_THAN,
Args: []Value{VariableValue{"c"}},
},
},
},
// TODO: If & if/else should probably be a special type, since it's a compound block statement.
Block{
Instruction: IF,
Args: []Value{IntegerValue{0}},
Statements: []Statement{
Block{
Instruction: IF_TRUE,
Args: []Value{},
Statements: []Statement{
Expression{
Instruction: PRINT,
Args: []Value{StringValue{"false is true?!"}},
},
},
},
Block{
Instruction: IF_FALSE,
Args: []Value{},
Statements: []Statement{
Expression{
Instruction: PRINT,
Args: []Value{StringValue{"false is not true"}},
},
},
},
},
},
},
},
Methods: []Method{
Method{
Name: "hello",
Statements: []Statement{
Expression{
Instruction: PRINT,
Args: []Value{StringValue{"hello"}},
},
},
},
Method{
Name: "double",
Parameters: []string{"number"},
Statements: []Statement{
Block{
Instruction: ASSIGNMENT,
Args: []Value{VariableValue{"result"}},
Statements: []Statement{
Expression{
Instruction: FIRST_OPERAND,
Args: []Value{VariableValue{"double"}},
},
Expression{
Instruction: MULTIPLY,
Args: []Value{IntegerValue{2}},
},
},
},
Expression{
Instruction: RETURN,
Args: []Value{VariableValue{"result"}},
},
},
},
},
}
if expect.String() != program.String() {
t.Errorf("Program does not match expectations.\n Expected:\n%s\n Got:\n%s", expect, program)
}
}