OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 class ParserTest { | |
6 static final String TAIL = '//comment\n\n'; | |
7 | |
8 static main() { | |
9 print('start ParserTest'); | |
10 initializeWorld(new FileSystem('.')); | |
11 testStatements(); | |
12 testLambdas(); | |
13 testExpressionsAsStatements(); | |
14 testDeclarationStatements(); | |
15 testTypeAmbiguities(); | |
16 | |
17 testDeclarations(); | |
18 | |
19 testLiterals(); | |
20 print('finished ParserTest'); | |
21 } | |
22 | |
23 static testStatements() { | |
24 testStatement('a - b - c - d;'); | |
25 | |
26 testStatement('if (true) return 1*2+3*4; else return 2;'); | |
27 testStatement('return 42 ? true : false;'); | |
28 testStatement('return true += 2+6*3;'); | |
29 | |
30 testStatement('int x;'); | |
31 testStatement('x.m y = 42, z;'); | |
32 testStatement('{ int x; return 22; }'); | |
33 testStatement('int f() { return 22; }'); | |
34 | |
35 testStatement('int f(int y) { return 22 + 3; }'); | |
36 testStatement('int f(int y, int x) { return 22 + x; }'); | |
37 | |
38 testStatement('int f(y, x) { return 22 + x; }'); | |
39 testStatement('foo() => 42;'); | |
40 | |
41 testStatement('throw;'); | |
42 testStatement('throw x(10);'); | |
43 | |
44 testStatement('break;'); | |
45 testStatement('continue;'); | |
46 testStatement('assert(true);'); | |
47 testStatement('assert(x < 10);'); | |
48 testStatement('break foo;'); | |
49 testStatement('continue bar;'); | |
50 | |
51 testStatement('var z=22, a=new C(1,2);'); | |
52 | |
53 testStatement('for (Map<String, Object> suite in stats) {}'); | |
54 } | |
55 | |
56 static testLambdas() { | |
57 testStatement('x = function() {};'); | |
58 testStatement('x = function() => 42;'); | |
59 testStatement('x = void f() {};'); | |
60 testStatement('x = func() => 42;'); | |
61 testStatement('x = void f(int x, int y) {};'); | |
62 testStatement('x = func(x) => 42;'); | |
63 testStatement('x = func(x,y,z) => 42;'); | |
64 | |
65 testStatement('x = func(x);'); | |
66 testStatement('x = func(x,y,z);'); | |
67 testStatement('x = func(42);'); | |
68 testStatement('x = func(x,y,42);'); | |
69 | |
70 | |
71 testStatement('f(x = function() {});'); | |
72 testStatement('f(x = function() => 42);'); | |
73 testStatement('f(x = void f() {});'); | |
74 testStatement('f(x = func() => 42);'); | |
75 | |
76 testStatement('f(foo() {});'); | |
77 | |
78 testStatement('f(void func(KV<K,V> e) {});'); | |
79 } | |
80 | |
81 static testExpressionsAsStatements() { | |
82 testStatement('x + 1;'); | |
83 | |
84 testStatement('(2+3);'); | |
85 testStatement('x.m(10);'); | |
86 testStatement('x(10);'); | |
87 | |
88 // TODO(jimhug): This is illegal - add as negative test... | |
89 //testStatement('var c = z=22, a=new C(1,2);'); | |
90 | |
91 testStatement('-a++;'); // TODO(jimhug): Ensure this parses as -(a++). | |
92 | |
93 testStatement('[(2+3), x(10), ++x, x++, --y, y--, x[42]];'); | |
94 testStatement('var m = {"a":42, "b":f(76),};'); | |
95 testStatement('var m = {};'); | |
96 testStatement('var m = {"a":"bye"};'); | |
97 testStatement('var m = {"a":42, "b":f(76)};'); | |
98 testStatement('var c = const [1,2];'); | |
99 testStatement('var c = const {"1":2};'); | |
100 | |
101 testStatement('final m = const <int>[1,2,3];'); | |
102 testStatement('final m = const <String, int>{"a":1,"b":2,"c":3};'); | |
103 | |
104 testStatement('if (a is double) {}'); | |
105 testStatement('if ((a is double) && b(10)) {}'); | |
106 | |
107 testStatement('try { foo(); } catch (e) {} catch (e, t) {} finally {}'); | |
108 testStatement('try { foo(); } catch (Ex1 e) {} catch (Ex2 e, St t) {}'); | |
109 | |
110 testStatement('for (i in set) {}'); | |
111 testStatement('for (final i in set) {}'); | |
112 testStatement('for (var i in set) {}'); | |
113 testStatement('for (final int i in set) {}'); | |
114 | |
115 testStatement('''switch (e) { | |
116 case 1: | |
117 foo(); | |
118 break; | |
119 case 2: case 3: | |
120 bar(); return 10; | |
121 default: return null; | |
122 }'''); | |
123 | |
124 // operator fun | |
125 testStatement('var o = x >> 2;'); | |
126 testStatement('var o = x >>> 2;'); | |
127 | |
128 testStatement('x >>= 2;'); | |
129 testStatement('x >>>= 2;'); | |
130 // TODO - need negatives! | |
131 | |
132 testStatement('var kv = new KeyValuePair<K, V>(key, value);'); | |
133 | |
134 testStatement('array.sort((a, b) => a < b);'); | |
135 | |
136 testStatement(';'); | |
137 testStatement('{;;;;;;;;;}'); | |
138 | |
139 testStatement('print("hello");'); | |
140 testStatement('print("hello \$foo");'); | |
141 testStatement('print("\${2 + x} = \${y(\'bar\')}");'); | |
142 } | |
143 | |
144 static testDeclarationStatements() { | |
145 testStatement('int m() {}'); | |
146 testStatement('m() {}'); | |
147 testStatement('m(x) {}'); | |
148 | |
149 testStatement('m(A<B> o) {}'); | |
150 | |
151 testStatement('m(A<B<C>> z) {}'); | |
152 | |
153 testStatement('A.B<C> m(int x, y, double z) {}'); | |
154 testStatement('A.B<C> m(int x, y, A<B<C>> z) {}'); | |
155 | |
156 testStatement('int x;'); | |
157 testStatement('A.B<C> x = 2+5;'); | |
158 testStatement('A.B<C> x = 2+5, y, z=42;'); | |
159 | |
160 testStatement('void f(e) { }'); | |
161 | |
162 testStatement('Promise<int> a = new Promise<int>();'); | |
163 testStatement('Promise<Promise<int>> b = new Promise<Promise<int>>();'); | |
164 testStatement('P<P<P<int>>> c = new P<P<P<int>>>();'); | |
165 testStatement('P<P<P<P<int>>>> c = new P<P<P<P<int>>>>();'); | |
166 } | |
167 | |
168 | |
169 static testDeclarations() { | |
170 testDeclaration('int m();'); | |
171 testDeclaration('m();'); | |
172 testDeclaration('m(x) {}'); | |
173 testDeclaration('A.B<C> m(int x, y, double z);'); | |
174 | |
175 | |
176 testDeclaration('A.B<C> m(int x, y, A<B<C>> z);'); | |
177 | |
178 testDeclaration('int x;'); | |
179 testDeclaration('A.B<C> x = 2+5;'); | |
180 testDeclaration('A.B<C> x = 2+5, y, z=42;'); | |
181 | |
182 testDeclaration('operator +(other) {}'); | |
183 testDeclaration('operator [](index) {}'); | |
184 testDeclaration('operator []=(index, value) {}'); | |
185 | |
186 testDeclaration('foo() => 42;'); | |
187 | |
188 testDeclaration('''class C extends D implements I { | |
189 void m() { return 43; } | |
190 int x; | |
191 }'''); | |
192 | |
193 testDeclaration('interface I { operator +(y) { return y + 10; }}'); | |
194 testDeclaration('interface I { int operator +(y) { return y + 10; }}'); | |
195 | |
196 testDeclaration('HashMap<K, DLLE<KeyValuePair<K, V>>> m_;'); | |
197 | |
198 // pseudo keywords? | |
199 testDeclaration('foo(A source) {}'); | |
200 testDeclaration('foo(A get, B assert, C static, D extends) {}'); | |
201 | |
202 testDeclaration('C(): b=x+y {}'); | |
203 | |
204 testDeclaration('C(): z=22, a=new C(1,2) {}'); | |
205 testDeclaration('C(b): _b = b == null ? 10 : 20 {}'); | |
206 | |
207 testDeclaration('C(this.x, this.y) {}'); | |
208 | |
209 testDeclaration('C(this.x, this.y): z=22, a=new C(1,2), b=x+y {}'); | |
210 | |
211 testDeclaration('void f(e) { }'); | |
212 } | |
213 | |
214 static testTypeAmbiguities() { | |
215 testMaybeType('A.B.C', false, false); | |
216 testMaybeType('A.B.C<10', false, true); | |
217 testMaybeType('A.B.C<D', false, true); | |
218 testMaybeType('A.B.C<D>', true, false); | |
219 testMaybeType('A.B.C<D,E>', true, false); | |
220 testMaybeType('A.B.C<D,E,F>', true, false); | |
221 testMaybeType('A.B.C<D,E,F,G>', true, false); | |
222 | |
223 testMaybeType('A<B1,B2<C>,D>', true, false); | |
224 | |
225 testMaybeType('A<B<C>,D>', true, false); | |
226 testMaybeType('A<B1,B2<C>,D>', true, false); | |
227 testMaybeType('A<B<C>>', true, false); | |
228 testMaybeType('A<B<C<D>>>', true, false); | |
229 | |
230 testMaybeType('KeyValuePair<K, V>', true, false); | |
231 testMaybeType('QueueEntry<KeyValuePair<K, V> >', true, false); | |
232 testMaybeType('QueueEntry<KeyValuePair<K, V>>', true, false); | |
233 testMaybeType('HashMap<K, QueueEntry<KeyValuePair<K, V> > >', | |
234 true, false); | |
235 testMaybeType('HashMap<K, QueueEntry<KeyValuePair<K, V>>>', | |
236 true, false); | |
237 } | |
238 | |
239 | |
240 static testLiterals() { | |
241 testLiteral('2', 2); | |
242 testLiteral('10e100', 10e100); | |
243 testLiteral('3.14159265', 3.14159265); | |
244 testLiteral('0x0', 0); | |
245 testLiteral('0xa8', 168); | |
246 testLiteral('0xfF', 255); | |
247 testLiteral('0XfF', 255); | |
248 | |
249 testLiteral('0xabcdef', 11259375); | |
250 testLiteral('0xABCDEF', 11259375); | |
251 // TODO(jimhug): This is too big for JS int | |
252 //testLiteral('0x123456789', 4886718345); | |
253 testLiteral('0x12345678', 305419896); | |
254 } | |
255 | |
256 static Parser makeParser(String filename, String code) { | |
257 return new Parser(new SourceFile(filename, code)); | |
258 } | |
259 | |
260 static void assertEqual(a, b) { | |
261 Expect.equals(a, b); | |
262 } | |
263 | |
264 static void validateNode(Node node, String filename, String code) { | |
265 // first, confirm sourcespan exists and is "correct" | |
266 var span = node.span; | |
267 assertEqual(span.file.filename, filename); | |
268 assertEqual(span.start, 0); | |
269 assertEqual(span.end, code.length); | |
270 | |
271 // TODO(jimhug): Walk and validate children spans and contents. | |
272 } | |
273 | |
274 static void testLiteral(String expr, var expected) { | |
275 print('>>>${expr}<<<'); | |
276 var filename = 'expr.dart'; | |
277 final parser = makeParser(filename, expr + TAIL); | |
278 var node = parser.expression(); | |
279 validateNode(node, filename, expr); | |
280 parser.checkEndOfFile(); | |
281 | |
282 assertEqual(expected, node.value); | |
283 } | |
284 | |
285 static void testDeclaration(String code, [String filename='test.dart']) { | |
286 print('>>>${code}<<<'); | |
287 final parser = makeParser(filename, code + TAIL); | |
288 var decl = parser.topLevelDefinition(); | |
289 validateNode(decl, filename, code); | |
290 parser.checkEndOfFile(); | |
291 } | |
292 | |
293 static void testStatement(String code, [String filename='test.dart']) { | |
294 print('>>>${code}<<<'); | |
295 final parser = makeParser(filename, code + TAIL); | |
296 var node = parser.statement(); | |
297 validateNode(node, filename, code); | |
298 parser.checkEndOfFile(); | |
299 } | |
300 | |
301 static void testMaybeType(String code, bool mustBeType, | |
302 bool mustBeExpression) { | |
303 if (!mustBeType) { | |
304 testStatement('x + ' + code + ';'); | |
305 } | |
306 if (!mustBeExpression) { | |
307 testStatement(code + ' x;'); | |
308 testDeclaration(code + ' x;'); | |
309 } | |
310 // TODO(jimhug): add negative test cases. | |
311 } | |
312 } | |
OLD | NEW |