| 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       '++', unary_e, (e) => ['preinc', e] // | 
| 171            [unary_op, cast_e, (o, e) => [o, e]], | 178     ], | 
| 172            [sizeof, unary_e, (e) => ['sizeof-expr', e]], | 179     [ | 
| 173            [sizeof, '(', type_name , ')', (t) => ['sizeof-type', t]], | 180       '--', unary_e, (e) => ['predec', e] // | 
| 174            postfix_e | 181     ], | 
| 175            ]); | 182     [ | 
|  | 183       unary_op, cast_e, (o, e) => [o, e] // | 
|  | 184     ], | 
|  | 185     [ | 
|  | 186       sizeof, unary_e, (e) => ['sizeof-expr', e] // | 
|  | 187     ], | 
|  | 188     [ | 
|  | 189       sizeof, '(', type_name, ')', (t) => ['sizeof-type', t] // | 
|  | 190     ], | 
|  | 191     postfix_e | 
|  | 192   ]); | 
| 176 | 193 | 
| 177   unary_e.def = MEMO(unary_e_plain); | 194   unary_e.def = MEMO(unary_e_plain); | 
| 178   //unary_e.def = unary_e_plain; | 195   //unary_e.def = unary_e_plain; | 
| 179 | 196 | 
| 180   cast_e.def = OR([ ['(', type_name, ')', cast_e, (t, e) => ['cast', t, e]], | 197   cast_e.def = OR([ | 
| 181                     unary_e, | 198     [ | 
| 182                          ]); | 199       '(', type_name, ')', cast_e, (t, e) => ['cast', t, e] // | 
|  | 200     ], | 
|  | 201     unary_e, | 
|  | 202   ]); | 
| 183 | 203 | 
| 184   var mult_ops = OR([['*', cast_e, binary('mult')], | 204   var mult_ops = OR([ | 
| 185                      ['/', cast_e, binary('div')], | 205     ['*', cast_e, binary('mult')], | 
| 186                      ['%', cast_e, binary('rem')], | 206     ['/', cast_e, binary('div')], | 
| 187                      ]); | 207     ['%', cast_e, binary('rem')], | 
| 188   mult_e.def = [cast_e, MANY(mult_ops, min:0), reform]; | 208   ]); | 
|  | 209   mult_e.def = [cast_e, MANY(mult_ops, min: 0), reform]; | 
| 189 | 210 | 
| 190   var add_ops = OR([['+', mult_e, binary('add')], | 211   var add_ops = OR([ | 
| 191                     ['-', mult_e, binary('sub')], | 212     ['+', mult_e, binary('add')], | 
| 192                     ]); | 213     ['-', mult_e, binary('sub')], | 
| 193   add_e.def = [mult_e, MANY(add_ops, min:0), reform]; | 214   ]); | 
|  | 215   add_e.def = [mult_e, MANY(add_ops, min: 0), reform]; | 
| 194 | 216 | 
| 195   var shift_ops = OR([['>>', add_e, binary('shl')], | 217   var shift_ops = OR([ | 
| 196                       ['<<', add_e, binary('shr')], | 218     ['>>', add_e, binary('shl')], | 
| 197                       ]); | 219     ['<<', add_e, binary('shr')], | 
| 198   shift_e.def = [add_e, MANY(shift_ops, min:0), reform]; | 220   ]); | 
|  | 221   shift_e.def = [add_e, MANY(shift_ops, min: 0), reform]; | 
| 199 | 222 | 
| 200   var relational_ops = OR([['<=', shift_e, binary('le')], | 223   var relational_ops = OR([ | 
| 201                            ['>=', shift_e, binary('ge')], | 224     ['<=', shift_e, binary('le')], | 
| 202                            ['<', shift_e, binary('lt')], | 225     ['>=', shift_e, binary('ge')], | 
| 203                            ['>', shift_e, binary('gt')], | 226     ['<', shift_e, binary('lt')], | 
| 204                            ]); | 227     ['>', shift_e, binary('gt')], | 
| 205   relational_e.def = [shift_e, MANY(relational_ops, min:0), reform]; | 228   ]); | 
|  | 229   relational_e.def = [shift_e, MANY(relational_ops, min: 0), reform]; | 
| 206 | 230 | 
|  | 231   var equality_ops = OR([ | 
|  | 232     ['==', shift_e, binary('eq')], | 
|  | 233     ['!=', shift_e, binary('ne')], | 
|  | 234   ]); | 
|  | 235   equality_e.def = [relational_e, MANY(equality_ops, min: 0), reform]; | 
| 207 | 236 | 
| 208   var equality_ops = OR([['==', shift_e, binary('eq')], | 237   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('|')]); | 238   var bit_or_op = LEX('|', ['|', NOT('|')]); | 
| 216 | 239 | 
| 217   var and_e = [equality_e, MANY([bit_and_op, equality_e, binary('bitand')], min:
     0), reform]; | 240   var and_e = [ | 
| 218   var xor_e = [and_e, MANY(['^', and_e, binary('bitxor')], min:0), reform]; | 241     equality_e, | 
| 219   var or_e = [xor_e, MANY([bit_or_op, xor_e, binary('bitor')], min:0), reform]; | 242     MANY([bit_and_op, equality_e, binary('bitand')], min: 0), | 
|  | 243     reform | 
|  | 244   ]; | 
|  | 245   var xor_e = [ | 
|  | 246     and_e, | 
|  | 247     MANY(['^', and_e, binary('bitxor')], min: 0), | 
|  | 248     reform | 
|  | 249   ]; | 
|  | 250   var or_e = [ | 
|  | 251     xor_e, | 
|  | 252     MANY([bit_or_op, xor_e, binary('bitor')], min: 0), | 
|  | 253     reform | 
|  | 254   ]; | 
| 220 | 255 | 
| 221   var log_and_e = [or_e, MANY(['&&', or_e, binary('and')], min:0), reform]; | 256   var log_and_e = [ | 
|  | 257     or_e, | 
|  | 258     MANY(['&&', or_e, binary('and')], min: 0), | 
|  | 259     reform | 
|  | 260   ]; | 
| 222 | 261 | 
| 223   var log_or_e = [log_and_e, MANY(['||', log_and_e, binary('or')], min:0), refor
     m]; | 262   var log_or_e = [ | 
|  | 263     log_and_e, | 
|  | 264     MANY(['||', log_and_e, binary('or')], min: 0), | 
|  | 265     reform | 
|  | 266   ]; | 
| 224 | 267 | 
| 225   //cond_e.def = OR([ [log_or_e, '?', expression, ':', cond_e, | 268   //cond_e.def = OR([ [log_or_e, '?', expression, ':', cond_e, | 
| 226   //                   (p,a,b) => ['cond', p, a, b]], | 269   //                   (p,a,b) => ['cond', p, a, b]], | 
| 227   //                  log_or_e]); | 270   //                  log_or_e]); | 
| 228   // Alternate version avoids reparsing log_or_e. | 271   // Alternate version avoids reparsing log_or_e. | 
| 229   cond_e.def = [log_or_e, MAYBE(['?', expression, ':', cond_e]), | 272   cond_e.def = [ | 
| 230                 (p, r) => r == null || r == false ? p : ['cond', p, r[0], r[1]]]
     ; | 273     log_or_e, | 
|  | 274     MAYBE(['?', expression, ':', cond_e]), | 
|  | 275     (p, r) => r == null || r == false ? p : ['cond', p, r[0], r[1]] | 
|  | 276   ]; | 
| 231 | 277 | 
| 232   var assign_op = OR([['*=', () => 'mulassign'], | 278   var assign_op = OR([ | 
| 233                       ['=', () => 'assign']]); | 279     ['*=', () => 'mulassign'], | 
|  | 280     ['=', () => 'assign'] | 
|  | 281   ]); | 
| 234 | 282 | 
| 235   // TODO: Figure out how not to re-parse a unary_e. | 283   // 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
     '. | 284   // 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, | 285   assignment_e.def = OR([ | 
