OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library peg_tests; | 5 library peg_tests; |
6 | |
6 import 'dart:core' hide Symbol; | 7 import 'dart:core' hide Symbol; |
7 import '../../peg/pegparser.dart'; | 8 import '../../peg/pegparser.dart'; |
8 | 9 |
9 testParens() { | 10 testParens() { |
10 Grammar g = new Grammar(); | 11 Grammar g = new Grammar(); |
11 Symbol a = g['A']; | 12 Symbol a = g['A']; |
12 | 13 |
13 a.def = ['(', MANY(a, min:0), ')', (a) => a]; | 14 a.def = ['(', MANY(a, min: 0), ')', (a) => a]; |
14 | 15 |
15 check(g, a, "", null); | 16 check(g, a, "", null); |
16 check(g, a, "()", '[]'); | 17 check(g, a, "()", '[]'); |
17 check(g, a, "(()())", '[[],[]]'); | 18 check(g, a, "(()())", '[[],[]]'); |
18 check(g, a, "(()((()))())", '[[],[[[]]],[]]'); | 19 check(g, a, "(()((()))())", '[[],[[[]]],[]]'); |
19 } | 20 } |
20 | 21 |
21 testBlockComment() { | 22 testBlockComment() { |
22 | |
23 // Block comment in whitespace. | 23 // Block comment in whitespace. |
24 | 24 |
25 Grammar g = new Grammar(); | 25 Grammar g = new Grammar(); |
26 Symbol blockComment = g['blockComment']; | 26 Symbol blockComment = g['blockComment']; |
27 | 27 |
28 blockComment.def = | 28 blockComment.def = [ |
29 ['/*', | 29 '/*', |
30 MANY(OR([blockComment, | 30 MANY( |
31 [NOT('*/'), CHAR()], | 31 OR([ |
32 [END, ERROR('EOF in block comment')] | 32 blockComment, |
33 ]), | 33 [NOT('*/'), CHAR()], |
34 min: 0), | 34 [END, ERROR('EOF in block comment')] |
35 '*/']; | 35 ]), |
36 min: 0), | |
37 '*/' | |
38 ]; | |
36 print(blockComment); | 39 print(blockComment); |
37 | 40 |
38 var a = MANY(TEXT('x')); | 41 var a = MANY(TEXT('x')); |
39 | 42 |
40 g.whitespace = OR([g.whitespace, blockComment]); | 43 g.whitespace = OR([g.whitespace, blockComment]); |
41 | 44 |
42 check(g, a, "x /**/ x", '[x,x]'); | 45 check(g, a, "x /**/ x", '[x,x]'); |
43 check(g, a, "x /*/**/*/ x", '[x,x]'); | 46 check(g, a, "x /*/**/*/ x", '[x,x]'); |
44 check(g, a, "x /*/***/ x", 'EOF in block comment'); | 47 check(g, a, "x /*/***/ x", 'EOF in block comment'); |
45 check(g, a, "x /*/*/x**/**/ x", '[x,x]'); | 48 check(g, a, "x /*/*/x**/**/ x", '[x,x]'); |
46 | 49 |
47 check(g, a, r""" | 50 check( |
51 g, | |
52 a, | |
53 r""" | |
48 /* Comment */ | 54 /* Comment */ |
49 /* Following comment with /* nested comment*/ */ | 55 /* Following comment with /* nested comment*/ */ |
50 x | 56 x |
51 /* x in comment */ | 57 /* x in comment */ |
52 x /* outside comment */ | 58 x /* outside comment */ |
53 """, | 59 """, |
54 '[x,x]'); | 60 '[x,x]'); |
55 } | 61 } |
56 | 62 |
57 testTEXT() { | 63 testTEXT() { |
58 Grammar g = new Grammar(); | 64 Grammar g = new Grammar(); |
59 | 65 |
60 // TEXT grabs the parsed text, | 66 // TEXT grabs the parsed text, |
61 check(g, TEXT(LEX(MANY(OR(['1','a'])))), ' 1a1 ', '1a1'); | 67 check(g, TEXT(LEX(MANY(OR(['1', 'a'])))), ' 1a1 ', '1a1'); |
62 | 68 |
63 // Without the lexical context, TEXT will grab intervening whitespace. | 69 // Without the lexical context, TEXT will grab intervening whitespace. |
64 check(g, TEXT(MANY(OR(['1','a']))), ' 1a1 ', '1a1'); | 70 check(g, TEXT(MANY(OR(['1', 'a']))), ' 1a1 ', '1a1'); |
65 check(g, TEXT(MANY(OR(['1','a']))), ' 1 a 1 ', '1 a 1'); | 71 check(g, TEXT(MANY(OR(['1', 'a']))), ' 1 a 1 ', '1 a 1'); |
66 | 72 |
67 // Custom processing of the TEXT substring. | 73 // Custom processing of the TEXT substring. |
68 var binaryNumber = | 74 var binaryNumber = TEXT(LEX(MANY(OR(['0', '1']))), (str, start, end) { |
69 TEXT(LEX(MANY(OR(['0','1']))), | 75 var r = 0; |
70 (str, start, end) { | 76 var zero = '0'.codeUnitAt(0); |
71 var r = 0; | 77 for (int i = start; i < end; i++) r = r * 2 + (str.codeUnitAt(i) - zero); |
72 var zero = '0'.codeUnitAt(0); | 78 return r; |
73 for (int i = start; i < end; i++) | 79 }); |
74 r = r * 2 + (str.codeUnitAt(i) - zero); | |
75 return r; | |
76 }); | |
77 | 80 |
78 check(g, binaryNumber, ' 10101 ', 21); | 81 check(g, binaryNumber, ' 10101 ', 21); |
79 check(g, binaryNumber, '1010111', 87); | 82 check(g, binaryNumber, '1010111', 87); |
80 check(g, binaryNumber, '1010 111', null); | 83 check(g, binaryNumber, '1010 111', null); |
81 } | 84 } |
82 | 85 |
83 testOR() { | 86 testOR() { |
84 // OR matches the first match. | 87 // OR matches the first match. |
85 Grammar g = new Grammar(); | 88 Grammar g = new Grammar(); |
86 check(g, OR([['a', NOT(END), () => 1], | 89 check( |
87 ['a', () => 2], | 90 g, |
88 ['a', () => 3]]), | 91 OR([ |
89 'a', 2); | 92 ['a', NOT(END), () => 1], |
93 ['a', () => 2], | |
94 ['a', () => 3] | |
95 ]), | |
96 'a', | |
97 2); | |
90 } | 98 } |
91 | 99 |
92 testCODE() { | 100 testCODE() { |
93 Grammar g = new Grammar(); | 101 Grammar g = new Grammar(); |
94 var a = TEXT(LEX('thing', MANY(CHAR('bcd')))); | 102 var a = TEXT(LEX('thing', MANY(CHAR('bcd')))); |
95 | 103 |
96 check(g, a, 'bbb', 'bbb'); | 104 check(g, a, 'bbb', 'bbb'); |
97 check(g, a, 'ccc', 'ccc'); | 105 check(g, a, 'ccc', 'ccc'); |
98 check(g, a, 'ddd', 'ddd'); | 106 check(g, a, 'ddd', 'ddd'); |
99 check(g, a, 'bad', null); // a is outside range. | 107 check(g, a, 'bad', null); // a is outside range. |
100 check(g, a, 'bed', null); // e is outside range. | 108 check(g, a, 'bed', null); // e is outside range. |
101 } | 109 } |
102 | 110 |
103 testC() { | 111 testC() { |
104 // Curried tree builders. | 112 // Curried tree builders. |
105 binary(operation) => (second) => (first) => [operation, first, second]; | 113 binary(operation) => (second) => (first) => [operation, first, second]; |
106 unary(operation) => () => (first) => [operation, first]; | 114 unary(operation) => () => (first) => [operation, first]; |
107 reform(a, fns) { | 115 reform(a, fns) { |
108 var r = a; | 116 var r = a; |
109 for (var fn in fns) | 117 for (var fn in fns) r = fn(r); |
110 r = fn(r); | |
111 return r; | 118 return r; |
112 } | 119 } |
113 | 120 |
114 Grammar g = new Grammar(); | 121 Grammar g = new Grammar(); |
115 | 122 |
116 Symbol expression = g['expression']; | 123 Symbol expression = g['expression']; |
117 Symbol postfix_e = g['postfix_e']; | 124 Symbol postfix_e = g['postfix_e']; |
118 Symbol unary_e = g['unary_e']; | 125 Symbol unary_e = g['unary_e']; |
119 Symbol cast_e = g['cast_e']; | 126 Symbol cast_e = g['cast_e']; |
120 Symbol mult_e = g['mult_e']; | 127 Symbol mult_e = g['mult_e']; |
121 Symbol add_e = g['add_e']; | 128 Symbol add_e = g['add_e']; |
122 Symbol shift_e = g['shift_e']; | 129 Symbol shift_e = g['shift_e']; |
123 Symbol relational_e = g['relational_e']; | 130 Symbol relational_e = g['relational_e']; |
124 Symbol equality_e = g['equality_e']; | 131 Symbol equality_e = g['equality_e']; |
125 Symbol cond_e = g['cond_e']; | 132 Symbol cond_e = g['cond_e']; |
126 Symbol assignment_e = g['assignment_e']; | 133 Symbol assignment_e = g['assignment_e']; |
127 | 134 |
128 // Lexical elements. | 135 // Lexical elements. |
129 var idStartChar = CHAR( | 136 var idStartChar = |
130 r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); | 137 CHAR(r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); |
131 var idNextChar = CHAR( | 138 var idNextChar = |
132 r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_"); | 139 CHAR(r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_"); |
133 | 140 |
134 var id = TEXT(LEX('identifier', [idStartChar, MANY(idNextChar, min: 0)])); | 141 var id = TEXT(LEX('identifier', [idStartChar, MANY(idNextChar, min: 0)])); |
135 | 142 |
136 var lit = TEXT(LEX('literal', MANY(CHAR('0123456789')))); | 143 var lit = TEXT(LEX('literal', MANY(CHAR('0123456789')))); |
137 | 144 |
138 | |
139 var type_name = id; | 145 var type_name = id; |
140 | 146 |
147 // Expression grammar. | |
148 var primary_e = OR([ | |
149 id, | |
150 lit, | |
151 ['(', expression, ')', (e) => e] | |
152 ]); | |
141 | 153 |
142 // Expression grammar. | 154 var postfixes = OR([ |
143 var primary_e = OR([id, | 155 ['(', MANY(assignment_e, separator: ',', min: 0), ')', binary('apply')], |
144 lit, | 156 ['++', unary('postinc')], |
145 ['(', expression, ')', (e) => e] | 157 ['--', unary('postdec')], |
146 ]); | 158 ['.', id, binary('field')], |
159 ['->', id, binary('ptr')], | |
160 ]); | |
147 | 161 |
148 var postfixes = OR([['(', MANY(assignment_e, separator: ',', min: 0), ')', bin ary('apply')], | 162 postfix_e.def = [primary_e, MANY(postfixes, min: 0), reform]; |
149 ['++', unary('postinc')], | |
150 ['--', unary('postdec')], | |
151 ['.', id, binary('field')], | |
152 ['->', id, binary('ptr')], | |
153 ]); | |
154 | 163 |
155 postfix_e.def = [primary_e, MANY(postfixes, min:0), reform]; | 164 var unary_op = OR([ |
156 | 165 ['&', () => 'address'], |
157 | 166 ['*', () => 'indir'], |
158 var unary_op = OR([['&', () => 'address'], | 167 ['!', () => 'not'], |
159 ['*', () => 'indir'], | 168 ['~', () => 'not'], |
160 ['!', () => 'not'], | 169 ['-', () => 'negate'], |
161 ['~', () => 'not'], | 170 ['+', () => 'uplus'], |
162 ['-', () => 'negate'], | 171 ]); |
163 ['+', () => 'uplus'], | |
164 ]); | |
165 var sizeof = LEX('sizeof', ['sizeof', NOT(idNextChar)]); | 172 var sizeof = LEX('sizeof', ['sizeof', NOT(idNextChar)]); |
166 | 173 |
167 Symbol unary_e_plain = g['unary_e_plain']; | 174 Symbol unary_e_plain = g['unary_e_plain']; |
168 unary_e_plain.def = | 175 unary_e_plain.def = OR([ |
169 OR([ ['++', unary_e, (e) => ['preinc', e]], | 176 [ |
170 ['--', unary_e, (e) => ['predec', e]], | 177 '++', |
171 [unary_op, cast_e, (o, e) => [o, e]], | 178 unary_e, |
172 [sizeof, unary_e, (e) => ['sizeof-expr', e]], | 179 (e) => ['preinc', e] |
173 [sizeof, '(', type_name , ')', (t) => ['sizeof-type', t]], | 180 ], |
174 postfix_e | 181 [ |
175 ]); | 182 '--', |
183 unary_e, | |
184 (e) => ['predec', e] | |
185 ], | |
186 [ | |
187 unary_op, | |
188 cast_e, | |
189 (o, e) => [o, e] | |
190 ], | |
191 [ | |
192 sizeof, | |
193 unary_e, | |
194 (e) => ['sizeof-expr', e] | |
195 ], | |
196 [ | |
197 sizeof, | |
198 '(', | |
199 type_name, | |
200 ')', | |
201 (t) => ['sizeof-type', t] | |
202 ], | |
203 postfix_e | |
204 ]); | |
terry
2017/04/20 13:16:37
Ugh!, old not dartfmt was easier to grasp.
Jacob
2017/04/20 15:33:14
I agree this is not ideal. Added // comments to ma
| |
176 | 205 |
177 unary_e.def = MEMO(unary_e_plain); | 206 unary_e.def = MEMO(unary_e_plain); |
178 //unary_e.def = unary_e_plain; | 207 //unary_e.def = unary_e_plain; |
179 | 208 |
180 cast_e.def = OR([ ['(', type_name, ')', cast_e, (t, e) => ['cast', t, e]], | 209 cast_e.def = OR([ |
181 unary_e, | 210 [ |
182 ]); | 211 '(', |
212 type_name, | |
213 ')', | |
214 cast_e, | |
215 (t, e) => ['cast', t, e] | |
216 ], | |
217 unary_e, | |
218 ]); | |
183 | 219 |
184 var mult_ops = OR([['*', cast_e, binary('mult')], | 220 var mult_ops = OR([ |
185 ['/', cast_e, binary('div')], | 221 ['*', cast_e, binary('mult')], |
186 ['%', cast_e, binary('rem')], | 222 ['/', cast_e, binary('div')], |
187 ]); | 223 ['%', cast_e, binary('rem')], |
188 mult_e.def = [cast_e, MANY(mult_ops, min:0), reform]; | 224 ]); |
225 mult_e.def = [cast_e, MANY(mult_ops, min: 0), reform]; | |
189 | 226 |
190 var add_ops = OR([['+', mult_e, binary('add')], | 227 var add_ops = OR([ |
191 ['-', mult_e, binary('sub')], | 228 ['+', mult_e, binary('add')], |
192 ]); | 229 ['-', mult_e, binary('sub')], |
193 add_e.def = [mult_e, MANY(add_ops, min:0), reform]; | 230 ]); |
231 add_e.def = [mult_e, MANY(add_ops, min: 0), reform]; | |
194 | 232 |
195 var shift_ops = OR([['>>', add_e, binary('shl')], | 233 var shift_ops = OR([ |
196 ['<<', add_e, binary('shr')], | 234 ['>>', add_e, binary('shl')], |
197 ]); | 235 ['<<', add_e, binary('shr')], |
198 shift_e.def = [add_e, MANY(shift_ops, min:0), reform]; | 236 ]); |
237 shift_e.def = [add_e, MANY(shift_ops, min: 0), reform]; | |
199 | 238 |
200 var relational_ops = OR([['<=', shift_e, binary('le')], | 239 var relational_ops = OR([ |
201 ['>=', shift_e, binary('ge')], | 240 ['<=', shift_e, binary('le')], |
202 ['<', shift_e, binary('lt')], | 241 ['>=', shift_e, binary('ge')], |
203 ['>', shift_e, binary('gt')], | 242 ['<', shift_e, binary('lt')], |
204 ]); | 243 ['>', shift_e, binary('gt')], |
205 relational_e.def = [shift_e, MANY(relational_ops, min:0), reform]; | 244 ]); |
245 relational_e.def = [shift_e, MANY(relational_ops, min: 0), reform]; | |
206 | 246 |
247 var equality_ops = OR([ | |
248 ['==', shift_e, binary('eq')], | |
249 ['!=', shift_e, binary('ne')], | |
250 ]); | |
251 equality_e.def = [relational_e, MANY(equality_ops, min: 0), reform]; | |
207 | 252 |
208 var equality_ops = OR([['==', shift_e, binary('eq')], | 253 var bit_and_op = LEX('&', ['&', NOT('&')]); // Don't see '&&' and '&', '&' |
209 ['!=', shift_e, binary('ne')], | |
210 ]); | |
211 equality_e.def = [relational_e, MANY(equality_ops, min:0), reform]; | |
212 | |
213 | |
214 var bit_and_op = LEX('&', ['&', NOT('&')]); // Don't see '&&' and '&', '&' | |
215 var bit_or_op = LEX('|', ['|', NOT('|')]); | 254 var bit_or_op = LEX('|', ['|', NOT('|')]); |
216 | 255 |
217 var and_e = [equality_e, MANY([bit_and_op, equality_e, binary('bitand')], min: 0), reform]; | 256 var and_e = [ |
218 var xor_e = [and_e, MANY(['^', and_e, binary('bitxor')], min:0), reform]; | 257 equality_e, |
219 var or_e = [xor_e, MANY([bit_or_op, xor_e, binary('bitor')], min:0), reform]; | 258 MANY([bit_and_op, equality_e, binary('bitand')], min: 0), |
259 reform | |
260 ]; | |
261 var xor_e = [ | |
262 and_e, | |
263 MANY(['^', and_e, binary('bitxor')], min: 0), | |
264 reform | |
265 ]; | |
266 var or_e = [ | |
267 xor_e, | |
268 MANY([bit_or_op, xor_e, binary('bitor')], min: 0), | |
269 reform | |
270 ]; | |
220 | 271 |
221 var log_and_e = [or_e, MANY(['&&', or_e, binary('and')], min:0), reform]; | 272 var log_and_e = [ |
273 or_e, | |
274 MANY(['&&', or_e, binary('and')], min: 0), | |
275 reform | |
276 ]; | |
222 | 277 |
223 var log_or_e = [log_and_e, MANY(['||', log_and_e, binary('or')], min:0), refor m]; | 278 var log_or_e = [ |
279 log_and_e, | |
280 MANY(['||', log_and_e, binary('or')], min: 0), | |
281 reform | |
282 ]; | |
224 | 283 |
225 //cond_e.def = OR([ [log_or_e, '?', expression, ':', cond_e, | 284 //cond_e.def = OR([ [log_or_e, '?', expression, ':', cond_e, |
226 // (p,a,b) => ['cond', p, a, b]], | 285 // (p,a,b) => ['cond', p, a, b]], |
227 // log_or_e]); | 286 // log_or_e]); |
228 // Alternate version avoids reparsing log_or_e. | 287 // Alternate version avoids reparsing log_or_e. |
229 cond_e.def = [log_or_e, MAYBE(['?', expression, ':', cond_e]), | 288 cond_e.def = [ |
230 (p, r) => r == null || r == false ? p : ['cond', p, r[0], r[1]]] ; | 289 log_or_e, |
290 MAYBE(['?', expression, ':', cond_e]), | |
291 (p, r) => r == null || r == false ? p : ['cond', p, r[0], r[1]] | |
292 ]; | |
231 | 293 |
232 var assign_op = OR([['*=', () => 'mulassign'], | 294 var assign_op = OR([ |
233 ['=', () => 'assign']]); | 295 ['*=', () => 'mulassign'], |
296 ['=', () => 'assign'] | |
297 ]); | |
234 | 298 |
235 // TODO: Figure out how not to re-parse a unary_e. | 299 // TODO: Figure out how not to re-parse a unary_e. |
236 // Order matters - cond_e can't go first since cond_e will succeed on, e.g. 'a '. | 300 // Order matters - cond_e can't go first since cond_e will succeed on, e.g. 'a '. |
237 assignment_e.def = OR([[unary_e, assign_op, assignment_e, | 301 assignment_e.def = OR([ |
238 (u, op, a) => [op, u, a]], | 302 [ |
239 cond_e]); | 303 unary_e, |
304 assign_op, | |
305 assignment_e, | |
306 (u, op, a) => [op, u, a] | |
307 ], | |
308 cond_e | |
309 ]); | |
240 | 310 |
241 expression.def = [assignment_e, | 311 expression.def = [ |
242 MANY([',', assignment_e, binary('comma')], min:0), | 312 assignment_e, |
243 reform]; | 313 MANY([',', assignment_e, binary('comma')], min: 0), |
314 reform | |
315 ]; | |
244 | 316 |
245 show(g, expression, 'a'); | 317 show(g, expression, 'a'); |
246 check(g, expression, 'a', 'a'); | 318 check(g, expression, 'a', 'a'); |
247 check(g, expression, '(a)', 'a'); | 319 check(g, expression, '(a)', 'a'); |
248 check(g, expression, ' ( ( a ) ) ', 'a'); | 320 check(g, expression, ' ( ( a ) ) ', 'a'); |
249 | 321 |
250 check(g, expression, 'a(~1,2)', '[apply,a,[[not,1],2]]'); | 322 check(g, expression, 'a(~1,2)', '[apply,a,[[not,1],2]]'); |
251 check(g, expression, 'a(1)(x,2)', '[apply,[apply,a,[1]],[x,2]]'); | 323 check(g, expression, 'a(1)(x,2)', '[apply,[apply,a,[1]],[x,2]]'); |
252 check(g, expression, 'a(1,2())', '[apply,a,[1,[apply,2,[]]]]'); | 324 check(g, expression, 'a(1,2())', '[apply,a,[1,[apply,2,[]]]]'); |
253 | 325 |
254 check(g, expression, '++a++', '[preinc,[postinc,a]]'); | 326 check(g, expression, '++a++', '[preinc,[postinc,a]]'); |
255 check(g, expression, 'a++++b', null); | 327 check(g, expression, 'a++++b', null); |
256 check(g, expression, 'a++ ++b', null); | 328 check(g, expression, 'a++ ++b', null); |
257 check(g, expression, 'a+ +++b', '[add,a,[preinc,[uplus,b]]]'); | 329 check(g, expression, 'a+ +++b', '[add,a,[preinc,[uplus,b]]]'); |
258 check(g, expression, 'a+ + ++b', '[add,a,[uplus,[preinc,b]]]'); | 330 check(g, expression, 'a+ + ++b', '[add,a,[uplus,[preinc,b]]]'); |
259 check(g, expression, 'a+ + + +b', '[add,a,[uplus,[uplus,[uplus,b]]]]'); | 331 check(g, expression, 'a+ + + +b', '[add,a,[uplus,[uplus,[uplus,b]]]]'); |
260 check(g, expression, 'a+ ++ +b', '[add,a,[preinc,[uplus,b]]]'); | 332 check(g, expression, 'a+ ++ +b', '[add,a,[preinc,[uplus,b]]]'); |
261 check(g, expression, 'a++ + +b', '[add,[postinc,a],[uplus,b]]'); | 333 check(g, expression, 'a++ + +b', '[add,[postinc,a],[uplus,b]]'); |
262 check(g, expression, 'a+++ +b', '[add,[postinc,a],[uplus,b]]'); | 334 check(g, expression, 'a+++ +b', '[add,[postinc,a],[uplus,b]]'); |
263 | 335 |
264 check(g, expression, '((T)f)(x)', '[apply,[cast,T,f],[x]]'); | 336 check(g, expression, '((T)f)(x)', '[apply,[cast,T,f],[x]]'); |
265 check(g, expression, '(T)f(x)', '[cast,T,[apply,f,[x]]]'); | 337 check(g, expression, '(T)f(x)', '[cast,T,[apply,f,[x]]]'); |
266 | 338 |
267 check(g, expression, 'a++*++b', '[mult,[postinc,a],[preinc,b]]'); | 339 check(g, expression, 'a++*++b', '[mult,[postinc,a],[preinc,b]]'); |
268 | 340 |
269 check(g, expression, 'a<<1>>++b', '[shl,[shr,a,1],[preinc,b]]'); | 341 check(g, expression, 'a<<1>>++b', '[shl,[shr,a,1],[preinc,b]]'); |
270 | 342 |
271 check(g, expression, 'a<1&&b', '[and,[lt,a,1],b]'); | 343 check(g, expression, 'a<1&&b', '[and,[lt,a,1],b]'); |
272 | 344 |
273 check(g, expression, 'a<1 & &b', '[bitand,[lt,a,1],[address,b]]'); | 345 check(g, expression, 'a<1 & &b', '[bitand,[lt,a,1],[address,b]]'); |
274 check(g, expression, | 346 check(g, expression, 'a ? b ? c : d : e ? f : g', |
275 'a ? b ? c : d : e ? f : g', | 347 '[cond,a,[cond,b,c,d],[cond,e,f,g]]'); |
276 '[cond,a,[cond,b,c,d],[cond,e,f,g]]'); | |
277 | 348 |
278 check(g, expression, 'a,b,c', '[comma,[comma,a,b],c]'); | 349 check(g, expression, 'a,b,c', '[comma,[comma,a,b],c]'); |
279 check(g, expression, 'a=1,b,c', '[comma,[comma,[assign,a,1],b],c]'); | 350 check(g, expression, 'a=1,b,c', '[comma,[comma,[assign,a,1],b],c]'); |
280 | 351 |
281 check(g, expression, | 352 check(g, expression, '((((((((((((a))))))))))))=1,b,c', |
282 '((((((((((((a))))))))))))=1,b,c', '[comma,[comma,[assign,a,1],b],c]'); | 353 '[comma,[comma,[assign,a,1],b],c]'); |
283 | 354 |
284 check(g, expression, 'sizeof a', '[sizeof-expr,a]'); | 355 check(g, expression, 'sizeof a', '[sizeof-expr,a]'); |
285 check(g, expression, 'sizeofa', 'sizeofa'); | 356 check(g, expression, 'sizeofa', 'sizeofa'); |
286 check(g, expression, 'sizeof (a)', '[sizeof-expr,a]'); | 357 check(g, expression, 'sizeof (a)', '[sizeof-expr,a]'); |
287 } | 358 } |
288 | 359 |
289 | |
290 show(grammar, rule, input) { | 360 show(grammar, rule, input) { |
291 print('show: "$input"'); | 361 print('show: "$input"'); |
292 var ast; | 362 var ast; |
293 try { | 363 try { |
294 ast = grammar.parse(rule, input); | 364 ast = grammar.parse(rule, input); |
295 } catch (exception) { | 365 } catch (exception) { |
296 if (exception is ParseError) | 366 if (exception is ParseError) |
297 ast = exception; | 367 ast = exception; |
298 else | 368 else |
299 rethrow; | 369 rethrow; |
300 } | 370 } |
301 print('${printList(ast)}'); | 371 print('${printList(ast)}'); |
302 } | 372 } |
303 | 373 |
304 void check(grammar, rule, input, expected) { | 374 void check(grammar, rule, input, expected) { |
305 // If [expected] is String then the result is coerced to string. | 375 // If [expected] is String then the result is coerced to string. |
306 // If [expected] is !String, the result is compared directly. | 376 // If [expected] is !String, the result is compared directly. |
307 print('check: "$input"'); | 377 print('check: "$input"'); |
308 var ast; | 378 var ast; |
309 try { | 379 try { |
310 ast = grammar.parse(rule, input); | 380 ast = grammar.parse(rule, input); |
311 } catch (exception) { | 381 } catch (exception) { |
312 ast = exception; | 382 ast = exception; |
313 } | 383 } |
314 | 384 |
315 var formatted = ast; | 385 var formatted = ast; |
316 if (expected is String) | 386 if (expected is String) formatted = printList(ast); |
317 formatted = printList(ast); | |
318 | 387 |
319 //Expect.equals(expected, formatted, "parse: $input"); | 388 //Expect.equals(expected, formatted, "parse: $input"); |
320 if (expected != formatted) { | 389 if (expected != formatted) { |
321 throw new ArgumentError( | 390 throw new ArgumentError("parse: $input" |
322 "parse: $input" | |
323 "\n expected: $expected" | 391 "\n expected: $expected" |
324 "\n found: $formatted"); | 392 "\n found: $formatted"); |
325 } | 393 } |
326 } | 394 } |
327 | 395 |
328 // Prints the list in [1,2,3] notation, including nested lists. | 396 // Prints the list in [1,2,3] notation, including nested lists. |
329 printList(item) { | 397 printList(item) { |
330 if (item is List) { | 398 if (item is List) { |
331 StringBuffer sb = new StringBuffer(); | 399 StringBuffer sb = new StringBuffer(); |
332 sb.write('['); | 400 sb.write('['); |
333 var sep = ''; | 401 var sep = ''; |
334 for (var x in item) { | 402 for (var x in item) { |
335 sb.write(sep); | 403 sb.write(sep); |
336 sb.write(printList(x)); | 404 sb.write(printList(x)); |
337 sep = ','; | 405 sep = ','; |
338 } | 406 } |
339 sb.write(']'); | 407 sb.write(']'); |
340 return sb.toString(); | 408 return sb.toString(); |
341 } | 409 } |
342 if (item == null) | 410 if (item == null) return 'null'; |
343 return 'null'; | |
344 return item.toString(); | 411 return item.toString(); |
345 } | 412 } |
346 | 413 |
347 main() { | 414 main() { |
348 testCODE(); | 415 testCODE(); |
349 testParens(); | 416 testParens(); |
350 testOR(); | 417 testOR(); |
351 testTEXT(); | 418 testTEXT(); |
352 testBlockComment(); | 419 testBlockComment(); |
353 testC(); | 420 testC(); |
354 } | 421 } |
OLD | NEW |