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

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

Issue 2748103010: Run dartfmt on js_ast (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/js_ast/lib/src/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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 178
181 What is not implemented: 179 What is not implemented:
182 180
183 - Array initializers and object initializers could support splicing. In the 181 - Array initializers and object initializers could support splicing. In the
184 array case, we would need some way to know if an ArrayInitializer argument 182 array case, we would need some way to know if an ArrayInitializer argument
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 */ 185 */
188 const JsBuilder js = const JsBuilder(); 186 const JsBuilder js = const JsBuilder();
189 187
190
191 class JsBuilder { 188 class JsBuilder {
192 const JsBuilder(); 189 const JsBuilder();
193 190
194 /** 191 /**
195 * Parses a bit of JavaScript, and returns an expression. 192 * Parses a bit of JavaScript, and returns an expression.
196 * 193 *
197 * See the MiniJsParser class. 194 * See the MiniJsParser class.
198 * 195 *
199 * [arguments] can be a single [Node] (e.g. an [Expression] or [Statement]) or 196 * [arguments] can be a single [Node] (e.g. an [Expression] or [Statement]) or
200 * a list of [Node]s, which will be interpolated into the source at the '#' 197 * a list of [Node]s, which will be interpolated into the source at the '#'
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 Template expressionTemplateFor(String source) { 261 Template expressionTemplateFor(String source) {
265 return _findExpressionTemplate(source); 262 return _findExpressionTemplate(source);
266 } 263 }
267 264
268 /** 265 /**
269 * Creates an Expression template without caching the result. 266 * Creates an Expression template without caching the result.
270 */ 267 */
271 Template uncachedExpressionTemplate(String source) { 268 Template uncachedExpressionTemplate(String source) {
272 MiniJsParser parser = new MiniJsParser(source); 269 MiniJsParser parser = new MiniJsParser(source);
273 Expression expression = parser.expression(); 270 Expression expression = parser.expression();
274 return new Template( 271 return new Template(source, expression,
275 source, expression, isExpression: true, forceCopy: false); 272 isExpression: true, forceCopy: false);
276 } 273 }
277 274
278 /** 275 /**
279 * Creates a Statement template without caching the result. 276 * Creates a Statement template without caching the result.
280 */ 277 */
281 Template uncachedStatementTemplate(String source) { 278 Template uncachedStatementTemplate(String source) {
282 MiniJsParser parser = new MiniJsParser(source); 279 MiniJsParser parser = new MiniJsParser(source);
283 Statement statement = parser.statement(); 280 Statement statement = parser.statement();
284 return new Template( 281 return new Template(source, statement,
285 source, statement, isExpression: false, forceCopy: false); 282 isExpression: false, forceCopy: false);
286 } 283 }
287 284
288 /** 285 /**
289 * Create an Expression template which has [ast] as the result. This is used 286 * Create an Expression template which has [ast] as the result. This is used
290 * to wrap a generated AST in a zero-argument Template so it can be passed to 287 * to wrap a generated AST in a zero-argument Template so it can be passed to
291 * context that expects a template. 288 * context that expects a template.
292 */ 289 */
293 Template expressionTemplateYielding(Node ast) { 290 Template expressionTemplateYielding(Node ast) {
294 return new Template.withExpressionResult(ast); 291 return new Template.withExpressionResult(ast);
295 } 292 }
296 293
297 Template statementTemplateYielding(Node ast) { 294 Template statementTemplateYielding(Node ast) {
298 return new Template.withStatementResult(ast); 295 return new Template.withStatementResult(ast);
299 } 296 }
300 297
301 /// Creates a literal js string from [value]. 298 /// Creates a literal js string from [value].
302 LiteralString _legacyEscapedString(String value) { 299 LiteralString _legacyEscapedString(String value) {
303 // Start by escaping the backslashes. 300 // Start by escaping the backslashes.
304 String escaped = value.replaceAll('\\', '\\\\'); 301 String escaped = value.replaceAll('\\', '\\\\');
305 // Do not escape unicode characters and ' because they are allowed in the 302 // Do not escape unicode characters and ' because they are allowed in the
306 // string literal anyway. 303 // string literal anyway.
307 escaped = escaped.replaceAllMapped(new RegExp('\n|"|\b|\t|\v|\r'), (match) { 304 escaped = escaped.replaceAllMapped(new RegExp('\n|"|\b|\t|\v|\r'), (match) {
308 switch (match.group(0)) { 305 switch (match.group(0)) {
309 case "\n" : return r"\n"; 306 case "\n":
310 case "\"" : return r'\"'; 307 return r"\n";
311 case "\b" : return r"\b"; 308 case "\"":
312 case "\t" : return r"\t"; 309 return r'\"';
313 case "\f" : return r"\f"; 310 case "\b":
314 case "\r" : return r"\r"; 311 return r"\b";
315 case "\v" : return r"\v"; 312 case "\t":
313 return r"\t";
314 case "\f":
315 return r"\f";
316 case "\r":
317 return r"\r";
318 case "\v":
319 return r"\v";
316 } 320 }
317 }); 321 });
318 LiteralString result = string(escaped); 322 LiteralString result = string(escaped);
319 // We don't escape ' under the assumption that the string is wrapped 323 // We don't escape ' under the assumption that the string is wrapped
320 // into ". Verify that assumption. 324 // into ". Verify that assumption.
321 assert(result.value.codeUnitAt(0) == '"'.codeUnitAt(0)); 325 assert(result.value.codeUnitAt(0) == '"'.codeUnitAt(0));
322 return result; 326 return result;
323 } 327 }
324 328
325 /// Creates a literal js string from [value]. 329 /// Creates a literal js string from [value].
326 LiteralString escapedString(String value, 330 LiteralString escapedString(String value,
327 {bool utf8: false, bool ascii: false}) { 331 {bool utf8: false, bool ascii: false}) {
328 if (utf8 == false && ascii == false) return _legacyEscapedString(value); 332 if (utf8 == false && ascii == false) return _legacyEscapedString(value);
329 if (utf8 && ascii) throw new ArgumentError('Cannot be both UTF8 and ASCII'); 333 if (utf8 && ascii) throw new ArgumentError('Cannot be both UTF8 and ASCII');
330 334
331 int singleQuotes = 0; 335 int singleQuotes = 0;
332 int doubleQuotes = 0; 336 int doubleQuotes = 0;
333 int otherEscapes = 0; 337 int otherEscapes = 0;
334 int unpairedSurrogates = 0; 338 int unpairedSurrogates = 0;
335 339
336 for (int rune in value.runes) { 340 for (int rune in value.runes) {
337 if (rune == charCodes.$BACKSLASH) { 341 if (rune == charCodes.$BACKSLASH) {
338 ++otherEscapes; 342 ++otherEscapes;
339 } else if (rune == charCodes.$SQ) { 343 } else if (rune == charCodes.$SQ) {
340 ++singleQuotes; 344 ++singleQuotes;
341 } else if (rune == charCodes.$DQ) { 345 } else if (rune == charCodes.$DQ) {
342 ++doubleQuotes; 346 ++doubleQuotes;
343 } else if (rune == charCodes.$LF || rune == charCodes.$CR || 347 } else if (rune == charCodes.$LF ||
344 rune == charCodes.$LS || rune == charCodes.$PS) { 348 rune == charCodes.$CR ||
349 rune == charCodes.$LS ||
350 rune == charCodes.$PS) {
345 // Line terminators. 351 // Line terminators.
346 ++otherEscapes; 352 ++otherEscapes;
347 } else if (rune == charCodes.$BS || rune == charCodes.$TAB || 353 } else if (rune == charCodes.$BS ||
348 rune == charCodes.$VTAB || rune == charCodes.$FF) { 354 rune == charCodes.$TAB ||
355 rune == charCodes.$VTAB ||
356 rune == charCodes.$FF) {
349 ++otherEscapes; 357 ++otherEscapes;
350 } else if (_isUnpairedSurrogate(rune)) { 358 } else if (_isUnpairedSurrogate(rune)) {
351 ++unpairedSurrogates; 359 ++unpairedSurrogates;
352 } else { 360 } else {
353 if (ascii && (rune < charCodes.$SPACE || rune >= charCodes.$DEL)) { 361 if (ascii && (rune < charCodes.$SPACE || rune >= charCodes.$DEL)) {
354 ++otherEscapes; 362 ++otherEscapes;
355 } 363 }
356 } 364 }
357 } 365 }
358 366
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 } 409 }
402 } 410 }
403 411
404 return finish(useSingleQuotes ? "'" : '"', sb.toString()); 412 return finish(useSingleQuotes ? "'" : '"', sb.toString());
405 } 413 }
406 414
407 static bool _isUnpairedSurrogate(int code) => (code & 0xFFFFF800) == 0xD800; 415 static bool _isUnpairedSurrogate(int code) => (code & 0xFFFFF800) == 0xD800;
408 416
409 static String _irregularEscape(int code, bool useSingleQuotes) { 417 static String _irregularEscape(int code, bool useSingleQuotes) {
410 switch (code) { 418 switch (code) {
411 case charCodes.$SQ: return useSingleQuotes ? r"\'" : r"'"; 419 case charCodes.$SQ:
412 case charCodes.$DQ: return useSingleQuotes ? r'"' : r'\"'; 420 return useSingleQuotes ? r"\'" : r"'";
413 case charCodes.$BACKSLASH: return r'\\'; 421 case charCodes.$DQ:
414 case charCodes.$BS: return r'\b'; 422 return useSingleQuotes ? r'"' : r'\"';
415 case charCodes.$TAB: return r'\t'; 423 case charCodes.$BACKSLASH:
416 case charCodes.$LF: return r'\n'; 424 return r'\\';
417 case charCodes.$VTAB: return r'\v'; 425 case charCodes.$BS:
418 case charCodes.$FF: return r'\f'; 426 return r'\b';
419 case charCodes.$CR: return r'\r'; 427 case charCodes.$TAB:
428 return r'\t';
429 case charCodes.$LF:
430 return r'\n';
431 case charCodes.$VTAB:
432 return r'\v';
433 case charCodes.$FF:
434 return r'\f';
435 case charCodes.$CR:
436 return r'\r';
420 } 437 }
421 return null; 438 return null;
422 } 439 }
423 440
424 /// Creates a literal js string from [value]. 441 /// Creates a literal js string from [value].
425 /// 442 ///
426 /// Note that this function only puts quotes around [value]. It does not do 443 /// Note that this function only puts quotes around [value]. It does not do
427 /// any escaping, so use only when you can guarantee that [value] does not 444 /// any escaping, so use only when you can guarantee that [value] does not
428 /// contain newlines or backslashes. For escaping the string use 445 /// contain newlines or backslashes. For escaping the string use
429 /// [escapedString]. 446 /// [escapedString].
430 LiteralString string(String value) => new LiteralString('"$value"'); 447 LiteralString string(String value) => new LiteralString('"$value"');
431 448
432 /// Creates an instance of [LiteralString] from [value]. 449 /// Creates an instance of [LiteralString] from [value].
433 /// 450 ///
434 /// Does not add quotes or do any escaping. 451 /// Does not add quotes or do any escaping.
435 LiteralString stringPart(String value) => new LiteralString(value); 452 LiteralString stringPart(String value) => new LiteralString(value);
436 453
437 StringConcatenation concatenateStrings(Iterable<Literal> parts, 454 StringConcatenation concatenateStrings(Iterable<Literal> parts,
438 {addQuotes: false}) { 455 {addQuotes: false}) {
439 List<Literal> _parts; 456 List<Literal> _parts;
440 if (addQuotes) { 457 if (addQuotes) {
441 Literal quote = stringPart('"'); 458 Literal quote = stringPart('"');
442 _parts = <Literal>[quote] 459 _parts = <Literal>[quote]
443 ..addAll(parts) 460 ..addAll(parts)
444 ..add(quote); 461 ..add(quote);
445 } else { 462 } else {
446 _parts = new List.from(parts, growable: false); 463 _parts = new List.from(parts, growable: false);
447 } 464 }
448 return new StringConcatenation(_parts); 465 return new StringConcatenation(_parts);
449 } 466 }
450 467
451 Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) { 468 Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) {
452 return new _InterleaveIterable(list, separator); 469 return new _InterleaveIterable(list, separator);
453 } 470 }
454 471
(...skipping 10 matching lines...) Expand all
465 LiteralBool boolean(bool value) => new LiteralBool(value); 482 LiteralBool boolean(bool value) => new LiteralBool(value);
466 483
467 ArrayInitializer numArray(Iterable<int> list) => 484 ArrayInitializer numArray(Iterable<int> list) =>
468 new ArrayInitializer(list.map(number).toList()); 485 new ArrayInitializer(list.map(number).toList());
469 486
470 ArrayInitializer stringArray(Iterable<String> list) => 487 ArrayInitializer stringArray(Iterable<String> list) =>
471 new ArrayInitializer(list.map(string).toList()); 488 new ArrayInitializer(list.map(string).toList());
472 489
473 Comment comment(String text) => new Comment(text); 490 Comment comment(String text) => new Comment(text);
474 491
475 Call propertyCall(Expression receiver, 492 Call propertyCall(
476 Expression fieldName, 493 Expression receiver, Expression fieldName, List<Expression> arguments) {
477 List<Expression> arguments) {
478 return new Call(new PropertyAccess(receiver, fieldName), arguments); 494 return new Call(new PropertyAccess(receiver, fieldName), arguments);
479 } 495 }
480 496
481 ObjectInitializer objectLiteral(Map<String, Expression> map) { 497 ObjectInitializer objectLiteral(Map<String, Expression> map) {
482 List<Property> properties = <Property>[]; 498 List<Property> properties = <Property>[];
483 map.forEach((name, value) { 499 map.forEach((name, value) {
484 properties.add(new Property(string(name), value)); 500 properties.add(new Property(string(name), value));
485 }); 501 });
486 return new ObjectInitializer(properties); 502 return new ObjectInitializer(properties);
487 } 503 }
488 } 504 }
489 505
490 LiteralString string(String value) => js.string(value); 506 LiteralString string(String value) => js.string(value);
491 LiteralString quoteName(Name name, {allowNull: false}) { 507 LiteralString quoteName(Name name, {allowNull: false}) {
492 return js.quoteName(name, allowNull: allowNull); 508 return js.quoteName(name, allowNull: allowNull);
493 } 509 }
510
494 LiteralString stringPart(String value) => js.stringPart(value); 511 LiteralString stringPart(String value) => js.stringPart(value);
495 Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) { 512 Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) {
496 return js.joinLiterals(list, separator); 513 return js.joinLiterals(list, separator);
497 } 514 }
515
498 StringConcatenation concatenateStrings(Iterable<Literal> parts, 516 StringConcatenation concatenateStrings(Iterable<Literal> parts,
499 {addQuotes: false}) { 517 {addQuotes: false}) {
500 return js.concatenateStrings(parts, addQuotes: addQuotes); 518 return js.concatenateStrings(parts, addQuotes: addQuotes);
501 } 519 }
502 520
503 LiteralNumber number(num value) => js.number(value); 521 LiteralNumber number(num value) => js.number(value);
504 ArrayInitializer numArray(Iterable<int> list) => js.numArray(list); 522 ArrayInitializer numArray(Iterable<int> list) => js.numArray(list);
505 ArrayInitializer stringArray(Iterable<String> list) => js.stringArray(list); 523 ArrayInitializer stringArray(Iterable<String> list) => js.stringArray(list);
506 Call propertyCall(Expression receiver, 524 Call propertyCall(
507 Expression fieldName, 525 Expression receiver, Expression fieldName, List<Expression> arguments) {
508 List<Expression> arguments) {
509 return js.propertyCall(receiver, fieldName, arguments); 526 return js.propertyCall(receiver, fieldName, arguments);
510 } 527 }
528
511 ObjectInitializer objectLiteral(Map<String, Expression> map) { 529 ObjectInitializer objectLiteral(Map<String, Expression> map) {
512 return js.objectLiteral(map); 530 return js.objectLiteral(map);
513 } 531 }
514 532
515 class MiniJsParserError { 533 class MiniJsParserError {
516 MiniJsParserError(this.parser, this.message) { } 534 MiniJsParserError(this.parser, this.message) {}
517 535
518 final MiniJsParser parser; 536 final MiniJsParser parser;
519 final String message; 537 final String message;
520 538
521 String toString() { 539 String toString() {
522 int pos = parser.lastPosition; 540 int pos = parser.lastPosition;
523 541
524 // Discard lines following the line containing lastPosition. 542 // Discard lines following the line containing lastPosition.
525 String src = parser.src; 543 String src = parser.src;
526 int newlinePos = src.indexOf('\n', pos); 544 int newlinePos = src.indexOf('\n', pos);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 lastToken = null, 586 lastToken = null,
569 lastPosition = 0, 587 lastPosition = 0,
570 position = 0 { 588 position = 0 {
571 getToken(); 589 getToken();
572 } 590 }
573 591
574 int lastCategory = NONE; 592 int lastCategory = NONE;
575 String lastToken = null; 593 String lastToken = null;
576 int lastPosition = 0; 594 int lastPosition = 0;
577 int position = 0; 595 int position = 0;
578 bool skippedNewline = false; // skipped newline in last getToken? 596 bool skippedNewline = false; // skipped newline in last getToken?
579 final String src; 597 final String src;
580 598
581 final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[]; 599 final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[];
582 bool get hasNamedHoles => 600 bool get hasNamedHoles =>
583 interpolatedValues.isNotEmpty && interpolatedValues.first.isNamed; 601 interpolatedValues.isNotEmpty && interpolatedValues.first.isNamed;
584 bool get hasPositionalHoles => 602 bool get hasPositionalHoles =>
585 interpolatedValues.isNotEmpty && interpolatedValues.first.isPositional; 603 interpolatedValues.isNotEmpty && interpolatedValues.first.isPositional;
586 604
587 static const NONE = -1; 605 static const NONE = -1;
588 static const ALPHA = 0; 606 static const ALPHA = 0;
(...skipping 14 matching lines...) Expand all
603 static const SEMICOLON = 15; 621 static const SEMICOLON = 15;
604 static const HASH = 16; 622 static const HASH = 16;
605 static const WHITESPACE = 17; 623 static const WHITESPACE = 17;
606 static const OTHER = 18; 624 static const OTHER = 18;
607 625
608 // Make sure that ]] is two symbols. 626 // Make sure that ]] is two symbols.
609 bool singleCharCategory(int category) => category >= DOT; 627 bool singleCharCategory(int category) => category >= DOT;
610 628
611 static String categoryToString(int cat) { 629 static String categoryToString(int cat) {
612 switch (cat) { 630 switch (cat) {
613 case NONE: return "NONE"; 631 case NONE:
614 case ALPHA: return "ALPHA"; 632 return "NONE";
615 case NUMERIC: return "NUMERIC"; 633 case ALPHA:
616 case SYMBOL: return "SYMBOL"; 634 return "ALPHA";
617 case ASSIGNMENT: return "ASSIGNMENT"; 635 case NUMERIC:
618 case DOT: return "DOT"; 636 return "NUMERIC";
619 case LPAREN: return "LPAREN"; 637 case SYMBOL:
620 case RPAREN: return "RPAREN"; 638 return "SYMBOL";
621 case LBRACE: return "LBRACE"; 639 case ASSIGNMENT:
622 case RBRACE: return "RBRACE"; 640 return "ASSIGNMENT";
623 case LSQUARE: return "LSQUARE"; 641 case DOT:
624 case RSQUARE: return "RSQUARE"; 642 return "DOT";
625 case STRING: return "STRING"; 643 case LPAREN:
626 case COMMA: return "COMMA"; 644 return "LPAREN";
627 case QUERY: return "QUERY"; 645 case RPAREN:
628 case COLON: return "COLON"; 646 return "RPAREN";
629 case SEMICOLON: return "SEMICOLON"; 647 case LBRACE:
630 case HASH: return "HASH"; 648 return "LBRACE";
631 case WHITESPACE: return "WHITESPACE"; 649 case RBRACE:
632 case OTHER: return "OTHER"; 650 return "RBRACE";
651 case LSQUARE:
652 return "LSQUARE";
653 case RSQUARE:
654 return "RSQUARE";
655 case STRING:
656 return "STRING";
657 case COMMA:
658 return "COMMA";
659 case QUERY:
660 return "QUERY";
661 case COLON:
662 return "COLON";
663 case SEMICOLON:
664 return "SEMICOLON";
665 case HASH:
666 return "HASH";
667 case WHITESPACE:
668 return "WHITESPACE";
669 case OTHER:
670 return "OTHER";
633 } 671 }
634 return "Unknown: $cat"; 672 return "Unknown: $cat";
635 } 673 }
636 674
637 static const CATEGORIES = const <int>[ 675 static const CATEGORIES = const <int>[
638 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 0-7 676 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 0-7
639 OTHER, WHITESPACE, WHITESPACE, OTHER, OTHER, WHITESPACE, // 8-13 677 OTHER, WHITESPACE, WHITESPACE, OTHER, OTHER, WHITESPACE, // 8-13
640 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 14-21 678 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 14-21
641 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 22-29 679 OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 22-29
642 OTHER, OTHER, WHITESPACE, // 30-32 680 OTHER, OTHER, WHITESPACE, // 30-32
643 SYMBOL, OTHER, HASH, ALPHA, SYMBOL, SYMBOL, OTHER, // !"#$%&´ 681 SYMBOL, OTHER, HASH, ALPHA, SYMBOL, SYMBOL, OTHER, // !"#$%&´
644 LPAREN, RPAREN, SYMBOL, SYMBOL, COMMA, SYMBOL, DOT, SYMBOL, // ()*+,-./ 682 LPAREN, RPAREN, SYMBOL, SYMBOL, COMMA, SYMBOL, DOT, SYMBOL, // ()*+,-./
645 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 01234 683 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 01234
646 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 56789 684 NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 56789
647 COLON, SEMICOLON, SYMBOL, SYMBOL, SYMBOL, QUERY, OTHER, // :;<=>?@ 685 COLON, SEMICOLON, SYMBOL, SYMBOL, SYMBOL, QUERY, OTHER, // :;<=>?@
648 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ABCDEFGH 686 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ABCDEFGH
649 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // IJKLMNOP 687 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // IJKLMNOP
650 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // QRSTUVWX 688 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // QRSTUVWX
651 ALPHA, ALPHA, LSQUARE, OTHER, RSQUARE, SYMBOL, ALPHA, OTHER, // YZ[\]^_' 689 ALPHA, ALPHA, LSQUARE, OTHER, RSQUARE, SYMBOL, ALPHA, OTHER, // YZ[\]^_'
652 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // abcdefgh 690 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // abcdefgh
653 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ijklmnop 691 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ijklmnop
654 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // qrstuvwx 692 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // qrstuvwx
655 ALPHA, ALPHA, LBRACE, SYMBOL, RBRACE, SYMBOL]; // yz{|}~ 693 ALPHA, ALPHA, LBRACE, SYMBOL, RBRACE, SYMBOL
694 ]; // yz{|}~
656 695
657 // This must be a >= the highest precedence number handled by parseBinary. 696 // This must be a >= the highest precedence number handled by parseBinary.
658 static var HIGHEST_PARSE_BINARY_PRECEDENCE = 16; 697 static var HIGHEST_PARSE_BINARY_PRECEDENCE = 16;
659 static bool isAssignment(String symbol) => BINARY_PRECEDENCE[symbol] == 17; 698 static bool isAssignment(String symbol) => BINARY_PRECEDENCE[symbol] == 17;
660 699
661 // From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operator s/Operator_Precedence 700 // From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operator s/Operator_Precedence
662 static final BINARY_PRECEDENCE = { 701 static final BINARY_PRECEDENCE = {
663 '+=': 17, '-=': 17, '*=': 17, '/=': 17, '%=': 17, '^=': 17, '|=': 17, 702 '+=': 17,
664 '&=': 17, '<<=': 17, '>>=': 17, '>>>=': 17, '=': 17, 703 '-=': 17,
665 '||': 14, 704 '*=': 17,
666 '&&': 13, 705 '/=': 17,
667 '|': 12, 706 '%=': 17,
668 '^': 11, 707 '^=': 17,
669 '&': 10, 708 '|=': 17,
670 '!=': 9, '==': 9, '!==': 9, '===': 9, 709 '&=': 17,
671 '<': 8, '<=': 8, '>=': 8, '>': 8, 'in': 8, 'instanceof': 8, 710 '<<=': 17,
672 '<<': 7, '>>': 7, '>>>': 7, 711 '>>=': 17,
673 '+': 6, '-': 6, 712 '>>>=': 17,
674 '*': 5, '/': 5, '%': 5 713 '=': 17,
714 '||': 14,
715 '&&': 13,
716 '|': 12,
717 '^': 11,
718 '&': 10,
719 '!=': 9,
720 '==': 9,
721 '!==': 9,
722 '===': 9,
723 '<': 8,
724 '<=': 8,
725 '>=': 8,
726 '>': 8,
727 'in': 8,
728 'instanceof': 8,
729 '<<': 7,
730 '>>': 7,
731 '>>>': 7,
732 '+': 6,
733 '-': 6,
734 '*': 5,
735 '/': 5,
736 '%': 5
675 }; 737 };
676 static final UNARY_OPERATORS = 738 static final UNARY_OPERATORS = [
677 ['++', '--', '+', '-', '~', '!', 'typeof', 'void', 'delete', 'await'] 739 '++',
678 .toSet(); 740 '--',
741 '+',
742 '-',
743 '~',
744 '!',
745 'typeof',
746 'void',
747 'delete',
748 'await'
749 ].toSet();
679 750
680 static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS = 751 static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS =
681 ['typeof', 'void', 'delete', 'in', 'instanceof', 'await'].toSet(); 752 ['typeof', 'void', 'delete', 'in', 'instanceof', 'await'].toSet();
682 753
683 static int category(int code) { 754 static int category(int code) {
684 if (code >= CATEGORIES.length) return OTHER; 755 if (code >= CATEGORIES.length) return OTHER;
685 return CATEGORIES[code]; 756 return CATEGORIES[code];
686 } 757 }
687 758
688 String getDelimited(int startPosition) { 759 String getDelimited(int startPosition) {
689 position = startPosition; 760 position = startPosition;
690 int delimiter = src.codeUnitAt(startPosition); 761 int delimiter = src.codeUnitAt(startPosition);
691 int currentCode; 762 int currentCode;
692 do { 763 do {
693 position++; 764 position++;
694 if (position >= src.length) error("Unterminated literal"); 765 if (position >= src.length) error("Unterminated literal");
695 currentCode = src.codeUnitAt(position); 766 currentCode = src.codeUnitAt(position);
696 if (currentCode == charCodes.$LF) error("Unterminated literal"); 767 if (currentCode == charCodes.$LF) error("Unterminated literal");
697 if (currentCode == charCodes.$BACKSLASH) { 768 if (currentCode == charCodes.$BACKSLASH) {
698 if (++position >= src.length) error("Unterminated literal"); 769 if (++position >= src.length) error("Unterminated literal");
699 int escaped = src.codeUnitAt(position); 770 int escaped = src.codeUnitAt(position);
700 if (escaped == charCodes.$x || escaped == charCodes.$X || 771 if (escaped == charCodes.$x ||
701 escaped == charCodes.$u || escaped == charCodes.$U || 772 escaped == charCodes.$X ||
773 escaped == charCodes.$u ||
774 escaped == charCodes.$U ||
702 category(escaped) == NUMERIC) { 775 category(escaped) == NUMERIC) {
703 error('Numeric and hex escapes are not allowed in literals'); 776 error('Numeric and hex escapes are not allowed in literals');
704 } 777 }
705 } 778 }
706 } while (currentCode != delimiter); 779 } while (currentCode != delimiter);
707 position++; 780 position++;
708 return src.substring(lastPosition, position); 781 return src.substring(lastPosition, position);
709 } 782 }
710 783
711 void getToken() { 784 void getToken() {
712 skippedNewline = false; 785 skippedNewline = false;
713 for (;;) { 786 for (;;) {
714 if (position >= src.length) break; 787 if (position >= src.length) break;
715 int code = src.codeUnitAt(position); 788 int code = src.codeUnitAt(position);
716 // Skip '//' and '/*' style comments. 789 // Skip '//' and '/*' style comments.
717 if (code == charCodes.$SLASH && 790 if (code == charCodes.$SLASH && position + 1 < src.length) {
718 position + 1 < src.length) {
719 if (src.codeUnitAt(position + 1) == charCodes.$SLASH) { 791 if (src.codeUnitAt(position + 1) == charCodes.$SLASH) {
720 int nextPosition = src.indexOf('\n', position); 792 int nextPosition = src.indexOf('\n', position);
721 if (nextPosition == -1) nextPosition = src.length; 793 if (nextPosition == -1) nextPosition = src.length;
722 position = nextPosition; 794 position = nextPosition;
723 continue; 795 continue;
724 } else if (src.codeUnitAt(position + 1) == charCodes.$STAR) { 796 } else if (src.codeUnitAt(position + 1) == charCodes.$STAR) {
725 int nextPosition = src.indexOf('*/', position + 2); 797 int nextPosition = src.indexOf('*/', position + 2);
726 if (nextPosition == -1) error('Unterminated comment'); 798 if (nextPosition == -1) error('Unterminated comment');
727 position = nextPosition + 2; 799 position = nextPosition + 2;
728 continue; 800 continue;
(...skipping 10 matching lines...) Expand all
739 lastPosition = position; 811 lastPosition = position;
740 return; 812 return;
741 } 813 }
742 int code = src.codeUnitAt(position); 814 int code = src.codeUnitAt(position);
743 lastPosition = position; 815 lastPosition = position;
744 if (code == charCodes.$SQ || code == charCodes.$DQ) { 816 if (code == charCodes.$SQ || code == charCodes.$DQ) {
745 // String literal. 817 // String literal.
746 lastCategory = STRING; 818 lastCategory = STRING;
747 lastToken = getDelimited(position); 819 lastToken = getDelimited(position);
748 } else if (code == charCodes.$0 && 820 } else if (code == charCodes.$0 &&
749 position + 2 < src.length && 821 position + 2 < src.length &&
750 src.codeUnitAt(position + 1) == charCodes.$x) { 822 src.codeUnitAt(position + 1) == charCodes.$x) {
751 // Hex literal. 823 // Hex literal.
752 for (position += 2; position < src.length; position++) { 824 for (position += 2; position < src.length; position++) {
753 int cat = category(src.codeUnitAt(position)); 825 int cat = category(src.codeUnitAt(position));
754 if (cat != NUMERIC && cat != ALPHA) break; 826 if (cat != NUMERIC && cat != ALPHA) break;
755 } 827 }
756 lastCategory = NUMERIC; 828 lastCategory = NUMERIC;
757 lastToken = src.substring(lastPosition, position); 829 lastToken = src.substring(lastPosition, position);
758 int.parse(lastToken, onError: (_) { 830 int.parse(lastToken, onError: (_) {
759 error("Unparseable number"); 831 error("Unparseable number");
760 }); 832 });
761 } else if (code == charCodes.$SLASH) { 833 } else if (code == charCodes.$SLASH) {
762 // Tokens that start with / are special due to regexp literals. 834 // Tokens that start with / are special due to regexp literals.
763 lastCategory = SYMBOL; 835 lastCategory = SYMBOL;
764 position++; 836 position++;
765 if (position < src.length && src.codeUnitAt(position) == charCodes.$EQ) { 837 if (position < src.length && src.codeUnitAt(position) == charCodes.$EQ) {
766 position++; 838 position++;
767 } 839 }
768 lastToken = src.substring(lastPosition, position); 840 lastToken = src.substring(lastPosition, position);
769 } else { 841 } else {
770 // All other tokens handled here. 842 // All other tokens handled here.
771 int cat = category(src.codeUnitAt(position)); 843 int cat = category(src.codeUnitAt(position));
772 int newCat; 844 int newCat;
773 do { 845 do {
774 position++; 846 position++;
775 if (position == src.length) break; 847 if (position == src.length) break;
776 int code = src.codeUnitAt(position); 848 int code = src.codeUnitAt(position);
777 // Special code to disallow !, ~ and / in non-first position in token, 849 // Special code to disallow !, ~ and / in non-first position in token,
778 // so that !! and ~~ parse as two tokens and != parses as one, while =/ 850 // so that !! and ~~ parse as two tokens and != parses as one, while =/
779 // parses as a an equals token followed by a regexp literal start. 851 // parses as a an equals token followed by a regexp literal start.
780 newCat = 852 newCat = (code == charCodes.$BANG ||
781 (code == charCodes.$BANG || 853 code == charCodes.$SLASH ||
782 code == charCodes.$SLASH || 854 code == charCodes.$TILDE)
783 code == charCodes.$TILDE)
784 ? NONE 855 ? NONE
785 : category(code); 856 : category(code);
786 } while (!singleCharCategory(cat) && 857 } while (!singleCharCategory(cat) &&
787 (cat == newCat || 858 (cat == newCat ||
788 (cat == ALPHA && newCat == NUMERIC) || // eg. level42. 859 (cat == ALPHA && newCat == NUMERIC) || // eg. level42.
789 (cat == NUMERIC && newCat == DOT))); // eg. 3.1415 860 (cat == NUMERIC && newCat == DOT))); // eg. 3.1415
790 lastCategory = cat; 861 lastCategory = cat;
791 lastToken = src.substring(lastPosition, position); 862 lastToken = src.substring(lastPosition, position);
792 if (cat == NUMERIC) { 863 if (cat == NUMERIC) {
793 double.parse(lastToken, (_) { 864 double.parse(lastToken, (_) {
794 error("Unparseable number"); 865 error("Unparseable number");
795 }); 866 });
796 } else if (cat == SYMBOL) { 867 } else if (cat == SYMBOL) {
797 int binaryPrecendence = BINARY_PRECEDENCE[lastToken]; 868 int binaryPrecendence = BINARY_PRECEDENCE[lastToken];
798 if (binaryPrecendence == null && !UNARY_OPERATORS.contains(lastToken)) { 869 if (binaryPrecendence == null && !UNARY_OPERATORS.contains(lastToken)) {
799 error("Unknown operator"); 870 error("Unknown operator");
(...skipping 22 matching lines...) Expand all
822 893
823 void expectSemicolon() { 894 void expectSemicolon() {
824 if (acceptSemicolon()) return; 895 if (acceptSemicolon()) return;
825 error('Expected SEMICOLON'); 896 error('Expected SEMICOLON');
826 } 897 }
827 898
828 bool acceptSemicolon() { 899 bool acceptSemicolon() {
829 // Accept semicolon or automatically inserted semicolon before close brace. 900 // Accept semicolon or automatically inserted semicolon before close brace.
830 // Miniparser forbids other kinds of semicolon insertion. 901 // Miniparser forbids other kinds of semicolon insertion.
831 if (RBRACE == lastCategory) return true; 902 if (RBRACE == lastCategory) return true;
832 if (NONE == lastCategory) return true; // end of input 903 if (NONE == lastCategory) return true; // end of input
833 if (skippedNewline) { 904 if (skippedNewline) {
834 error('No automatic semicolon insertion at preceding newline'); 905 error('No automatic semicolon insertion at preceding newline');
835 } 906 }
836 return acceptCategory(SEMICOLON); 907 return acceptCategory(SEMICOLON);
837 } 908 }
838 909
839 bool acceptString(String string) { 910 bool acceptString(String string) {
840 if (lastToken == string) { 911 if (lastToken == string) {
841 getToken(); 912 getToken();
842 return true; 913 return true;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 List<Property> properties = <Property>[]; 1048 List<Property> properties = <Property>[];
978 for (;;) { 1049 for (;;) {
979 if (acceptCategory(RBRACE)) break; 1050 if (acceptCategory(RBRACE)) break;
980 // Limited subset: keys are identifiers, no 'get' or 'set' properties. 1051 // Limited subset: keys are identifiers, no 'get' or 'set' properties.
981 Literal propertyName; 1052 Literal propertyName;
982 String identifier = lastToken; 1053 String identifier = lastToken;
983 if (acceptCategory(ALPHA)) { 1054 if (acceptCategory(ALPHA)) {
984 propertyName = new LiteralString('"$identifier"'); 1055 propertyName = new LiteralString('"$identifier"');
985 } else if (acceptCategory(STRING)) { 1056 } else if (acceptCategory(STRING)) {
986 propertyName = new LiteralString(identifier); 1057 propertyName = new LiteralString(identifier);
987 } else if (acceptCategory(SYMBOL)) { // e.g. void 1058 } else if (acceptCategory(SYMBOL)) {
1059 // e.g. void
988 propertyName = new LiteralString('"$identifier"'); 1060 propertyName = new LiteralString('"$identifier"');
989 } else if (acceptCategory(HASH)) { 1061 } else if (acceptCategory(HASH)) {
990 var nameOrPosition = parseHash(); 1062 var nameOrPosition = parseHash();
991 InterpolatedLiteral interpolatedLiteral = 1063 InterpolatedLiteral interpolatedLiteral =
992 new InterpolatedLiteral(nameOrPosition); 1064 new InterpolatedLiteral(nameOrPosition);
993 interpolatedValues.add(interpolatedLiteral); 1065 interpolatedValues.add(interpolatedLiteral);
994 propertyName = interpolatedLiteral; 1066 propertyName = interpolatedLiteral;
995 } else { 1067 } else {
996 error('Expected property name'); 1068 error('Expected property name');
997 } 1069 }
(...skipping 29 matching lines...) Expand all
1027 if (acceptCategory(LPAREN)) { 1099 if (acceptCategory(LPAREN)) {
1028 final arguments = <Expression>[]; 1100 final arguments = <Expression>[];
1029 if (!acceptCategory(RPAREN)) { 1101 if (!acceptCategory(RPAREN)) {
1030 while (true) { 1102 while (true) {
1031 Expression argument = parseAssignment(); 1103 Expression argument = parseAssignment();
1032 arguments.add(argument); 1104 arguments.add(argument);
1033 if (acceptCategory(RPAREN)) break; 1105 if (acceptCategory(RPAREN)) break;
1034 expectCategory(COMMA); 1106 expectCategory(COMMA);
1035 } 1107 }
1036 } 1108 }
1037 receiver = constructor ? 1109 receiver = constructor
1038 new New(receiver, arguments) : 1110 ? new New(receiver, arguments)
1039 new Call(receiver, arguments); 1111 : new Call(receiver, arguments);
1040 constructor = false; 1112 constructor = false;
1041 } else if (!constructor && acceptCategory(LSQUARE)) { 1113 } else if (!constructor && acceptCategory(LSQUARE)) {
1042 Expression inBraces = parseExpression(); 1114 Expression inBraces = parseExpression();
1043 expectCategory(RSQUARE); 1115 expectCategory(RSQUARE);
1044 receiver = new PropertyAccess(receiver, inBraces); 1116 receiver = new PropertyAccess(receiver, inBraces);
1045 } else if (!constructor && acceptCategory(DOT)) { 1117 } else if (!constructor && acceptCategory(DOT)) {
1046 receiver = getDotRhs(receiver); 1118 receiver = getDotRhs(receiver);
1047 } else { 1119 } else {
1048 // JS allows new without (), but we don't. 1120 // JS allows new without (), but we don't.
1049 if (constructor) error("Parentheses are required for new"); 1121 if (constructor) error("Parentheses are required for new");
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 return new Postfix(operator, expression); 1156 return new Postfix(operator, expression);
1085 } 1157 }
1086 // If we don't accept '++' or '--' due to skippedNewline a newline, no other 1158 // If we don't accept '++' or '--' due to skippedNewline a newline, no other
1087 // part of the parser will accept the token and we will get an error at the 1159 // part of the parser will accept the token and we will get an error at the
1088 // whole expression level. 1160 // whole expression level.
1089 return expression; 1161 return expression;
1090 } 1162 }
1091 1163
1092 Expression parseUnaryHigh() { 1164 Expression parseUnaryHigh() {
1093 String operator = lastToken; 1165 String operator = lastToken;
1094 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && 1166 if (lastCategory == SYMBOL &&
1167 UNARY_OPERATORS.contains(operator) &&
1095 (acceptString("++") || acceptString("--") || acceptString('await'))) { 1168 (acceptString("++") || acceptString("--") || acceptString('await'))) {
1096 if (operator == "await") return new Await(parsePostfix()); 1169 if (operator == "await") return new Await(parsePostfix());
1097 return new Prefix(operator, parsePostfix()); 1170 return new Prefix(operator, parsePostfix());
1098 } 1171 }
1099 return parsePostfix(); 1172 return parsePostfix();
1100 } 1173 }
1101 1174
1102 Expression parseUnaryLow() { 1175 Expression parseUnaryLow() {
1103 String operator = lastToken; 1176 String operator = lastToken;
1104 if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) && 1177 if (lastCategory == SYMBOL &&
1105 operator != "++" && operator != "--") { 1178 UNARY_OPERATORS.contains(operator) &&
1179 operator != "++" &&
1180 operator != "--") {
1106 expectCategory(SYMBOL); 1181 expectCategory(SYMBOL);
1107 if (operator == "await") return new Await(parsePostfix()); 1182 if (operator == "await") return new Await(parsePostfix());
1108 return new Prefix(operator, parseUnaryLow()); 1183 return new Prefix(operator, parseUnaryLow());
1109 } 1184 }
1110 return parseUnaryHigh(); 1185 return parseUnaryHigh();
1111 } 1186 }
1112 1187
1113 Expression parseBinary(int maxPrecedence) { 1188 Expression parseBinary(int maxPrecedence) {
1114 Expression lhs = parseUnaryLow(); 1189 Expression lhs = parseUnaryLow();
1115 int minPrecedence; 1190 int minPrecedence;
1116 String lastSymbol; 1191 String lastSymbol;
1117 Expression rhs; // This is null first time around. 1192 Expression rhs; // This is null first time around.
1118 while (true) { 1193 while (true) {
1119 String symbol = lastToken; 1194 String symbol = lastToken;
1120 if (lastCategory != SYMBOL || 1195 if (lastCategory != SYMBOL ||
1121 !BINARY_PRECEDENCE.containsKey(symbol) || 1196 !BINARY_PRECEDENCE.containsKey(symbol) ||
1122 BINARY_PRECEDENCE[symbol] > maxPrecedence) { 1197 BINARY_PRECEDENCE[symbol] > maxPrecedence) {
1123 break; 1198 break;
1124 } 1199 }
1125 expectCategory(SYMBOL); 1200 expectCategory(SYMBOL);
1126 if (rhs == null || BINARY_PRECEDENCE[symbol] >= minPrecedence) { 1201 if (rhs == null || BINARY_PRECEDENCE[symbol] >= minPrecedence) {
1127 if (rhs != null) lhs = new Binary(lastSymbol, lhs, rhs); 1202 if (rhs != null) lhs = new Binary(lastSymbol, lhs, rhs);
(...skipping 11 matching lines...) Expand all
1139 1214
1140 Expression parseConditional() { 1215 Expression parseConditional() {
1141 Expression lhs = parseBinary(HIGHEST_PARSE_BINARY_PRECEDENCE); 1216 Expression lhs = parseBinary(HIGHEST_PARSE_BINARY_PRECEDENCE);
1142 if (!acceptCategory(QUERY)) return lhs; 1217 if (!acceptCategory(QUERY)) return lhs;
1143 Expression ifTrue = parseAssignment(); 1218 Expression ifTrue = parseAssignment();
1144 expectCategory(COLON); 1219 expectCategory(COLON);
1145 Expression ifFalse = parseAssignment(); 1220 Expression ifFalse = parseAssignment();
1146 return new Conditional(lhs, ifTrue, ifFalse); 1221 return new Conditional(lhs, ifTrue, ifFalse);
1147 } 1222 }
1148 1223
1149
1150 Expression parseAssignment() { 1224 Expression parseAssignment() {
1151 Expression lhs = parseConditional(); 1225 Expression lhs = parseConditional();
1152 String assignmentOperator = lastToken; 1226 String assignmentOperator = lastToken;
1153 if (acceptCategory(ASSIGNMENT)) { 1227 if (acceptCategory(ASSIGNMENT)) {
1154 Expression rhs = parseAssignment(); 1228 Expression rhs = parseAssignment();
1155 if (assignmentOperator == "=") { 1229 if (assignmentOperator == "=") {
1156 return new Assignment(lhs, rhs); 1230 return new Assignment(lhs, rhs);
1157 } else { 1231 } else {
1158 // Handle +=, -=, etc. 1232 // Handle +=, -=, etc.
1159 String operator = 1233 String operator =
1160 assignmentOperator.substring(0, assignmentOperator.length - 1); 1234 assignmentOperator.substring(0, assignmentOperator.length - 1);
1161 return new Assignment.compound(lhs, operator, rhs); 1235 return new Assignment.compound(lhs, operator, rhs);
1162 } 1236 }
1163 } 1237 }
1164 return lhs; 1238 return lhs;
1165 } 1239 }
1166 1240
1167 Expression parseExpression() { 1241 Expression parseExpression() {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 1347
1274 if (lastToken == 'case') error("Case outside switch."); 1348 if (lastToken == 'case') error("Case outside switch.");
1275 1349
1276 if (lastToken == 'default') error("Default outside switch."); 1350 if (lastToken == 'default') error("Default outside switch.");
1277 1351
1278 if (lastToken == 'yield') return parseYield(); 1352 if (lastToken == 'yield') return parseYield();
1279 1353
1280 if (lastToken == 'with') { 1354 if (lastToken == 'with') {
1281 error('Not implemented in mini parser'); 1355 error('Not implemented in mini parser');
1282 } 1356 }
1283
1284 } 1357 }
1285 1358
1286 bool checkForInterpolatedStatement = lastCategory == HASH; 1359 bool checkForInterpolatedStatement = lastCategory == HASH;
1287 1360
1288 Expression expression = parseExpression(); 1361 Expression expression = parseExpression();
1289 1362
1290 if (expression is VariableUse && acceptCategory(COLON)) { 1363 if (expression is VariableUse && acceptCategory(COLON)) {
1291 return new LabeledStatement(expression.name, parseStatement()); 1364 return new LabeledStatement(expression.name, parseStatement());
1292 } 1365 }
1293 1366
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 return finishFor(null); 1453 return finishFor(null);
1381 } 1454 }
1382 1455
1383 if (acceptString('var')) { 1456 if (acceptString('var')) {
1384 Declaration declaration = parseVariableDeclaration(); 1457 Declaration declaration = parseVariableDeclaration();
1385 if (acceptString('in')) { 1458 if (acceptString('in')) {
1386 Expression objectExpression = parseExpression(); 1459 Expression objectExpression = parseExpression();
1387 expectCategory(RPAREN); 1460 expectCategory(RPAREN);
1388 Statement body = parseStatement(); 1461 Statement body = parseStatement();
1389 return new ForIn( 1462 return new ForIn(
1390 new VariableDeclarationList([ 1463 new VariableDeclarationList(
1391 new VariableInitialization(declaration, null)]), 1464 [new VariableInitialization(declaration, null)]),
1392 objectExpression, 1465 objectExpression,
1393 body); 1466 body);
1394 } 1467 }
1395 Expression declarations = finishVariableDeclarationList(declaration); 1468 Expression declarations = finishVariableDeclarationList(declaration);
1396 expectCategory(SEMICOLON); 1469 expectCategory(SEMICOLON);
1397 return finishFor(declarations); 1470 return finishFor(declarations);
1398 } 1471 }
1399 1472
1400 Expression init = parseExpression(); 1473 Expression init = parseExpression();
1401 expectCategory(SEMICOLON); 1474 expectCategory(SEMICOLON);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1443 expression = parseExpression(); 1516 expression = parseExpression();
1444 expectCategory(COLON); 1517 expectCategory(COLON);
1445 } else { 1518 } else {
1446 if (!acceptString('default')) { 1519 if (!acceptString('default')) {
1447 error('expected case or default'); 1520 error('expected case or default');
1448 } 1521 }
1449 expectCategory(COLON); 1522 expectCategory(COLON);
1450 } 1523 }
1451 List statements = new List<Statement>(); 1524 List statements = new List<Statement>();
1452 while (lastCategory != RBRACE && 1525 while (lastCategory != RBRACE &&
1453 lastToken != 'case' && 1526 lastToken != 'case' &&
1454 lastToken != 'default') { 1527 lastToken != 'default') {
1455 statements.add(parseStatement()); 1528 statements.add(parseStatement());
1456 } 1529 }
1457 return expression == null 1530 return expression == null
1458 ? new Default(new Block(statements)) 1531 ? new Default(new Block(statements))
1459 : new Case(expression, new Block(statements)); 1532 : new Case(expression, new Block(statements));
1460 } 1533 }
1461 1534
1462 Statement parseWhile() { 1535 Statement parseWhile() {
1463 expectCategory(LPAREN); 1536 expectCategory(LPAREN);
1464 Expression condition = parseExpression(); 1537 Expression condition = parseExpression();
(...skipping 12 matching lines...) Expand all
1477 expectSemicolon(); 1550 expectSemicolon();
1478 return new Do(body, condition); 1551 return new Do(body, condition);
1479 } 1552 }
1480 1553
1481 Statement parseSwitch() { 1554 Statement parseSwitch() {
1482 expectCategory(LPAREN); 1555 expectCategory(LPAREN);
1483 Expression key = parseExpression(); 1556 Expression key = parseExpression();
1484 expectCategory(RPAREN); 1557 expectCategory(RPAREN);
1485 expectCategory(LBRACE); 1558 expectCategory(LBRACE);
1486 List<SwitchClause> clauses = new List<SwitchClause>(); 1559 List<SwitchClause> clauses = new List<SwitchClause>();
1487 while(lastCategory != RBRACE) { 1560 while (lastCategory != RBRACE) {
1488 clauses.add(parseSwitchClause()); 1561 clauses.add(parseSwitchClause());
1489 } 1562 }
1490 expectCategory(RBRACE); 1563 expectCategory(RBRACE);
1491 return new Switch(key, clauses); 1564 return new Switch(key, clauses);
1492 } 1565 }
1493 1566
1494 Catch parseCatch() { 1567 Catch parseCatch() {
1495 expectCategory(LPAREN); 1568 expectCategory(LPAREN);
1496 Declaration errorName = parseVariableDeclaration(); 1569 Declaration errorName = parseVariableDeclaration();
1497 expectCategory(RPAREN); 1570 expectCategory(RPAREN);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 class _InterleaveIterable extends IterableBase { 1603 class _InterleaveIterable extends IterableBase {
1531 Iterable<Node> source; 1604 Iterable<Node> source;
1532 Node separator; 1605 Node separator;
1533 1606
1534 _InterleaveIterable(this.source, this.separator); 1607 _InterleaveIterable(this.source, this.separator);
1535 1608
1536 Iterator<Node> get iterator { 1609 Iterator<Node> get iterator {
1537 return new _InterleaveIterator(source.iterator, separator); 1610 return new _InterleaveIterator(source.iterator, separator);
1538 } 1611 }
1539 } 1612 }
OLDNEW
« no previous file with comments | « no previous file | pkg/js_ast/lib/src/characters.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698