-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParserIntegrationTest.groovy
413 lines (358 loc) · 32.8 KB
/
ParserIntegrationTest.groovy
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
package org.example.parser
import org.example.ast.Program
import org.example.ast.Statement
import org.example.ast.ValueType
import org.example.ast.expression.Argument
import org.example.ast.expression.BlockStatement
import org.example.ast.expression.ExplicitCastExpression
import org.example.ast.expression.FunctionCallExpression
import org.example.ast.expression.IdentifierExpression
import org.example.ast.expression.MapExpression
import org.example.ast.expression.MethodCallExpression
import org.example.ast.expression.SelectExpression
import org.example.ast.expression.TupleCallExpression
import org.example.ast.expression.TupleExpression
import org.example.ast.expression.arithmetic.AddArithmeticExpression
import org.example.ast.expression.arithmetic.DivideArithmeticExpression
import org.example.ast.expression.arithmetic.MultiplyArithmeticExpression
import org.example.ast.expression.arithmetic.SubtractArithmeticExpression
import org.example.ast.expression.logical.AndLogicalExpression
import org.example.ast.expression.logical.OrLogicalExpression
import org.example.ast.statement.AssignmentStatement
import org.example.ast.statement.DeclarationStatement
import org.example.ast.statement.ForStatement
import org.example.ast.statement.FunctionDefinitionStatement
import org.example.ast.statement.IfStatement
import org.example.ast.statement.ReturnStatement
import org.example.ast.statement.WhileStatement
import org.example.ast.type.BooleanExpression
import org.example.ast.type.FloatingPointExpression
import org.example.ast.type.IntegerExpression
import org.example.ast.type.StringExpression
import org.example.ast.type.TypeDeclaration
import org.example.error.ErrorHandler
import org.example.lexer.LexerImpl
import org.example.parser.error.CriticalParserException
import org.example.parser.error.ParserException
import org.example.parser.error.UnexpectedTokenException
import org.example.token.Position
import spock.lang.Shared
import spock.lang.Specification
class ParserIntegrationTest extends Specification {
@Shared
var position = Position.builder().characterNumber(1).line(1).build()
Parser toParser(String content) {
var errorHandler = Mock(ErrorHandler)
return toParser(content, errorHandler)
}
Parser toParser(String content, ErrorHandler errorHandler) {
var reader = new StringReader(content)
var lexer = new LexerImpl(reader, errorHandler)
return new ParserImpl(lexer, errorHandler)
}
Program wrapStatements(List<Statement> statements) {
return new Program(
Map.of(
"main",
new FunctionDefinitionStatement(
"main",
List.of(),
new TypeDeclaration(ValueType.VOID),
new BlockStatement(statements, position),
position
)
),
Map.of()
)
}
def 'Should be able to parse empty program'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
" " || new Program(Map.of(), Map.of())
";" || new Program(Map.of(), Map.of())
"; ; ;" || new Program(Map.of(), Map.of())
}
def 'Should be able to parse basic function definition'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {}" || wrapStatements(List.of())
"fun main() {;;}" || wrapStatements(List.of())
"fun main() {func();}" || wrapStatements(List.of(new FunctionCallExpression("func", List.of(), position)))
"fun main() {func1(); func2();}" || wrapStatements(List.of(new FunctionCallExpression("func1", List.of(), position), new FunctionCallExpression("func2", List.of(), position)))
"fun main(): int {return 1;}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(), new TypeDeclaration(ValueType.INTEGER), new BlockStatement(List.of(new ReturnStatement(new IntegerExpression(1, position), position)), position), position)), Map.of())
"fun main(a: int) {}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(new Argument("a", new TypeDeclaration(ValueType.INTEGER))), new TypeDeclaration(ValueType.VOID), new BlockStatement(List.of(), position), position)), Map.of())
"fun main(a: int, b: int) {}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new Argument("b", new TypeDeclaration(ValueType.INTEGER))), new TypeDeclaration(ValueType.VOID), new BlockStatement(List.of(), position), position)), Map.of())
}
def 'Should be able to parse basic declaration statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"int a = 1;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new IntegerExpression(1, position), position)))
"int a = b;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new IdentifierExpression("b", position), position)))
"double a = 1.0;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.FLOATING_POINT)), new FloatingPointExpression(1.0, position), position)))
"boolean a = true;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new BooleanExpression(true, position), position)))
"String a = 'b';" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.STRING)), new StringExpression("b", position), position)))
"Comparator<int> a = func;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.COMPARATOR, List.of(new TypeDeclaration(ValueType.INTEGER)))), new IdentifierExpression("func", position), position)))
"Tuple<String> a = |b AS c|;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.TUPLE, List.of(new TypeDeclaration(ValueType.STRING)))), new TupleExpression(Map.of("c", new IdentifierExpression("b", position)), position), position)))
"Tuple<String, int> a = |b AS c, d AS e|;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.TUPLE, List.of(new TypeDeclaration(ValueType.STRING), new TypeDeclaration(ValueType.INTEGER)))), new TupleExpression(Map.of("c", new IdentifierExpression("b", position), "e", new IdentifierExpression("d", position)), position), position)))
"Tuple<String, int> a = (|b AS c, d AS e|);" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.TUPLE, List.of(new TypeDeclaration(ValueType.STRING), new TypeDeclaration(ValueType.INTEGER)))), new TupleExpression(Map.of("c", new IdentifierExpression("b", position), "e", new IdentifierExpression("d", position)), position), position)))
"Map<int, String> a = [];" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.MAP, List.of(new TypeDeclaration(ValueType.INTEGER), new TypeDeclaration(ValueType.STRING)))), new MapExpression(Map.of(), position), position)))
"Map<int, String> a = [b : c];" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.MAP, List.of(new TypeDeclaration(ValueType.INTEGER), new TypeDeclaration(ValueType.STRING)))), new MapExpression(Map.of(new IdentifierExpression("b", position), new IdentifierExpression("c", position)), position), position)))
"Map<int, String> a = [b : c, d : e];" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.MAP, List.of(new TypeDeclaration(ValueType.INTEGER), new TypeDeclaration(ValueType.STRING)))), new MapExpression(Map.of(new IdentifierExpression("b", position), new IdentifierExpression("c", position), new IdentifierExpression("d", position), new IdentifierExpression("e", position)), position), position)))
"Map<int, String> a = [b : c, d : []];" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.MAP, List.of(new TypeDeclaration(ValueType.INTEGER), new TypeDeclaration(ValueType.STRING)))), new MapExpression(Map.of(new IdentifierExpression("b", position), new IdentifierExpression("c", position), new IdentifierExpression("d", position), new MapExpression(Map.of(), position)), position), position)))
"Iterable<int> a = SELECT entry.key AS key FROM map AS entry;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.ITERABLE, List.of(new TypeDeclaration(ValueType.INTEGER)))), new SelectExpression(new TupleExpression(Map.of("key", new TupleCallExpression(new IdentifierExpression("entry", position), "key", position)), position), Map.entry("entry", new IdentifierExpression("map", position)), List.of(), new BooleanExpression(true, position), List.of(), new BooleanExpression(true, position), List.of(), position), position)))
}
def 'Should be able to parse while loop'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {boolean a = true; while a {a = false;}}" || wrapStatements(List.of(new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new BooleanExpression(true, position), position), new WhileStatement(new IdentifierExpression("a", position), new BlockStatement(List.of(new AssignmentStatement("a", new BooleanExpression(false, position), position)), position), position)))
"fun main() {boolean a = true; while (a) {a = false;}}" || wrapStatements(List.of(new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new BooleanExpression(true, position), position), new WhileStatement(new IdentifierExpression("a", position), new BlockStatement(List.of(new AssignmentStatement("a", new BooleanExpression(false, position), position)), position), position)))
}
def 'Should be able to parse if statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {boolean a = true; if a {a = false;}}" || wrapStatements(List.of(new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new BooleanExpression(true, position), position), new IfStatement(new IdentifierExpression("a", position), new BlockStatement(List.of(new AssignmentStatement("a", new BooleanExpression(false, position), position)), position), new BlockStatement(List.of(), position), position)))
"fun main() {boolean a = true; if (a) {a = false;}}" || wrapStatements(List.of(new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new BooleanExpression(true, position), position), new IfStatement(new IdentifierExpression("a", position), new BlockStatement(List.of(new AssignmentStatement("a", new BooleanExpression(false, position), position)), position), new BlockStatement(List.of(), position), position)))
}
def 'Should be able to parse for statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {for (Tuple<String> a : b) {print(a);}}" || wrapStatements(List.of(new ForStatement(new Argument("a", new TypeDeclaration(ValueType.TUPLE, List.of(new TypeDeclaration(ValueType.STRING)))), new IdentifierExpression("b", position), new BlockStatement(List.of(new FunctionCallExpression("print", List.of(new IdentifierExpression("a", position)), position)), position), position)))
}
def 'Should be able to parse assignment statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {a = b or c;}" || wrapStatements(List.of(new AssignmentStatement("a", new OrLogicalExpression(new IdentifierExpression("b", position), new IdentifierExpression("c", position), position), position)))
}
def 'Should be able to parse single expression statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {functionCall();}" || wrapStatements(List.of(new FunctionCallExpression("functionCall", List.of(), position)))
"fun main() {i[mapCall];}" || wrapStatements(List.of(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("operator[]", List.of(new IdentifierExpression("mapCall", position)), position), position)))
"fun main() {i[mapCall1][mapCall2];}" || wrapStatements(List.of(new MethodCallExpression(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("operator[]", List.of(new IdentifierExpression("mapCall1", position)), position), position), new FunctionCallExpression("operator[]", List.of(new IdentifierExpression("mapCall2", position)), position), position)))
"fun main() {i[mapCall1].methodCall();}" || wrapStatements(List.of(new MethodCallExpression(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("operator[]", List.of(new IdentifierExpression("mapCall1", position)), position), position), new FunctionCallExpression("methodCall", List.of(), position), position)))
"fun main() {i.methodCall();}" || wrapStatements(List.of(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("methodCall", List.of(), position), position)))
"fun main() {i.methodCall1().methodCall2();}" || wrapStatements(List.of(new MethodCallExpression(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("methodCall1", List.of(), position), position), new FunctionCallExpression("methodCall2", List.of(), position), position)))
"fun main() {i.methodCall1().tupleCall2;}" || wrapStatements(List.of(new TupleCallExpression(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("methodCall1", List.of(), position), position), "tupleCall2", position)))
"fun main() {i.tupleCall1.methodCall2();}" || wrapStatements(List.of(new MethodCallExpression(new TupleCallExpression(new IdentifierExpression("i", position), "tupleCall1", position), new FunctionCallExpression("methodCall2", List.of(), position), position)))
"fun main() {i.tupleCall;}" || wrapStatements(List.of(new TupleCallExpression(new IdentifierExpression("i", position), "tupleCall", position)))
"fun main() {i.tupleCall1.tupleCall2;}" || wrapStatements(List.of(new TupleCallExpression(new TupleCallExpression(new IdentifierExpression("i", position), "tupleCall1", position), "tupleCall2", position)))
}
def 'Should be able to parse return statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main(): int {return 1 + 2;}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(), new TypeDeclaration(ValueType.INTEGER), new BlockStatement(List.of(new ReturnStatement(new AddArithmeticExpression(new IntegerExpression(1, position), new IntegerExpression(2, position), position), position)), position), position)), Map.of())
"fun main(): int {return 1 - 2;}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(), new TypeDeclaration(ValueType.INTEGER), new BlockStatement(List.of(new ReturnStatement(new SubtractArithmeticExpression(new IntegerExpression(1, position), new IntegerExpression(2, position), position), position)), position), position)), Map.of())
"fun main(): int {return 1 / 2;}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(), new TypeDeclaration(ValueType.INTEGER), new BlockStatement(List.of(new ReturnStatement(new DivideArithmeticExpression(new IntegerExpression(1, position), new IntegerExpression(2, position), position), position)), position), position)), Map.of())
"fun main(): int {return 1 * 2;}" || new Program(Map.of("main", new FunctionDefinitionStatement("main", List.of(), new TypeDeclaration(ValueType.INTEGER), new BlockStatement(List.of(new ReturnStatement(new MultiplyArithmeticExpression(new IntegerExpression(1, position), new IntegerExpression(2, position), position), position)), position), position)), Map.of())
}
def 'Should be able to parse nested block statement'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"fun main() {{functionCall();}}" || wrapStatements(List.of(new BlockStatement(List.of(new FunctionCallExpression("functionCall", List.of(), position)), position)))
}
def 'Should be able to perform mathematical operations'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"int a = 1 + 2 * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new AddArithmeticExpression(new IntegerExpression(1, position), new MultiplyArithmeticExpression(new IntegerExpression(2, position), new IntegerExpression(3, position), position), position), position)))
"int a = (1 + 2) * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new MultiplyArithmeticExpression(new AddArithmeticExpression(new IntegerExpression(1, position), new IntegerExpression(2, position), position), new IntegerExpression(3, position), position), position)))
"int a = 1 + i * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new AddArithmeticExpression(new IntegerExpression(1, position), new MultiplyArithmeticExpression(new IdentifierExpression("i", position), new IntegerExpression(3, position), position), position), position)))
"int a = 1 + i.tupleCall * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new AddArithmeticExpression(new IntegerExpression(1, position), new MultiplyArithmeticExpression(new TupleCallExpression(new IdentifierExpression("i", position), "tupleCall", position), new IntegerExpression(3, position), position), position), position)))
"int a = 1 + i[mapCall] * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new AddArithmeticExpression(new IntegerExpression(1, position), new MultiplyArithmeticExpression(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("operator[]", List.of(new IdentifierExpression("mapCall", position)), position), position), new IntegerExpression(3, position), position), position), position)))
"int a = 1 + i.methodCall() * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new AddArithmeticExpression(new IntegerExpression(1, position), new MultiplyArithmeticExpression(new MethodCallExpression(new IdentifierExpression("i", position), new FunctionCallExpression("methodCall", List.of(), position), position), new IntegerExpression(3, position), position), position), position)))
"int a = 1 + functionCall() * 3;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.INTEGER)), new AddArithmeticExpression(new IntegerExpression(1, position), new MultiplyArithmeticExpression(new FunctionCallExpression("functionCall", List.of(), position), new IntegerExpression(3, position), position), position), position)))
"double a = (@double 1) + 2.0;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.FLOATING_POINT)), new AddArithmeticExpression(new ExplicitCastExpression(new TypeDeclaration(ValueType.FLOATING_POINT), new IntegerExpression(1, position), position), new FloatingPointExpression(2, position), position), position)))
}
def 'Should be able to perform logical operations'() {
given:
var parser = toParser(program)
expect:
parser.parseProgram() == result
where:
program || result
"boolean a = false or true and false;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new OrLogicalExpression(new BooleanExpression(false, position), new AndLogicalExpression(new BooleanExpression(true, position), new BooleanExpression(false, position), position), position), position)))
"boolean a = (false or true) and false;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new AndLogicalExpression(new OrLogicalExpression(new BooleanExpression(false, position), new BooleanExpression(true, position), position), new BooleanExpression(false, position), position), position)))
"boolean a = false or b and false;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new OrLogicalExpression(new BooleanExpression(false, position), new AndLogicalExpression(new IdentifierExpression("b", position), new BooleanExpression(false, position), position), position), position)))
"boolean a = not false;" || new Program(Map.of(), Map.of("a", new DeclarationStatement(new Argument("a", new TypeDeclaration(ValueType.BOOLEAN)), new BooleanExpression(true, position), position)))
}
// ERRORS
def 'Should throw critical exception when did not find necessary expression'() {
given:
var errorHandler = Mock(ErrorHandler)
var parser = toParser(program, errorHandler)
when:
parser.parseProgram()
then:
1 * errorHandler.handleParserException(_ as CriticalParserException)
thrown(CriticalParserException)
where:
program << [
"int a =",
"int a =;",
"int a = 1 +;",
"int a = 1 -;",
"int a = 1 *;",
"int a = 1 /;",
"int a = (1;",
"Map<String, String> map = [a:b",
"Tuple<String> tuple = |expression AS key",
"boolean a = not;",
"boolean a = b;boolean a = b;",
"boolean a = true and;",
"boolean a = true or;",
"Map<String, String> map = [a:b,]",
"Map<String, String> map = [a:]",
"Map<String, String> map = [a]",
"Tuple<String> tuple = |expression AS |",
"Tuple<String, String> tuple = |expression AS key,",
"Tuple<String> tuple = |expression key|",
"Tuple<String> tuple = | AS key|",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + ;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int, int> iterable = SELECT db1.value + db2.value AS value, FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int, int> iterable = SELECT;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"fun main(: int) {}",
"fun main() {",
"fun main() {}fun main() {}",
"fun main() {(}",
"fun main() {[}",
"fun main() {|}",
"fun main(a: int, : int) {}",
"fun main() {while {}}",
"fun main() {while () {}}",
"fun main() {while ) {}}",
"fun main() {while (true {}}",
"fun main() {if (true) {}",
"fun main() {(true) {} else {}}",
"fun main() {if (true) { else {}}",
"fun main() {if (true) {} else {}",
"fun main() {if true) {}}",
"fun main() {if () {}}",
"fun main() {if (true {}}",
"fun main() {if true) {} else {}}",
"fun main() {if () {} else {}}",
"fun main() {if (true {} else {}}",
"fun main() {if (true) } else {}}",
"fun main() {(int a: expression) {expression;}}",
"fun main() {for (int a: expression {expression;}}",
"fun main() {for int a: expression) {expression;}}",
"fun main() {for (a: expression) {expression;}}",
"fun main() {for (int: expression) {expression;}}",
"fun main() {for (int a expression) {expression;}}",
"fun main() {for (int a:) {expression;}}",
"fun main() {for (int a: expression) {expression;}",
"fun main() {a =;}",
"fun main() {a + b = expression;}",
]
}
def 'Should raise an exception when a enclosing token is expected'() {
given:
var errorHandler = Mock(ErrorHandler)
var parser = toParser(program, errorHandler)
when:
parser.parseProgram()
then:
(1.._) * errorHandler.handleParserException(_ as UnexpectedTokenException)
noExceptionThrown()
where:
program << [
"identifier;",
"int a = 1",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUPBY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key == db2.key db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 ON db1.key db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 JOIN map2 AS db2 db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"Iterable<int> iterable = SELECT db1.value + db2.value AS value FROM map1 AS db1 map2 AS db2 ON db1.key == db2.key WHERE db1.value > 2 GROUP BY value HAVING value > 0 ORDER BY db1.key DESC, db2.key ASC, db1.key + db2.key;",
"fun main() {(true) {}}",
"fun main() {for (int a: expression) expression;}}",
"fun main() {a = expression}",
]
}
def 'Should raise an exception when expecting type declaration on function'() {
given:
var errorHandler = Mock(ErrorHandler)
var parser = toParser(program, errorHandler)
when:
parser.parseProgram()
then:
1 * errorHandler.handleParserException(_ as ParserException)
noExceptionThrown()
where:
program << [
"fun main():{}",
"fun main(a: int, b: int):{}",
"fun main(a: int, b: int):int",
"fun main(a: int, b: int)",
"fun main() {while(true)}",
"fun main() {for (int a: expression)}",
]
}
}