| 238                           (u, op, a) => [op, u, a]], | 286     [ | 
| 239                          cond_e]); | 287       unary_e, | 
|  | 288       assign_op, | 
|  | 289       assignment_e, | 
|  | 290       (u, op, a) => [op, u, a] | 
|  | 291     ], | 
|  | 292     cond_e | 
|  | 293   ]); | 
| 240 | 294 | 
| 241   expression.def = [assignment_e, | 295   expression.def = [ | 
| 242                     MANY([',', assignment_e, binary('comma')], min:0), | 296     assignment_e, | 
| 243                     reform]; | 297     MANY([',', assignment_e, binary('comma')], min: 0), | 
|  | 298     reform | 
|  | 299   ]; | 
| 244 | 300 | 
| 245   show(g, expression, 'a'); | 301   show(g, expression, 'a'); | 
| 246   check(g, expression, 'a', 'a'); | 302   check(g, expression, 'a', 'a'); | 
| 247   check(g, expression, '(a)', 'a'); | 303   check(g, expression, '(a)', 'a'); | 
| 248   check(g, expression, '  (  ( a ) ) ', 'a'); | 304   check(g, expression, '  (  ( a ) ) ', 'a'); | 
| 249 | 305 | 
| 250   check(g, expression, 'a(~1,2)',  '[apply,a,[[not,1],2]]'); | 306   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]]'); | 307   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,[]]]]'); | 308   check(g, expression, 'a(1,2())', '[apply,a,[1,[apply,2,[]]]]'); | 
| 253 | 309 | 
| 254   check(g, expression, '++a++', '[preinc,[postinc,a]]'); | 310   check(g, expression, '++a++', '[preinc,[postinc,a]]'); | 
| 255   check(g, expression, 'a++++b', null); | 311   check(g, expression, 'a++++b', null); | 
| 256   check(g, expression, 'a++ ++b', null); | 312   check(g, expression, 'a++ ++b', null); | 
| 257   check(g, expression, 'a+ +++b', '[add,a,[preinc,[uplus,b]]]'); | 313   check(g, expression, 'a+ +++b', '[add,a,[preinc,[uplus,b]]]'); | 
| 258   check(g, expression, 'a+ + ++b', '[add,a,[uplus,[preinc,b]]]'); | 314   check(g, expression, 'a+ + ++b', '[add,a,[uplus,[preinc,b]]]'); | 
| 259   check(g, expression, 'a+ + + +b', '[add,a,[uplus,[uplus,[uplus,b]]]]'); | 315   check(g, expression, 'a+ + + +b', '[add,a,[uplus,[uplus,[uplus,b]]]]'); | 
| 260   check(g, expression, 'a+ ++ +b', '[add,a,[preinc,[uplus,b]]]'); | 316   check(g, expression, 'a+ ++ +b', '[add,a,[preinc,[uplus,b]]]'); | 
| 261   check(g, expression, 'a++ + +b', '[add,[postinc,a],[uplus,b]]'); | 317   check(g, expression, 'a++ + +b', '[add,[postinc,a],[uplus,b]]'); | 
| 262   check(g, expression, 'a+++ +b', '[add,[postinc,a],[uplus,b]]'); | 318   check(g, expression, 'a+++ +b', '[add,[postinc,a],[uplus,b]]'); | 
| 263 | 319 | 
| 264   check(g, expression, '((T)f)(x)', '[apply,[cast,T,f],[x]]'); | 320   check(g, expression, '((T)f)(x)', '[apply,[cast,T,f],[x]]'); | 
| 265   check(g, expression, '(T)f(x)', '[cast,T,[apply,f,[x]]]'); | 321   check(g, expression, '(T)f(x)', '[cast,T,[apply,f,[x]]]'); | 
| 266 | 322 | 
| 267   check(g, expression, 'a++*++b', '[mult,[postinc,a],[preinc,b]]'); | 323   check(g, expression, 'a++*++b', '[mult,[postinc,a],[preinc,b]]'); | 
| 268 | 324 | 
| 269   check(g, expression, 'a<<1>>++b', '[shl,[shr,a,1],[preinc,b]]'); | 325   check(g, expression, 'a<<1>>++b', '[shl,[shr,a,1],[preinc,b]]'); | 
| 270 | 326 | 
| 271   check(g, expression, 'a<1&&b', '[and,[lt,a,1],b]'); | 327   check(g, expression, 'a<1&&b', '[and,[lt,a,1],b]'); | 
| 272 | 328 | 
| 273   check(g, expression, 'a<1 & &b', '[bitand,[lt,a,1],[address,b]]'); | 329   check(g, expression, 'a<1 & &b', '[bitand,[lt,a,1],[address,b]]'); | 
| 274   check(g, expression, | 330   check(g, expression, 'a ? b ? c : d : e ? f : g', | 
| 275         'a ? b ? c : d : e ? f : g', | 331       '[cond,a,[cond,b,c,d],[cond,e,f,g]]'); | 
| 276         '[cond,a,[cond,b,c,d],[cond,e,f,g]]'); |  | 
| 277 | 332 | 
| 278   check(g, expression, 'a,b,c', '[comma,[comma,a,b],c]'); | 333   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]'); | 334   check(g, expression, 'a=1,b,c', '[comma,[comma,[assign,a,1],b],c]'); | 
| 280 | 335 | 
| 281   check(g, expression, | 336   check(g, expression, '((((((((((((a))))))))))))=1,b,c', | 
| 282         '((((((((((((a))))))))))))=1,b,c', '[comma,[comma,[assign,a,1],b],c]'); | 337       '[comma,[comma,[assign,a,1],b],c]'); | 
| 283 | 338 | 
| 284   check(g, expression, 'sizeof a', '[sizeof-expr,a]'); | 339   check(g, expression, 'sizeof a', '[sizeof-expr,a]'); | 
| 285   check(g, expression, 'sizeofa', 'sizeofa'); | 340   check(g, expression, 'sizeofa', 'sizeofa'); | 
| 286   check(g, expression, 'sizeof (a)', '[sizeof-expr,a]'); | 341   check(g, expression, 'sizeof (a)', '[sizeof-expr,a]'); | 
| 287 } | 342 } | 
| 288 | 343 | 
| 289 |  | 
| 290 show(grammar, rule, input) { | 344 show(grammar, rule, input) { | 
| 291   print('show: "$input"'); | 345   print('show: "$input"'); | 
| 292   var ast; | 346   var ast; | 
| 293   try { | 347   try { | 
| 294     ast = grammar.parse(rule, input); | 348     ast = grammar.parse(rule, input); | 
| 295   } catch (exception) { | 349   } catch (exception) { | 
| 296     if (exception is ParseError) | 350     if (exception is ParseError) | 
| 297       ast = exception; | 351       ast = exception; | 
| 298     else | 352     else | 
| 299       rethrow; | 353       rethrow; | 
| 300   } | 354   } | 
| 301   print('${printList(ast)}'); | 355   print('${printList(ast)}'); | 
| 302 } | 356 } | 
| 303 | 357 | 
| 304 void check(grammar, rule, input, expected) { | 358 void check(grammar, rule, input, expected) { | 
| 305   // If [expected] is String then the result is coerced to string. | 359   // If [expected] is String then the result is coerced to string. | 
| 306   // If [expected] is !String, the result is compared directly. | 360   // If [expected] is !String, the result is compared directly. | 
| 307   print('check: "$input"'); | 361   print('check: "$input"'); | 
| 308   var ast; | 362   var ast; | 
| 309   try { | 363   try { | 
| 310     ast = grammar.parse(rule, input); | 364     ast = grammar.parse(rule, input); | 
| 311   } catch (exception) { | 365   } catch (exception) { | 
| 312     ast = exception; | 366     ast = exception; | 
| 313   } | 367   } | 
| 314 | 368 | 
| 315   var formatted = ast; | 369   var formatted = ast; | 
| 316   if (expected is String) | 370   if (expected is String) formatted = printList(ast); | 
| 317     formatted = printList(ast); |  | 
| 318 | 371 | 
| 319   //Expect.equals(expected, formatted, "parse: $input"); | 372   //Expect.equals(expected, formatted, "parse: $input"); | 
| 320   if (expected != formatted) { | 373   if (expected != formatted) { | 
| 321     throw new ArgumentError( | 374     throw new ArgumentError("parse: $input" | 
| 322         "parse: $input" |  | 
| 323         "\n  expected: $expected" | 375         "\n  expected: $expected" | 
| 324         "\n     found: $formatted"); | 376         "\n     found: $formatted"); | 
| 325   } | 377   } | 
| 326 } | 378 } | 
| 327 | 379 | 
| 328 // Prints the list in [1,2,3] notation, including nested lists. | 380 // Prints the list in [1,2,3] notation, including nested lists. | 
| 329 printList(item) { | 381 printList(item) { | 
| 330   if (item is List) { | 382   if (item is List) { | 
| 331     StringBuffer sb = new StringBuffer(); | 383     StringBuffer sb = new StringBuffer(); | 
| 332     sb.write('['); | 384     sb.write('['); | 
| 333     var sep = ''; | 385     var sep = ''; | 
| 334     for (var x in item) { | 386     for (var x in item) { | 
| 335       sb.write(sep); | 387       sb.write(sep); | 
| 336       sb.write(printList(x)); | 388       sb.write(printList(x)); | 
| 337       sep = ','; | 389       sep = ','; | 
| 338     } | 390     } | 
| 339     sb.write(']'); | 391     sb.write(']'); | 
| 340     return sb.toString(); | 392     return sb.toString(); | 
| 341   } | 393   } | 
| 342   if (item == null) | 394   if (item == null) return 'null'; | 
| 343     return 'null'; |  | 
| 344   return item.toString(); | 395   return item.toString(); | 
| 345 } | 396 } | 
| 346 | 397 | 
| 347 main() { | 398 main() { | 
| 348   testCODE(); | 399   testCODE(); | 
| 349   testParens(); | 400   testParens(); | 
| 350   testOR(); | 401   testOR(); | 
| 351   testTEXT(); | 402   testTEXT(); | 
| 352   testBlockComment(); | 403   testBlockComment(); | 
| 353   testC(); | 404   testC(); | 
| 354 } | 405 } | 
| OLD | NEW | 
|---|