Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: pkg/dev_compiler/lib/src/js_ast/builder.dart

Issue 2752163002: Format all dart dev compiler files (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/dev_compiler/lib/src/js_ast/characters.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // Utilities for building JS ASTs at runtime. Contains a builder class 5 // Utilities for building JS ASTs at runtime. Contains a builder class
6 // and a parser that parses part of the language. 6 // and a parser that parses part of the language.
7 7
8 part of js_ast; 8 part of js_ast;
9 9
10
11 /** 10 /**
12 * Global template manager. We should aim to have a fixed number of 11 * Global template manager. We should aim to have a fixed number of
13 * templates. This implies that we do not use js('xxx') to parse text that is 12 * templates. This implies that we do not use js('xxx') to parse text that is
14 * constructed from values that depend on names in the Dart program. 13 * constructed from values that depend on names in the Dart program.
15 * 14 *
16 * TODO(sra): Find the remaining places where js('xxx') used to parse an 15 * TODO(sra): Find the remaining places where js('xxx') used to parse an
17 * unbounded number of expression, or institute a cache policy. 16 * unbounded number of expression, or institute a cache policy.
18 */ 17 */
19 TemplateManager templateManager = new TemplateManager(); 18 TemplateManager templateManager = new TemplateManager();
20 19
21
22 /** 20 /**
23 21
24 [js] is a singleton instace of JsBuilder. JsBuilder is a set of conveniences 22 [js] is a singleton instace of JsBuilder. JsBuilder is a set of conveniences
25 for constructing JavaScript ASTs. 23 for constructing JavaScript ASTs.
26 24
27 [string] and [number] are used to create leaf AST nodes: 25 [string] and [number] are used to create leaf AST nodes:
28 26
29 var s = js.string('hello'); // s = new LiteralString('"hello"') 27 var s = js.string('hello'); // s = new LiteralString('"hello"')
30 var n = js.number(123); // n = new LiteralNumber(123) 28 var n = js.number(123); // n = new LiteralNumber(123)
31 29
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 should be splice or is intended as a single value. 183 should be splice or is intended as a single value.
186 184
187 - There are no placeholders in definition contexts: 185 - There are no placeholders in definition contexts:
188 186
189 function #(){} 187 function #(){}
190 var # = 1; 188 var # = 1;
191 189
192 */ 190 */
193 const JsBuilder js = const JsBuilder(); 191 const JsBuilder js = const JsBuilder();
194 192
195
196 class JsBuilder { 193 class JsBuilder {
197 const JsBuilder(); 194 const JsBuilder();
198 195
199 /** 196 /**
200 * Parses a bit of JavaScript, and returns an expression. 197 * Parses a bit of JavaScript, and returns an expression.
201 * 198 *
202 * See the MiniJsParser class. 199 * See the MiniJsParser class.
203 * 200 *
204 * [arguments] can be a single [Node] (e.g. an [Expression] or [Statement]) or 201 * [arguments] can be a single [Node] (e.g. an [Expression] or [Statement]) or
205 * a list of [Node]s, which will be interpolated into the source at the '#' 202 * a list of [Node]s, which will be interpolated into the source at the '#'
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 } 257 }
261 return template; 258 return template;
262 } 259 }
263 260
264 /** 261 /**
265 * Creates an Expression template without caching the result. 262 * Creates an Expression template without caching the result.
266 */ 263 */
267 Template uncachedExpressionTemplate(String source) { 264 Template uncachedExpressionTemplate(String source) {
268 MiniJsParser parser = new MiniJsParser(source); 265 MiniJsParser parser = new MiniJsParser(source);
269 Expression expression = parser.expression(); 266 Expression expression = parser.expression();
270 return new Template( 267 return new Template(source, expression,
271 source, expression, isExpression: true, forceCopy: false); 268 isExpression: true, forceCopy: false);
272 } 269 }
273 270
274 /** 271 /**
275 * Creates a Statement template without caching the result. 272 * Creates a Statement template without caching the result.
276 */ 273 */
277 Template uncachedStatementTemplate(String source) { 274 Template uncachedStatementTemplate(String source) {
278 MiniJsParser parser = new MiniJsParser(source); 275 MiniJsParser parser = new MiniJsParser(source);
279 Statement statement = parser.statement(); 276 Statement statement = parser.statement();
280 return new Template( 277 return new Template(source, statement,
281 source, statement, isExpression: false, forceCopy: false); 278 isExpression: false, forceCopy: false);
282 } 279 }
283 280
284 /** 281 /**
285 * Create an Expression template which has [ast] as the result. This is used 282 * Create an Expression template which has [ast] as the result. This is used
286 * to wrap a generated AST in a zero-argument Template so it can be passed to 283 * to wrap a generated AST in a zero-argument Template so it can be passed to
287 * context that expects a template. 284 * context that expects a template.
288 */ 285 */
289 Template expressionTemplateYielding(Node ast) { 286 Template expressionTemplateYielding(Node ast) {
290 return new Template.withExpressionResult(ast); 287 return new Template.withExpressionResult(ast);
291 } 288 }
292 289
293 Template statementTemplateYielding(Node ast) { 290 Template statementTemplateYielding(Node ast) {
294 return new Template.withStatementResult(ast); 291 return new Template.withStatementResult(ast);
295 } 292 }
296 293
297 /// Creates a literal js string from [value]. 294 /// Creates a literal js string from [value].
298 LiteralString escapedString(String value, [String quote = '"']) { 295 LiteralString escapedString(String value, [String quote = '"']) {
299 // Start by escaping the backslashes. 296 // Start by escaping the backslashes.
300 String escaped = value.replaceAll('\\', '\\\\'); 297 String escaped = value.replaceAll('\\', '\\\\');
301 298
302
303 // Replace $ in template strings: 299 // Replace $ in template strings:
304 // http://www.ecma-international.org/ecma-262/6.0/#sec-template-literal-lexi cal-components 300 // http://www.ecma-international.org/ecma-262/6.0/#sec-template-literal-lexi cal-components
305 var quoteReplace = quote == '`' ? r'`$' : quote; 301 var quoteReplace = quote == '`' ? r'`$' : quote;
306 302
307 // http://www.ecma-international.org/ecma-262/6.0/#sec-literals-string-liter als 303 // http://www.ecma-international.org/ecma-262/6.0/#sec-literals-string-liter als
308 // > All code points may appear literally in a string literal except for the 304 // > All code points may appear literally in a string literal except for the
309 // > closing quote code points, U+005C (REVERSE SOLIDUS), 305 // > closing quote code points, U+005C (REVERSE SOLIDUS),
310 // > U+000D (CARRIAGE RETURN), U+2028 (LINE SEPARATOR), 306 // > U+000D (CARRIAGE RETURN), U+2028 (LINE SEPARATOR),
311 // > U+2029 (PARAGRAPH SEPARATOR), and U+000A (LINE FEED). 307 // > U+2029 (PARAGRAPH SEPARATOR), and U+000A (LINE FEED).
312 var re = new RegExp('[\n\r$quoteReplace\b\f\t\v\u2028\u2029]'); 308 var re = new RegExp('[\n\r$quoteReplace\b\f\t\v\u2028\u2029]');
313 escaped = escaped.replaceAllMapped(re, (m) { 309 escaped = escaped.replaceAllMapped(re, (m) {
314 switch (m.group(0)) { 310 switch (m.group(0)) {
315 case "\n" : return r"\n"; 311 case "\n":
316 case "\r" : return r"\r"; 312 return r"\n";
317 case "\u2028": return r"\u2028"; 313 case "\r":
318 case "\u2029": return r"\u2029"; 314 return r"\r";
315 case "\u2028":
316 return r"\u2028";
317 case "\u2029":
318 return r"\u2029";
319 // Quotes and $ are only replaced if they conflict with the containing 319 // Quotes and $ are only replaced if they conflict with the containing
320 // quote, see regex above. 320 // quote, see regex above.
321 case '"': return r'\"'; 321 case '"':
322 case "'": return r"\'"; 322 return r'\"';
323 case "`": return r"\`"; 323 case "'":
324 case r"$": return r"\$"; 324 return r"\'";
325 case "`":
326 return r"\`";
327 case r"$":
328 return r"\$";
325 // TODO(jmesserly): these don't need to be escaped for correctness, 329 // TODO(jmesserly): these don't need to be escaped for correctness,
326 // but they are conventionally escaped. 330 // but they are conventionally escaped.
327 case "\b": return r"\b"; 331 case "\b":
328 case "\t": return r"\t"; 332 return r"\b";
329 case "\f": return r"\f"; 333 case "\t":
330 case "\v": return r"\v"; 334 return r"\t";
335 case "\f":
336 return r"\f";
337 case "\v":
338 return r"\v";
331 } 339 }
332 }); 340 });
333 LiteralString result = new LiteralString('$quote$escaped$quote'); 341 LiteralString result = new LiteralString('$quote$escaped$quote');
334 // We don't escape quotes of a different style under the assumption that the 342 // We don't escape quotes of a different style under the assumption that the
335 // string is wrapped into quotes. Verify that assumption. 343 // string is wrapped into quotes. Verify that assumption.
336 assert(result.value.codeUnitAt(0) == quote.codeUnitAt(0)); 344 assert(result.value.codeUnitAt(0) == quote.codeUnitAt(0));
337 return result; 345 return result;
338 } 346 }
339 347
340 /// Creates a literal js string from [value]. 348 /// Creates a literal js string from [value].
(...skipping 12 matching lines...) Expand all
353 ArrayInitializer numArray(Iterable<int> list) => 361 ArrayInitializer numArray(Iterable<int> list) =>
354 new ArrayInitializer(list.map(number).toList()); 362 new ArrayInitializer(list.map(number).toList());
355 363
356 ArrayInitializer stringArray(Iterable<String> list) => 364 ArrayInitializer stringArray(Iterable<String> list) =>
357 new ArrayInitializer(list.map(string).toList()); 365 new ArrayInitializer(list.map(string).toList());
358 366
359 Comment comment(String text) => new Comment(text); 367 Comment comment(String text) => new Comment(text);
360 CommentExpression commentExpression(String text, Expression expression) => 368 CommentExpression commentExpression(String text, Expression expression) =>
361 new CommentExpression(text, expression); 369 new CommentExpression(text, expression);
362 370
363 Call propertyCall(Expression receiver, 371 Call propertyCall(
364 String fieldName, 372 Expression receiver, String fieldName, List<Expression> arguments) {
365 List<Expression> arguments) {
366 return new Call(new PropertyAccess.field(receiver, fieldName), arguments); 373 return new Call(new PropertyAccess.field(receiver, fieldName), arguments);
367 } 374 }
368 } 375 }
369 376
370 LiteralString string(String value) => js.string(value); 377 LiteralString string(String value) => js.string(value);
371 LiteralNumber number(num value) => js.number(value); 378 LiteralNumber number(num value) => js.number(value);
372 ArrayInitializer numArray(Iterable<int> list) => js.numArray(list); 379 ArrayInitializer numArray(Iterable<int> list) => js.numArray(list);
373 ArrayInitializer stringArray(Iterable<String> list) => js.stringArray(list); 380 ArrayInitializer stringArray(Iterable<String> list) => js.stringArray(list);
374 Call propertyCall(Expression receiver, 381 Call propertyCall(
375 String fieldName, 382 Expression receiver, String fieldName, List<Expression> arguments) {
376 List<Expression> arguments) {
377 return js.propertyCall(receiver, fieldName, arguments); 383 return js.propertyCall(receiver, fieldName, arguments);
378 } 384 }
379 385
380 class MiniJsParserError { 386 class MiniJsParserError {
381 MiniJsParserError(this.parser, this.message) { } 387 MiniJsParserError(this.parser, this.message) {}
382 388
383 final MiniJsParser parser; 389 final MiniJsParser parser;
384 final String message; 390 final String message;
385 391
386 String toString() { 392 String toString() {
387 int pos = parser.lastPosition; 393 int pos = parser.lastPosition;
388 394
389 // Discard lines following the line containing lastPosition. 395 // Discard lines following the line containing lastPosition.
390 String src = parser.src; 396 String src = parser.src;
391 int newlinePos = src.indexOf('\n', pos); 397 int newlinePos = src.indexOf('\n', pos);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 lastToken = null, 439 lastToken = null,
434 lastPosition = 0, 440 lastPosition = 0,
435 position = 0 { 441 position = 0 {
436 getToken(); 442 getToken();
437 } 443 }
438 444
439 int lastCategory = NONE; 445 int lastCategory = NONE;
440 String lastToken = null; 446 String lastToken = null;
441 int lastPosition = 0; 447 int lastPosition = 0;
442 int position = 0; 448 int position = 0;
443 bool skippedNewline = false; // skipped newline in last getToken? 449 bool skippedNewline = false; // skipped newline in last getToken?
444 final String src; 450 final String src;
445 451
446 final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[]; 452 final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[];
447 bool get hasNamedHoles => 453 bool get hasNamedHoles =>
448 interpolatedValues.isNotEmpty && interpolatedValues.first.isNamed; 454 interpolatedValues.isNotEmpty && interpolatedValues.first.isNamed;
449 bool get hasPositionalHoles => 455 bool get hasPositionalHoles =>
450 interpolatedValues.isNotEmpty && interpolatedValues.first.isPositional; 456 interpolatedValues.isNotEmpty && interpolatedValues.first.isPositional;
451 457
452 static const NONE = -1; 458 static const NONE = -1;
453 static const ALPHA = 0; 459 static const ALPHA = 0;
(...skipping 19 matching lines...) Expand all
473 static const OTHER = 20; 479 static const OTHER = 20;
474 480
475 // Make sure that ]] is two symbols. 481 // Make sure that ]] is two symbols.
476 // TODO(jmesserly): => and ... are not single char tokens, should we change 482 // TODO(jmesserly): => and ... are not single char tokens, should we change
477 // their numbers? It shouldn't matter because this is only called on values 483 // their numbers? It shouldn't matter because this is only called on values
478 // from the [CATEGORIES] table. 484 // from the [CATEGORIES] table.
479 bool singleCharCategory(int category) => category > DOT; 485 bool singleCharCategory(int category) => category > DOT;
480 486
481 static String categoryToString(int cat) { 487 static String categoryToString(int cat) {
482 switch (cat) { 488 switch (cat) {
483 case NONE: return "NONE"; 489 case NONE:
484 case ALPHA: return "ALPHA"; 490 return "NONE";
485 case NUMERIC: return "NUMERIC"; 491 case ALPHA:
486 case SYMBOL: return "SYMBOL"; 492 return "ALPHA";
487 case ASSIGNMENT: return "ASSIGNMENT"; 493 case NUMERIC:
488 case DOT: return "DOT"; 494 return "NUMERIC";
489 case LPAREN: return "LPAREN"; 495 case SYMBOL:
490 case RPAREN: return "RPAREN"; 496 return "SYMBOL";
491 case LBRACE: return "LBRACE"; 497 case ASSIGNMENT:
492 case RBRACE: return "RBRACE"; 498 return "ASSIGNMENT";
493 case LSQUARE: return "LSQUARE"; 499 case DOT:
494 case RSQUARE: return "RSQUARE"; 500 return "DOT";
495 case STRING: return "STRING"; 501 case LPAREN:
496 case COMMA: return "COMMA"; 502 return "LPAREN";
497 case QUERY: return "QUERY"; 503 case RPAREN:
498 case COLON: return "COLON"; 504 return "RPAREN";
499 case SEMICOLON: return "SEMICOLON"; 505 case LBRACE:
500 case ARROW: return "ARROW"; 506 return "LBRACE";
501 case ELLIPSIS: return "ELLIPSIS"; 507 case RBRACE:
502 case HASH: return "HASH"; 508 return "RBRACE";
503 case WHITESPACE: return "WHITESPACE"; 509 case LSQUARE:
504 case OTHER: return "OTHER"; 510 return "LSQUARE";
511 case RSQUARE:
512 return "RSQUARE";
513 case STRING:
514 return "STRING";
515 case COMMA:
516 return "COMMA";
517 case QUERY:
518 return "QUERY";
519 case COLON:
520 return "COLON";
521 case SEMICOLON:
522 return "SEMICOLON";
523 case ARROW:
524 return "ARROW";
525 case ELLIPSIS:
526 return "ELLIPSIS";
527 case HASH:
528 return "HASH";
529 case WHITESPACE:
530 return "WHITESPACE";
531 case OTHER:
532 return "OTHER";
505 } 533 }
506 return "Unknown: $cat"; 534 return "Unknown: $cat";
507 } 535 }
508 536
509 static const CATEGORIES = const <int>[ 537 static const CATEGORIES = const <int>[
510 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 0-7 538 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 0-7
511 OTHER, WHITESPACE, WHITESPACE, OTHER, OTHER, WHITESPACE, // 8-13 539 OTHER, WHITESPACE, WHITESPACE, OTHER, OTHER, WHITESPACE, // 8-13
512 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 14-21 540 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 14-21
513 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 22-29 541 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 22-29
514 OTHER, OTHER, WHITESPACE, // 30-32 542 OTHER, OTHER, WHITESPACE, // 30-32
515 SYMBOL, OTHER, HASH, ALPHA, SYMBOL, SYMBOL, OTHER, // !"#$%&´ 543 SYMBOL, OTHER, HASH, ALPHA, SYMBOL, SYMBOL, OTHER, // !"#$%&´
516 LPAREN, RPAREN, SYMBOL, SYMBOL, COMMA, SYMBOL, DOT, SYMBOL, // ()*+,-./ 544 LPAREN, RPAREN, SYMBOL, SYMBOL, COMMA, SYMBOL, DOT, SYMBOL, // ()*+,-./
517 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 01234 545 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 01234
518 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 56789 546 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 56789
519 COLON, SEMICOLON, SYMBOL, SYMBOL, SYMBOL, QUERY, OTHER, // :;<=>?@ 547 COLON, SEMICOLON, SYMBOL, SYMBOL, SYMBOL, QUERY, OTHER, // :;<=>?@
520 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ABCDEFGH 548 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ABCDEFGH
521 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // IJKLMNOP 549 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // IJKLMNOP
522 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // QRSTUVWX 550 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // QRSTUVWX
523 ALPHA, ALPHA, LSQUARE, OTHER, RSQUARE, SYMBOL, ALPHA, OTHER, // YZ[\]^_' 551 ALPHA, ALPHA, LSQUARE, OTHER, RSQUARE, SYMBOL, ALPHA, OTHER, // YZ[\]^_'
524 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // abcdefgh 552 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // abcdefgh
525 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ijklmnop 553 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ijklmnop
526 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // qrstuvwx 554 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // qrstuvwx
527 ALPHA, ALPHA, LBRACE, SYMBOL, RBRACE, SYMBOL]; // yz{|}~ 555 ALPHA, ALPHA, LBRACE, SYMBOL, RBRACE, SYMBOL
556 ]; // yz{|}~
528 557
529 // This must be a >= the highest precedence number handled by parseBinary. 558 // This must be a >= the highest precedence number handled by parseBinary.
530 static var HIGHEST_PARSE_BINARY_PRECEDENCE = 16; 559 static var HIGHEST_PARSE_BINARY_PRECEDENCE = 16;
531 static bool isAssignment(String symbol) => BINARY_PRECEDENCE[symbol] == 17; 560 static bool isAssignment(String symbol) => BINARY_PRECEDENCE[symbol] == 17;
532 561
533 // From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operator s/Operator_Precedence 562 // From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operator s/Operator_Precedence
534 static final BINARY_PRECEDENCE = { 563 static final BINARY_PRECEDENCE = {
535 '+=': 17, '-=': 17, '*=': 17, '/=': 17, '%=': 17, '^=': 17, '|=': 17, 564 '+=': 17,
536 '&=': 17, '<<=': 17, '>>=': 17, '>>>=': 17, '=': 17, 565 '-=': 17,
537 '||': 14, 566 '*=': 17,
538 '&&': 13, 567 '/=': 17,
539 '|': 12, 568 '%=': 17,
540 '^': 11, 569 '^=': 17,
541 '&': 10, 570 '|=': 17,
542 '!=': 9, '==': 9, '!==': 9, '===': 9, 571 '&=': 17,
543 '<': 8, '<=': 8, '>=': 8, '>': 8, 'in': 8, 'instanceof': 8, 572 '<<=': 17,
544 '<<': 7, '>>': 7, '>>>': 7, 573 '>>=': 17,
545 '+': 6, '-': 6, 574 '>>>=': 17,
546 '*': 5, '/': 5, '%': 5 575 '=': 17,
576 '||': 14,
577 '&&': 13,
578 '|': 12,
579 '^': 11,
580 '&': 10,
581 '!=': 9,
582 '==': 9,
583 '!==': 9,
584 '===': 9,
585 '<': 8,
586 '<=': 8,
587 '>=': 8,
588 '>': 8,
589 'in': 8,
590 'instanceof': 8,
591 '<<': 7,
592 '>>': 7,
593 '>>>': 7,
594 '+': 6,
595 '-': 6,
596 '*': 5,
597 '/': 5,
598 '%': 5
547 }; 599 };
548 static final UNARY_OPERATORS = 600 static final UNARY_OPERATORS = [
549 ['++', '--', '+', '-', '~', '!', 'typeof', 'void', 'delete', 'await'] 601 '++',
550 .toSet(); 602 '--',
603 '+',
604 '-',
605 '~',
606 '!',
607 'typeof',
608 'void',
609 'delete',
610 'await'
611 ].toSet();
551 612
552 static final ARROW_TOKEN = '=>'; 613 static final ARROW_TOKEN = '=>';
553 static final ELLIPSIS_TOKEN = '...'; 614 static final ELLIPSIS_TOKEN = '...';
554 615
555 static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS = 616 static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS =
556 ['typeof', 'void', 'delete', 'in', 'instanceof', 'await'].toSet(); 617 ['typeof', 'void', 'delete', 'in', 'instanceof', 'await'].toSet();
557 618
558 static int category(int code) { 619 static int category(int code) {
559 if (code >= CATEGORIES.length) return OTHER; 620 if (code >= CATEGORIES.length) return OTHER;
560 return CATEGORIES[code]; 621 return CATEGORIES[code];
561 } 622 }
562 623
563 String getDelimited(int startPosition) { 624 String getDelimited(int startPosition) {
564 position = startPosition; 625 position = startPosition;
565 int delimiter = src.codeUnitAt(startPosition); 626 int delimiter = src.codeUnitAt(startPosition);
566 int currentCode; 627 int currentCode;
567 do { 628 do {
568 position++; 629 position++;
569 if (position >= src.length) error("Unterminated literal"); 630 if (position >= src.length) error("Unterminated literal");
570 currentCode = src.codeUnitAt(position); 631 currentCode = src.codeUnitAt(position);
571 if (currentCode == charCodes.$LF) error("Unterminated literal"); 632 if (currentCode == charCodes.$LF) error("Unterminated literal");
572 if (currentCode == charCodes.$BACKSLASH) { 633 if (currentCode == charCodes.$BACKSLASH) {
573 if (++position >= src.length) error("Unterminated literal"); 634 if (++position >= src.length) error("Unterminated literal");
574 int escaped = src.codeUnitAt(position); 635 int escaped = src.codeUnitAt(position);
575 if (escaped == charCodes.$x || escaped == charCodes.$X || 636 if (escaped == charCodes.$x ||
576 escaped == charCodes.$u || escaped == charCodes.$U || 637 escaped == charCodes.$X ||
638 escaped == charCodes.$u ||
639 escaped == charCodes.$U ||
577 category(escaped) == NUMERIC) { 640 category(escaped) == NUMERIC) {
578 error('Numeric and hex escapes are not allowed in literals'); 641 error('Numeric and hex escapes are not allowed in literals');
579 } 642 }
580 } 643 }
581 } while (currentCode != delimiter); 644 } while (currentCode != delimiter);
582 position++; 645 position++;
583 return src.substring(lastPosition, position); 646 return src.substring(lastPosition, position);
584 } 647 }
585 648
586 void getToken() { 649 void getToken() {
587 skippedNewline = false; 650 skippedNewline = false;
588 for (;;) { 651 for (;;) {
589 if (position >= src.length) break; 652 if (position >= src.length) break;
590 int code = src.codeUnitAt(position); 653 int code = src.codeUnitAt(position);
591 // Skip '//' and '/*' style comments. 654 // Skip '//' and '/*' style comments.
592 if (code == charCodes.$SLASH && 655 if (code == charCodes.$SLASH && position + 1 < src.length) {
593 position + 1 < src.length) {
594 if (src.codeUnitAt(position + 1) == charCodes.$SLASH) { 656 if (src.codeUnitAt(position + 1) == charCodes.$SLASH) {
595 int nextPosition = src.indexOf('\n', position); 657 int nextPosition = src.indexOf('\n', position);
596 if (nextPosition == -1) nextPosition = src.length; 658 if (nextPosition == -1) nextPosition = src.length;
597 position = nextPosition; 659 position = nextPosition;
598 continue; 660 continue;
599 } else if (src.codeUnitAt(position + 1) == charCodes.$STAR) { 661 } else if (src.codeUnitAt(position + 1) == charCodes.$STAR) {
600 int nextPosition = src.indexOf('*/', position + 2); 662 int nextPosition = src.indexOf('*/', position + 2);
601 if (nextPosition == -1) error('Unterminated comment'); 663 if (nextPosition == -1) error('Unterminated comment');
602 position = nextPosition + 2; 664 position = nextPosition + 2;
603 continue; 665 continue;
(...skipping 10 matching lines...) Expand all
614 lastPosition = position; 676 lastPosition = position;
615 return; 677 return;
616 } 678 }
617 int code = src.codeUnitAt(position); 679 int code = src.codeUnitAt(position);
618 lastPosition = position; 680 lastPosition = position;
619 if (code == charCodes.$SQ || code == charCodes.$DQ) { 681 if (code == charCodes.$SQ || code == charCodes.$DQ) {
620 // String literal. 682 // String literal.
621 lastCategory = STRING; 683 lastCategory = STRING;
622 lastToken = getDelimited(position); 684 lastToken = getDelimited(position);
623 } else if (code == charCodes.$0 && 685 } else if (code == charCodes.$0 &&
624 position + 2 < src.length && 686 position + 2 < src.length &&
625 src.codeUnitAt(position + 1) == charCodes.$x) { 687 src.codeUnitAt(position + 1) == charCodes.$x) {
626 // Hex literal. 688 // Hex literal.
627 for (position += 2; position < src.length; position++) { 689 for (position += 2; position < src.length; position++) {
628 int cat = category(src.codeUnitAt(position)); 690 int cat = category(src.codeUnitAt(position));
629 if (cat != NUMERIC && cat != ALPHA) break; 691 if (cat != NUMERIC && cat != ALPHA) break;
630 } 692 }
631 lastCategory = NUMERIC; 693 lastCategory = NUMERIC;
632 lastToken = src.substring(lastPosition, position); 694 lastToken = src.substring(lastPosition, position);
633 int.parse(lastToken, onError: (_) { 695 int.parse(lastToken, onError: (_) {
634 error("Unparseable number"); 696 error("Unparseable number");
635 }); 697 });
(...skipping 10 matching lines...) Expand all
646 int cat = category(src.codeUnitAt(position)); 708 int cat = category(src.codeUnitAt(position));
647 int newCat; 709 int newCat;
648 do { 710 do {
649 position++; 711 position++;
650 if (position == src.length) break; 712 if (position == src.length) break;
651 int code = src.codeUnitAt(position); 713 int code = src.codeUnitAt(position);
652 // Special code to disallow ! and / in non-first position in token, so 714 // Special code to disallow ! and / in non-first position in token, so
653 // that !! parses as two tokens and != parses as one, while =/ parses 715 // that !! parses as two tokens and != parses as one, while =/ parses
654 // as a an equals token followed by a regexp literal start. 716 // as a an equals token followed by a regexp literal start.
655 newCat = (code == charCodes.$BANG || code == charCodes.$SLASH) 717 newCat = (code == charCodes.$BANG || code == charCodes.$SLASH)
656 ? NONE 718 ? NONE
657 : category(code); 719 : category(code);
658 } while (!singleCharCategory(cat) && 720 } while (!singleCharCategory(cat) &&
659 (cat == newCat || 721 (cat == newCat ||
660 (cat == ALPHA && newCat == NUMERIC) || // eg. level42. 722 (cat == ALPHA && newCat == NUMERIC) || // eg. level42.
661 (cat == NUMERIC && newCat == DOT))); // eg. 3.1415 723 (cat == NUMERIC && newCat == DOT))); // eg. 3.1415
662 lastCategory = cat; 724 lastCategory = cat;
663 lastToken = src.substring(lastPosition, position); 725 lastToken = src.substring(lastPosition, position);
664 if (cat == NUMERIC) { 726 if (cat == NUMERIC) {
665 double.parse(lastToken, (_) { 727 double.parse(lastToken, (_) {
666 error("Unparseable number"); 728 error("Unparseable number");
667 }); 729 });
668 } else if (cat == DOT && lastToken.length > 1) { 730 } else if (cat == DOT && lastToken.length > 1) {
669 if (lastToken == ELLIPSIS_TOKEN) { 731 if (lastToken == ELLIPSIS_TOKEN) {
670 lastCategory = ELLIPSIS; 732 lastCategory = ELLIPSIS;
671 } else { 733 } else {
672 error("Unknown operator"); 734 error("Unknown operator");
673 } 735 }
674 } else if (cat == SYMBOL) { 736 } else if (cat == SYMBOL) {
675 if (lastToken == ARROW_TOKEN) { 737 if (lastToken == ARROW_TOKEN) {
676 lastCategory = ARROW; 738 lastCategory = ARROW;
677 } else { 739 } else {
678 int binaryPrecendence = BINARY_PRECEDENCE[lastToken]; 740 int binaryPrecendence = BINARY_PRECEDENCE[lastToken];
679 if (binaryPrecendence == null && !UNARY_OPERATORS.contains(lastToken)) { 741 if (binaryPrecendence == null &&
742 !UNARY_OPERATORS.contains(lastToken)) {
680 error("Unknown operator"); 743 error("Unknown operator");
681 } 744 }
682 if (isAssignment(lastToken)) lastCategory = ASSIGNMENT; 745 if (isAssignment(lastToken)) lastCategory = ASSIGNMENT;
683 } 746 }
684 } else if (cat == ALPHA) { 747 } else if (cat == ALPHA) {
685 if (OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS.contains(lastToken)) { 748 if (OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS.contains(lastToken)) {
686 lastCategory = SYMBOL; 749 lastCategory = SYMBOL;
687 } 750 }
688 } 751 }
689 } 752 }
(...skipping 14 matching lines...) Expand all
704 767
705 void expectSemicolon() { 768 void expectSemicolon() {
706 if (acceptSemicolon()) return; 769 if (acceptSemicolon()) return;
707 error('Expected SEMICOLON'); 770 error('Expected SEMICOLON');
708 } 771 }
709 772
710 bool acceptSemicolon() { 773 bool acceptSemicolon() {
711 // Accept semicolon or automatically inserted semicolon before close brace. 774 // Accept semicolon or automatically inserted semicolon before close brace.
712 // Miniparser forbids other kinds of semicolon insertion. 775 // Miniparser forbids other kinds of semicolon insertion.
713 if (RBRACE == lastCategory) return true; 776 if (RBRACE == lastCategory) return true;
714 if (NONE == lastCategory) return true; // end of input 777 if (NONE == lastCategory) return true; // end of input
715 if (skippedNewline) { 778 if (skippedNewline) {
716 error('No automatic semicolon insertion at preceding newline'); 779 error('No automatic semicolon insertion at preceding newline');
717 } 780 }
718 return acceptCategory(SEMICOLON); 781 return acceptCategory(SEMICOLON);
719 } 782 }
720 783
721 bool acceptString(String string) { 784 bool acceptString(String string) {
722 if (lastToken == string) { 785 if (lastToken == string) {
723 getToken(); 786 getToken();
724 return true; 787 return true;
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 } else { 958 } else {
896 body = parseAssignment(); 959 body = parseAssignment();
897 } 960 }
898 return new ArrowFun(params, body); 961 return new ArrowFun(params, body);
899 } 962 }
900 963
901 Expression parseFunctionExpression() { 964 Expression parseFunctionExpression() {
902 String last = lastToken; 965 String last = lastToken;
903 if (acceptCategory(ALPHA)) { 966 if (acceptCategory(ALPHA)) {
904 String functionName = last; 967 String functionName = last;
905 return new NamedFunction(new Identifier(functionName), 968 return new NamedFunction(new Identifier(functionName), parseFun());
906 parseFun());
907 } 969 }
908 return parseFun(); 970 return parseFun();
909 } 971 }
910 972
911 Expression parseFun() { 973 Expression parseFun() {
912 List<Parameter> params = <Parameter>[]; 974 List<Parameter> params = <Parameter>[];
913 975
914 expectCategory(LPAREN); 976 expectCategory(LPAREN);
915 if (!acceptCategory(RPAREN)) { 977 if (!acceptCategory(RPAREN)) {
916 for (;;) { 978 for (;;) {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 if (acceptCategory(ELLIPSIS)) { 1066 if (acceptCategory(ELLIPSIS)) {
1005 arguments.add(new Spread(parseAssignment())); 1067 arguments.add(new Spread(parseAssignment()));
1006 expectCategory(RPAREN); 1068 expectCategory(RPAREN);
1007 break; 1069 break;
1008 } 1070 }
1009 arguments.add(parseAssignment()); 1071 arguments.add(parseAssignment());
1010 if (acceptCategory(RPAREN)) break; 1072 if (acceptCategory(RPAREN)) break;
1011 expectCategory(COMMA); 1073 expectCategory(COMMA);
1012 } 1074 }
1013 } 1075 }
1014 receiver = constructor ? 1076 receiver = constructor
1015 new New(receiver, arguments) : 1077 ? new New(receiver, arguments)
1016 new Call(receiver, arguments); 1078 : new Call(receiver, arguments);
1017 constructor = false; 1079 constructor = false;
1018 } else if (!constructor && acceptCategory(LSQUARE)) { 1080 } else if (!constructor && acceptCategory(LSQUARE)) {
1019 Expression inBraces = parseExpression(); 1081 Expression inBraces = parseExpression();
1020 expectCategory(RSQUARE); 1082 expectCategory(RSQUARE);
1021 receiver = new PropertyAccess(receiver, inBraces); 1083 receiver = new PropertyAccess(receiver, inBraces);
1022 } else if (!constructor && acceptCategory(DOT)) { 1084 } else if (!constructor && acceptCategory(DOT)) {
1023 receiver = getDotRhs(receiver); 1085 receiver = getDotRhs(receiver);
1024 } else { 1086 } else {
1025 // JS allows new without (), but we don't. 1087 // JS allows new without (), but we don't.
1026 if (constructor) error("Parentheses are required for new"); 1088 if (constructor) error("Parentheses are required for new");
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 return new Postfix(operator, expression); 1123 return new Postfix(operator, expression);
1062 } 1124 }
1063 // If we don't accept '++' or '--' due to skippedNewline a newline, no other 1125 // If we don't accept '++' or '--' due to skippedNewline a newline, no other
1064 // part of the parser will accept the token and we will get an error at the 1126 // part of the parser will accept the token and we will get an error at the
1065 // whole expression level. 1127 // whole expression level.
1066 return expression; 1128 return expression;
1067 } 1129 }
1068 1130
1069 Expression parseUnaryHigh() { 1131 Expression parseUnaryHigh() {
1070 String operator = lastToken; 1132 String operator = lastToken;
1071 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && 1133 if (lastCategory == SYMBOL &&
1134 UNARY_OPERATORS.contains(operator) &&
1072 (acceptString("++") || acceptString("--") || acceptString('await'))) { 1135 (acceptString("++") || acceptString("--") || acceptString('await'))) {
1073 if (operator == "await") return new Await(parsePostfix()); 1136 if (operator == "await") return new Await(parsePostfix());
1074 return new Prefix(operator, parsePostfix()); 1137 return new Prefix(operator, parsePostfix());
1075 } 1138 }
1076 return parsePostfix(); 1139 return parsePostfix();
1077 } 1140 }
1078 1141
1079 Expression parseUnaryLow() { 1142 Expression parseUnaryLow() {
1080 String operator = lastToken; 1143 String operator = lastToken;
1081 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && 1144 if (lastCategory == SYMBOL &&
1082 operator != "++" && operator != "--") { 1145 UNARY_OPERATORS.contains(operator) &&
1146 operator != "++" &&
1147 operator != "--") {
1083 expectCategory(SYMBOL); 1148 expectCategory(SYMBOL);
1084 if (operator == "await") return new Await(parsePostfix()); 1149 if (operator == "await") return new Await(parsePostfix());
1085 return new Prefix(operator, parseUnaryLow()); 1150 return new Prefix(operator, parseUnaryLow());
1086 } 1151 }
1087 return parseUnaryHigh(); 1152 return parseUnaryHigh();
1088 } 1153 }
1089 1154
1090 Expression parseBinary(int maxPrecedence) { 1155 Expression parseBinary(int maxPrecedence) {
1091 Expression lhs = parseUnaryLow(); 1156 Expression lhs = parseUnaryLow();
1092 int minPrecedence; 1157 int minPrecedence;
1093 String lastSymbol; 1158 String lastSymbol;
1094 Expression rhs; // This is null first time around. 1159 Expression rhs; // This is null first time around.
1095 while (true) { 1160 while (true) {
1096 String symbol = lastToken; 1161 String symbol = lastToken;
1097 if (lastCategory != SYMBOL || 1162 if (lastCategory != SYMBOL ||
1098 !BINARY_PRECEDENCE.containsKey(symbol) || 1163 !BINARY_PRECEDENCE.containsKey(symbol) ||
1099 BINARY_PRECEDENCE[symbol] > maxPrecedence) { 1164 BINARY_PRECEDENCE[symbol] > maxPrecedence) {
1100 break; 1165 break;
1101 } 1166 }
1102 expectCategory(SYMBOL); 1167 expectCategory(SYMBOL);
1103 if (rhs == null || BINARY_PRECEDENCE[symbol] >= minPrecedence) { 1168 if (rhs == null || BINARY_PRECEDENCE[symbol] >= minPrecedence) {
1104 if (rhs != null) lhs = new Binary(lastSymbol, lhs, rhs); 1169 if (rhs != null) lhs = new Binary(lastSymbol, lhs, rhs);
(...skipping 20 matching lines...) Expand all
1125 1190
1126 Expression parseLeftHandSide() => parseConditional(); 1191 Expression parseLeftHandSide() => parseConditional();
1127 1192
1128 Expression parseAssignment() { 1193 Expression parseAssignment() {
1129 Expression lhs = parseLeftHandSide(); 1194 Expression lhs = parseLeftHandSide();
1130 String assignmentOperator = lastToken; 1195 String assignmentOperator = lastToken;
1131 if (acceptCategory(ASSIGNMENT)) { 1196 if (acceptCategory(ASSIGNMENT)) {
1132 Expression rhs = parseAssignment(); 1197 Expression rhs = parseAssignment();
1133 if (assignmentOperator == "=") { 1198 if (assignmentOperator == "=") {
1134 return new Assignment(lhs, rhs); 1199 return new Assignment(lhs, rhs);
1135 } else { 1200 } else {
1136 // Handle +=, -=, etc. 1201 // Handle +=, -=, etc.
1137 String operator = 1202 String operator =
1138 assignmentOperator.substring(0, assignmentOperator.length - 1); 1203 assignmentOperator.substring(0, assignmentOperator.length - 1);
1139 return new Assignment.compound(lhs, operator, rhs); 1204 return new Assignment.compound(lhs, operator, rhs);
1140 } 1205 }
1141 } 1206 }
1142 return lhs; 1207 return lhs;
1143 } 1208 }
1144 1209
1145 Expression parseExpression() { 1210 Expression parseExpression() {
1146 Expression expression = parseAssignment(); 1211 Expression expression = parseAssignment();
1147 while (acceptCategory(COMMA)) { 1212 while (acceptCategory(COMMA)) {
1148 Expression right = parseAssignment(); 1213 Expression right = parseAssignment();
1149 expression = new Binary(',', expression, right); 1214 expression = new Binary(',', expression, right);
1150 } 1215 }
1151 return expression; 1216 return expression;
1152 } 1217 }
1153 1218
1154 /** Parse a variable declaration list, with `var` or `let` [keyword] */ 1219 /** Parse a variable declaration list, with `var` or `let` [keyword] */
1155 VariableDeclarationList parseVariableDeclarationList( 1220 VariableDeclarationList parseVariableDeclarationList(String keyword,
1156 String keyword, [String firstIdentifier]) { 1221 [String firstIdentifier]) {
1157 var initialization = <VariableInitialization>[]; 1222 var initialization = <VariableInitialization>[];
1158 1223
1159 do { 1224 do {
1160 var declarator; 1225 var declarator;
1161 if (firstIdentifier != null) { 1226 if (firstIdentifier != null) {
1162 declarator = new Identifier(firstIdentifier); 1227 declarator = new Identifier(firstIdentifier);
1163 firstIdentifier = null; 1228 firstIdentifier = null;
1164 } else { 1229 } else {
1165 declarator = parseVariableBinding(); 1230 declarator = parseVariableBinding();
1166 } 1231 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 } 1267 }
1203 1268
1204 ArrayBindingPattern parseArrayBindingPattern() { 1269 ArrayBindingPattern parseArrayBindingPattern() {
1205 var variables = <DestructuredVariable>[]; 1270 var variables = <DestructuredVariable>[];
1206 do { 1271 do {
1207 var name; 1272 var name;
1208 var structure; 1273 var structure;
1209 var defaultValue; 1274 var defaultValue;
1210 1275
1211 var declarator = parseVariableBinding(); 1276 var declarator = parseVariableBinding();
1212 if (declarator is Identifier) name = declarator; 1277 if (declarator is Identifier)
1213 else if (declarator is BindingPattern) structure = declarator; 1278 name = declarator;
1214 else error("Unexpected LHS: $declarator"); 1279 else if (declarator is BindingPattern)
1280 structure = declarator;
1281 else
1282 error("Unexpected LHS: $declarator");
1215 1283
1216 if (acceptString("=")) { 1284 if (acceptString("=")) {
1217 defaultValue = parseExpression(); 1285 defaultValue = parseExpression();
1218 } 1286 }
1219 variables.add(new DestructuredVariable( 1287 variables.add(new DestructuredVariable(
1220 name: name, structure: structure, defaultValue: defaultValue)); 1288 name: name, structure: structure, defaultValue: defaultValue));
1221 } while (acceptCategory(COMMA)); 1289 } while (acceptCategory(COMMA));
1222 1290
1223 expectCategory(RSQUARE); 1291 expectCategory(RSQUARE);
1224 return new ArrayBindingPattern(variables); 1292 return new ArrayBindingPattern(variables);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 1399
1332 if (lastToken == 'case') error("Case outside switch."); 1400 if (lastToken == 'case') error("Case outside switch.");
1333 1401
1334 if (lastToken == 'default') error("Default outside switch."); 1402 if (lastToken == 'default') error("Default outside switch.");
1335 1403
1336 if (lastToken == 'yield') return parseYield(); 1404 if (lastToken == 'yield') return parseYield();
1337 1405
1338 if (lastToken == 'with') { 1406 if (lastToken == 'with') {
1339 error('Not implemented in mini parser'); 1407 error('Not implemented in mini parser');
1340 } 1408 }
1341
1342 } 1409 }
1343 1410
1344 bool checkForInterpolatedStatement = lastCategory == HASH; 1411 bool checkForInterpolatedStatement = lastCategory == HASH;
1345 1412
1346 Expression expression = parseExpression(); 1413 Expression expression = parseExpression();
1347 1414
1348 if (expression is Identifier && acceptCategory(COLON)) { 1415 if (expression is Identifier && acceptCategory(COLON)) {
1349 return new LabeledStatement(expression.name, parseStatement()); 1416 return new LabeledStatement(expression.name, parseStatement());
1350 } 1417 }
1351 1418
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 1511
1445 var keyword = acceptVarLetOrConst(); 1512 var keyword = acceptVarLetOrConst();
1446 if (keyword != null) { 1513 if (keyword != null) {
1447 String identifier = lastToken; 1514 String identifier = lastToken;
1448 expectCategory(ALPHA); 1515 expectCategory(ALPHA);
1449 1516
1450 if (acceptString('in')) { 1517 if (acceptString('in')) {
1451 Expression objectExpression = parseExpression(); 1518 Expression objectExpression = parseExpression();
1452 expectCategory(RPAREN); 1519 expectCategory(RPAREN);
1453 Statement body = parseStatement(); 1520 Statement body = parseStatement();
1454 return new ForIn( 1521 return new ForIn(_createVariableDeclarationList(keyword, identifier),
1455 _createVariableDeclarationList(keyword, identifier), 1522 objectExpression, body);
1456 objectExpression,
1457 body);
1458 } else if (acceptString('of')) { 1523 } else if (acceptString('of')) {
1459 Expression iterableExpression = parseAssignment(); 1524 Expression iterableExpression = parseAssignment();
1460 expectCategory(RPAREN); 1525 expectCategory(RPAREN);
1461 Statement body = parseStatement(); 1526 Statement body = parseStatement();
1462 return new ForOf( 1527 return new ForOf(_createVariableDeclarationList(keyword, identifier),
1463 _createVariableDeclarationList(keyword, identifier), 1528 iterableExpression, body);
1464 iterableExpression,
1465 body);
1466 } 1529 }
1467 var declarations = parseVariableDeclarationList(keyword, identifier); 1530 var declarations = parseVariableDeclarationList(keyword, identifier);
1468 expectCategory(SEMICOLON); 1531 expectCategory(SEMICOLON);
1469 return finishFor(declarations); 1532 return finishFor(declarations);
1470 } 1533 }
1471 1534
1472 Expression init = parseExpression(); 1535 Expression init = parseExpression();
1473 expectCategory(SEMICOLON); 1536 expectCategory(SEMICOLON);
1474 return finishFor(init); 1537 return finishFor(init);
1475 } 1538 }
1476 1539
1477 static VariableDeclarationList _createVariableDeclarationList( 1540 static VariableDeclarationList _createVariableDeclarationList(
1478 String keyword, String identifier) { 1541 String keyword, String identifier) {
1479 return new VariableDeclarationList(keyword, [ 1542 return new VariableDeclarationList(keyword,
1480 new VariableInitialization( 1543 [new VariableInitialization(new Identifier(identifier), null)]);
1481 new Identifier(identifier), null)]);
1482 } 1544 }
1483 1545
1484 Statement parseFunctionDeclaration() { 1546 Statement parseFunctionDeclaration() {
1485 String name = lastToken; 1547 String name = lastToken;
1486 expectCategory(ALPHA); 1548 expectCategory(ALPHA);
1487 Expression fun = parseFun(); 1549 Expression fun = parseFun();
1488 return new FunctionDeclaration(new Identifier(name), fun); 1550 return new FunctionDeclaration(new Identifier(name), fun);
1489 } 1551 }
1490 1552
1491 Statement parseTry() { 1553 Statement parseTry() {
(...skipping 17 matching lines...) Expand all
1509 expression = parseExpression(); 1571 expression = parseExpression();
1510 expectCategory(COLON); 1572 expectCategory(COLON);
1511 } else { 1573 } else {
1512 if (!acceptString('default')) { 1574 if (!acceptString('default')) {
1513 error('expected case or default'); 1575 error('expected case or default');
1514 } 1576 }
1515 expectCategory(COLON); 1577 expectCategory(COLON);
1516 } 1578 }
1517 var statements = <Statement>[]; 1579 var statements = <Statement>[];
1518 while (lastCategory != RBRACE && 1580 while (lastCategory != RBRACE &&
1519 lastToken != 'case' && 1581 lastToken != 'case' &&
1520 lastToken != 'default') { 1582 lastToken != 'default') {
1521 statements.add(parseStatement()); 1583 statements.add(parseStatement());
1522 } 1584 }
1523 return expression == null 1585 return expression == null
1524 ? new Default(new Block(statements)) 1586 ? new Default(new Block(statements))
1525 : new Case(expression, new Block(statements)); 1587 : new Case(expression, new Block(statements));
1526 } 1588 }
1527 1589
1528 Statement parseWhile() { 1590 Statement parseWhile() {
1529 expectCategory(LPAREN); 1591 expectCategory(LPAREN);
1530 Expression condition = parseExpression(); 1592 Expression condition = parseExpression();
(...skipping 12 matching lines...) Expand all
1543 expectSemicolon(); 1605 expectSemicolon();
1544 return new Do(body, condition); 1606 return new Do(body, condition);
1545 } 1607 }
1546 1608
1547 Statement parseSwitch() { 1609 Statement parseSwitch() {
1548 expectCategory(LPAREN); 1610 expectCategory(LPAREN);
1549 Expression key = parseExpression(); 1611 Expression key = parseExpression();
1550 expectCategory(RPAREN); 1612 expectCategory(RPAREN);
1551 expectCategory(LBRACE); 1613 expectCategory(LBRACE);
1552 List<SwitchClause> clauses = new List<SwitchClause>(); 1614 List<SwitchClause> clauses = new List<SwitchClause>();
1553 while(lastCategory != RBRACE) { 1615 while (lastCategory != RBRACE) {
1554 clauses.add(parseSwitchClause()); 1616 clauses.add(parseSwitchClause());
1555 } 1617 }
1556 expectCategory(RBRACE); 1618 expectCategory(RBRACE);
1557 return new Switch(key, clauses); 1619 return new Switch(key, clauses);
1558 } 1620 }
1559 1621
1560 Catch parseCatch() { 1622 Catch parseCatch() {
1561 expectCategory(LPAREN); 1623 expectCategory(LPAREN);
1562 String identifier = lastToken; 1624 String identifier = lastToken;
1563 expectCategory(ALPHA); 1625 expectCategory(ALPHA);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1642 expectCategory(RSQUARE); 1704 expectCategory(RSQUARE);
1643 return expr; 1705 return expr;
1644 } else if (acceptCategory(HASH)) { 1706 } else if (acceptCategory(HASH)) {
1645 return parseInterpolatedExpression(); 1707 return parseInterpolatedExpression();
1646 } else { 1708 } else {
1647 error('Expected property name'); 1709 error('Expected property name');
1648 return null; 1710 return null;
1649 } 1711 }
1650 } 1712 }
1651 } 1713 }
OLDNEW
« no previous file with comments | « no previous file | pkg/dev_compiler/lib/src/js_ast/characters.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698