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

Side by Side Diff: pkg/analyzer/lib/src/generated/parser.dart

Issue 995003002: Clean up parser comments (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.parser; 8 library engine.parser;
9 9
10 import "dart:math" as math; 10 import "dart:math" as math;
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 420
421 Object invokeParserMethodImpl( 421 Object invokeParserMethodImpl(
422 Parser parser, String methodName, List<Object> objects, Token tokenStream) { 422 Parser parser, String methodName, List<Object> objects, Token tokenStream) {
423 parser.currentToken = tokenStream; 423 parser.currentToken = tokenStream;
424 MethodTrampoline method = 424 MethodTrampoline method =
425 methodTable_Parser['${methodName}_${objects.length}']; 425 methodTable_Parser['${methodName}_${objects.length}'];
426 return method.invoke(parser, objects); 426 return method.invoke(parser, objects);
427 } 427 }
428 428
429 /** 429 /**
430 * Instances of the class `CommentAndMetadata` implement a simple data-holder fo r a method 430 * A simple data-holder for a method that needs to return multiple values.
431 * that needs to return multiple values.
432 */ 431 */
433 class CommentAndMetadata { 432 class CommentAndMetadata {
434 /** 433 /**
435 * The documentation comment that was parsed, or `null` if none was given. 434 * The documentation comment that was parsed, or `null` if none was given.
436 */ 435 */
437 final Comment comment; 436 final Comment comment;
438 437
439 /** 438 /**
440 * The metadata that was parsed. 439 * The metadata that was parsed.
441 */ 440 */
442 final List<Annotation> metadata; 441 final List<Annotation> metadata;
443 442
444 /** 443 /**
445 * Initialize a newly created holder with the given data. 444 * Initialize a newly created holder with the given [comment] and [metadata].
446 *
447 * @param comment the documentation comment that was parsed
448 * @param metadata the metadata that was parsed
449 */ 445 */
450 CommentAndMetadata(this.comment, this.metadata); 446 CommentAndMetadata(this.comment, this.metadata);
451 } 447 }
452 448
453 /** 449 /**
454 * Instances of the class `FinalConstVarOrType` implement a simple data-holder f or a method 450 * A simple data-holder for a method that needs to return multiple values.
455 * that needs to return multiple values.
456 */ 451 */
457 class FinalConstVarOrType { 452 class FinalConstVarOrType {
458 /** 453 /**
459 * The 'final', 'const' or 'var' keyword, or `null` if none was given. 454 * The 'final', 'const' or 'var' keyword, or `null` if none was given.
460 */ 455 */
461 final Token keyword; 456 final Token keyword;
462 457
463 /** 458 /**
464 * The type, of `null` if no type was specified. 459 * The type, of `null` if no type was specified.
465 */ 460 */
466 final TypeName type; 461 final TypeName type;
467 462
468 /** 463 /**
469 * Initialize a newly created holder with the given data. 464 * Initialize a newly created holder with the given [keyword] and [type].
470 *
471 * @param keyword the 'final', 'const' or 'var' keyword
472 * @param type the type
473 */ 465 */
474 FinalConstVarOrType(this.keyword, this.type); 466 FinalConstVarOrType(this.keyword, this.type);
475 } 467 }
476 468
477 /** 469 /**
478 * Instances of the class `IncrementalParseDispatcher` implement a dispatcher th at will invoke 470 * A dispatcher that will invoke the right parse method when re-parsing a
479 * the right parse method when re-parsing a specified child of the visited node. All of the methods 471 * specified child of the visited node. All of the methods in this class assume
480 * in this class assume that the parser is positioned to parse the replacement f or the node. All of 472 * that the parser is positioned to parse the replacement for the node. All of
481 * the methods will throw an [IncrementalParseException] if the node could not b e parsed for 473 * the methods will throw an [IncrementalParseException] if the node could not
482 * some reason. 474 * be parsed for some reason.
483 */ 475 */
484 class IncrementalParseDispatcher implements AstVisitor<AstNode> { 476 class IncrementalParseDispatcher implements AstVisitor<AstNode> {
485 /** 477 /**
486 * The parser used to parse the replacement for the node. 478 * The parser used to parse the replacement for the node.
487 */ 479 */
488 final Parser _parser; 480 final Parser _parser;
489 481
490 /** 482 /**
491 * The node that is to be replaced. 483 * The node that is to be replaced.
492 */ 484 */
493 final AstNode _oldNode; 485 final AstNode _oldNode;
494 486
495 /** 487 /**
496 * Initialize a newly created dispatcher to parse a single node that will repl ace the given node. 488 * Initialize a newly created dispatcher to parse a single node that will
497 * 489 * use the [_parser] to replace the [_oldNode].
498 * @param parser the parser used to parse the replacement for the node
499 * @param oldNode the node that is to be replaced
500 */ 490 */
501 IncrementalParseDispatcher(this._parser, this._oldNode); 491 IncrementalParseDispatcher(this._parser, this._oldNode);
502 492
503 @override 493 @override
504 AstNode visitAdjacentStrings(AdjacentStrings node) { 494 AstNode visitAdjacentStrings(AdjacentStrings node) {
505 if (node.strings.contains(_oldNode)) { 495 if (node.strings.contains(_oldNode)) {
506 return _parser.parseStringLiteral(); 496 return _parser.parseStringLiteral();
507 } 497 }
508 return _notAChild(node); 498 return _notAChild(node);
509 } 499 }
(...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 1549
1560 @override 1550 @override
1561 AstNode visitYieldStatement(YieldStatement node) { 1551 AstNode visitYieldStatement(YieldStatement node) {
1562 if (identical(_oldNode, node.expression)) { 1552 if (identical(_oldNode, node.expression)) {
1563 return _parser.parseExpression2(); 1553 return _parser.parseExpression2();
1564 } 1554 }
1565 return _notAChild(node); 1555 return _notAChild(node);
1566 } 1556 }
1567 1557
1568 /** 1558 /**
1569 * Return `true` if the given assignment expression can have a cascade express ion on the 1559 * Return `true` if the given assignment [expression] can have a cascade
1570 * right-hand side. 1560 * expression on the right-hand side.
1571 *
1572 * @param node the assignment expression being tested
1573 * @return `true` if the right-hand side can be a cascade expression
1574 */ 1561 */
1575 bool _isCascadeAllowedInAssignment(AssignmentExpression node) { 1562 bool _isCascadeAllowedInAssignment(AssignmentExpression expression) {
1576 // TODO(brianwilkerson) Implement this method. 1563 // TODO(brianwilkerson) Implement this method.
1577 throw new InsufficientContextException(); 1564 throw new InsufficientContextException();
1578 } 1565 }
1579 1566
1580 /** 1567 /**
1581 * Return `true` if the given throw expression can have a cascade expression. 1568 * Return `true` if the given throw [expression] can have a cascade
1582 * 1569 * expression.
1583 * @param node the throw expression being tested
1584 * @return `true` if the expression can be a cascade expression
1585 */ 1570 */
1586 bool _isCascadeAllowedInThrow(ThrowExpression node) { 1571 bool _isCascadeAllowedInThrow(ThrowExpression expression) {
1587 // TODO(brianwilkerson) Implement this method. 1572 // TODO(brianwilkerson) Implement this method.
1588 throw new InsufficientContextException(); 1573 throw new InsufficientContextException();
1589 } 1574 }
1590 1575
1591 /** 1576 /**
1592 * Throw an exception indicating that the visited node was not the parent of t he node to be 1577 * Throw an exception indicating that the visited [node] was not the parent of
1593 * replaced. 1578 * the node to be replaced.
1594 *
1595 * @param visitedNode the visited node that should have been the parent of the node to be replaced
1596 */ 1579 */
1597 AstNode _notAChild(AstNode visitedNode) { 1580 AstNode _notAChild(AstNode node) {
1598 throw new IncrementalParseException.con1( 1581 throw new IncrementalParseException.con1(
1599 "Internal error: the visited node (a ${visitedNode.runtimeType}) was not the parent of the node to be replaced (a ${_oldNode.runtimeType})"); 1582 "Internal error: the visited node (a ${node.runtimeType}) was not the pa rent of the node to be replaced (a ${_oldNode.runtimeType})");
1600 } 1583 }
1601 } 1584 }
1602 1585
1603 /** 1586 /**
1604 * Instances of the class `IncrementalParseException` represent an exception tha t occurred 1587 * An exception that occurred while attempting to parse a replacement for a
1605 * while attempting to parse a replacement for a specified node in an existing A ST structure. 1588 * specified node in an existing AST structure.
1606 */ 1589 */
1607 class IncrementalParseException extends RuntimeException { 1590 class IncrementalParseException extends RuntimeException {
1608 /** 1591 /**
1609 * Initialize a newly created exception to have no message and to be its own c ause. 1592 * Initialize a newly created exception to have no message and to be its own
1593 * cause.
1610 */ 1594 */
1611 IncrementalParseException() : super(); 1595 IncrementalParseException() : super();
1612 1596
1613 /** 1597 /**
1614 * Initialize a newly created exception to have the given message and to be it s own cause. 1598 * Initialize a newly created exception to have the given [message] and to be
1615 * 1599 * its own cause.
1616 * @param message the message describing the reason for the exception
1617 */ 1600 */
1618 IncrementalParseException.con1(String message) : super(message: message); 1601 IncrementalParseException.con1(String message) : super(message: message);
1619 1602
1620 /** 1603 /**
1621 * Initialize a newly created exception to have no message and to have the giv en cause. 1604 * Initialize a newly created exception to have no message and to have the
1622 * 1605 * given [cause].
1623 * @param cause the exception that caused this exception
1624 */ 1606 */
1625 IncrementalParseException.con2(Exception cause) : super(cause: cause); 1607 IncrementalParseException.con2(Exception cause) : super(cause: cause);
1626 } 1608 }
1627 1609
1628 /** 1610 /**
1629 * Instances of the class `IncrementalParser` re-parse a single AST structure wi thin a larger 1611 * An object used to re-parse a single AST structure within a larger AST
1630 * AST structure. 1612 * structure.
1631 */ 1613 */
1632 class IncrementalParser { 1614 class IncrementalParser {
1633 /** 1615 /**
1634 * The source being parsed. 1616 * The source being parsed.
1635 */ 1617 */
1636 final Source _source; 1618 final Source _source;
1637 1619
1638 /** 1620 /**
1639 * A map from old tokens to new tokens used during the cloning process. 1621 * A map from old tokens to new tokens used during the cloning process.
1640 */ 1622 */
1641 final TokenMap _tokenMap; 1623 final TokenMap _tokenMap;
1642 1624
1643 /** 1625 /**
1644 * The error listener that will be informed of any errors that are found durin g the parse. 1626 * The error listener that will be informed of any errors that are found
1627 * during the parse.
1645 */ 1628 */
1646 final AnalysisErrorListener _errorListener; 1629 final AnalysisErrorListener _errorListener;
1647 1630
1648 /** 1631 /**
1649 * The node in the AST structure that contains the revised content. 1632 * The node in the AST structure that contains the revised content.
1650 */ 1633 */
1651 AstNode _updatedNode; 1634 AstNode _updatedNode;
1652 1635
1653 /** 1636 /**
1654 * Initialize a newly created incremental parser to parse a portion of the con tent of the given 1637 * Initialize a newly created incremental parser to parse a portion of the
1655 * source. 1638 * content of the given [_source]. The [_tokenMap] is a map from old tokens to
1656 * 1639 * new tokens that is used during the cloning process. The [_errorListener]
1657 * @param source the source being parsed 1640 * will be informed of any errors that are found during the parse.
1658 * @param tokenMap a map from old tokens to new tokens used during the cloning process
1659 * @param errorListener the error listener that will be informed of any errors that are found
1660 * during the parse
1661 */ 1641 */
1662 IncrementalParser(this._source, this._tokenMap, this._errorListener); 1642 IncrementalParser(this._source, this._tokenMap, this._errorListener);
1663 1643
1664 /** 1644 /**
1665 * Return the node in the AST structure that contains the revised content. 1645 * Return the node in the AST structure that contains the revised content.
1666 *
1667 * @return the updated node
1668 */ 1646 */
1669 AstNode get updatedNode => _updatedNode; 1647 AstNode get updatedNode => _updatedNode;
1670 1648
1671 /** 1649 /**
1672 * Given a range of tokens that were re-scanned, re-parse the minimum number o f tokens to produce 1650 * Given a range of tokens that were re-scanned, re-parse the minimum number
1673 * a consistent AST structure. The range is represented by the first and last tokens in the range. 1651 * of tokens to produce a consistent AST structure. The range is represented
1652 * by the first and last tokens in the range.
1653 *
1654 * More specifically, the [leftToken] is the token in the new token stream
1655 * immediately to the left of the range of tokens that were inserted and the
1656 * [rightToken] is the token in the new token stream immediately to the right
1657 * of the range of tokens that were inserted. The [originalStart] and
1658 * [originalEnd] are the offsets in the original source of the first and last
1659 * characters that were modified.
1660 *
1674 * The tokens are assumed to be contained in the same token stream. 1661 * The tokens are assumed to be contained in the same token stream.
1675 *
1676 * @param leftToken the token in the new token stream immediately to the left of the range of
1677 * tokens that were inserted
1678 * @param rightToken the token in the new token stream immediately to the righ t of the range of
1679 * tokens that were inserted
1680 * @param originalStart the offset in the original source of the first charact er that was modified
1681 * @param originalEnd the offset in the original source of the last character that was modified
1682 */ 1662 */
1683 AstNode reparse(AstNode originalStructure, Token leftToken, Token rightToken, 1663 AstNode reparse(AstNode originalStructure, Token leftToken, Token rightToken,
1684 int originalStart, int originalEnd) { 1664 int originalStart, int originalEnd) {
1685 AstNode oldNode = null; 1665 AstNode oldNode = null;
1686 AstNode newNode = null; 1666 AstNode newNode = null;
1687 // 1667 //
1688 // Find the first token that needs to be re-parsed. 1668 // Find the first token that needs to be re-parsed.
1689 // 1669 //
1690 Token firstToken = leftToken.next; 1670 Token firstToken = leftToken.next;
1691 if (identical(firstToken, rightToken)) { 1671 if (identical(firstToken, rightToken)) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1766 ResolutionCopier.copyResolutionData(oldNode, newNode); 1746 ResolutionCopier.copyResolutionData(oldNode, newNode);
1767 return newNode; 1747 return newNode;
1768 } 1748 }
1769 ResolutionCopier.copyResolutionData(oldNode, newNode); 1749 ResolutionCopier.copyResolutionData(oldNode, newNode);
1770 IncrementalAstCloner cloner = 1750 IncrementalAstCloner cloner =
1771 new IncrementalAstCloner(oldNode, newNode, _tokenMap); 1751 new IncrementalAstCloner(oldNode, newNode, _tokenMap);
1772 return originalStructure.accept(cloner) as AstNode; 1752 return originalStructure.accept(cloner) as AstNode;
1773 } 1753 }
1774 1754
1775 /** 1755 /**
1776 * Return the first (non-EOF) token in the token stream containing the given t oken. 1756 * Return the first (non-EOF) token in the token stream containing the
1777 * 1757 * [firstToken].
1778 * @param firstToken the token from which the search is to begin
1779 * @return the first token in the token stream containing the given token
1780 */ 1758 */
1781 Token _findFirstToken(Token firstToken) { 1759 Token _findFirstToken(Token firstToken) {
1782 while (firstToken.type != TokenType.EOF) { 1760 while (firstToken.type != TokenType.EOF) {
1783 firstToken = firstToken.previous; 1761 firstToken = firstToken.previous;
1784 } 1762 }
1785 return firstToken.next; 1763 return firstToken.next;
1786 } 1764 }
1787 1765
1788 /** 1766 /**
1789 * Find the token at or before the given token with the given offset, or `null ` if there is 1767 * Find the token at or before the [firstToken] with the given [offset], or
1790 * no such token. 1768 * `null` if there is no such token.
1791 *
1792 * @param firstToken the token from which the search is to begin
1793 * @param offset the offset of the token to be returned
1794 * @return the token with the given offset
1795 */ 1769 */
1796 Token _findTokenAt(Token firstToken, int offset) { 1770 Token _findTokenAt(Token firstToken, int offset) {
1797 while (firstToken.offset > offset && firstToken.type != TokenType.EOF) { 1771 while (firstToken.offset > offset && firstToken.type != TokenType.EOF) {
1798 firstToken = firstToken.previous; 1772 firstToken = firstToken.previous;
1799 } 1773 }
1800 return firstToken; 1774 return firstToken;
1801 } 1775 }
1802 } 1776 }
1803 1777
1804 /** 1778 /**
1805 * Visitor capable of inferring the correct parser state for incremental 1779 * A visitor capable of inferring the correct parser state for incremental
1806 * parsing. This visitor visits each parent/child relationship in the chain of 1780 * parsing. This visitor visits each parent/child relationship in the chain of
1807 * ancestors of the node to be replaced (starting with the root of the parse 1781 * ancestors of the node to be replaced (starting with the root of the parse
1808 * tree), updating the parser to the correct state for parsing the child of the 1782 * tree), updating the parser to the correct state for parsing the child of the
1809 * given parent. Once it has visited all of these relationships, the parser 1783 * given parent. Once it has visited all of these relationships, the parser
1810 * will be in the correct state for reparsing the node to be replaced. 1784 * will be in the correct state for reparsing the node to be replaced.
1811 *
1812 * TODO(paulberry): add support for other pieces of parser state (_inAsync,
1813 * _inGenerator, _inLoop, and _inSwitch). Note that _inLoop and _inSwitch only
1814 * affect error message generation.
1815 */ 1785 */
1816 class IncrementalParseStateBuilder extends SimpleAstVisitor { 1786 class IncrementalParseStateBuilder extends SimpleAstVisitor {
1787 // TODO(paulberry): add support for other pieces of parser state (_inAsync,
1788 // _inGenerator, _inLoop, and _inSwitch). Note that _inLoop and _inSwitch
1789 // only affect error message generation.
1790
1817 /** 1791 /**
1818 * The parser whose state should be built. 1792 * The parser whose state should be built.
1819 */ 1793 */
1820 final Parser _parser; 1794 final Parser _parser;
1821 1795
1822 /** 1796 /**
1823 * The child node in the parent/child relationship currently being visited. 1797 * The child node in the parent/child relationship currently being visited.
1824 * (The corresponding parent is the node passed to the visit...() function.) 1798 * (The corresponding parent is the node passed to the visit...() function.)
1825 */ 1799 */
1826 AstNode _childNode; 1800 AstNode _childNode;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1889 1863
1890 @override 1864 @override
1891 void visitParenthesizedExpression(ParenthesizedExpression node) { 1865 void visitParenthesizedExpression(ParenthesizedExpression node) {
1892 if (identical(_childNode, node.expression)) { 1866 if (identical(_childNode, node.expression)) {
1893 _parser._inInitializer = false; 1867 _parser._inInitializer = false;
1894 } 1868 }
1895 } 1869 }
1896 } 1870 }
1897 1871
1898 /** 1872 /**
1899 * Instances of the class `InsufficientContextException` represent a situation i n which an AST 1873 * An exception indicating that an AST node cannot be re-parsed because there is
1900 * node cannot be re-parsed because there is not enough context to know how to r e-parse the node. 1874 * not enough context to know how to re-parse the node. Clients can attempt to
1901 * Clients can attempt to re-parse the parent of the node. 1875 * re-parse the parent of the node.
1902 */ 1876 */
1903 class InsufficientContextException extends IncrementalParseException { 1877 class InsufficientContextException extends IncrementalParseException {
1904 /** 1878 /**
1905 * Initialize a newly created exception to have no message and to be its own c ause. 1879 * Initialize a newly created exception to have no message and to be its own
1880 * cause.
1906 */ 1881 */
1907 InsufficientContextException() : super(); 1882 InsufficientContextException() : super();
1908 1883
1909 /** 1884 /**
1910 * Initialize a newly created exception to have the given message and to be it s own cause. 1885 * Initialize a newly created exception to have the given [message] and to be
1911 * 1886 * its own cause.
1912 * @param message the message describing the reason for the exception
1913 */ 1887 */
1914 InsufficientContextException.con1(String message) : super.con1(message); 1888 InsufficientContextException.con1(String message) : super.con1(message);
1915 1889
1916 /** 1890 /**
1917 * Initialize a newly created exception to have no message and to have the giv en cause. 1891 * Initialize a newly created exception to have no message and to have the
1918 * 1892 * given [cause].
1919 * @param cause the exception that caused this exception
1920 */ 1893 */
1921 InsufficientContextException.con2(Exception cause) : super.con2(cause); 1894 InsufficientContextException.con2(Exception cause) : super.con2(cause);
1922 } 1895 }
1923 1896
1924 /** 1897 /**
1925 * Wrapper around [Function] which should be called with "target" and "arguments ". 1898 * Wrapper around [Function] which should be called with "target" and
1899 * "arguments".
1926 */ 1900 */
1927 class MethodTrampoline { 1901 class MethodTrampoline {
1928 int parameterCount; 1902 int parameterCount;
1929 Function trampoline; 1903 Function trampoline;
1930 MethodTrampoline(this.parameterCount, this.trampoline); 1904 MethodTrampoline(this.parameterCount, this.trampoline);
1931 Object invoke(target, List arguments) { 1905 Object invoke(target, List arguments) {
1932 if (arguments.length != parameterCount) { 1906 if (arguments.length != parameterCount) {
1933 throw new IllegalArgumentException( 1907 throw new IllegalArgumentException(
1934 "${arguments.length} != $parameterCount"); 1908 "${arguments.length} != $parameterCount");
1935 } 1909 }
1936 switch (parameterCount) { 1910 switch (parameterCount) {
1937 case 0: 1911 case 0:
1938 return trampoline(target); 1912 return trampoline(target);
1939 case 1: 1913 case 1:
1940 return trampoline(target, arguments[0]); 1914 return trampoline(target, arguments[0]);
1941 case 2: 1915 case 2:
1942 return trampoline(target, arguments[0], arguments[1]); 1916 return trampoline(target, arguments[0], arguments[1]);
1943 case 3: 1917 case 3:
1944 return trampoline(target, arguments[0], arguments[1], arguments[2]); 1918 return trampoline(target, arguments[0], arguments[1], arguments[2]);
1945 case 4: 1919 case 4:
1946 return trampoline( 1920 return trampoline(
1947 target, arguments[0], arguments[1], arguments[2], arguments[3]); 1921 target, arguments[0], arguments[1], arguments[2], arguments[3]);
1948 default: 1922 default:
1949 throw new IllegalArgumentException("Not implemented for > 4 arguments"); 1923 throw new IllegalArgumentException("Not implemented for > 4 arguments");
1950 } 1924 }
1951 } 1925 }
1952 } 1926 }
1953 1927
1954 /** 1928 /**
1955 * Instances of the class `Modifiers` implement a simple data-holder for a metho d that needs 1929 * A simple data-holder for a method that needs to return multiple values.
1956 * to return multiple values.
1957 */ 1930 */
1958 class Modifiers { 1931 class Modifiers {
1959 /** 1932 /**
1960 * The token representing the keyword 'abstract', or `null` if the keyword was not found. 1933 * The token representing the keyword 'abstract', or `null` if the keyword was
1934 * not found.
1961 */ 1935 */
1962 Token abstractKeyword; 1936 Token abstractKeyword;
1963 1937
1964 /** 1938 /**
1965 * The token representing the keyword 'const', or `null` if the keyword was no t found. 1939 * The token representing the keyword 'const', or `null` if the keyword was
1940 * not found.
1966 */ 1941 */
1967 Token constKeyword; 1942 Token constKeyword;
1968 1943
1969 /** 1944 /**
1970 * The token representing the keyword 'external', or `null` if the keyword was not found. 1945 * The token representing the keyword 'external', or `null` if the keyword was
1946 * not found.
1971 */ 1947 */
1972 Token externalKeyword; 1948 Token externalKeyword;
1973 1949
1974 /** 1950 /**
1975 * The token representing the keyword 'factory', or `null` if the keyword was not found. 1951 * The token representing the keyword 'factory', or `null` if the keyword was
1952 * not found.
1976 */ 1953 */
1977 Token factoryKeyword; 1954 Token factoryKeyword;
1978 1955
1979 /** 1956 /**
1980 * The token representing the keyword 'final', or `null` if the keyword was no t found. 1957 * The token representing the keyword 'final', or `null` if the keyword was
1958 * not found.
1981 */ 1959 */
1982 Token finalKeyword; 1960 Token finalKeyword;
1983 1961
1984 /** 1962 /**
1985 * The token representing the keyword 'static', or `null` if the keyword was n ot found. 1963 * The token representing the keyword 'static', or `null` if the keyword was
1964 * not found.
1986 */ 1965 */
1987 Token staticKeyword; 1966 Token staticKeyword;
1988 1967
1989 /** 1968 /**
1990 * The token representing the keyword 'var', or `null` if the keyword was not found. 1969 * The token representing the keyword 'var', or `null` if the keyword was not
1970 * found.
1991 */ 1971 */
1992 Token varKeyword; 1972 Token varKeyword;
1993 1973
1994 @override 1974 @override
1995 String toString() { 1975 String toString() {
1996 StringBuffer buffer = new StringBuffer(); 1976 StringBuffer buffer = new StringBuffer();
1997 bool needsSpace = _appendKeyword(buffer, false, abstractKeyword); 1977 bool needsSpace = _appendKeyword(buffer, false, abstractKeyword);
1998 needsSpace = _appendKeyword(buffer, needsSpace, constKeyword); 1978 needsSpace = _appendKeyword(buffer, needsSpace, constKeyword);
1999 needsSpace = _appendKeyword(buffer, needsSpace, externalKeyword); 1979 needsSpace = _appendKeyword(buffer, needsSpace, externalKeyword);
2000 needsSpace = _appendKeyword(buffer, needsSpace, factoryKeyword); 1980 needsSpace = _appendKeyword(buffer, needsSpace, factoryKeyword);
2001 needsSpace = _appendKeyword(buffer, needsSpace, finalKeyword); 1981 needsSpace = _appendKeyword(buffer, needsSpace, finalKeyword);
2002 needsSpace = _appendKeyword(buffer, needsSpace, staticKeyword); 1982 needsSpace = _appendKeyword(buffer, needsSpace, staticKeyword);
2003 _appendKeyword(buffer, needsSpace, varKeyword); 1983 _appendKeyword(buffer, needsSpace, varKeyword);
2004 return buffer.toString(); 1984 return buffer.toString();
2005 } 1985 }
2006 1986
2007 /** 1987 /**
2008 * If the given keyword is not `null`, append it to the given builder, prefixi ng it with a 1988 * If the given [keyword] is not `null`, append it to the given [builder],
2009 * space if needed. 1989 * prefixing it with a space if [needsSpace] is `true`. Return `true` if
2010 * 1990 * subsequent keywords need to be prefixed with a space.
2011 * @param builder the builder to which the keyword will be appended
2012 * @param needsSpace `true` if the keyword needs to be prefixed with a space
2013 * @param keyword the keyword to be appended
2014 * @return `true` if subsequent keywords need to be prefixed with a space
2015 */ 1991 */
2016 bool _appendKeyword(StringBuffer buffer, bool needsSpace, Token keyword) { 1992 bool _appendKeyword(StringBuffer buffer, bool needsSpace, Token keyword) {
2017 if (keyword != null) { 1993 if (keyword != null) {
2018 if (needsSpace) { 1994 if (needsSpace) {
2019 buffer.writeCharCode(0x20); 1995 buffer.writeCharCode(0x20);
2020 } 1996 }
2021 buffer.write(keyword.lexeme); 1997 buffer.write(keyword.lexeme);
2022 return true; 1998 return true;
2023 } 1999 }
2024 return needsSpace; 2000 return needsSpace;
2025 } 2001 }
2026 } 2002 }
2027 2003
2028 /** 2004 /**
2029 * Instances of the class `Parser` are used to parse tokens into an AST structur e. 2005 * A parser used to parse tokens into an AST structure.
2030 */ 2006 */
2031 class Parser { 2007 class Parser {
2032 static String ASYNC = "async"; 2008 static String ASYNC = "async";
2033 2009
2034 static String _AWAIT = "await"; 2010 static String _AWAIT = "await";
2035 2011
2036 static String _HIDE = "hide"; 2012 static String _HIDE = "hide";
2037 2013
2038 static String _OF = "of"; 2014 static String _OF = "of";
2039 2015
2040 static String _ON = "on"; 2016 static String _ON = "on";
2041 2017
2042 static String _NATIVE = "native"; 2018 static String _NATIVE = "native";
2043 2019
2044 static String _SHOW = "show"; 2020 static String _SHOW = "show";
2045 2021
2046 static String SYNC = "sync"; 2022 static String SYNC = "sync";
2047 2023
2048 static String _YIELD = "yield"; 2024 static String _YIELD = "yield";
2049 2025
2050 /** 2026 /**
2051 * The source being parsed. 2027 * The source being parsed.
2052 */ 2028 */
2053 final Source _source; 2029 final Source _source;
2054 2030
2055 /** 2031 /**
2056 * The error listener that will be informed of any errors that are found durin g the parse. 2032 * The error listener that will be informed of any errors that are found
2033 * during the parse.
2057 */ 2034 */
2058 final AnalysisErrorListener _errorListener; 2035 final AnalysisErrorListener _errorListener;
2059 2036
2060 /** 2037 /**
2061 * An [errorListener] lock, if more than `0`, then errors are not reported. 2038 * An [errorListener] lock, if more than `0`, then errors are not reported.
2062 */ 2039 */
2063 int _errorListenerLock = 0; 2040 int _errorListenerLock = 0;
2064 2041
2065 /** 2042 /**
2066 * A flag indicating whether parser is to parse function bodies. 2043 * A flag indicating whether parser is to parse function bodies.
2067 */ 2044 */
2068 bool _parseFunctionBodies = true; 2045 bool _parseFunctionBodies = true;
2069 2046
2070 /** 2047 /**
2071 * The next token to be parsed. 2048 * The next token to be parsed.
2072 */ 2049 */
2073 Token _currentToken; 2050 Token _currentToken;
2074 2051
2075 /** 2052 /**
2076 * A flag indicating whether the parser is currently in a function body marked as being 'async'. 2053 * A flag indicating whether the parser is currently in a function body marked
2054 * as being 'async'.
2077 */ 2055 */
2078 bool _inAsync = false; 2056 bool _inAsync = false;
2079 2057
2080 /** 2058 /**
2081 * A flag indicating whether the parser is currently in a function body marked as being 'async'. 2059 * A flag indicating whether the parser is currently in a function body marked
2060 * as being 'async'.
2082 */ 2061 */
2083 bool _inGenerator = false; 2062 bool _inGenerator = false;
2084 2063
2085 /** 2064 /**
2086 * A flag indicating whether the parser is currently in the body of a loop. 2065 * A flag indicating whether the parser is currently in the body of a loop.
2087 */ 2066 */
2088 bool _inLoop = false; 2067 bool _inLoop = false;
2089 2068
2090 /** 2069 /**
2091 * A flag indicating whether the parser is currently in a switch statement. 2070 * A flag indicating whether the parser is currently in a switch statement.
2092 */ 2071 */
2093 bool _inSwitch = false; 2072 bool _inSwitch = false;
2094 2073
2095 /** 2074 /**
2096 * A flag indicating whether the parser is currently in a constructor field in itializer, with no 2075 * A flag indicating whether the parser is currently in a constructor field
2097 * intervening parens, braces, or brackets. 2076 * initializer, with no intervening parens, braces, or brackets.
2098 */ 2077 */
2099 bool _inInitializer = false; 2078 bool _inInitializer = false;
2100 2079
2101 /** 2080 /**
2102 * Initialize a newly created parser. 2081 * Initialize a newly created parser to parse the content of the given
2103 * 2082 * [_source] and to report any errors that are found to the given
2104 * @param source the source being parsed 2083 * [_errorListener].
2105 * @param errorListener the error listener that will be informed of any errors that are found
2106 * during the parse
2107 */ 2084 */
2108 Parser(this._source, this._errorListener); 2085 Parser(this._source, this._errorListener);
2109 2086
2110 void set currentToken(Token currentToken) { 2087 void set currentToken(Token currentToken) {
2111 this._currentToken = currentToken; 2088 this._currentToken = currentToken;
2112 } 2089 }
2113 2090
2114 /** 2091 /**
2115 * Return `true` if the current token is the first token of a return type that is followed 2092 * Return `true` if the current token is the first token of a return type that
2116 * by an identifier, possibly followed by a list of type parameters, followed by a 2093 * is followed by an identifier, possibly followed by a list of type
2117 * left-parenthesis. This is used by parseTypeAlias to determine whether or no t to parse a return 2094 * parameters, followed by a left-parenthesis. This is used by
2118 * type. 2095 * [_parseTypeAlias] to determine whether or not to parse a return type.
2119 *
2120 * @return `true` if we can successfully parse the rest of a type alias if we first parse a
2121 * return type.
2122 */ 2096 */
2123 bool get hasReturnTypeInTypeAlias { 2097 bool get hasReturnTypeInTypeAlias {
2124 Token next = _skipReturnType(_currentToken); 2098 Token next = _skipReturnType(_currentToken);
2125 if (next == null) { 2099 if (next == null) {
2126 return false; 2100 return false;
2127 } 2101 }
2128 return _tokenMatchesIdentifier(next); 2102 return _tokenMatchesIdentifier(next);
2129 } 2103 }
2130 2104
2131 /** 2105 /**
2132 * Set whether the parser is to parse the async support. 2106 * Set whether the parser is to parse the async support.
2133 *
2134 * @param parseAsync `true` if the parser is to parse the async support
2135 */ 2107 */
2108 @deprecated
2136 void set parseAsync(bool parseAsync) { 2109 void set parseAsync(bool parseAsync) {
2137 // Async support cannot be disabled 2110 // Async support cannot be disabled
2138 } 2111 }
2139 2112
2140 /** 2113 /**
2141 * Set whether the parser is to parse deferred libraries. 2114 * Set whether the parser is to parse deferred libraries.
2142 *
2143 * @param parseDeferredLibraries `true` if the parser is to parse deferred lib raries
2144 */ 2115 */
2116 @deprecated
2145 void set parseDeferredLibraries(bool parseDeferredLibraries) { 2117 void set parseDeferredLibraries(bool parseDeferredLibraries) {
2146 // Deferred libraries support cannot be disabled 2118 // Deferred libraries support cannot be disabled
2147 } 2119 }
2148 2120
2149 /** 2121 /**
2150 * Set whether the parser is to parse enum declarations. 2122 * Set whether the parser is to parse enum declarations.
2151 *
2152 * @param parseEnum `true` if the parser is to parse enum declarations
2153 */ 2123 */
2124 @deprecated
2154 void set parseEnum(bool parseEnum) { 2125 void set parseEnum(bool parseEnum) {
2155 // Enum support cannot be disabled 2126 // Enum support cannot be disabled
2156 } 2127 }
2157 2128
2158 /** 2129 /**
2159 * Set whether parser is to parse function bodies. 2130 * Set whether parser is to parse function bodies.
2160 *
2161 * @param parseFunctionBodies `true` if parser is to parse function bodies
2162 */ 2131 */
2163 void set parseFunctionBodies(bool parseFunctionBodies) { 2132 void set parseFunctionBodies(bool parseFunctionBodies) {
2164 this._parseFunctionBodies = parseFunctionBodies; 2133 this._parseFunctionBodies = parseFunctionBodies;
2165 } 2134 }
2166 2135
2167 /** 2136 /**
2168 * Advance to the next token in the token stream, making it the new current 2137 * Advance to the next token in the token stream, making it the new current
2169 * token and return the token that was current before this method was invoked. 2138 * token and return the token that was current before this method was invoked.
2170 */ 2139 */
2171 Token getAndAdvance() { 2140 Token getAndAdvance() {
2172 Token token = _currentToken; 2141 Token token = _currentToken;
2173 _advance(); 2142 _advance();
2174 return token; 2143 return token;
2175 } 2144 }
2176 2145
2177 /** 2146 /**
2178 * Parse an annotation. 2147 * Parse an annotation. Return the annotation that was parsed.
2179 * 2148 *
2180 * <pre> 2149 * annotation ::=
2181 * annotation ::= 2150 * '@' qualified ('.' identifier)? arguments?
2182 * '@' qualified ('.' identifier)? arguments?
2183 * </pre>
2184 * 2151 *
2185 * @return the annotation that was parsed
2186 */ 2152 */
2187 Annotation parseAnnotation() { 2153 Annotation parseAnnotation() {
2188 Token atSign = _expect(TokenType.AT); 2154 Token atSign = _expect(TokenType.AT);
2189 Identifier name = parsePrefixedIdentifier(); 2155 Identifier name = parsePrefixedIdentifier();
2190 Token period = null; 2156 Token period = null;
2191 SimpleIdentifier constructorName = null; 2157 SimpleIdentifier constructorName = null;
2192 if (_matches(TokenType.PERIOD)) { 2158 if (_matches(TokenType.PERIOD)) {
2193 period = getAndAdvance(); 2159 period = getAndAdvance();
2194 constructorName = parseSimpleIdentifier(); 2160 constructorName = parseSimpleIdentifier();
2195 } 2161 }
2196 ArgumentList arguments = null; 2162 ArgumentList arguments = null;
2197 if (_matches(TokenType.OPEN_PAREN)) { 2163 if (_matches(TokenType.OPEN_PAREN)) {
2198 arguments = parseArgumentList(); 2164 arguments = parseArgumentList();
2199 } 2165 }
2200 return new Annotation(atSign, name, period, constructorName, arguments); 2166 return new Annotation(atSign, name, period, constructorName, arguments);
2201 } 2167 }
2202 2168
2203 /** 2169 /**
2204 * Parse an argument. 2170 * Parse an argument. Return the argument that was parsed.
2205 * 2171 *
2206 * <pre> 2172 * argument ::=
2207 * argument ::= 2173 * namedArgument
2208 * namedArgument 2174 * | expression
2209 * | expression
2210 * 2175 *
2211 * namedArgument ::= 2176 * namedArgument ::=
2212 * label expression 2177 * label expression
2213 * </pre>
2214 *
2215 * @return the argument that was parsed
2216 */ 2178 */
2217 Expression parseArgument() { 2179 Expression parseArgument() {
2218 // 2180 //
2219 // Both namedArgument and expression can start with an identifier, but only 2181 // Both namedArgument and expression can start with an identifier, but only
2220 // namedArgument can have an identifier followed by a colon. 2182 // namedArgument can have an identifier followed by a colon.
2221 // 2183 //
2222 if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) { 2184 if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
2223 return new NamedExpression(parseLabel(), parseExpression2()); 2185 return new NamedExpression(parseLabel(), parseExpression2());
2224 } else { 2186 } else {
2225 return parseExpression2(); 2187 return parseExpression2();
2226 } 2188 }
2227 } 2189 }
2228 2190
2229 /** 2191 /**
2230 * Parse a list of arguments. 2192 * Parse a list of arguments. Return the argument list that was parsed.
2231 * 2193 *
2232 * <pre> 2194 * arguments ::=
2233 * arguments ::= 2195 * '(' argumentList? ')'
2234 * '(' argumentList? ')'
2235 * 2196 *
2236 * argumentList ::= 2197 * argumentList ::=
2237 * namedArgument (',' namedArgument)* 2198 * namedArgument (',' namedArgument)*
2238 * | expressionList (',' namedArgument)* 2199 * | expressionList (',' namedArgument)*
2239 * </pre>
2240 *
2241 * @return the argument list that was parsed
2242 */ 2200 */
2243 ArgumentList parseArgumentList() { 2201 ArgumentList parseArgumentList() {
2244 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); 2202 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
2245 List<Expression> arguments = new List<Expression>(); 2203 List<Expression> arguments = new List<Expression>();
2246 if (_matches(TokenType.CLOSE_PAREN)) { 2204 if (_matches(TokenType.CLOSE_PAREN)) {
2247 return new ArgumentList(leftParenthesis, arguments, getAndAdvance()); 2205 return new ArgumentList(leftParenthesis, arguments, getAndAdvance());
2248 } 2206 }
2249 // 2207 //
2250 // Even though unnamed arguments must all appear before any named arguments, 2208 // Even though unnamed arguments must all appear before any named arguments,
2251 // we allow them to appear in any order so that we can recover faster. 2209 // we allow them to appear in any order so that we can recover faster.
(...skipping 27 matching lines...) Expand all
2279 // whether there is a matching right parenthesis. If there is, then we're 2237 // whether there is a matching right parenthesis. If there is, then we're
2280 // more likely missing a comma and should go back to parsing arguments. 2238 // more likely missing a comma and should go back to parsing arguments.
2281 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); 2239 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
2282 return new ArgumentList(leftParenthesis, arguments, rightParenthesis); 2240 return new ArgumentList(leftParenthesis, arguments, rightParenthesis);
2283 } finally { 2241 } finally {
2284 _inInitializer = wasInInitializer; 2242 _inInitializer = wasInInitializer;
2285 } 2243 }
2286 } 2244 }
2287 2245
2288 /** 2246 /**
2289 * Parse a bitwise or expression. 2247 * Parse a bitwise or expression. Return the bitwise or expression that was
2248 * parsed.
2290 * 2249 *
2291 * <pre> 2250 * bitwiseOrExpression ::=
2292 * bitwiseOrExpression ::= 2251 * bitwiseXorExpression ('|' bitwiseXorExpression)*
2293 * bitwiseXorExpression ('|' bitwiseXorExpression)* 2252 * | 'super' ('|' bitwiseXorExpression)+
2294 * | 'super' ('|' bitwiseXorExpression)+
2295 * </pre>
2296 *
2297 * @return the bitwise or expression that was parsed
2298 */ 2253 */
2299 Expression parseBitwiseOrExpression() { 2254 Expression parseBitwiseOrExpression() {
2300 Expression expression; 2255 Expression expression;
2301 if (_matchesKeyword(Keyword.SUPER) && 2256 if (_matchesKeyword(Keyword.SUPER) &&
2302 _tokenMatches(_peek(), TokenType.BAR)) { 2257 _tokenMatches(_peek(), TokenType.BAR)) {
2303 expression = new SuperExpression(getAndAdvance()); 2258 expression = new SuperExpression(getAndAdvance());
2304 } else { 2259 } else {
2305 expression = _parseBitwiseXorExpression(); 2260 expression = _parseBitwiseXorExpression();
2306 } 2261 }
2307 while (_matches(TokenType.BAR)) { 2262 while (_matches(TokenType.BAR)) {
2308 Token operator = getAndAdvance(); 2263 Token operator = getAndAdvance();
2309 expression = new BinaryExpression( 2264 expression = new BinaryExpression(
2310 expression, operator, _parseBitwiseXorExpression()); 2265 expression, operator, _parseBitwiseXorExpression());
2311 } 2266 }
2312 return expression; 2267 return expression;
2313 } 2268 }
2314 2269
2315 /** 2270 /**
2316 * Parse a block. 2271 * Parse a block. Return the block that was parsed.
2317 * 2272 *
2318 * <pre> 2273 * block ::=
2319 * block ::= 2274 * '{' statements '}'
2320 * '{' statements '}'
2321 * </pre>
2322 *
2323 * @return the block that was parsed
2324 */ 2275 */
2325 Block parseBlock() { 2276 Block parseBlock() {
2326 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); 2277 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
2327 List<Statement> statements = new List<Statement>(); 2278 List<Statement> statements = new List<Statement>();
2328 Token statementStart = _currentToken; 2279 Token statementStart = _currentToken;
2329 while ( 2280 while (
2330 !_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET)) { 2281 !_matches(TokenType.EOF) && !_matches(TokenType.CLOSE_CURLY_BRACKET)) {
2331 Statement statement = parseStatement2(); 2282 Statement statement = parseStatement2();
2332 if (statement != null) { 2283 if (statement != null) {
2333 statements.add(statement); 2284 statements.add(statement);
2334 } 2285 }
2335 if (identical(_currentToken, statementStart)) { 2286 if (identical(_currentToken, statementStart)) {
2336 // Ensure that we are making progress and report an error if we're not. 2287 // Ensure that we are making progress and report an error if we're not.
2337 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, 2288 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
2338 [_currentToken.lexeme]); 2289 [_currentToken.lexeme]);
2339 _advance(); 2290 _advance();
2340 } 2291 }
2341 statementStart = _currentToken; 2292 statementStart = _currentToken;
2342 } 2293 }
2343 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); 2294 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
2344 return new Block(leftBracket, statements, rightBracket); 2295 return new Block(leftBracket, statements, rightBracket);
2345 } 2296 }
2346 2297
2347 /** 2298 /**
2348 * Parse a class member. 2299 * Parse a class member. The [className] is the name of the class containing
2300 * the member being parsed. Return the class member that was parsed, or `null`
2301 * if what was found was not a valid class member.
2349 * 2302 *
2350 * <pre> 2303 * classMemberDefinition ::=
2351 * classMemberDefinition ::= 2304 * declaration ';'
2352 * declaration ';' 2305 * | methodSignature functionBody
2353 * | methodSignature functionBody
2354 * </pre>
2355 *
2356 * @param className the name of the class containing the member being parsed
2357 * @return the class member that was parsed, or `null` if what was found was n ot a valid
2358 * class member
2359 */ 2306 */
2360 ClassMember parseClassMember(String className) { 2307 ClassMember parseClassMember(String className) {
2361 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 2308 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2362 Modifiers modifiers = _parseModifiers(); 2309 Modifiers modifiers = _parseModifiers();
2363 if (_matchesKeyword(Keyword.VOID)) { 2310 if (_matchesKeyword(Keyword.VOID)) {
2364 TypeName returnType = parseReturnType(); 2311 TypeName returnType = parseReturnType();
2365 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) { 2312 if (_matchesKeyword(Keyword.GET) && _tokenMatchesIdentifier(_peek())) {
2366 _validateModifiersForGetterOrSetterOrMethod(modifiers); 2313 _validateModifiersForGetterOrSetterOrMethod(modifiers);
2367 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, 2314 return _parseGetter(commentAndMetadata, modifiers.externalKeyword,
2368 modifiers.staticKeyword, returnType); 2315 modifiers.staticKeyword, returnType);
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2606 _currentToken = _injectToken( 2553 _currentToken = _injectToken(
2607 new Parser_SyntheticKeywordToken(Keyword.GET, _currentToken.offset)); 2554 new Parser_SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
2608 return _parseGetter(commentAndMetadata, modifiers.externalKeyword, 2555 return _parseGetter(commentAndMetadata, modifiers.externalKeyword,
2609 modifiers.staticKeyword, type); 2556 modifiers.staticKeyword, type);
2610 } 2557 }
2611 return _parseInitializedIdentifierList(commentAndMetadata, 2558 return _parseInitializedIdentifierList(commentAndMetadata,
2612 modifiers.staticKeyword, _validateModifiersForField(modifiers), type); 2559 modifiers.staticKeyword, _validateModifiersForField(modifiers), type);
2613 } 2560 }
2614 2561
2615 /** 2562 /**
2616 * Parse a single import combinator. If no combinator is found, return 2563 * Parse a single combinator. Return the combinator that was parsed, or `null`
2617 * `null`. 2564 * if no combinator is found.
2618 * 2565 *
2619 * <pre> 2566 * combinator ::=
2620 * combinator ::= 2567 * 'show' identifier (',' identifier)*
2621 * 'show' identifier (',' identifier)* 2568 * | 'hide' identifier (',' identifier)*
2622 * | 'hide' identifier (',' identifier)*
2623 * </pre>
2624 */ 2569 */
2625 Combinator parseCombinator() { 2570 Combinator parseCombinator() {
2626 if (_matchesString(_SHOW) || _matchesString(_HIDE)) { 2571 if (_matchesString(_SHOW) || _matchesString(_HIDE)) {
2627 Token keyword = getAndAdvance(); 2572 Token keyword = getAndAdvance();
2628 List<SimpleIdentifier> names = _parseIdentifierList(); 2573 List<SimpleIdentifier> names = _parseIdentifierList();
2629 if (keyword.lexeme == _SHOW) { 2574 if (keyword.lexeme == _SHOW) {
2630 return new ShowCombinator(keyword, names); 2575 return new ShowCombinator(keyword, names);
2631 } else { 2576 } else {
2632 return new HideCombinator(keyword, names); 2577 return new HideCombinator(keyword, names);
2633 } 2578 }
2634 } 2579 }
2635 return null; 2580 return null;
2636 } 2581 }
2637 2582
2638 /** 2583 /**
2639 * Parse a compilation unit, starting with the given token. 2584 * Parse a compilation unit, starting with the given [token]. Return the
2640 * 2585 * compilation unit that was parsed.
2641 * @param token the first token of the compilation unit
2642 * @return the compilation unit that was parsed
2643 */ 2586 */
2644 CompilationUnit parseCompilationUnit(Token token) { 2587 CompilationUnit parseCompilationUnit(Token token) {
2645 _currentToken = token; 2588 _currentToken = token;
2646 return parseCompilationUnit2(); 2589 return parseCompilationUnit2();
2647 } 2590 }
2648 2591
2649 /** 2592 /**
2650 * Parse a compilation unit. 2593 * Parse a compilation unit. Return the compilation unit that was parsed.
2651 * 2594 *
2652 * Specified: 2595 * Specified:
2653 * 2596 *
2654 * <pre> 2597 * compilationUnit ::=
2655 * compilationUnit ::= 2598 * scriptTag? directive* topLevelDeclaration*
2656 * scriptTag? directive* topLevelDeclaration* 2599 *
2657 * </pre>
2658 * Actual: 2600 * Actual:
2659 * 2601 *
2660 * <pre> 2602 * compilationUnit ::=
2661 * compilationUnit ::= 2603 * scriptTag? topLevelElement*
2662 * scriptTag? topLevelElement*
2663 * 2604 *
2664 * topLevelElement ::= 2605 * topLevelElement ::=
2665 * directive 2606 * directive
2666 * | topLevelDeclaration 2607 * | topLevelDeclaration
2667 * </pre>
2668 *
2669 * @return the compilation unit that was parsed
2670 */ 2608 */
2671 CompilationUnit parseCompilationUnit2() { 2609 CompilationUnit parseCompilationUnit2() {
2672 Token firstToken = _currentToken; 2610 Token firstToken = _currentToken;
2673 ScriptTag scriptTag = null; 2611 ScriptTag scriptTag = null;
2674 if (_matches(TokenType.SCRIPT_TAG)) { 2612 if (_matches(TokenType.SCRIPT_TAG)) {
2675 scriptTag = new ScriptTag(getAndAdvance()); 2613 scriptTag = new ScriptTag(getAndAdvance());
2676 } 2614 }
2677 // 2615 //
2678 // Even though all directives must appear before declarations and must occur 2616 // Even though all directives must appear before declarations and must occur
2679 // in a given order, we allow directives and declarations to occur in any 2617 // in a given order, we allow directives and declarations to occur in any
(...skipping 11 matching lines...) Expand all
2691 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 2629 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
2692 if ((_matchesKeyword(Keyword.IMPORT) || 2630 if ((_matchesKeyword(Keyword.IMPORT) ||
2693 _matchesKeyword(Keyword.EXPORT) || 2631 _matchesKeyword(Keyword.EXPORT) ||
2694 _matchesKeyword(Keyword.LIBRARY) || 2632 _matchesKeyword(Keyword.LIBRARY) ||
2695 _matchesKeyword(Keyword.PART)) && 2633 _matchesKeyword(Keyword.PART)) &&
2696 !_tokenMatches(_peek(), TokenType.PERIOD) && 2634 !_tokenMatches(_peek(), TokenType.PERIOD) &&
2697 !_tokenMatches(_peek(), TokenType.LT) && 2635 !_tokenMatches(_peek(), TokenType.LT) &&
2698 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 2636 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
2699 Directive directive = _parseDirective(commentAndMetadata); 2637 Directive directive = _parseDirective(commentAndMetadata);
2700 if (declarations.length > 0 && !directiveFoundAfterDeclaration) { 2638 if (declarations.length > 0 && !directiveFoundAfterDeclaration) {
2701 _reportErrorForToken( 2639 _reportErrorForToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION,
2702 ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, directive.beginToken) ; 2640 directive.beginToken);
2703 directiveFoundAfterDeclaration = true; 2641 directiveFoundAfterDeclaration = true;
2704 } 2642 }
2705 if (directive is LibraryDirective) { 2643 if (directive is LibraryDirective) {
2706 if (libraryDirectiveFound) { 2644 if (libraryDirectiveFound) {
2707 _reportErrorForCurrentToken( 2645 _reportErrorForCurrentToken(
2708 ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES); 2646 ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES);
2709 } else { 2647 } else {
2710 if (directives.length > 0) { 2648 if (directives.length > 0) {
2711 _reportErrorForToken(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 2649 _reportErrorForToken(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST,
2712 directive.libraryKeyword); 2650 directive.libraryKeyword);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2768 _advance(); 2706 _advance();
2769 } 2707 }
2770 } 2708 }
2771 memberStart = _currentToken; 2709 memberStart = _currentToken;
2772 } 2710 }
2773 return new CompilationUnit( 2711 return new CompilationUnit(
2774 firstToken, scriptTag, directives, declarations, _currentToken); 2712 firstToken, scriptTag, directives, declarations, _currentToken);
2775 } 2713 }
2776 2714
2777 /** 2715 /**
2778 * Parse a conditional expression. 2716 * Parse a conditional expression. Return the conditional expression that was
2717 * parsed.
2779 * 2718 *
2780 * <pre> 2719 * conditionalExpression ::=
2781 * conditionalExpression ::= 2720 * logicalOrExpression ('?' expressionWithoutCascade ':' expressionWit houtCascade)?
2782 * logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithout Cascade)?
2783 * </pre>
2784 *
2785 * @return the conditional expression that was parsed
2786 */ 2721 */
2787 Expression parseConditionalExpression() { 2722 Expression parseConditionalExpression() {
2788 Expression condition = parseLogicalOrExpression(); 2723 Expression condition = parseLogicalOrExpression();
2789 if (!_matches(TokenType.QUESTION)) { 2724 if (!_matches(TokenType.QUESTION)) {
2790 return condition; 2725 return condition;
2791 } 2726 }
2792 Token question = getAndAdvance(); 2727 Token question = getAndAdvance();
2793 Expression thenExpression = parseExpressionWithoutCascade(); 2728 Expression thenExpression = parseExpressionWithoutCascade();
2794 Token colon = _expect(TokenType.COLON); 2729 Token colon = _expect(TokenType.COLON);
2795 Expression elseExpression = parseExpressionWithoutCascade(); 2730 Expression elseExpression = parseExpressionWithoutCascade();
2796 return new ConditionalExpression( 2731 return new ConditionalExpression(
2797 condition, question, thenExpression, colon, elseExpression); 2732 condition, question, thenExpression, colon, elseExpression);
2798 } 2733 }
2799 2734
2800 /** 2735 /**
2801 * Parse the name of a constructor. 2736 * Parse the name of a constructor. Return the constructor name that was
2737 * parsed.
2802 * 2738 *
2803 * <pre> 2739 * constructorName:
2804 * constructorName: 2740 * type ('.' identifier)?
2805 * type ('.' identifier)?
2806 * </pre>
2807 *
2808 * @return the constructor name that was parsed
2809 */ 2741 */
2810 ConstructorName parseConstructorName() { 2742 ConstructorName parseConstructorName() {
2811 TypeName type = parseTypeName(); 2743 TypeName type = parseTypeName();
2812 Token period = null; 2744 Token period = null;
2813 SimpleIdentifier name = null; 2745 SimpleIdentifier name = null;
2814 if (_matches(TokenType.PERIOD)) { 2746 if (_matches(TokenType.PERIOD)) {
2815 period = getAndAdvance(); 2747 period = getAndAdvance();
2816 name = parseSimpleIdentifier(); 2748 name = parseSimpleIdentifier();
2817 } 2749 }
2818 return new ConstructorName(type, period, name); 2750 return new ConstructorName(type, period, name);
2819 } 2751 }
2820 2752
2821 /** 2753 /**
2822 * Parse the script tag and directives in a compilation unit, starting with th e given token, until 2754 * Parse the script tag and directives in a compilation unit, starting with
2823 * the first non-directive is encountered. The remainder of the compilation un it will not be 2755 * the given [token], until the first non-directive is encountered. The
2824 * parsed. Specifically, if there are directives later in the file, they will not be parsed. 2756 * remainder of the compilation unit will not be parsed. Specifically, if
2825 * 2757 * there are directives later in the file, they will not be parsed. Return the
2826 * @param token the first token of the compilation unit 2758 * compilation unit that was parsed.
2827 * @return the compilation unit that was parsed
2828 */ 2759 */
2829 CompilationUnit parseDirectives(Token token) { 2760 CompilationUnit parseDirectives(Token token) {
2830 _currentToken = token; 2761 _currentToken = token;
2831 return _parseDirectives(); 2762 return _parseDirectives();
2832 } 2763 }
2833 2764
2834 /** 2765 /**
2835 * Parse an expression, starting with the given token. 2766 * Parse an expression, starting with the given [token]. Return the expression
2836 * 2767 * that was parsed, or `null` if the tokens do not represent a recognizable
2837 * @param token the first token of the expression 2768 * expression.
2838 * @return the expression that was parsed, or `null` if the tokens do not repr esent a
2839 * recognizable expression
2840 */ 2769 */
2841 Expression parseExpression(Token token) { 2770 Expression parseExpression(Token token) {
2842 _currentToken = token; 2771 _currentToken = token;
2843 return parseExpression2(); 2772 return parseExpression2();
2844 } 2773 }
2845 2774
2846 /** 2775 /**
2847 * Parse an expression that might contain a cascade. 2776 * Parse an expression that might contain a cascade. Return the expression
2777 * that was parsed.
2848 * 2778 *
2849 * <pre> 2779 * expression ::=
2850 * expression ::= 2780 * assignableExpression assignmentOperator expression
2851 * assignableExpression assignmentOperator expression 2781 * | conditionalExpression cascadeSection*
2852 * | conditionalExpression cascadeSection* 2782 * | throwExpression
2853 * | throwExpression
2854 * </pre>
2855 *
2856 * @return the expression that was parsed
2857 */ 2783 */
2858 Expression parseExpression2() { 2784 Expression parseExpression2() {
2859 if (_matchesKeyword(Keyword.THROW)) { 2785 if (_matchesKeyword(Keyword.THROW)) {
2860 return _parseThrowExpression(); 2786 return _parseThrowExpression();
2861 } else if (_matchesKeyword(Keyword.RETHROW)) { 2787 } else if (_matchesKeyword(Keyword.RETHROW)) {
2862 // TODO(brianwilkerson) Rethrow is a statement again. 2788 // TODO(brianwilkerson) Rethrow is a statement again.
2863 return _parseRethrowExpression(); 2789 return _parseRethrowExpression();
2864 } 2790 }
2865 // 2791 //
2866 // assignableExpression is a subset of conditionalExpression, so we can 2792 // assignableExpression is a subset of conditionalExpression, so we can
(...skipping 15 matching lines...) Expand all
2882 return new CascadeExpression(expression, cascadeSections); 2808 return new CascadeExpression(expression, cascadeSections);
2883 } else if (tokenType.isAssignmentOperator) { 2809 } else if (tokenType.isAssignmentOperator) {
2884 Token operator = getAndAdvance(); 2810 Token operator = getAndAdvance();
2885 _ensureAssignable(expression); 2811 _ensureAssignable(expression);
2886 return new AssignmentExpression(expression, operator, parseExpression2()); 2812 return new AssignmentExpression(expression, operator, parseExpression2());
2887 } 2813 }
2888 return expression; 2814 return expression;
2889 } 2815 }
2890 2816
2891 /** 2817 /**
2892 * Parse an expression that does not contain any cascades. 2818 * Parse an expression that does not contain any cascades. Return the
2819 * expression that was parsed.
2893 * 2820 *
2894 * <pre> 2821 * expressionWithoutCascade ::=
2895 * expressionWithoutCascade ::= 2822 * assignableExpression assignmentOperator expressionWithoutCascade
2896 * assignableExpression assignmentOperator expressionWithoutCascade 2823 * | conditionalExpression
2897 * | conditionalExpression 2824 * | throwExpressionWithoutCascade
2898 * | throwExpressionWithoutCascade
2899 * </pre>
2900 *
2901 * @return the expression that was parsed
2902 */ 2825 */
2903 Expression parseExpressionWithoutCascade() { 2826 Expression parseExpressionWithoutCascade() {
2904 if (_matchesKeyword(Keyword.THROW)) { 2827 if (_matchesKeyword(Keyword.THROW)) {
2905 return _parseThrowExpressionWithoutCascade(); 2828 return _parseThrowExpressionWithoutCascade();
2906 } else if (_matchesKeyword(Keyword.RETHROW)) { 2829 } else if (_matchesKeyword(Keyword.RETHROW)) {
2907 return _parseRethrowExpression(); 2830 return _parseRethrowExpression();
2908 } 2831 }
2909 // 2832 //
2910 // assignableExpression is a subset of conditionalExpression, so we can 2833 // assignableExpression is a subset of conditionalExpression, so we can
2911 // parse a conditional expression and then determine whether it is followed 2834 // parse a conditional expression and then determine whether it is followed
2912 // by an assignmentOperator, checking for conformance to the restricted 2835 // by an assignmentOperator, checking for conformance to the restricted
2913 // grammar after making that determination. 2836 // grammar after making that determination.
2914 // 2837 //
2915 Expression expression = parseConditionalExpression(); 2838 Expression expression = parseConditionalExpression();
2916 if (_currentToken.type.isAssignmentOperator) { 2839 if (_currentToken.type.isAssignmentOperator) {
2917 Token operator = getAndAdvance(); 2840 Token operator = getAndAdvance();
2918 _ensureAssignable(expression); 2841 _ensureAssignable(expression);
2919 expression = new AssignmentExpression( 2842 expression = new AssignmentExpression(
2920 expression, operator, parseExpressionWithoutCascade()); 2843 expression, operator, parseExpressionWithoutCascade());
2921 } 2844 }
2922 return expression; 2845 return expression;
2923 } 2846 }
2924 2847
2925 /** 2848 /**
2926 * Parse a class extends clause. 2849 * Parse a class extends clause. Return the class extends clause that was
2850 * parsed.
2927 * 2851 *
2928 * <pre> 2852 * classExtendsClause ::=
2929 * classExtendsClause ::= 2853 * 'extends' type
2930 * 'extends' type
2931 * </pre>
2932 *
2933 * @return the class extends clause that was parsed
2934 */ 2854 */
2935 ExtendsClause parseExtendsClause() { 2855 ExtendsClause parseExtendsClause() {
2936 Token keyword = _expectKeyword(Keyword.EXTENDS); 2856 Token keyword = _expectKeyword(Keyword.EXTENDS);
2937 TypeName superclass = parseTypeName(); 2857 TypeName superclass = parseTypeName();
2938 return new ExtendsClause(keyword, superclass); 2858 return new ExtendsClause(keyword, superclass);
2939 } 2859 }
2940 2860
2941 /** 2861 /**
2942 * Parse a list of formal parameters. 2862 * Parse a list of formal parameters. Return the formal parameters that were
2863 * parsed.
2943 * 2864 *
2944 * <pre> 2865 * formalParameterList ::=
2945 * formalParameterList ::= 2866 * '(' ')'
2946 * '(' ')' 2867 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
2947 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' 2868 * | '(' optionalFormalParameters ')'
2948 * | '(' optionalFormalParameters ')'
2949 * 2869 *
2950 * normalFormalParameters ::= 2870 * normalFormalParameters ::=
2951 * normalFormalParameter (',' normalFormalParameter)* 2871 * normalFormalParameter (',' normalFormalParameter)*
2952 * 2872 *
2953 * optionalFormalParameters ::= 2873 * optionalFormalParameters ::=
2954 * optionalPositionalFormalParameters 2874 * optionalPositionalFormalParameters
2955 * | namedFormalParameters 2875 * | namedFormalParameters
2956 * 2876 *
2957 * optionalPositionalFormalParameters ::= 2877 * optionalPositionalFormalParameters ::=
2958 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']' 2878 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
2959 * 2879 *
2960 * namedFormalParameters ::= 2880 * namedFormalParameters ::=
2961 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' 2881 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
2962 * </pre>
2963 *
2964 * @return the formal parameters that were parsed
2965 */ 2882 */
2966 FormalParameterList parseFormalParameterList() { 2883 FormalParameterList parseFormalParameterList() {
2967 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); 2884 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
2968 if (_matches(TokenType.CLOSE_PAREN)) { 2885 if (_matches(TokenType.CLOSE_PAREN)) {
2969 return new FormalParameterList( 2886 return new FormalParameterList(
2970 leftParenthesis, null, null, null, getAndAdvance()); 2887 leftParenthesis, null, null, null, getAndAdvance());
2971 } 2888 }
2972 // 2889 //
2973 // Even though it is invalid to have default parameters outside of brackets, 2890 // Even though it is invalid to have default parameters outside of brackets,
2974 // required parameters inside of brackets, or multiple groups of default and 2891 // required parameters inside of brackets, or multiple groups of default and
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3110 leftSquareBracket = leftCurlyBracket; 3027 leftSquareBracket = leftCurlyBracket;
3111 } 3028 }
3112 if (rightSquareBracket == null) { 3029 if (rightSquareBracket == null) {
3113 rightSquareBracket = rightCurlyBracket; 3030 rightSquareBracket = rightCurlyBracket;
3114 } 3031 }
3115 return new FormalParameterList(leftParenthesis, parameters, 3032 return new FormalParameterList(leftParenthesis, parameters,
3116 leftSquareBracket, rightSquareBracket, rightParenthesis); 3033 leftSquareBracket, rightSquareBracket, rightParenthesis);
3117 } 3034 }
3118 3035
3119 /** 3036 /**
3120 * Parse a function expression. 3037 * Parse a function expression. Return the function expression that was
3038 * parsed.
3121 * 3039 *
3122 * <pre> 3040 * functionExpression ::=
3123 * functionExpression ::= 3041 * formalParameterList functionExpressionBody
3124 * formalParameterList functionExpressionBody
3125 * </pre>
3126 *
3127 * @return the function expression that was parsed
3128 */ 3042 */
3129 FunctionExpression parseFunctionExpression() { 3043 FunctionExpression parseFunctionExpression() {
3130 FormalParameterList parameters = parseFormalParameterList(); 3044 FormalParameterList parameters = parseFormalParameterList();
3131 _validateFormalParameterList(parameters); 3045 _validateFormalParameterList(parameters);
3132 FunctionBody body = 3046 FunctionBody body =
3133 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true); 3047 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
3134 return new FunctionExpression(parameters, body); 3048 return new FunctionExpression(parameters, body);
3135 } 3049 }
3136 3050
3137 /** 3051 /**
3138 * Parse an implements clause. 3052 * Parse an implements clause. Return the implements clause that was parsed.
3139 * 3053 *
3140 * <pre> 3054 * implementsClause ::=
3141 * implementsClause ::= 3055 * 'implements' type (',' type)*
3142 * 'implements' type (',' type)*
3143 * </pre>
3144 *
3145 * @return the implements clause that was parsed
3146 */ 3056 */
3147 ImplementsClause parseImplementsClause() { 3057 ImplementsClause parseImplementsClause() {
3148 Token keyword = _expectKeyword(Keyword.IMPLEMENTS); 3058 Token keyword = _expectKeyword(Keyword.IMPLEMENTS);
3149 List<TypeName> interfaces = new List<TypeName>(); 3059 List<TypeName> interfaces = new List<TypeName>();
3150 interfaces.add(parseTypeName()); 3060 interfaces.add(parseTypeName());
3151 while (_optional(TokenType.COMMA)) { 3061 while (_optional(TokenType.COMMA)) {
3152 interfaces.add(parseTypeName()); 3062 interfaces.add(parseTypeName());
3153 } 3063 }
3154 return new ImplementsClause(keyword, interfaces); 3064 return new ImplementsClause(keyword, interfaces);
3155 } 3065 }
3156 3066
3157 /** 3067 /**
3158 * Parse a label. 3068 * Parse a label. Return the label that was parsed.
3159 * 3069 *
3160 * <pre> 3070 * label ::=
3161 * label ::= 3071 * identifier ':'
3162 * identifier ':'
3163 * </pre>
3164 *
3165 * @return the label that was parsed
3166 */ 3072 */
3167 Label parseLabel() { 3073 Label parseLabel() {
3168 SimpleIdentifier label = parseSimpleIdentifier(); 3074 SimpleIdentifier label = parseSimpleIdentifier();
3169 Token colon = _expect(TokenType.COLON); 3075 Token colon = _expect(TokenType.COLON);
3170 return new Label(label, colon); 3076 return new Label(label, colon);
3171 } 3077 }
3172 3078
3173 /** 3079 /**
3174 * Parse a library identifier. 3080 * Parse a library identifier. Return the library identifier that was parsed.
3175 * 3081 *
3176 * <pre> 3082 * libraryIdentifier ::=
3177 * libraryIdentifier ::= 3083 * identifier ('.' identifier)*
3178 * identifier ('.' identifier)*
3179 * </pre>
3180 *
3181 * @return the library identifier that was parsed
3182 */ 3084 */
3183 LibraryIdentifier parseLibraryIdentifier() { 3085 LibraryIdentifier parseLibraryIdentifier() {
3184 List<SimpleIdentifier> components = new List<SimpleIdentifier>(); 3086 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
3185 components.add(parseSimpleIdentifier()); 3087 components.add(parseSimpleIdentifier());
3186 while (_matches(TokenType.PERIOD)) { 3088 while (_matches(TokenType.PERIOD)) {
3187 _advance(); 3089 _advance();
3188 components.add(parseSimpleIdentifier()); 3090 components.add(parseSimpleIdentifier());
3189 } 3091 }
3190 return new LibraryIdentifier(components); 3092 return new LibraryIdentifier(components);
3191 } 3093 }
3192 3094
3193 /** 3095 /**
3194 * Parse a logical or expression. 3096 * Parse a logical or expression. Return the logical or expression that was
3097 * parsed.
3195 * 3098 *
3196 * <pre> 3099 * logicalOrExpression ::=
3197 * logicalOrExpression ::= 3100 * logicalAndExpression ('||' logicalAndExpression)*
3198 * logicalAndExpression ('||' logicalAndExpression)*
3199 * </pre>
3200 *
3201 * @return the logical or expression that was parsed
3202 */ 3101 */
3203 Expression parseLogicalOrExpression() { 3102 Expression parseLogicalOrExpression() {
3204 Expression expression = _parseLogicalAndExpression(); 3103 Expression expression = _parseLogicalAndExpression();
3205 while (_matches(TokenType.BAR_BAR)) { 3104 while (_matches(TokenType.BAR_BAR)) {
3206 Token operator = getAndAdvance(); 3105 Token operator = getAndAdvance();
3207 expression = new BinaryExpression( 3106 expression = new BinaryExpression(
3208 expression, operator, _parseLogicalAndExpression()); 3107 expression, operator, _parseLogicalAndExpression());
3209 } 3108 }
3210 return expression; 3109 return expression;
3211 } 3110 }
3212 3111
3213 /** 3112 /**
3214 * Parse a map literal entry. 3113 * Parse a map literal entry. Return the map literal entry that was parsed.
3215 * 3114 *
3216 * <pre> 3115 * mapLiteralEntry ::=
3217 * mapLiteralEntry ::= 3116 * expression ':' expression
3218 * expression ':' expression
3219 * </pre>
3220 *
3221 * @return the map literal entry that was parsed
3222 */ 3117 */
3223 MapLiteralEntry parseMapLiteralEntry() { 3118 MapLiteralEntry parseMapLiteralEntry() {
3224 Expression key = parseExpression2(); 3119 Expression key = parseExpression2();
3225 Token separator = _expect(TokenType.COLON); 3120 Token separator = _expect(TokenType.COLON);
3226 Expression value = parseExpression2(); 3121 Expression value = parseExpression2();
3227 return new MapLiteralEntry(key, separator, value); 3122 return new MapLiteralEntry(key, separator, value);
3228 } 3123 }
3229 3124
3230 /** 3125 /**
3231 * Parse a normal formal parameter and return the normal formal parameter that 3126 * Parse a normal formal parameter. Return the normal formal parameter that
3232 * was parsed. 3127 * was parsed.
3233 * 3128 *
3234 * <pre> 3129 * normalFormalParameter ::=
3235 * normalFormalParameter ::= 3130 * functionSignature
3236 * functionSignature 3131 * | fieldFormalParameter
3237 * | fieldFormalParameter 3132 * | simpleFormalParameter
3238 * | simpleFormalParameter
3239 * 3133 *
3240 * functionSignature: 3134 * functionSignature:
3241 * metadata returnType? identifier formalParameterList 3135 * metadata returnType? identifier formalParameterList
3242 * 3136 *
3243 * fieldFormalParameter ::= 3137 * fieldFormalParameter ::=
3244 * metadata finalConstVarOrType? 'this' '.' identifier 3138 * metadata finalConstVarOrType? 'this' '.' identifier
3245 * 3139 *
3246 * simpleFormalParameter ::= 3140 * simpleFormalParameter ::=
3247 * declaredIdentifier 3141 * declaredIdentifier
3248 * | metadata identifier 3142 * | metadata identifier
3249 * </pre>
3250 */ 3143 */
3251 NormalFormalParameter parseNormalFormalParameter() { 3144 NormalFormalParameter parseNormalFormalParameter() {
3252 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 3145 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
3253 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); 3146 FinalConstVarOrType holder = _parseFinalConstVarOrType(true);
3254 Token thisKeyword = null; 3147 Token thisKeyword = null;
3255 Token period = null; 3148 Token period = null;
3256 if (_matchesKeyword(Keyword.THIS)) { 3149 if (_matchesKeyword(Keyword.THIS)) {
3257 thisKeyword = getAndAdvance(); 3150 thisKeyword = getAndAdvance();
3258 period = _expect(TokenType.PERIOD); 3151 period = _expect(TokenType.PERIOD);
3259 } 3152 }
(...skipping 26 matching lines...) Expand all
3286 if (thisKeyword != null) { 3179 if (thisKeyword != null) {
3287 return new FieldFormalParameter(commentAndMetadata.comment, 3180 return new FieldFormalParameter(commentAndMetadata.comment,
3288 commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword, 3181 commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword,
3289 period, identifier, null); 3182 period, identifier, null);
3290 } 3183 }
3291 return new SimpleFormalParameter(commentAndMetadata.comment, 3184 return new SimpleFormalParameter(commentAndMetadata.comment,
3292 commentAndMetadata.metadata, holder.keyword, holder.type, identifier); 3185 commentAndMetadata.metadata, holder.keyword, holder.type, identifier);
3293 } 3186 }
3294 3187
3295 /** 3188 /**
3296 * Parse a prefixed identifier. 3189 * Parse a prefixed identifier. Return the prefixed identifier that was
3190 * parsed.
3297 * 3191 *
3298 * <pre> 3192 * prefixedIdentifier ::=
3299 * prefixedIdentifier ::= 3193 * identifier ('.' identifier)?
3300 * identifier ('.' identifier)?
3301 * </pre>
3302 *
3303 * @return the prefixed identifier that was parsed
3304 */ 3194 */
3305 Identifier parsePrefixedIdentifier() { 3195 Identifier parsePrefixedIdentifier() {
3306 SimpleIdentifier qualifier = parseSimpleIdentifier(); 3196 SimpleIdentifier qualifier = parseSimpleIdentifier();
3307 if (!_matches(TokenType.PERIOD)) { 3197 if (!_matches(TokenType.PERIOD)) {
3308 return qualifier; 3198 return qualifier;
3309 } 3199 }
3310 Token period = getAndAdvance(); 3200 Token period = getAndAdvance();
3311 SimpleIdentifier qualified = parseSimpleIdentifier(); 3201 SimpleIdentifier qualified = parseSimpleIdentifier();
3312 return new PrefixedIdentifier(qualifier, period, qualified); 3202 return new PrefixedIdentifier(qualifier, period, qualified);
3313 } 3203 }
3314 3204
3315 /** 3205 /**
3316 * Parse a return type. 3206 * Parse a return type. Return the return type that was parsed.
3317 * 3207 *
3318 * <pre> 3208 * returnType ::=
3319 * returnType ::= 3209 * 'void'
3320 * 'void' 3210 * | type
3321 * | type
3322 * </pre>
3323 *
3324 * @return the return type that was parsed
3325 */ 3211 */
3326 TypeName parseReturnType() { 3212 TypeName parseReturnType() {
3327 if (_matchesKeyword(Keyword.VOID)) { 3213 if (_matchesKeyword(Keyword.VOID)) {
3328 return new TypeName(new SimpleIdentifier(getAndAdvance()), null); 3214 return new TypeName(new SimpleIdentifier(getAndAdvance()), null);
3329 } else { 3215 } else {
3330 return parseTypeName(); 3216 return parseTypeName();
3331 } 3217 }
3332 } 3218 }
3333 3219
3334 /** 3220 /**
3335 * Parse a simple identifier. 3221 * Parse a simple identifier. Return the simple identifier that was parsed.
3336 * 3222 *
3337 * <pre> 3223 * identifier ::=
3338 * identifier ::= 3224 * IDENTIFIER
3339 * IDENTIFIER
3340 * </pre>
3341 *
3342 * @return the simple identifier that was parsed
3343 */ 3225 */
3344 SimpleIdentifier parseSimpleIdentifier() { 3226 SimpleIdentifier parseSimpleIdentifier() {
3345 if (_matchesIdentifier()) { 3227 if (_matchesIdentifier()) {
3346 String lexeme = _currentToken.lexeme; 3228 String lexeme = _currentToken.lexeme;
3347 if ((_inAsync || _inGenerator) && 3229 if ((_inAsync || _inGenerator) &&
3348 (lexeme == 'async' || lexeme == 'await' || lexeme == 'yield')) { 3230 (lexeme == 'async' || lexeme == 'await' || lexeme == 'yield')) {
3349 _reportErrorForCurrentToken( 3231 _reportErrorForCurrentToken(
3350 ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER); 3232 ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
3351 } 3233 }
3352 return new SimpleIdentifier(getAndAdvance()); 3234 return new SimpleIdentifier(getAndAdvance());
3353 } 3235 }
3354 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER); 3236 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
3355 return _createSyntheticIdentifier(); 3237 return _createSyntheticIdentifier();
3356 } 3238 }
3357 3239
3358 /** 3240 /**
3359 * Parse a statement, starting with the given token. 3241 * Parse a statement, starting with the given [token]. Return the statement
3360 * 3242 * that was parsed, or `null` if the tokens do not represent a recognizable
3361 * @param token the first token of the statement 3243 * statement.
3362 * @return the statement that was parsed, or `null` if the tokens do not repre sent a
3363 * recognizable statement
3364 */ 3244 */
3365 Statement parseStatement(Token token) { 3245 Statement parseStatement(Token token) {
3366 _currentToken = token; 3246 _currentToken = token;
3367 return parseStatement2(); 3247 return parseStatement2();
3368 } 3248 }
3369 3249
3370 /** 3250 /**
3371 * Parse a statement. 3251 * Parse a statement. Return the statement that was parsed.
3372 * 3252 *
3373 * <pre> 3253 * statement ::=
3374 * statement ::= 3254 * label* nonLabeledStatement
3375 * label* nonLabeledStatement
3376 * </pre>
3377 *
3378 * @return the statement that was parsed
3379 */ 3255 */
3380 Statement parseStatement2() { 3256 Statement parseStatement2() {
3381 List<Label> labels = new List<Label>(); 3257 List<Label> labels = new List<Label>();
3382 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) { 3258 while (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
3383 labels.add(parseLabel()); 3259 labels.add(parseLabel());
3384 } 3260 }
3385 Statement statement = _parseNonLabeledStatement(); 3261 Statement statement = _parseNonLabeledStatement();
3386 if (labels.isEmpty) { 3262 if (labels.isEmpty) {
3387 return statement; 3263 return statement;
3388 } 3264 }
3389 return new LabeledStatement(labels, statement); 3265 return new LabeledStatement(labels, statement);
3390 } 3266 }
3391 3267
3392 /** 3268 /**
3393 * Parse a sequence of statements, starting with the given token. 3269 * Parse a sequence of statements, starting with the given [token]. Return the
3394 * 3270 * statements that were parsed, or `null` if the tokens do not represent a
3395 * @param token the first token of the sequence of statement 3271 * recognizable sequence of statements.
3396 * @return the statements that were parsed, or `null` if the tokens do not rep resent a
3397 * recognizable sequence of statements
3398 */ 3272 */
3399 List<Statement> parseStatements(Token token) { 3273 List<Statement> parseStatements(Token token) {
3400 _currentToken = token; 3274 _currentToken = token;
3401 return _parseStatementList(); 3275 return _parseStatementList();
3402 } 3276 }
3403 3277
3404 /** 3278 /**
3405 * Parse a string literal. 3279 * Parse a string literal. Return the string literal that was parsed.
3406 * 3280 *
3407 * <pre> 3281 * stringLiteral ::=
3408 * stringLiteral ::= 3282 * MULTI_LINE_STRING+
3409 * MULTI_LINE_STRING+ 3283 * | SINGLE_LINE_STRING+
3410 * | SINGLE_LINE_STRING+
3411 * </pre>
3412 *
3413 * @return the string literal that was parsed
3414 */ 3284 */
3415 StringLiteral parseStringLiteral() { 3285 StringLiteral parseStringLiteral() {
3416 List<StringLiteral> strings = new List<StringLiteral>(); 3286 List<StringLiteral> strings = new List<StringLiteral>();
3417 while (_matches(TokenType.STRING)) { 3287 while (_matches(TokenType.STRING)) {
3418 Token string = getAndAdvance(); 3288 Token string = getAndAdvance();
3419 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || 3289 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
3420 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER)) { 3290 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
3421 strings.add(_parseStringInterpolation(string)); 3291 strings.add(_parseStringInterpolation(string));
3422 } else { 3292 } else {
3423 strings.add(new SimpleStringLiteral( 3293 strings.add(new SimpleStringLiteral(
3424 string, _computeStringValue(string.lexeme, true, true))); 3294 string, _computeStringValue(string.lexeme, true, true)));
3425 } 3295 }
3426 } 3296 }
3427 if (strings.length < 1) { 3297 if (strings.length < 1) {
3428 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL); 3298 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL);
3429 return _createSyntheticStringLiteral(); 3299 return _createSyntheticStringLiteral();
3430 } else if (strings.length == 1) { 3300 } else if (strings.length == 1) {
3431 return strings[0]; 3301 return strings[0];
3432 } else { 3302 } else {
3433 return new AdjacentStrings(strings); 3303 return new AdjacentStrings(strings);
3434 } 3304 }
3435 } 3305 }
3436 3306
3437 /** 3307 /**
3438 * Parse a list of type arguments. 3308 * Parse a list of type arguments. Return the type argument list that was
3309 * parsed.
3439 * 3310 *
3440 * <pre> 3311 * typeArguments ::=
3441 * typeArguments ::= 3312 * '<' typeList '>'
3442 * '<' typeList '>'
3443 * 3313 *
3444 * typeList ::= 3314 * typeList ::=
3445 * type (',' type)* 3315 * type (',' type)*
3446 * </pre>
3447 *
3448 * @return the type argument list that was parsed
3449 */ 3316 */
3450 TypeArgumentList parseTypeArgumentList() { 3317 TypeArgumentList parseTypeArgumentList() {
3451 Token leftBracket = _expect(TokenType.LT); 3318 Token leftBracket = _expect(TokenType.LT);
3452 List<TypeName> arguments = new List<TypeName>(); 3319 List<TypeName> arguments = new List<TypeName>();
3453 arguments.add(parseTypeName()); 3320 arguments.add(parseTypeName());
3454 while (_optional(TokenType.COMMA)) { 3321 while (_optional(TokenType.COMMA)) {
3455 arguments.add(parseTypeName()); 3322 arguments.add(parseTypeName());
3456 } 3323 }
3457 Token rightBracket = _expectGt(); 3324 Token rightBracket = _expectGt();
3458 return new TypeArgumentList(leftBracket, arguments, rightBracket); 3325 return new TypeArgumentList(leftBracket, arguments, rightBracket);
3459 } 3326 }
3460 3327
3461 /** 3328 /**
3462 * Parse a type name. 3329 * Parse a type name. Return the type name that was parsed.
3463 * 3330 *
3464 * <pre> 3331 * type ::=
3465 * type ::= 3332 * qualified typeArguments?
3466 * qualified typeArguments?
3467 * </pre>
3468 *
3469 * @return the type name that was parsed
3470 */ 3333 */
3471 TypeName parseTypeName() { 3334 TypeName parseTypeName() {
3472 Identifier typeName; 3335 Identifier typeName;
3473 if (_matchesKeyword(Keyword.VAR)) { 3336 if (_matchesKeyword(Keyword.VAR)) {
3474 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); 3337 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME);
3475 typeName = new SimpleIdentifier(getAndAdvance()); 3338 typeName = new SimpleIdentifier(getAndAdvance());
3476 } else if (_matchesIdentifier()) { 3339 } else if (_matchesIdentifier()) {
3477 typeName = parsePrefixedIdentifier(); 3340 typeName = parsePrefixedIdentifier();
3478 } else { 3341 } else {
3479 typeName = _createSyntheticIdentifier(); 3342 typeName = _createSyntheticIdentifier();
3480 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); 3343 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
3481 } 3344 }
3482 TypeArgumentList typeArguments = null; 3345 TypeArgumentList typeArguments = null;
3483 if (_matches(TokenType.LT)) { 3346 if (_matches(TokenType.LT)) {
3484 typeArguments = parseTypeArgumentList(); 3347 typeArguments = parseTypeArgumentList();
3485 } 3348 }
3486 return new TypeName(typeName, typeArguments); 3349 return new TypeName(typeName, typeArguments);
3487 } 3350 }
3488 3351
3489 /** 3352 /**
3490 * Parse a type parameter. 3353 * Parse a type parameter. Return the type parameter that was parsed.
3491 * 3354 *
3492 * <pre> 3355 * typeParameter ::=
3493 * typeParameter ::= 3356 * metadata name ('extends' bound)?
3494 * metadata name ('extends' bound)?
3495 * </pre>
3496 *
3497 * @return the type parameter that was parsed
3498 */ 3357 */
3499 TypeParameter parseTypeParameter() { 3358 TypeParameter parseTypeParameter() {
3500 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 3359 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
3501 SimpleIdentifier name = parseSimpleIdentifier(); 3360 SimpleIdentifier name = parseSimpleIdentifier();
3502 if (_matchesKeyword(Keyword.EXTENDS)) { 3361 if (_matchesKeyword(Keyword.EXTENDS)) {
3503 Token keyword = getAndAdvance(); 3362 Token keyword = getAndAdvance();
3504 TypeName bound = parseTypeName(); 3363 TypeName bound = parseTypeName();
3505 return new TypeParameter(commentAndMetadata.comment, 3364 return new TypeParameter(commentAndMetadata.comment,
3506 commentAndMetadata.metadata, name, keyword, bound); 3365 commentAndMetadata.metadata, name, keyword, bound);
3507 } 3366 }
3508 return new TypeParameter(commentAndMetadata.comment, 3367 return new TypeParameter(commentAndMetadata.comment,
3509 commentAndMetadata.metadata, name, null, null); 3368 commentAndMetadata.metadata, name, null, null);
3510 } 3369 }
3511 3370
3512 /** 3371 /**
3513 * Parse a list of type parameters. 3372 * Parse a list of type parameters. Return the list of type parameters that
3373 * were parsed.
3514 * 3374 *
3515 * <pre> 3375 * typeParameterList ::=
3516 * typeParameterList ::= 3376 * '<' typeParameter (',' typeParameter)* '>'
3517 * '<' typeParameter (',' typeParameter)* '>'
3518 * </pre>
3519 *
3520 * @return the list of type parameters that were parsed
3521 */ 3377 */
3522 TypeParameterList parseTypeParameterList() { 3378 TypeParameterList parseTypeParameterList() {
3523 Token leftBracket = _expect(TokenType.LT); 3379 Token leftBracket = _expect(TokenType.LT);
3524 List<TypeParameter> typeParameters = new List<TypeParameter>(); 3380 List<TypeParameter> typeParameters = new List<TypeParameter>();
3525 typeParameters.add(parseTypeParameter()); 3381 typeParameters.add(parseTypeParameter());
3526 while (_optional(TokenType.COMMA)) { 3382 while (_optional(TokenType.COMMA)) {
3527 typeParameters.add(parseTypeParameter()); 3383 typeParameters.add(parseTypeParameter());
3528 } 3384 }
3529 Token rightBracket = _expectGt(); 3385 Token rightBracket = _expectGt();
3530 return new TypeParameterList(leftBracket, typeParameters, rightBracket); 3386 return new TypeParameterList(leftBracket, typeParameters, rightBracket);
3531 } 3387 }
3532 3388
3533 /** 3389 /**
3534 * Parse a with clause. 3390 * Parse a with clause. Return the with clause that was parsed.
3535 * 3391 *
3536 * <pre> 3392 * withClause ::=
3537 * withClause ::= 3393 * 'with' typeName (',' typeName)*
3538 * 'with' typeName (',' typeName)*
3539 * </pre>
3540 *
3541 * @return the with clause that was parsed
3542 */ 3394 */
3543 WithClause parseWithClause() { 3395 WithClause parseWithClause() {
3544 Token with2 = _expectKeyword(Keyword.WITH); 3396 Token with2 = _expectKeyword(Keyword.WITH);
3545 List<TypeName> types = new List<TypeName>(); 3397 List<TypeName> types = new List<TypeName>();
3546 types.add(parseTypeName()); 3398 types.add(parseTypeName());
3547 while (_optional(TokenType.COMMA)) { 3399 while (_optional(TokenType.COMMA)) {
3548 types.add(parseTypeName()); 3400 types.add(parseTypeName());
3549 } 3401 }
3550 return new WithClause(with2, types); 3402 return new WithClause(with2, types);
3551 } 3403 }
3552 3404
3553 /** 3405 /**
3554 * Advance to the next token in the token stream. 3406 * Advance to the next token in the token stream.
3555 */ 3407 */
3556 void _advance() { 3408 void _advance() {
3557 _currentToken = _currentToken.next; 3409 _currentToken = _currentToken.next;
3558 } 3410 }
3559 3411
3560 /** 3412 /**
3561 * Append the character equivalent of the given scalar value to the given buil der. Use the start 3413 * Append the character equivalent of the given [scalarValue] to the given
3562 * and end indices to report an error, and don't append anything to the builde r, if the scalar 3414 * [builder]. Use the [startIndex] and [endIndex] to report an error, and
3563 * value is invalid. 3415 * don't append anything to the builder, if the scalar value is invalid. The
3564 * 3416 * [escapeSequence] is the escape sequence that was parsed to produce the
3565 * @param builder the builder to which the scalar value is to be appended 3417 * scalar value (used for error reporting).
3566 * @param escapeSequence the escape sequence that was parsed to produce the sc alar value
3567 * @param scalarValue the value to be appended
3568 * @param startIndex the index of the first character representing the scalar value
3569 * @param endIndex the index of the last character representing the scalar val ue
3570 */ 3418 */
3571 void _appendScalarValue(StringBuffer buffer, String escapeSequence, 3419 void _appendScalarValue(StringBuffer buffer, String escapeSequence,
3572 int scalarValue, int startIndex, int endIndex) { 3420 int scalarValue, int startIndex, int endIndex) {
3573 if (scalarValue < 0 || 3421 if (scalarValue < 0 ||
3574 scalarValue > Character.MAX_CODE_POINT || 3422 scalarValue > Character.MAX_CODE_POINT ||
3575 (scalarValue >= 0xD800 && scalarValue <= 0xDFFF)) { 3423 (scalarValue >= 0xD800 && scalarValue <= 0xDFFF)) {
3576 _reportErrorForCurrentToken( 3424 _reportErrorForCurrentToken(
3577 ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]); 3425 ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
3578 return; 3426 return;
3579 } 3427 }
3580 if (scalarValue < Character.MAX_VALUE) { 3428 if (scalarValue < Character.MAX_VALUE) {
3581 buffer.writeCharCode(scalarValue); 3429 buffer.writeCharCode(scalarValue);
3582 } else { 3430 } else {
3583 buffer.write(Character.toChars(scalarValue)); 3431 buffer.write(Character.toChars(scalarValue));
3584 } 3432 }
3585 } 3433 }
3586 3434
3587 /** 3435 /**
3588 * Compute the content of a string with the given literal representation. 3436 * Return the content of a string with the given literal representation. The
3589 * 3437 * [lexeme] is the literal representation of the string. The flag [first] is
3590 * @param lexeme the literal representation of the string 3438 * `true` if this is the first token in a string literal. The flag [last] is
3591 * @param first `true` if this is the first token in a string literal 3439 * `true` if this is the last token in a string literal.
3592 * @param last `true` if this is the last token in a string literal
3593 * @return the actual value of the string
3594 */ 3440 */
3595 String _computeStringValue(String lexeme, bool first, bool last) { 3441 String _computeStringValue(String lexeme, bool first, bool last) {
3596 bool isRaw = false; 3442 bool isRaw = false;
3597 int start = 0; 3443 int start = 0;
3598 if (first) { 3444 if (first) {
3599 if (StringUtilities.startsWith4(lexeme, 0, 0x72, 0x22, 0x22, 0x22) || 3445 if (StringUtilities.startsWith4(lexeme, 0, 0x72, 0x22, 0x22, 0x22) ||
3600 StringUtilities.startsWith4(lexeme, 0, 0x72, 0x27, 0x27, 0x27)) { 3446 StringUtilities.startsWith4(lexeme, 0, 0x72, 0x27, 0x27, 0x27)) {
3601 isRaw = true; 3447 isRaw = true;
3602 start += 4; 3448 start += 4;
3603 } else if (StringUtilities.startsWith2(lexeme, 0, 0x72, 0x22) || 3449 } else if (StringUtilities.startsWith2(lexeme, 0, 0x72, 0x22) ||
(...skipping 28 matching lines...) Expand all
3632 } 3478 }
3633 StringBuffer buffer = new StringBuffer(); 3479 StringBuffer buffer = new StringBuffer();
3634 int index = start; 3480 int index = start;
3635 while (index < end) { 3481 while (index < end) {
3636 index = _translateCharacter(buffer, lexeme, index); 3482 index = _translateCharacter(buffer, lexeme, index);
3637 } 3483 }
3638 return buffer.toString(); 3484 return buffer.toString();
3639 } 3485 }
3640 3486
3641 /** 3487 /**
3642 * Convert the given method declaration into the nearest valid top-level funct ion declaration. 3488 * Convert the given [method] declaration into the nearest valid top-level
3643 * 3489 * function declaration (that is, the function declaration that most closely
3644 * @param method the method to be converted 3490 * captures the components of the given method declaration).
3645 * @return the function declaration that most closely captures the components of the given method
3646 * declaration
3647 */ 3491 */
3648 FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) => 3492 FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
3649 new FunctionDeclaration(method.documentationComment, method.metadata, 3493 new FunctionDeclaration(method.documentationComment, method.metadata,
3650 method.externalKeyword, method.returnType, method.propertyKeyword, 3494 method.externalKeyword, method.returnType, method.propertyKeyword,
3651 method.name, new FunctionExpression(method.parameters, method.body)); 3495 method.name, new FunctionExpression(method.parameters, method.body));
3652 3496
3653 /** 3497 /**
3654 * Return `true` if the current token could be the start of a compilation unit member. This 3498 * Return `true` if the current token could be the start of a compilation unit
3655 * method is used for recovery purposes to decide when to stop skipping tokens after finding an 3499 * member. This method is used for recovery purposes to decide when to stop
3656 * error while parsing a compilation unit member. 3500 * skipping tokens after finding an error while parsing a compilation unit
3657 * 3501 * member.
3658 * @return `true` if the current token could be the start of a compilation uni t member
3659 */ 3502 */
3660 bool _couldBeStartOfCompilationUnitMember() { 3503 bool _couldBeStartOfCompilationUnitMember() {
3661 if ((_matchesKeyword(Keyword.IMPORT) || 3504 if ((_matchesKeyword(Keyword.IMPORT) ||
3662 _matchesKeyword(Keyword.EXPORT) || 3505 _matchesKeyword(Keyword.EXPORT) ||
3663 _matchesKeyword(Keyword.LIBRARY) || 3506 _matchesKeyword(Keyword.LIBRARY) ||
3664 _matchesKeyword(Keyword.PART)) && 3507 _matchesKeyword(Keyword.PART)) &&
3665 !_tokenMatches(_peek(), TokenType.PERIOD) && 3508 !_tokenMatches(_peek(), TokenType.PERIOD) &&
3666 !_tokenMatches(_peek(), TokenType.LT)) { 3509 !_tokenMatches(_peek(), TokenType.LT)) {
3667 // This looks like the start of a directive 3510 // This looks like the start of a directive
3668 return true; 3511 return true;
(...skipping 24 matching lines...) Expand all
3693 _matchesKeyword(Keyword.SET) || 3536 _matchesKeyword(Keyword.SET) ||
3694 (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) || 3537 (_matchesKeyword(Keyword.OPERATOR) && _isOperator(_peek())) ||
3695 _matchesIdentifier()) { 3538 _matchesIdentifier()) {
3696 return true; 3539 return true;
3697 } 3540 }
3698 } 3541 }
3699 return false; 3542 return false;
3700 } 3543 }
3701 3544
3702 /** 3545 /**
3703 * Create a synthetic identifier. 3546 * Return a synthetic identifier.
3704 *
3705 * @return the synthetic identifier that was created
3706 */ 3547 */
3707 SimpleIdentifier _createSyntheticIdentifier() { 3548 SimpleIdentifier _createSyntheticIdentifier() {
3708 Token syntheticToken; 3549 Token syntheticToken;
3709 if (_currentToken.type == TokenType.KEYWORD) { 3550 if (_currentToken.type == TokenType.KEYWORD) {
3710 // Consider current keyword token as an identifier. 3551 // Consider current keyword token as an identifier.
3711 // It is not always true, e.g. "^is T" where "^" is place the place for 3552 // It is not always true, e.g. "^is T" where "^" is place the place for
3712 // synthetic identifier. By creating SyntheticStringToken we can 3553 // synthetic identifier. By creating SyntheticStringToken we can
3713 // distinguish a real identifier from synthetic. In the code completion 3554 // distinguish a real identifier from synthetic. In the code completion
3714 // behavior will depend on a cursor position - before or on "is". 3555 // behavior will depend on a cursor position - before or on "is".
3715 syntheticToken = _injectToken(new SyntheticStringToken( 3556 syntheticToken = _injectToken(new SyntheticStringToken(
3716 TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset)); 3557 TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
3717 } else { 3558 } else {
3718 syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER); 3559 syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
3719 } 3560 }
3720 return new SimpleIdentifier(syntheticToken); 3561 return new SimpleIdentifier(syntheticToken);
3721 } 3562 }
3722 3563
3723 /** 3564 /**
3724 * Create a synthetic token representing the given keyword. 3565 * Return a synthetic token representing the given [keyword].
3725 *
3726 * @return the synthetic token that was created
3727 */ 3566 */
3728 Token _createSyntheticKeyword(Keyword keyword) => _injectToken( 3567 Token _createSyntheticKeyword(Keyword keyword) => _injectToken(
3729 new Parser_SyntheticKeywordToken(keyword, _currentToken.offset)); 3568 new Parser_SyntheticKeywordToken(keyword, _currentToken.offset));
3730 3569
3731 /** 3570 /**
3732 * Create a synthetic string literal. 3571 * Return a synthetic string literal.
3733 *
3734 * @return the synthetic string literal that was created
3735 */ 3572 */
3736 SimpleStringLiteral _createSyntheticStringLiteral() => 3573 SimpleStringLiteral _createSyntheticStringLiteral() =>
3737 new SimpleStringLiteral(_createSyntheticToken(TokenType.STRING), ""); 3574 new SimpleStringLiteral(_createSyntheticToken(TokenType.STRING), "");
3738 3575
3739 /** 3576 /**
3740 * Create a synthetic token with the given type. 3577 * Return a synthetic token with the given [type].
3741 *
3742 * @return the synthetic token that was created
3743 */ 3578 */
3744 Token _createSyntheticToken(TokenType type) => 3579 Token _createSyntheticToken(TokenType type) =>
3745 _injectToken(new StringToken(type, "", _currentToken.offset)); 3580 _injectToken(new StringToken(type, "", _currentToken.offset));
3746 3581
3747 /** 3582 /**
3748 * Create and return a new token with the given [type]. The token will replace 3583 * Create and return a new token with the given [type]. The token will replace
3749 * the first portion of the given [token], so it will have the same offset and 3584 * the first portion of the given [token], so it will have the same offset and
3750 * will have any comments that might have preceeded the token. 3585 * will have any comments that might have preceeded the token.
3751 */ 3586 */
3752 Token _createToken(Token token, TokenType type, {bool isBegin: false}) { 3587 Token _createToken(Token token, TokenType type, {bool isBegin: false}) {
3753 CommentToken comments = token.precedingComments; 3588 CommentToken comments = token.precedingComments;
3754 if (comments == null) { 3589 if (comments == null) {
3755 if (isBegin) { 3590 if (isBegin) {
3756 return new BeginToken(type, token.offset); 3591 return new BeginToken(type, token.offset);
3757 } 3592 }
3758 return new Token(type, token.offset); 3593 return new Token(type, token.offset);
3759 } else if (isBegin) { 3594 } else if (isBegin) {
3760 return new BeginTokenWithComment(type, token.offset, comments); 3595 return new BeginTokenWithComment(type, token.offset, comments);
3761 } 3596 }
3762 return new TokenWithComment(type, token.offset, comments); 3597 return new TokenWithComment(type, token.offset, comments);
3763 } 3598 }
3764 3599
3765 /** 3600 /**
3766 * Check that the given expression is assignable and report an error if it isn 't. 3601 * Check that the given [expression] is assignable and report an error if it
3602 * isn't.
3767 * 3603 *
3768 * <pre> 3604 * assignableExpression ::=
3769 * assignableExpression ::= 3605 * primary (arguments* assignableSelector)+
3770 * primary (arguments* assignableSelector)+ 3606 * | 'super' assignableSelector
3771 * | 'super' assignableSelector 3607 * | identifier
3772 * | identifier
3773 * 3608 *
3774 * assignableSelector ::= 3609 * assignableSelector ::=
3775 * '[' expression ']' 3610 * '[' expression ']'
3776 * | '.' identifier 3611 * | '.' identifier
3777 * </pre>
3778 *
3779 * @param expression the expression being checked
3780 */ 3612 */
3781 void _ensureAssignable(Expression expression) { 3613 void _ensureAssignable(Expression expression) {
3782 if (expression != null && !expression.isAssignable) { 3614 if (expression != null && !expression.isAssignable) {
3783 _reportErrorForCurrentToken( 3615 _reportErrorForCurrentToken(
3784 ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE); 3616 ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE);
3785 } 3617 }
3786 } 3618 }
3787 3619
3788 /** 3620 /**
3789 * If the current token has the expected type, return it after advancing to 3621 * If the current token has the expected type, return it after advancing to
(...skipping 21 matching lines...) Expand all
3811 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN, 3643 _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
3812 _currentToken.previous, [type.lexeme]); 3644 _currentToken.previous, [type.lexeme]);
3813 } else { 3645 } else {
3814 _reportErrorForCurrentToken( 3646 _reportErrorForCurrentToken(
3815 ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]); 3647 ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
3816 } 3648 }
3817 return _currentToken; 3649 return _currentToken;
3818 } 3650 }
3819 3651
3820 /** 3652 /**
3821 * If the current token has the type [TokenType.GT], return it after advancing to the next 3653 * If the current token has the type [TokenType.GT], return it after advancing
3822 * token. Otherwise report an error and return the current token without advan cing. 3654 * to the next token. Otherwise report an error and return the current token
3823 * 3655 * without advancing.
3824 * @return the token that matched the given type
3825 */ 3656 */
3826 Token _expectGt() { 3657 Token _expectGt() {
3827 if (_matchesGt()) { 3658 if (_matchesGt()) {
3828 return getAndAdvance(); 3659 return getAndAdvance();
3829 } 3660 }
3830 _reportErrorForCurrentToken( 3661 _reportErrorForCurrentToken(
3831 ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]); 3662 ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]);
3832 return _currentToken; 3663 return _currentToken;
3833 } 3664 }
3834 3665
3835 /** 3666 /**
3836 * If the current token is a keyword matching the given string, return it afte r advancing to the 3667 * If the current token is a keyword matching the given [keyword], return it
3837 * next token. Otherwise report an error and return the current token without advancing. 3668 * after advancing to the next token. Otherwise report an error and return the
3838 * 3669 * current token without advancing.
3839 * @param keyword the keyword that is expected
3840 * @return the token that matched the given type
3841 */ 3670 */
3842 Token _expectKeyword(Keyword keyword) { 3671 Token _expectKeyword(Keyword keyword) {
3843 if (_matchesKeyword(keyword)) { 3672 if (_matchesKeyword(keyword)) {
3844 return getAndAdvance(); 3673 return getAndAdvance();
3845 } 3674 }
3846 // Remove uses of this method in favor of matches? 3675 // Remove uses of this method in favor of matches?
3847 // Pass in the error code to use to report the error? 3676 // Pass in the error code to use to report the error?
3848 _reportErrorForCurrentToken( 3677 _reportErrorForCurrentToken(
3849 ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]); 3678 ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
3850 return _currentToken; 3679 return _currentToken;
3851 } 3680 }
3852 3681
3853 /** 3682 /**
3854 * If [currentToken] is a semicolon, returns it; otherwise reports error and c reates a 3683 * If the current token is a semicolon, return it after advancing to the next
3855 * synthetic one. 3684 * token. Otherwise report an error and create a synthetic semicolon.
3856 *
3857 * TODO(scheglov) consider pushing this into [expect]
3858 */ 3685 */
3859 Token _expectSemicolon() { 3686 Token _expectSemicolon() {
3687 // TODO(scheglov) consider pushing this behavior into [_expect]
3860 if (_matches(TokenType.SEMICOLON)) { 3688 if (_matches(TokenType.SEMICOLON)) {
3861 return getAndAdvance(); 3689 return getAndAdvance();
3862 } else { 3690 } else {
3863 _reportErrorForToken( 3691 _reportErrorForToken(
3864 ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [";"]); 3692 ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [";"]);
3865 return _createSyntheticToken(TokenType.SEMICOLON); 3693 return _createSyntheticToken(TokenType.SEMICOLON);
3866 } 3694 }
3867 } 3695 }
3868 3696
3869 /** 3697 /**
3870 * Search the given list of ranges for a range that contains the given index. Return the range 3698 * Search the given list of [ranges] for a range that contains the given
3871 * that was found, or `null` if none of the ranges contain the index. 3699 * [index]. Return the range that was found, or `null` if none of the ranges
3872 * 3700 * contain the index.
3873 * @param ranges the ranges to be searched
3874 * @param index the index contained in the returned range
3875 * @return the range that was found
3876 */ 3701 */
3877 List<int> _findRange(List<List<int>> ranges, int index) { 3702 List<int> _findRange(List<List<int>> ranges, int index) {
3878 int rangeCount = ranges.length; 3703 int rangeCount = ranges.length;
3879 for (int i = 0; i < rangeCount; i++) { 3704 for (int i = 0; i < rangeCount; i++) {
3880 List<int> range = ranges[i]; 3705 List<int> range = ranges[i];
3881 if (range[0] <= index && index <= range[1]) { 3706 if (range[0] <= index && index <= range[1]) {
3882 return range; 3707 return range;
3883 } else if (index < range[0]) { 3708 } else if (index < range[0]) {
3884 return null; 3709 return null;
3885 } 3710 }
3886 } 3711 }
3887 return null; 3712 return null;
3888 } 3713 }
3889 3714
3890 /** 3715 /**
3891 * Return a list of the ranges of characters in the given comment string that should be treated as 3716 * Return a list of the ranges of characters in the given [comment] that
3892 * code blocks. 3717 * should be treated as code blocks.
3893 *
3894 * @param comment the comment being processed
3895 * @return the ranges of characters that should be treated as code blocks
3896 */ 3718 */
3897 List<List<int>> _getCodeBlockRanges(String comment) { 3719 List<List<int>> _getCodeBlockRanges(String comment) {
3898 List<List<int>> ranges = new List<List<int>>(); 3720 List<List<int>> ranges = new List<List<int>>();
3899 int length = comment.length; 3721 int length = comment.length;
3900 if (length < 3) { 3722 if (length < 3) {
3901 return ranges; 3723 return ranges;
3902 } 3724 }
3903 int index = 0; 3725 int index = 0;
3904 int firstChar = comment.codeUnitAt(0); 3726 int firstChar = comment.codeUnitAt(0);
3905 if (firstChar == 0x2F) { 3727 if (firstChar == 0x2F) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3939 ranges.add(<int>[index, end]); 3761 ranges.add(<int>[index, end]);
3940 index = end + 1; 3762 index = end + 1;
3941 } else { 3763 } else {
3942 index = index + 1; 3764 index = index + 1;
3943 } 3765 }
3944 } 3766 }
3945 return ranges; 3767 return ranges;
3946 } 3768 }
3947 3769
3948 /** 3770 /**
3949 * Return the end token associated with the given begin token, or `null` if ei ther the given 3771 * Return the end token associated with the given [beginToken], or `null` if
3950 * token is not a begin token or it does not have an end token associated with it. 3772 * either the given token is not a begin token or it does not have an end
3951 * 3773 * token associated with it.
3952 * @param beginToken the token that is expected to have an end token associate d with it
3953 * @return the end token associated with the begin token
3954 */ 3774 */
3955 Token _getEndToken(Token beginToken) { 3775 Token _getEndToken(Token beginToken) {
3956 if (beginToken is BeginToken) { 3776 if (beginToken is BeginToken) {
3957 return beginToken.endToken; 3777 return beginToken.endToken;
3958 } 3778 }
3959 return null; 3779 return null;
3960 } 3780 }
3961 3781
3962 /** 3782 /**
3963 * Inject the given token into the token stream immediately before the current token. 3783 * Inject the given [token] into the token stream immediately before the
3964 * 3784 * current token.
3965 * @param token the token to be added to the token stream
3966 * @return the token that was just added to the token stream
3967 */ 3785 */
3968 Token _injectToken(Token token) { 3786 Token _injectToken(Token token) {
3969 Token previous = _currentToken.previous; 3787 Token previous = _currentToken.previous;
3970 token.setNext(_currentToken); 3788 token.setNext(_currentToken);
3971 previous.setNext(token); 3789 previous.setNext(token);
3972 return token; 3790 return token;
3973 } 3791 }
3974 3792
3975 /** 3793 /**
3976 * Return `true` if the current token appears to be the beginning of a 3794 * Return `true` if the current token appears to be the beginning of a
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4012 if (afterName == null) { 3830 if (afterName == null) {
4013 return false; 3831 return false;
4014 } 3832 }
4015 return _tokenMatches(afterName, TokenType.FUNCTION) || 3833 return _tokenMatches(afterName, TokenType.FUNCTION) ||
4016 _tokenMatches(afterName, TokenType.OPEN_CURLY_BRACKET); 3834 _tokenMatches(afterName, TokenType.OPEN_CURLY_BRACKET);
4017 } 3835 }
4018 return false; 3836 return false;
4019 } 3837 }
4020 3838
4021 /** 3839 /**
4022 * Return `true` if the given token appears to be the beginning of a function expression. 3840 * Return `true` if the given [token] appears to be the beginning of a
4023 * 3841 * function expression.
4024 * @param startToken the token that might be the start of a function expressio n
4025 * @return `true` if the given token appears to be the beginning of a function expression
4026 */ 3842 */
4027 bool _isFunctionExpression(Token startToken) { 3843 bool _isFunctionExpression(Token token) {
4028 // Function expressions aren't allowed in initializer lists. 3844 // Function expressions aren't allowed in initializer lists.
4029 if (_inInitializer) { 3845 if (_inInitializer) {
4030 return false; 3846 return false;
4031 } 3847 }
4032 Token afterParameters = _skipFormalParameterList(startToken); 3848 Token afterParameters = _skipFormalParameterList(token);
4033 if (afterParameters == null) { 3849 if (afterParameters == null) {
4034 return false; 3850 return false;
4035 } 3851 }
4036 if (afterParameters 3852 if (afterParameters
4037 .matchesAny([TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) { 3853 .matchesAny([TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
4038 return true; 3854 return true;
4039 } 3855 }
4040 String lexeme = afterParameters.lexeme; 3856 String lexeme = afterParameters.lexeme;
4041 return lexeme == ASYNC || lexeme == SYNC; 3857 return lexeme == ASYNC || lexeme == SYNC;
4042 } 3858 }
4043 3859
4044 /** 3860 /**
4045 * Return `true` if the given character is a valid hexadecimal digit. 3861 * Return `true` if the given [character] is a valid hexadecimal digit.
4046 *
4047 * @param character the character being tested
4048 * @return `true` if the character is a valid hexadecimal digit
4049 */ 3862 */
4050 bool _isHexDigit(int character) => (0x30 <= character && character <= 0x39) || 3863 bool _isHexDigit(int character) => (0x30 <= character && character <= 0x39) ||
4051 (0x41 <= character && character <= 0x46) || 3864 (0x41 <= character && character <= 0x46) ||
4052 (0x61 <= character && character <= 0x66); 3865 (0x61 <= character && character <= 0x66);
4053 3866
4054 /** 3867 /**
4055 * Return `true` if the current token is the first token in an initialized var iable 3868 * Return `true` if the current token is the first token in an initialized
4056 * declaration rather than an expression. This method assumes that we have alr eady skipped past 3869 * variable declaration rather than an expression. This method assumes that we
4057 * any metadata that might be associated with the declaration. 3870 * have already skipped past any metadata that might be associated with the
3871 * declaration.
4058 * 3872 *
4059 * <pre> 3873 * initializedVariableDeclaration ::=
4060 * initializedVariableDeclaration ::= 3874 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
4061 * declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
4062 * 3875 *
4063 * declaredIdentifier ::= 3876 * declaredIdentifier ::=
4064 * metadata finalConstVarOrType identifier 3877 * metadata finalConstVarOrType identifier
4065 * 3878 *
4066 * finalConstVarOrType ::= 3879 * finalConstVarOrType ::=
4067 * 'final' type? 3880 * 'final' type?
4068 * | 'const' type? 3881 * | 'const' type?
4069 * | 'var' 3882 * | 'var'
4070 * | type 3883 * | type
4071 * 3884 *
4072 * type ::= 3885 * type ::=
4073 * qualified typeArguments? 3886 * qualified typeArguments?
4074 * 3887 *
4075 * initializedIdentifier ::= 3888 * initializedIdentifier ::=
4076 * identifier ('=' expression)? 3889 * identifier ('=' expression)?
4077 * </pre>
4078 *
4079 * @return `true` if the current token is the first token in an initialized va riable
4080 * declaration
4081 */ 3890 */
4082 bool _isInitializedVariableDeclaration() { 3891 bool _isInitializedVariableDeclaration() {
4083 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.VAR)) { 3892 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.VAR)) {
4084 // An expression cannot start with a keyword other than 'const', 3893 // An expression cannot start with a keyword other than 'const',
4085 // 'rethrow', or 'throw'. 3894 // 'rethrow', or 'throw'.
4086 return true; 3895 return true;
4087 } 3896 }
4088 if (_matchesKeyword(Keyword.CONST)) { 3897 if (_matchesKeyword(Keyword.CONST)) {
4089 // Look to see whether we might be at the start of a list or map literal, 3898 // Look to see whether we might be at the start of a list or map literal,
4090 // otherwise this should be the start of a variable declaration. 3899 // otherwise this should be the start of a variable declaration.
(...skipping 16 matching lines...) Expand all
4107 return false; 3916 return false;
4108 } 3917 }
4109 TokenType type = token.type; 3918 TokenType type = token.type;
4110 return type == TokenType.EQ || 3919 return type == TokenType.EQ ||
4111 type == TokenType.COMMA || 3920 type == TokenType.COMMA ||
4112 type == TokenType.SEMICOLON || 3921 type == TokenType.SEMICOLON ||
4113 _tokenMatchesKeyword(token, Keyword.IN); 3922 _tokenMatchesKeyword(token, Keyword.IN);
4114 } 3923 }
4115 3924
4116 /** 3925 /**
4117 * Given that we have just found bracketed text within a comment, look to see whether that text is 3926 * Given that we have just found bracketed text within the given [comment],
4118 * (a) followed by a parenthesized link address, (b) followed by a colon, or ( c) followed by 3927 * look to see whether that text is (a) followed by a parenthesized link
4119 * optional whitespace and another square bracket. 3928 * address, (b) followed by a colon, or (c) followed by optional whitespace
3929 * and another square bracket. The [rightIndex] is the index of the right
3930 * bracket. Return `true` if the bracketed text is followed by a link address.
4120 * 3931 *
4121 * This method uses the syntax described by the <a 3932 * This method uses the syntax described by the
4122 * href="http://daringfireball.net/projects/markdown/syntax">markdown</a> proj ect. 3933 * <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a>
4123 * 3934 * project.
4124 * @param comment the comment text in which the bracketed text was found
4125 * @param rightIndex the index of the right bracket
4126 * @return `true` if the bracketed text is followed by a link address
4127 */ 3935 */
4128 bool _isLinkText(String comment, int rightIndex) { 3936 bool _isLinkText(String comment, int rightIndex) {
4129 int length = comment.length; 3937 int length = comment.length;
4130 int index = rightIndex + 1; 3938 int index = rightIndex + 1;
4131 if (index >= length) { 3939 if (index >= length) {
4132 return false; 3940 return false;
4133 } 3941 }
4134 int nextChar = comment.codeUnitAt(index); 3942 int nextChar = comment.codeUnitAt(index);
4135 if (nextChar == 0x28 || nextChar == 0x3A) { 3943 if (nextChar == 0x28 || nextChar == 0x3A) {
4136 return true; 3944 return true;
4137 } 3945 }
4138 while (Character.isWhitespace(nextChar)) { 3946 while (Character.isWhitespace(nextChar)) {
4139 index = index + 1; 3947 index = index + 1;
4140 if (index >= length) { 3948 if (index >= length) {
4141 return false; 3949 return false;
4142 } 3950 }
4143 nextChar = comment.codeUnitAt(index); 3951 nextChar = comment.codeUnitAt(index);
4144 } 3952 }
4145 return nextChar == 0x5B; 3953 return nextChar == 0x5B;
4146 } 3954 }
4147 3955
4148 /** 3956 /**
4149 * Return `true` if the given token appears to be the beginning of an operator declaration. 3957 * Return `true` if the given [startToken] appears to be the beginning of an
4150 * 3958 * operator declaration.
4151 * @param startToken the token that might be the start of an operator declarat ion
4152 * @return `true` if the given token appears to be the beginning of an operato r declaration
4153 */ 3959 */
4154 bool _isOperator(Token startToken) { 3960 bool _isOperator(Token startToken) {
4155 // Accept any operator here, even if it is not user definable. 3961 // Accept any operator here, even if it is not user definable.
4156 if (!startToken.isOperator) { 3962 if (!startToken.isOperator) {
4157 return false; 3963 return false;
4158 } 3964 }
4159 // Token "=" means that it is actually field initializer. 3965 // Token "=" means that it is actually field initializer.
4160 if (startToken.type == TokenType.EQ) { 3966 if (startToken.type == TokenType.EQ) {
4161 return false; 3967 return false;
4162 } 3968 }
4163 // Consume all operator tokens. 3969 // Consume all operator tokens.
4164 Token token = startToken.next; 3970 Token token = startToken.next;
4165 while (token.isOperator) { 3971 while (token.isOperator) {
4166 token = token.next; 3972 token = token.next;
4167 } 3973 }
4168 // Formal parameter list is expect now. 3974 // Formal parameter list is expect now.
4169 return _tokenMatches(token, TokenType.OPEN_PAREN); 3975 return _tokenMatches(token, TokenType.OPEN_PAREN);
4170 } 3976 }
4171 3977
4172 /** 3978 /**
4173 * Return `true` if the current token appears to be the beginning of a switch member. 3979 * Return `true` if the current token appears to be the beginning of a switch
4174 * 3980 * member.
4175 * @return `true` if the current token appears to be the beginning of a switch member
4176 */ 3981 */
4177 bool _isSwitchMember() { 3982 bool _isSwitchMember() {
4178 Token token = _currentToken; 3983 Token token = _currentToken;
4179 while (_tokenMatches(token, TokenType.IDENTIFIER) && 3984 while (_tokenMatches(token, TokenType.IDENTIFIER) &&
4180 _tokenMatches(token.next, TokenType.COLON)) { 3985 _tokenMatches(token.next, TokenType.COLON)) {
4181 token = token.next.next; 3986 token = token.next.next;
4182 } 3987 }
4183 if (token.type == TokenType.KEYWORD) { 3988 if (token.type == TokenType.KEYWORD) {
4184 Keyword keyword = (token as KeywordToken).keyword; 3989 Keyword keyword = (token as KeywordToken).keyword;
4185 return keyword == Keyword.CASE || keyword == Keyword.DEFAULT; 3990 return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
(...skipping 29 matching lines...) Expand all
4215 4020
4216 /** 4021 /**
4217 * Increments the error reporting lock level. If level is more than `0`, then 4022 * Increments the error reporting lock level. If level is more than `0`, then
4218 * [reportError] wont report any error. 4023 * [reportError] wont report any error.
4219 */ 4024 */
4220 void _lockErrorListener() { 4025 void _lockErrorListener() {
4221 _errorListenerLock++; 4026 _errorListenerLock++;
4222 } 4027 }
4223 4028
4224 /** 4029 /**
4225 * Return `true` if the current token has the given type. Note that the method 4030 * Return `true` if the current token has the given [type]. Note that the
4226 * [_matchesGt] should be used if the argument to this method would be 4031 * method [_matchesGt] should be used if the argument to this method would be
4227 * [TokenType.GT]. 4032 * [TokenType.GT].
4228 *
4229 * @param type the type of token that can optionally appear in the current loc ation
4230 * @return `true` if the current token has the given type
4231 */ 4033 */
4232 bool _matches(TokenType type) => _currentToken.type == type; 4034 bool _matches(TokenType type) => _currentToken.type == type;
4233 4035
4234 /** 4036 /**
4235 * Return `true` if the current token has a type of [TokenType.GT]. Note that this 4037 * Return `true` if the current token has a type of [TokenType.GT]. Note that
4236 * method, unlike other variants, will modify the token stream if possible to match desired type. 4038 * this method, unlike other variants, will modify the token stream if
4237 * In particular, if the next token is either a '>>' or '>>>', the token strea m will be re-written 4039 * possible to match desired type. In particular, if the next token is either
4238 * and `true` will be returned. 4040 * a '>>' or '>>>', the token stream will be re-written and `true` will be
4239 * 4041 * returned.
4240 * @return `true` if the current token has a type of [TokenType.GT]
4241 */ 4042 */
4242 bool _matchesGt() { 4043 bool _matchesGt() {
4243 TokenType currentType = _currentToken.type; 4044 TokenType currentType = _currentToken.type;
4244 if (currentType == TokenType.GT) { 4045 if (currentType == TokenType.GT) {
4245 return true; 4046 return true;
4246 } else if (currentType == TokenType.GT_GT) { 4047 } else if (currentType == TokenType.GT_GT) {
4247 Token first = _createToken(_currentToken, TokenType.GT); 4048 Token first = _createToken(_currentToken, TokenType.GT);
4248 Token second = new Token(TokenType.GT, _currentToken.offset + 1); 4049 Token second = new Token(TokenType.GT, _currentToken.offset + 1);
4249 second.setNext(_currentToken.next); 4050 second.setNext(_currentToken.next);
4250 first.setNext(second); 4051 first.setNext(second);
(...skipping 17 matching lines...) Expand all
4268 second.setNext(third); 4069 second.setNext(third);
4269 first.setNext(second); 4070 first.setNext(second);
4270 _currentToken.previous.setNext(first); 4071 _currentToken.previous.setNext(first);
4271 _currentToken = first; 4072 _currentToken = first;
4272 return true; 4073 return true;
4273 } 4074 }
4274 return false; 4075 return false;
4275 } 4076 }
4276 4077
4277 /** 4078 /**
4278 * Return `true` if the current token is a valid identifier. Valid identifiers include 4079 * Return `true` if the current token is a valid identifier. Valid identifiers
4279 * built-in identifiers (pseudo-keywords). 4080 * include built-in identifiers (pseudo-keywords).
4280 *
4281 * @return `true` if the current token is a valid identifier
4282 */ 4081 */
4283 bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken); 4082 bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken);
4284 4083
4285 /** 4084 /**
4286 * Return `true` if the current token matches the given keyword. 4085 * Return `true` if the current token matches the given [keyword].
4287 *
4288 * @param keyword the keyword that can optionally appear in the current locati on
4289 * @return `true` if the current token matches the given keyword
4290 */ 4086 */
4291 bool _matchesKeyword(Keyword keyword) => 4087 bool _matchesKeyword(Keyword keyword) =>
4292 _tokenMatchesKeyword(_currentToken, keyword); 4088 _tokenMatchesKeyword(_currentToken, keyword);
4293 4089
4294 /** 4090 /**
4295 * Return `true` if the current token matches the given identifier. 4091 * Return `true` if the current token matches the given [identifier].
4296 *
4297 * @param identifier the identifier that can optionally appear in the current location
4298 * @return `true` if the current token matches the given identifier
4299 */ 4092 */
4300 bool _matchesString(String identifier) => 4093 bool _matchesString(String identifier) =>
4301 _currentToken.type == TokenType.IDENTIFIER && 4094 _currentToken.type == TokenType.IDENTIFIER &&
4302 _currentToken.lexeme == identifier; 4095 _currentToken.lexeme == identifier;
4303 4096
4304 /** 4097 /**
4305 * If the current token has the given type, then advance to the next token and return `true` 4098 * If the current token has the given [type], then advance to the next token
4306 * . Otherwise, return `false` without advancing. This method should not be in voked with an 4099 * and return `true`. Otherwise, return `false` without advancing. This method
4307 * argument value of [TokenType.GT]. 4100 * should not be invoked with an argument value of [TokenType.GT].
4308 *
4309 * @param type the type of token that can optionally appear in the current loc ation
4310 * @return `true` if the current token has the given type
4311 */ 4101 */
4312 bool _optional(TokenType type) { 4102 bool _optional(TokenType type) {
4313 if (_matches(type)) { 4103 if (_matches(type)) {
4314 _advance(); 4104 _advance();
4315 return true; 4105 return true;
4316 } 4106 }
4317 return false; 4107 return false;
4318 } 4108 }
4319 4109
4320 /** 4110 /**
4321 * Parse an additive expression. 4111 * Parse an additive expression. Return the additive expression that was
4112 * parsed.
4322 * 4113 *
4323 * <pre> 4114 * additiveExpression ::=
4324 * additiveExpression ::= 4115 * multiplicativeExpression (additiveOperator multiplicativeExpression )*
4325 * multiplicativeExpression (additiveOperator multiplicativeExpression)* 4116 * | 'super' (additiveOperator multiplicativeExpression)+
4326 * | 'super' (additiveOperator multiplicativeExpression)+
4327 * </pre>
4328 *
4329 * @return the additive expression that was parsed
4330 */ 4117 */
4331 Expression _parseAdditiveExpression() { 4118 Expression _parseAdditiveExpression() {
4332 Expression expression; 4119 Expression expression;
4333 if (_matchesKeyword(Keyword.SUPER) && 4120 if (_matchesKeyword(Keyword.SUPER) &&
4334 _currentToken.next.type.isAdditiveOperator) { 4121 _currentToken.next.type.isAdditiveOperator) {
4335 expression = new SuperExpression(getAndAdvance()); 4122 expression = new SuperExpression(getAndAdvance());
4336 } else { 4123 } else {
4337 expression = _parseMultiplicativeExpression(); 4124 expression = _parseMultiplicativeExpression();
4338 } 4125 }
4339 while (_currentToken.type.isAdditiveOperator) { 4126 while (_currentToken.type.isAdditiveOperator) {
4340 Token operator = getAndAdvance(); 4127 Token operator = getAndAdvance();
4341 expression = new BinaryExpression( 4128 expression = new BinaryExpression(
4342 expression, operator, _parseMultiplicativeExpression()); 4129 expression, operator, _parseMultiplicativeExpression());
4343 } 4130 }
4344 return expression; 4131 return expression;
4345 } 4132 }
4346 4133
4347 /** 4134 /**
4348 * Parse an assert statement. 4135 * Parse an assert statement. Return the assert statement.
4349 * 4136 *
4350 * <pre> 4137 * assertStatement ::=
4351 * assertStatement ::= 4138 * 'assert' '(' conditionalExpression ')' ';'
4352 * 'assert' '(' conditionalExpression ')' ';'
4353 * </pre>
4354 *
4355 * @return the assert statement
4356 */ 4139 */
4357 AssertStatement _parseAssertStatement() { 4140 AssertStatement _parseAssertStatement() {
4358 Token keyword = _expectKeyword(Keyword.ASSERT); 4141 Token keyword = _expectKeyword(Keyword.ASSERT);
4359 Token leftParen = _expect(TokenType.OPEN_PAREN); 4142 Token leftParen = _expect(TokenType.OPEN_PAREN);
4360 Expression expression = parseExpression2(); 4143 Expression expression = parseExpression2();
4361 if (expression is AssignmentExpression) { 4144 if (expression is AssignmentExpression) {
4362 _reportErrorForNode( 4145 _reportErrorForNode(
4363 ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expression); 4146 ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expression);
4364 } else if (expression is CascadeExpression) { 4147 } else if (expression is CascadeExpression) {
4365 _reportErrorForNode( 4148 _reportErrorForNode(
4366 ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expression); 4149 ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expression);
4367 } else if (expression is ThrowExpression) { 4150 } else if (expression is ThrowExpression) {
4368 _reportErrorForNode( 4151 _reportErrorForNode(
4369 ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression); 4152 ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression);
4370 } else if (expression is RethrowExpression) { 4153 } else if (expression is RethrowExpression) {
4371 _reportErrorForNode( 4154 _reportErrorForNode(
4372 ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expression); 4155 ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expression);
4373 } 4156 }
4374 Token rightParen = _expect(TokenType.CLOSE_PAREN); 4157 Token rightParen = _expect(TokenType.CLOSE_PAREN);
4375 Token semicolon = _expect(TokenType.SEMICOLON); 4158 Token semicolon = _expect(TokenType.SEMICOLON);
4376 return new AssertStatement( 4159 return new AssertStatement(
4377 keyword, leftParen, expression, rightParen, semicolon); 4160 keyword, leftParen, expression, rightParen, semicolon);
4378 } 4161 }
4379 4162
4380 /** 4163 /**
4381 * Parse an assignable expression. 4164 * Parse an assignable expression. The [primaryAllowed] is `true` if the
4165 * expression is allowed to be a primary without any assignable selector.
4166 * Return the assignable expression that was parsed.
4382 * 4167 *
4383 * <pre> 4168 * assignableExpression ::=
4384 * assignableExpression ::= 4169 * primary (arguments* assignableSelector)+
4385 * primary (arguments* assignableSelector)+ 4170 * | 'super' assignableSelector
4386 * | 'super' assignableSelector 4171 * | identifier
4387 * | identifier
4388 * </pre>
4389 *
4390 * @param primaryAllowed `true` if the expression is allowed to be a primary w ithout any
4391 * assignable selector
4392 * @return the assignable expression that was parsed
4393 */ 4172 */
4394 Expression _parseAssignableExpression(bool primaryAllowed) { 4173 Expression _parseAssignableExpression(bool primaryAllowed) {
4395 if (_matchesKeyword(Keyword.SUPER)) { 4174 if (_matchesKeyword(Keyword.SUPER)) {
4396 return _parseAssignableSelector( 4175 return _parseAssignableSelector(
4397 new SuperExpression(getAndAdvance()), false); 4176 new SuperExpression(getAndAdvance()), false);
4398 } 4177 }
4399 // 4178 //
4400 // A primary expression can start with an identifier. We resolve the 4179 // A primary expression can start with an identifier. We resolve the
4401 // ambiguity by determining whether the primary consists of anything other 4180 // ambiguity by determining whether the primary consists of anything other
4402 // than an identifier and/or is followed by an assignableSelector. 4181 // than an identifier and/or is followed by an assignableSelector.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4434 identifier.prefix, identifier.period, identifier.identifier); 4213 identifier.prefix, identifier.period, identifier.identifier);
4435 } 4214 }
4436 return expression; 4215 return expression;
4437 } 4216 }
4438 expression = selectorExpression; 4217 expression = selectorExpression;
4439 isOptional = true; 4218 isOptional = true;
4440 } 4219 }
4441 } 4220 }
4442 4221
4443 /** 4222 /**
4444 * Parse an assignable selector. 4223 * Parse an assignable selector. The [prefix] is the expression preceding the
4224 * selector. The [optional] is `true` if the selector is optional. Return the
4225 * assignable selector that was parsed, or the original prefix if there was no
4226 * assignable selector.
4445 * 4227 *
4446 * <pre> 4228 * assignableSelector ::=
4447 * assignableSelector ::= 4229 * '[' expression ']'
4448 * '[' expression ']' 4230 * | '.' identifier
4449 * | '.' identifier
4450 * </pre>
4451 *
4452 * @param prefix the expression preceding the selector
4453 * @param optional `true` if the selector is optional
4454 * @return the assignable selector that was parsed, or the original prefix if there was no
4455 * assignable selector
4456 */ 4231 */
4457 Expression _parseAssignableSelector(Expression prefix, bool optional) { 4232 Expression _parseAssignableSelector(Expression prefix, bool optional) {
4458 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) { 4233 if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
4459 Token leftBracket = getAndAdvance(); 4234 Token leftBracket = getAndAdvance();
4460 bool wasInInitializer = _inInitializer; 4235 bool wasInInitializer = _inInitializer;
4461 _inInitializer = false; 4236 _inInitializer = false;
4462 try { 4237 try {
4463 Expression index = parseExpression2(); 4238 Expression index = parseExpression2();
4464 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET); 4239 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
4465 return new IndexExpression.forTarget( 4240 return new IndexExpression.forTarget(
4466 prefix, leftBracket, index, rightBracket); 4241 prefix, leftBracket, index, rightBracket);
4467 } finally { 4242 } finally {
4468 _inInitializer = wasInInitializer; 4243 _inInitializer = wasInInitializer;
4469 } 4244 }
4470 } else if (_matches(TokenType.PERIOD)) { 4245 } else if (_matches(TokenType.PERIOD)) {
4471 Token period = getAndAdvance(); 4246 Token period = getAndAdvance();
4472 return new PropertyAccess(prefix, period, parseSimpleIdentifier()); 4247 return new PropertyAccess(prefix, period, parseSimpleIdentifier());
4473 } else { 4248 } else {
4474 if (!optional) { 4249 if (!optional) {
4475 // Report the missing selector. 4250 // Report the missing selector.
4476 _reportErrorForCurrentToken( 4251 _reportErrorForCurrentToken(
4477 ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR); 4252 ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR);
4478 } 4253 }
4479 return prefix; 4254 return prefix;
4480 } 4255 }
4481 } 4256 }
4482 4257
4483 /** 4258 /**
4484 * Parse a await expression. 4259 * Parse a await expression. Return the await expression that was parsed.
4485 * 4260 *
4486 * <pre> 4261 * awaitExpression ::=
4487 * awaitExpression ::= 4262 * 'await' unaryExpression
4488 * 'await' unaryExpression
4489 * </pre>
4490 *
4491 * @return the await expression that was parsed
4492 */ 4263 */
4493 AwaitExpression _parseAwaitExpression() { 4264 AwaitExpression _parseAwaitExpression() {
4494 Token awaitToken = getAndAdvance(); 4265 Token awaitToken = getAndAdvance();
4495 Expression expression = _parseUnaryExpression(); 4266 Expression expression = _parseUnaryExpression();
4496 return new AwaitExpression(awaitToken, expression); 4267 return new AwaitExpression(awaitToken, expression);
4497 } 4268 }
4498 4269
4499 /** 4270 /**
4500 * Parse a bitwise and expression. 4271 * Parse a bitwise and expression. Return the bitwise and expression that was
4272 * parsed.
4501 * 4273 *
4502 * <pre> 4274 * bitwiseAndExpression ::=
4503 * bitwiseAndExpression ::= 4275 * shiftExpression ('&' shiftExpression)*
4504 * shiftExpression ('&' shiftExpression)* 4276 * | 'super' ('&' shiftExpression)+
4505 * | 'super' ('&' shiftExpression)+
4506 * </pre>
4507 *
4508 * @return the bitwise and expression that was parsed
4509 */ 4277 */
4510 Expression _parseBitwiseAndExpression() { 4278 Expression _parseBitwiseAndExpression() {
4511 Expression expression; 4279 Expression expression;
4512 if (_matchesKeyword(Keyword.SUPER) && 4280 if (_matchesKeyword(Keyword.SUPER) &&
4513 _tokenMatches(_peek(), TokenType.AMPERSAND)) { 4281 _tokenMatches(_peek(), TokenType.AMPERSAND)) {
4514 expression = new SuperExpression(getAndAdvance()); 4282 expression = new SuperExpression(getAndAdvance());
4515 } else { 4283 } else {
4516 expression = _parseShiftExpression(); 4284 expression = _parseShiftExpression();
4517 } 4285 }
4518 while (_matches(TokenType.AMPERSAND)) { 4286 while (_matches(TokenType.AMPERSAND)) {
4519 Token operator = getAndAdvance(); 4287 Token operator = getAndAdvance();
4520 expression = 4288 expression =
4521 new BinaryExpression(expression, operator, _parseShiftExpression()); 4289 new BinaryExpression(expression, operator, _parseShiftExpression());
4522 } 4290 }
4523 return expression; 4291 return expression;
4524 } 4292 }
4525 4293
4526 /** 4294 /**
4527 * Parse a bitwise exclusive-or expression. 4295 * Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or
4296 * expression that was parsed.
4528 * 4297 *
4529 * <pre> 4298 * bitwiseXorExpression ::=
4530 * bitwiseXorExpression ::= 4299 * bitwiseAndExpression ('^' bitwiseAndExpression)*
4531 * bitwiseAndExpression ('^' bitwiseAndExpression)* 4300 * | 'super' ('^' bitwiseAndExpression)+
4532 * | 'super' ('^' bitwiseAndExpression)+
4533 * </pre>
4534 *
4535 * @return the bitwise exclusive-or expression that was parsed
4536 */ 4301 */
4537 Expression _parseBitwiseXorExpression() { 4302 Expression _parseBitwiseXorExpression() {
4538 Expression expression; 4303 Expression expression;
4539 if (_matchesKeyword(Keyword.SUPER) && 4304 if (_matchesKeyword(Keyword.SUPER) &&
4540 _tokenMatches(_peek(), TokenType.CARET)) { 4305 _tokenMatches(_peek(), TokenType.CARET)) {
4541 expression = new SuperExpression(getAndAdvance()); 4306 expression = new SuperExpression(getAndAdvance());
4542 } else { 4307 } else {
4543 expression = _parseBitwiseAndExpression(); 4308 expression = _parseBitwiseAndExpression();
4544 } 4309 }
4545 while (_matches(TokenType.CARET)) { 4310 while (_matches(TokenType.CARET)) {
4546 Token operator = getAndAdvance(); 4311 Token operator = getAndAdvance();
4547 expression = new BinaryExpression( 4312 expression = new BinaryExpression(
4548 expression, operator, _parseBitwiseAndExpression()); 4313 expression, operator, _parseBitwiseAndExpression());
4549 } 4314 }
4550 return expression; 4315 return expression;
4551 } 4316 }
4552 4317
4553 /** 4318 /**
4554 * Parse a break statement. 4319 * Parse a break statement. Return the break statement that was parsed.
4555 * 4320 *
4556 * <pre> 4321 * breakStatement ::=
4557 * breakStatement ::= 4322 * 'break' identifier? ';'
4558 * 'break' identifier? ';'
4559 * </pre>
4560 *
4561 * @return the break statement that was parsed
4562 */ 4323 */
4563 Statement _parseBreakStatement() { 4324 Statement _parseBreakStatement() {
4564 Token breakKeyword = _expectKeyword(Keyword.BREAK); 4325 Token breakKeyword = _expectKeyword(Keyword.BREAK);
4565 SimpleIdentifier label = null; 4326 SimpleIdentifier label = null;
4566 if (_matchesIdentifier()) { 4327 if (_matchesIdentifier()) {
4567 label = parseSimpleIdentifier(); 4328 label = parseSimpleIdentifier();
4568 } 4329 }
4569 if (!_inLoop && !_inSwitch && label == null) { 4330 if (!_inLoop && !_inSwitch && label == null) {
4570 _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword); 4331 _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword);
4571 } 4332 }
4572 Token semicolon = _expect(TokenType.SEMICOLON); 4333 Token semicolon = _expect(TokenType.SEMICOLON);
4573 return new BreakStatement(breakKeyword, label, semicolon); 4334 return new BreakStatement(breakKeyword, label, semicolon);
4574 } 4335 }
4575 4336
4576 /** 4337 /**
4577 * Parse a cascade section. 4338 * Parse a cascade section. Return the expression representing the cascaded
4339 * method invocation.
4578 * 4340 *
4579 * <pre> 4341 * cascadeSection ::=
4580 * cascadeSection ::= 4342 * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* cascadeAssignment?
4581 * '..' (cascadeSelector arguments*) (assignableSelector arguments*)* casc adeAssignment?
4582 * 4343 *
4583 * cascadeSelector ::= 4344 * cascadeSelector ::=
4584 * '[' expression ']' 4345 * '[' expression ']'
4585 * | identifier 4346 * | identifier
4586 * 4347 *
4587 * cascadeAssignment ::= 4348 * cascadeAssignment ::=
4588 * assignmentOperator expressionWithoutCascade 4349 * assignmentOperator expressionWithoutCascade
4589 * </pre>
4590 *
4591 * @return the expression representing the cascaded method invocation
4592 */ 4350 */
4593 Expression _parseCascadeSection() { 4351 Expression _parseCascadeSection() {
4594 Token period = _expect(TokenType.PERIOD_PERIOD); 4352 Token period = _expect(TokenType.PERIOD_PERIOD);
4595 Expression expression = null; 4353 Expression expression = null;
4596 SimpleIdentifier functionName = null; 4354 SimpleIdentifier functionName = null;
4597 if (_matchesIdentifier()) { 4355 if (_matchesIdentifier()) {
4598 functionName = parseSimpleIdentifier(); 4356 functionName = parseSimpleIdentifier();
4599 } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) { 4357 } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) {
4600 Token leftBracket = getAndAdvance(); 4358 Token leftBracket = getAndAdvance();
4601 bool wasInInitializer = _inInitializer; 4359 bool wasInInitializer = _inInitializer;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
4661 if (_currentToken.type.isAssignmentOperator) { 4419 if (_currentToken.type.isAssignmentOperator) {
4662 Token operator = getAndAdvance(); 4420 Token operator = getAndAdvance();
4663 _ensureAssignable(expression); 4421 _ensureAssignable(expression);
4664 expression = new AssignmentExpression( 4422 expression = new AssignmentExpression(
4665 expression, operator, parseExpressionWithoutCascade()); 4423 expression, operator, parseExpressionWithoutCascade());
4666 } 4424 }
4667 return expression; 4425 return expression;
4668 } 4426 }
4669 4427
4670 /** 4428 /**
4671 * Parse a class declaration. 4429 * Parse a class declaration. The [commentAndMetadata] is the metadata to be
4430 * associated with the member. The [abstractKeyword] is the token for the
4431 * keyword 'abstract', or `null` if the keyword was not given. Return the
4432 * class declaration that was parsed.
4672 * 4433 *
4673 * <pre> 4434 * classDeclaration ::=
4674 * classDeclaration ::= 4435 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' |
4675 * metadata 'abstract'? 'class' name typeParameterList? (extendsClause wit hClause?)? implementsClause? '{' classMembers '}' | 4436 * metadata 'abstract'? 'class' mixinApplicationClass
4676 * metadata 'abstract'? 'class' mixinApplicationClass
4677 * </pre>
4678 *
4679 * @param commentAndMetadata the metadata to be associated with the member
4680 * @param abstractKeyword the token for the keyword 'abstract', or `null` if t he keyword was
4681 * not given
4682 * @return the class declaration that was parsed
4683 */ 4437 */
4684 CompilationUnitMember _parseClassDeclaration( 4438 CompilationUnitMember _parseClassDeclaration(
4685 CommentAndMetadata commentAndMetadata, Token abstractKeyword) { 4439 CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
4686 Token keyword = _expectKeyword(Keyword.CLASS); 4440 Token keyword = _expectKeyword(Keyword.CLASS);
4687 if (_matchesIdentifier()) { 4441 if (_matchesIdentifier()) {
4688 Token next = _peek(); 4442 Token next = _peek();
4689 if (_tokenMatches(next, TokenType.LT)) { 4443 if (_tokenMatches(next, TokenType.LT)) {
4690 next = _skipTypeParameterList(next); 4444 next = _skipTypeParameterList(next);
4691 if (next != null && _tokenMatches(next, TokenType.EQ)) { 4445 if (next != null && _tokenMatches(next, TokenType.EQ)) {
4692 return _parseClassTypeAlias( 4446 return _parseClassTypeAlias(
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
4784 } 4538 }
4785 ClassDeclaration classDeclaration = new ClassDeclaration( 4539 ClassDeclaration classDeclaration = new ClassDeclaration(
4786 commentAndMetadata.comment, commentAndMetadata.metadata, 4540 commentAndMetadata.comment, commentAndMetadata.metadata,
4787 abstractKeyword, keyword, name, typeParameters, extendsClause, 4541 abstractKeyword, keyword, name, typeParameters, extendsClause,
4788 withClause, implementsClause, leftBracket, members, rightBracket); 4542 withClause, implementsClause, leftBracket, members, rightBracket);
4789 classDeclaration.nativeClause = nativeClause; 4543 classDeclaration.nativeClause = nativeClause;
4790 return classDeclaration; 4544 return classDeclaration;
4791 } 4545 }
4792 4546
4793 /** 4547 /**
4794 * Parse a list of class members. 4548 * Parse a list of class members. The [className] is the name of the class
4549 * whose members are being parsed. The [closingBracket] is the closing bracket
4550 * for the class, or `null` if the closing bracket is missing. Return the list
4551 * of class members that were parsed.
4795 * 4552 *
4796 * <pre> 4553 * classMembers ::=
4797 * classMembers ::= 4554 * (metadata memberDefinition)*
4798 * (metadata memberDefinition)*
4799 * </pre>
4800 *
4801 * @param className the name of the class whose members are being parsed
4802 * @param closingBracket the closing bracket for the class, or `null` if the c losing bracket
4803 * is missing
4804 * @return the list of class members that were parsed
4805 */ 4555 */
4806 List<ClassMember> _parseClassMembers(String className, Token closingBracket) { 4556 List<ClassMember> _parseClassMembers(String className, Token closingBracket) {
4807 List<ClassMember> members = new List<ClassMember>(); 4557 List<ClassMember> members = new List<ClassMember>();
4808 Token memberStart = _currentToken; 4558 Token memberStart = _currentToken;
4809 while (!_matches(TokenType.EOF) && 4559 while (!_matches(TokenType.EOF) &&
4810 !_matches(TokenType.CLOSE_CURLY_BRACKET) && 4560 !_matches(TokenType.CLOSE_CURLY_BRACKET) &&
4811 (closingBracket != null || 4561 (closingBracket != null ||
4812 (!_matchesKeyword(Keyword.CLASS) && 4562 (!_matchesKeyword(Keyword.CLASS) &&
4813 !_matchesKeyword(Keyword.TYPEDEF)))) { 4563 !_matchesKeyword(Keyword.TYPEDEF)))) {
4814 if (_matches(TokenType.SEMICOLON)) { 4564 if (_matches(TokenType.SEMICOLON)) {
(...skipping 12 matching lines...) Expand all
4827 _currentToken.lexeme 4577 _currentToken.lexeme
4828 ]); 4578 ]);
4829 _advance(); 4579 _advance();
4830 } 4580 }
4831 memberStart = _currentToken; 4581 memberStart = _currentToken;
4832 } 4582 }
4833 return members; 4583 return members;
4834 } 4584 }
4835 4585
4836 /** 4586 /**
4837 * Parse a class type alias. 4587 * Parse a class type alias. The [commentAndMetadata] is the metadata to be
4588 * associated with the member. The [abstractKeyword] is the token representing
4589 * the 'abstract' keyword. The [classKeyword] is the token representing the
4590 * 'class' keyword. Return the class type alias that was parsed.
4838 * 4591 *
4839 * <pre> 4592 * classTypeAlias ::=
4840 * classTypeAlias ::= 4593 * identifier typeParameters? '=' 'abstract'? mixinApplication
4841 * identifier typeParameters? '=' 'abstract'? mixinApplication
4842 * 4594 *
4843 * mixinApplication ::= 4595 * mixinApplication ::=
4844 * type withClause implementsClause? ';' 4596 * type withClause implementsClause? ';'
4845 * </pre>
4846 *
4847 * @param commentAndMetadata the metadata to be associated with the member
4848 * @param abstractKeyword the token representing the 'abstract' keyword
4849 * @param classKeyword the token representing the 'class' keyword
4850 * @return the class type alias that was parsed
4851 */ 4597 */
4852 ClassTypeAlias _parseClassTypeAlias(CommentAndMetadata commentAndMetadata, 4598 ClassTypeAlias _parseClassTypeAlias(CommentAndMetadata commentAndMetadata,
4853 Token abstractKeyword, Token classKeyword) { 4599 Token abstractKeyword, Token classKeyword) {
4854 SimpleIdentifier className = parseSimpleIdentifier(); 4600 SimpleIdentifier className = parseSimpleIdentifier();
4855 TypeParameterList typeParameters = null; 4601 TypeParameterList typeParameters = null;
4856 if (_matches(TokenType.LT)) { 4602 if (_matches(TokenType.LT)) {
4857 typeParameters = parseTypeParameterList(); 4603 typeParameters = parseTypeParameterList();
4858 } 4604 }
4859 Token equals = _expect(TokenType.EQ); 4605 Token equals = _expect(TokenType.EQ);
4860 TypeName superclass = parseTypeName(); 4606 TypeName superclass = parseTypeName();
(...skipping 24 matching lines...) Expand all
4885 } 4631 }
4886 semicolon = _createSyntheticToken(TokenType.SEMICOLON); 4632 semicolon = _createSyntheticToken(TokenType.SEMICOLON);
4887 } 4633 }
4888 return new ClassTypeAlias(commentAndMetadata.comment, 4634 return new ClassTypeAlias(commentAndMetadata.comment,
4889 commentAndMetadata.metadata, classKeyword, className, typeParameters, 4635 commentAndMetadata.metadata, classKeyword, className, typeParameters,
4890 equals, abstractKeyword, superclass, withClause, implementsClause, 4636 equals, abstractKeyword, superclass, withClause, implementsClause,
4891 semicolon); 4637 semicolon);
4892 } 4638 }
4893 4639
4894 /** 4640 /**
4895 * Parse a list of combinators in a directive. 4641 * Parse a list of combinators in a directive. Return the combinators that
4642 * were parsed.
4896 * 4643 *
4897 * <pre> 4644 * combinator ::=
4898 * combinator ::= 4645 * 'show' identifier (',' identifier)*
4899 * 'show' identifier (',' identifier)* 4646 * | 'hide' identifier (',' identifier)*
4900 * | 'hide' identifier (',' identifier)*
4901 * </pre>
4902 *
4903 * @return the combinators that were parsed
4904 */ 4647 */
4905 List<Combinator> _parseCombinators() { 4648 List<Combinator> _parseCombinators() {
4906 List<Combinator> combinators = new List<Combinator>(); 4649 List<Combinator> combinators = new List<Combinator>();
4907 while (true) { 4650 while (true) {
4908 Combinator combinator = parseCombinator(); 4651 Combinator combinator = parseCombinator();
4909 if (combinator == null) { 4652 if (combinator == null) {
4910 break; 4653 break;
4911 } 4654 }
4912 combinators.add(combinator); 4655 combinators.add(combinator);
4913 } 4656 }
4914 return combinators; 4657 return combinators;
4915 } 4658 }
4916 4659
4917 /** 4660 /**
4918 * Parse the documentation comment and metadata preceding a declaration. This method allows any 4661 * Parse the documentation comment and metadata preceding a declaration. This
4919 * number of documentation comments to occur before, after or between the meta data, but only 4662 * method allows any number of documentation comments to occur before, after
4920 * returns the last (right-most) documentation comment that is found. 4663 * or between the metadata, but only returns the last (right-most)
4664 * documentation comment that is found. Return the documentation comment and
4665 * metadata that were parsed.
4921 * 4666 *
4922 * <pre> 4667 * metadata ::=
4923 * metadata ::= 4668 * annotation*
4924 * annotation*
4925 * </pre>
4926 *
4927 * @return the documentation comment and metadata that were parsed
4928 */ 4669 */
4929 CommentAndMetadata _parseCommentAndMetadata() { 4670 CommentAndMetadata _parseCommentAndMetadata() {
4930 Comment comment = _parseDocumentationComment(); 4671 Comment comment = _parseDocumentationComment();
4931 List<Annotation> metadata = new List<Annotation>(); 4672 List<Annotation> metadata = new List<Annotation>();
4932 while (_matches(TokenType.AT)) { 4673 while (_matches(TokenType.AT)) {
4933 metadata.add(parseAnnotation()); 4674 metadata.add(parseAnnotation());
4934 Comment optionalComment = _parseDocumentationComment(); 4675 Comment optionalComment = _parseDocumentationComment();
4935 if (optionalComment != null) { 4676 if (optionalComment != null) {
4936 comment = optionalComment; 4677 comment = optionalComment;
4937 } 4678 }
4938 } 4679 }
4939 return new CommentAndMetadata(comment, metadata); 4680 return new CommentAndMetadata(comment, metadata);
4940 } 4681 }
4941 4682
4942 /** 4683 /**
4943 * Parse a comment reference from the source between square brackets. 4684 * Parse a comment reference from the source between square brackets. The
4685 * [referenceSource] is the source occurring between the square brackets
4686 * within a documentation comment. The [sourceOffset] is the offset of the
4687 * first character of the reference source. Return the comment reference that
4688 * was parsed, or `null` if no reference could be found.
4944 * 4689 *
4945 * <pre> 4690 * commentReference ::=
4946 * commentReference ::= 4691 * 'new'? prefixedIdentifier
4947 * 'new'? prefixedIdentifier
4948 * </pre>
4949 *
4950 * @param referenceSource the source occurring between the square brackets wit hin a documentation
4951 * comment
4952 * @param sourceOffset the offset of the first character of the reference sour ce
4953 * @return the comment reference that was parsed, or `null` if no reference co uld be found
4954 */ 4692 */
4955 CommentReference _parseCommentReference( 4693 CommentReference _parseCommentReference(
4956 String referenceSource, int sourceOffset) { 4694 String referenceSource, int sourceOffset) {
4957 // TODO(brianwilkerson) The errors are not getting the right offset/length 4695 // TODO(brianwilkerson) The errors are not getting the right offset/length
4958 // and are being duplicated. 4696 // and are being duplicated.
4959 if (referenceSource.length == 0) { 4697 if (referenceSource.length == 0) {
4960 Token syntheticToken = 4698 Token syntheticToken =
4961 new SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset); 4699 new SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
4962 return new CommentReference(null, new SimpleIdentifier(syntheticToken)); 4700 return new CommentReference(null, new SimpleIdentifier(syntheticToken));
4963 } 4701 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
5004 // approach. 4742 // approach.
5005 return null; 4743 return null;
5006 } 4744 }
5007 } catch (exception) { 4745 } catch (exception) {
5008 // Ignored because we assume that it wasn't a real comment reference. 4746 // Ignored because we assume that it wasn't a real comment reference.
5009 } 4747 }
5010 return null; 4748 return null;
5011 } 4749 }
5012 4750
5013 /** 4751 /**
5014 * Parse all of the comment references occurring in the given array of documen tation comments. 4752 * Parse all of the comment references occurring in the given array of
4753 * documentation comments. The [tokens] are the comment tokens representing
4754 * the documentation comments to be parsed. Return the comment references that
4755 * were parsed.
5015 * 4756 *
5016 * <pre> 4757 * commentReference ::=
5017 * commentReference ::= 4758 * '[' 'new'? qualified ']' libraryReference?
5018 * '[' 'new'? qualified ']' libraryReference?
5019 * 4759 *
5020 * libraryReference ::= 4760 * libraryReference ::=
5021 * '(' stringLiteral ')' 4761 * '(' stringLiteral ')'
5022 * </pre>
5023 *
5024 * @param tokens the comment tokens representing the documentation comments to be parsed
5025 * @return the comment references that were parsed
5026 */ 4762 */
5027 List<CommentReference> _parseCommentReferences( 4763 List<CommentReference> _parseCommentReferences(
5028 List<DocumentationCommentToken> tokens) { 4764 List<DocumentationCommentToken> tokens) {
5029 List<CommentReference> references = new List<CommentReference>(); 4765 List<CommentReference> references = new List<CommentReference>();
5030 for (DocumentationCommentToken token in tokens) { 4766 for (DocumentationCommentToken token in tokens) {
5031 String comment = token.lexeme; 4767 String comment = token.lexeme;
5032 int length = comment.length; 4768 int length = comment.length;
5033 List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment); 4769 List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
5034 int leftIndex = comment.indexOf('['); 4770 int leftIndex = comment.indexOf('[');
5035 while (leftIndex >= 0 && leftIndex + 1 < length) { 4771 while (leftIndex >= 0 && leftIndex + 1 < length) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
5075 leftIndex = JavaString.indexOf(comment, '[', rightIndex); 4811 leftIndex = JavaString.indexOf(comment, '[', rightIndex);
5076 } else { 4812 } else {
5077 leftIndex = JavaString.indexOf(comment, '[', range[1] + 1); 4813 leftIndex = JavaString.indexOf(comment, '[', range[1] + 1);
5078 } 4814 }
5079 } 4815 }
5080 } 4816 }
5081 return references; 4817 return references;
5082 } 4818 }
5083 4819
5084 /** 4820 /**
5085 * Parse a compilation unit member. 4821 * Parse a compilation unit member. The [commentAndMetadata] is the metadata
4822 * to be associated with the member. Return the compilation unit member that
4823 * was parsed, or `null` if what was parsed could not be represented as a
4824 * compilation unit member.
5086 * 4825 *
5087 * <pre> 4826 * compilationUnitMember ::=
5088 * compilationUnitMember ::= 4827 * classDefinition
5089 * classDefinition 4828 * | functionTypeAlias
5090 * | functionTypeAlias 4829 * | external functionSignature
5091 * | external functionSignature 4830 * | external getterSignature
5092 * | external getterSignature 4831 * | external setterSignature
5093 * | external setterSignature 4832 * | functionSignature functionBody
5094 * | functionSignature functionBody 4833 * | returnType? getOrSet identifier formalParameterList functionBody
5095 * | returnType? getOrSet identifier formalParameterList functionBody 4834 * | (final | const) type? staticFinalDeclarationList ';'
5096 * | (final | const) type? staticFinalDeclarationList ';' 4835 * | variableDeclaration ';'
5097 * | variableDeclaration ';'
5098 * </pre>
5099 *
5100 * @param commentAndMetadata the metadata to be associated with the member
5101 * @return the compilation unit member that was parsed, or `null` if what was parsed could
5102 * not be represented as a compilation unit member
5103 */ 4836 */
5104 CompilationUnitMember _parseCompilationUnitMember( 4837 CompilationUnitMember _parseCompilationUnitMember(
5105 CommentAndMetadata commentAndMetadata) { 4838 CommentAndMetadata commentAndMetadata) {
5106 Modifiers modifiers = _parseModifiers(); 4839 Modifiers modifiers = _parseModifiers();
5107 if (_matchesKeyword(Keyword.CLASS)) { 4840 if (_matchesKeyword(Keyword.CLASS)) {
5108 return _parseClassDeclaration( 4841 return _parseClassDeclaration(
5109 commentAndMetadata, _validateModifiersForClass(modifiers)); 4842 commentAndMetadata, _validateModifiersForClass(modifiers));
5110 } else if (_matchesKeyword(Keyword.TYPEDEF) && 4843 } else if (_matchesKeyword(Keyword.TYPEDEF) &&
5111 !_tokenMatches(_peek(), TokenType.PERIOD) && 4844 !_tokenMatches(_peek(), TokenType.PERIOD) &&
5112 !_tokenMatches(_peek(), TokenType.LT) && 4845 !_tokenMatches(_peek(), TokenType.LT) &&
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
5250 return _parseFunctionDeclaration( 4983 return _parseFunctionDeclaration(
5251 commentAndMetadata, modifiers.externalKeyword, returnType); 4984 commentAndMetadata, modifiers.externalKeyword, returnType);
5252 } 4985 }
5253 return new TopLevelVariableDeclaration(commentAndMetadata.comment, 4986 return new TopLevelVariableDeclaration(commentAndMetadata.comment,
5254 commentAndMetadata.metadata, _parseVariableDeclarationListAfterType( 4987 commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
5255 null, _validateModifiersForTopLevelVariable(modifiers), returnType), 4988 null, _validateModifiersForTopLevelVariable(modifiers), returnType),
5256 _expect(TokenType.SEMICOLON)); 4989 _expect(TokenType.SEMICOLON));
5257 } 4990 }
5258 4991
5259 /** 4992 /**
5260 * Parse a const expression. 4993 * Parse a const expression. Return the const expression that was parsed.
5261 * 4994 *
5262 * <pre> 4995 * constExpression ::=
5263 * constExpression ::= 4996 * instanceCreationExpression
5264 * instanceCreationExpression 4997 * | listLiteral
5265 * | listLiteral 4998 * | mapLiteral
5266 * | mapLiteral
5267 * </pre>
5268 *
5269 * @return the const expression that was parsed
5270 */ 4999 */
5271 Expression _parseConstExpression() { 5000 Expression _parseConstExpression() {
5272 Token keyword = _expectKeyword(Keyword.CONST); 5001 Token keyword = _expectKeyword(Keyword.CONST);
5273 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.INDEX)) { 5002 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.INDEX)) {
5274 return _parseListLiteral(keyword, null); 5003 return _parseListLiteral(keyword, null);
5275 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) { 5004 } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5276 return _parseMapLiteral(keyword, null); 5005 return _parseMapLiteral(keyword, null);
5277 } else if (_matches(TokenType.LT)) { 5006 } else if (_matches(TokenType.LT)) {
5278 return _parseListOrMapLiteral(keyword); 5007 return _parseListOrMapLiteral(keyword);
5279 } 5008 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
5349 } 5078 }
5350 } 5079 }
5351 } 5080 }
5352 return new ConstructorDeclaration(commentAndMetadata.comment, 5081 return new ConstructorDeclaration(commentAndMetadata.comment,
5353 commentAndMetadata.metadata, externalKeyword, constKeyword, 5082 commentAndMetadata.metadata, externalKeyword, constKeyword,
5354 factoryKeyword, returnType, period, name, parameters, separator, 5083 factoryKeyword, returnType, period, name, parameters, separator,
5355 initializers, redirectedConstructor, body); 5084 initializers, redirectedConstructor, body);
5356 } 5085 }
5357 5086
5358 /** 5087 /**
5359 * Parse a field initializer within a constructor. 5088 * Parse a field initializer within a constructor. Return the field
5089 * initializer that was parsed.
5360 * 5090 *
5361 * <pre> 5091 * fieldInitializer:
5362 * fieldInitializer: 5092 * ('this' '.')? identifier '=' conditionalExpression cascadeSection*
5363 * ('this' '.')? identifier '=' conditionalExpression cascadeSection*
5364 * </pre>
5365 *
5366 * @return the field initializer that was parsed
5367 */ 5093 */
5368 ConstructorFieldInitializer _parseConstructorFieldInitializer() { 5094 ConstructorFieldInitializer _parseConstructorFieldInitializer() {
5369 Token keyword = null; 5095 Token keyword = null;
5370 Token period = null; 5096 Token period = null;
5371 if (_matchesKeyword(Keyword.THIS)) { 5097 if (_matchesKeyword(Keyword.THIS)) {
5372 keyword = getAndAdvance(); 5098 keyword = getAndAdvance();
5373 period = _expect(TokenType.PERIOD); 5099 period = _expect(TokenType.PERIOD);
5374 } 5100 }
5375 SimpleIdentifier fieldName = parseSimpleIdentifier(); 5101 SimpleIdentifier fieldName = parseSimpleIdentifier();
5376 Token equals = null; 5102 Token equals = null;
(...skipping 29 matching lines...) Expand all
5406 expression = new CascadeExpression(expression, cascadeSections); 5132 expression = new CascadeExpression(expression, cascadeSections);
5407 } 5133 }
5408 return new ConstructorFieldInitializer( 5134 return new ConstructorFieldInitializer(
5409 keyword, period, fieldName, equals, expression); 5135 keyword, period, fieldName, equals, expression);
5410 } finally { 5136 } finally {
5411 _inInitializer = wasInInitializer; 5137 _inInitializer = wasInInitializer;
5412 } 5138 }
5413 } 5139 }
5414 5140
5415 /** 5141 /**
5416 * Parse a continue statement. 5142 * Parse a continue statement. Return the continue statement that was parsed.
5417 * 5143 *
5418 * <pre> 5144 * continueStatement ::=
5419 * continueStatement ::= 5145 * 'continue' identifier? ';'
5420 * 'continue' identifier? ';'
5421 * </pre>
5422 *
5423 * @return the continue statement that was parsed
5424 */ 5146 */
5425 Statement _parseContinueStatement() { 5147 Statement _parseContinueStatement() {
5426 Token continueKeyword = _expectKeyword(Keyword.CONTINUE); 5148 Token continueKeyword = _expectKeyword(Keyword.CONTINUE);
5427 if (!_inLoop && !_inSwitch) { 5149 if (!_inLoop && !_inSwitch) {
5428 _reportErrorForToken( 5150 _reportErrorForToken(
5429 ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword); 5151 ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword);
5430 } 5152 }
5431 SimpleIdentifier label = null; 5153 SimpleIdentifier label = null;
5432 if (_matchesIdentifier()) { 5154 if (_matchesIdentifier()) {
5433 label = parseSimpleIdentifier(); 5155 label = parseSimpleIdentifier();
5434 } 5156 }
5435 if (_inSwitch && !_inLoop && label == null) { 5157 if (_inSwitch && !_inLoop && label == null) {
5436 _reportErrorForToken( 5158 _reportErrorForToken(
5437 ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword); 5159 ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword);
5438 } 5160 }
5439 Token semicolon = _expect(TokenType.SEMICOLON); 5161 Token semicolon = _expect(TokenType.SEMICOLON);
5440 return new ContinueStatement(continueKeyword, label, semicolon); 5162 return new ContinueStatement(continueKeyword, label, semicolon);
5441 } 5163 }
5442 5164
5443 /** 5165 /**
5444 * Parse a directive. 5166 * Parse a directive. The [commentAndMetadata] is the metadata to be
5167 * associated with the directive. Return the directive that was parsed.
5445 * 5168 *
5446 * <pre> 5169 * directive ::=
5447 * directive ::= 5170 * exportDirective
5448 * exportDirective 5171 * | libraryDirective
5449 * | libraryDirective 5172 * | importDirective
5450 * | importDirective 5173 * | partDirective
5451 * | partDirective
5452 * </pre>
5453 *
5454 * @param commentAndMetadata the metadata to be associated with the directive
5455 * @return the directive that was parsed
5456 */ 5174 */
5457 Directive _parseDirective(CommentAndMetadata commentAndMetadata) { 5175 Directive _parseDirective(CommentAndMetadata commentAndMetadata) {
5458 if (_matchesKeyword(Keyword.IMPORT)) { 5176 if (_matchesKeyword(Keyword.IMPORT)) {
5459 return _parseImportDirective(commentAndMetadata); 5177 return _parseImportDirective(commentAndMetadata);
5460 } else if (_matchesKeyword(Keyword.EXPORT)) { 5178 } else if (_matchesKeyword(Keyword.EXPORT)) {
5461 return _parseExportDirective(commentAndMetadata); 5179 return _parseExportDirective(commentAndMetadata);
5462 } else if (_matchesKeyword(Keyword.LIBRARY)) { 5180 } else if (_matchesKeyword(Keyword.LIBRARY)) {
5463 return _parseLibraryDirective(commentAndMetadata); 5181 return _parseLibraryDirective(commentAndMetadata);
5464 } else if (_matchesKeyword(Keyword.PART)) { 5182 } else if (_matchesKeyword(Keyword.PART)) {
5465 return _parsePartDirective(commentAndMetadata); 5183 return _parsePartDirective(commentAndMetadata);
5466 } else { 5184 } else {
5467 // Internal error: this method should not have been invoked if the current 5185 // Internal error: this method should not have been invoked if the current
5468 // token was something other than one of the above. 5186 // token was something other than one of the above.
5469 throw new IllegalStateException( 5187 throw new IllegalStateException(
5470 "parseDirective invoked in an invalid state; currentToken = $_currentT oken"); 5188 "parseDirective invoked in an invalid state; currentToken = $_currentT oken");
5471 } 5189 }
5472 } 5190 }
5473 5191
5474 /** 5192 /**
5475 * Parse the script tag and directives in a compilation unit until the first n on-directive is 5193 * Parse the script tag and directives in a compilation unit until the first
5476 * encountered. 5194 * non-directive is encountered. Return the compilation unit that was parsed.
5477 * 5195 *
5478 * 5196 * compilationUnit ::=
5479 * <pre> 5197 * scriptTag? directive*
5480 * compilationUnit ::=
5481 * scriptTag? directive*
5482 * </pre>
5483 *
5484 * @return the compilation unit that was parsed
5485 */ 5198 */
5486 CompilationUnit _parseDirectives() { 5199 CompilationUnit _parseDirectives() {
5487 Token firstToken = _currentToken; 5200 Token firstToken = _currentToken;
5488 ScriptTag scriptTag = null; 5201 ScriptTag scriptTag = null;
5489 if (_matches(TokenType.SCRIPT_TAG)) { 5202 if (_matches(TokenType.SCRIPT_TAG)) {
5490 scriptTag = new ScriptTag(getAndAdvance()); 5203 scriptTag = new ScriptTag(getAndAdvance());
5491 } 5204 }
5492 List<Directive> directives = new List<Directive>(); 5205 List<Directive> directives = new List<Directive>();
5493 while (!_matches(TokenType.EOF)) { 5206 while (!_matches(TokenType.EOF)) {
5494 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 5207 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
(...skipping 13 matching lines...) Expand all
5508 } 5221 }
5509 return new CompilationUnit(firstToken, scriptTag, directives, 5222 return new CompilationUnit(firstToken, scriptTag, directives,
5510 new List<CompilationUnitMember>(), _currentToken); 5223 new List<CompilationUnitMember>(), _currentToken);
5511 } 5224 }
5512 } 5225 }
5513 return new CompilationUnit(firstToken, scriptTag, directives, 5226 return new CompilationUnit(firstToken, scriptTag, directives,
5514 new List<CompilationUnitMember>(), _currentToken); 5227 new List<CompilationUnitMember>(), _currentToken);
5515 } 5228 }
5516 5229
5517 /** 5230 /**
5518 * Parse a documentation comment. 5231 * Parse a documentation comment. Return the documentation comment that was
5232 * parsed, or `null` if there was no comment.
5519 * 5233 *
5520 * <pre> 5234 * documentationComment ::=
5521 * documentationComment ::= 5235 * multiLineComment?
5522 * multiLineComment? 5236 * | singleLineComment*
5523 * | singleLineComment*
5524 * </pre>
5525 *
5526 * @return the documentation comment that was parsed, or `null` if there was n o comment
5527 */ 5237 */
5528 Comment _parseDocumentationComment() { 5238 Comment _parseDocumentationComment() {
5529 List<DocumentationCommentToken> documentationTokens = 5239 List<DocumentationCommentToken> documentationTokens =
5530 <DocumentationCommentToken>[]; 5240 <DocumentationCommentToken>[];
5531 CommentToken commentToken = _currentToken.precedingComments; 5241 CommentToken commentToken = _currentToken.precedingComments;
5532 while (commentToken != null) { 5242 while (commentToken != null) {
5533 if (commentToken is DocumentationCommentToken) { 5243 if (commentToken is DocumentationCommentToken) {
5534 if (documentationTokens.isNotEmpty) { 5244 if (documentationTokens.isNotEmpty) {
5535 if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) { 5245 if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
5536 if (documentationTokens[0].type != TokenType.SINGLE_LINE_COMMENT) { 5246 if (documentationTokens[0].type != TokenType.SINGLE_LINE_COMMENT) {
(...skipping 10 matching lines...) Expand all
5547 if (documentationTokens.isEmpty) { 5257 if (documentationTokens.isEmpty) {
5548 return null; 5258 return null;
5549 } 5259 }
5550 List<CommentReference> references = 5260 List<CommentReference> references =
5551 _parseCommentReferences(documentationTokens); 5261 _parseCommentReferences(documentationTokens);
5552 return Comment.createDocumentationCommentWithReferences( 5262 return Comment.createDocumentationCommentWithReferences(
5553 documentationTokens, references); 5263 documentationTokens, references);
5554 } 5264 }
5555 5265
5556 /** 5266 /**
5557 * Parse a do statement. 5267 * Parse a do statement. Return the do statement that was parsed.
5558 * 5268 *
5559 * <pre> 5269 * doStatement ::=
5560 * doStatement ::= 5270 * 'do' statement 'while' '(' expression ')' ';'
5561 * 'do' statement 'while' '(' expression ')' ';'
5562 * </pre>
5563 *
5564 * @return the do statement that was parsed
5565 */ 5271 */
5566 Statement _parseDoStatement() { 5272 Statement _parseDoStatement() {
5567 bool wasInLoop = _inLoop; 5273 bool wasInLoop = _inLoop;
5568 _inLoop = true; 5274 _inLoop = true;
5569 try { 5275 try {
5570 Token doKeyword = _expectKeyword(Keyword.DO); 5276 Token doKeyword = _expectKeyword(Keyword.DO);
5571 Statement body = parseStatement2(); 5277 Statement body = parseStatement2();
5572 Token whileKeyword = _expectKeyword(Keyword.WHILE); 5278 Token whileKeyword = _expectKeyword(Keyword.WHILE);
5573 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); 5279 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
5574 Expression condition = parseExpression2(); 5280 Expression condition = parseExpression2();
5575 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); 5281 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
5576 Token semicolon = _expect(TokenType.SEMICOLON); 5282 Token semicolon = _expect(TokenType.SEMICOLON);
5577 return new DoStatement(doKeyword, body, whileKeyword, leftParenthesis, 5283 return new DoStatement(doKeyword, body, whileKeyword, leftParenthesis,
5578 condition, rightParenthesis, semicolon); 5284 condition, rightParenthesis, semicolon);
5579 } finally { 5285 } finally {
5580 _inLoop = wasInLoop; 5286 _inLoop = wasInLoop;
5581 } 5287 }
5582 } 5288 }
5583 5289
5584 /** 5290 /**
5585 * Parse an empty statement. 5291 * Parse an empty statement. Return the empty statement that was parsed.
5586 * 5292 *
5587 * <pre> 5293 * emptyStatement ::=
5588 * emptyStatement ::= 5294 * ';'
5589 * ';'
5590 * </pre>
5591 *
5592 * @return the empty statement that was parsed
5593 */ 5295 */
5594 Statement _parseEmptyStatement() => new EmptyStatement(getAndAdvance()); 5296 Statement _parseEmptyStatement() => new EmptyStatement(getAndAdvance());
5595 5297
5596 EnumConstantDeclaration _parseEnumConstantDeclaration() { 5298 EnumConstantDeclaration _parseEnumConstantDeclaration() {
5597 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 5299 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
5598 SimpleIdentifier name; 5300 SimpleIdentifier name;
5599 if (_matchesIdentifier()) { 5301 if (_matchesIdentifier()) {
5600 name = parseSimpleIdentifier(); 5302 name = parseSimpleIdentifier();
5601 } else { 5303 } else {
5602 name = _createSyntheticIdentifier(); 5304 name = _createSyntheticIdentifier();
5603 } 5305 }
5604 if (commentAndMetadata.metadata.isNotEmpty) { 5306 if (commentAndMetadata.metadata.isNotEmpty) {
5605 _reportErrorForNode(ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT, 5307 _reportErrorForNode(ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT,
5606 commentAndMetadata.metadata[0]); 5308 commentAndMetadata.metadata[0]);
5607 } 5309 }
5608 return new EnumConstantDeclaration( 5310 return new EnumConstantDeclaration(
5609 commentAndMetadata.comment, commentAndMetadata.metadata, name); 5311 commentAndMetadata.comment, commentAndMetadata.metadata, name);
5610 } 5312 }
5611 5313
5612 /** 5314 /**
5613 * Parse an enum declaration. 5315 * Parse an enum declaration. The [commentAndMetadata] is the metadata to be
5316 * associated with the member. Return the enum declaration that was parsed.
5614 * 5317 *
5615 * <pre> 5318 * enumType ::=
5616 * enumType ::= 5319 * metadata 'enum' id '{' id (',' id)* (',')? '}'
5617 * metadata 'enum' id '{' id (',' id)* (',')? '}'
5618 * </pre>
5619 *
5620 * @param commentAndMetadata the metadata to be associated with the member
5621 * @return the enum declaration that was parsed
5622 */ 5320 */
5623 EnumDeclaration _parseEnumDeclaration(CommentAndMetadata commentAndMetadata) { 5321 EnumDeclaration _parseEnumDeclaration(CommentAndMetadata commentAndMetadata) {
5624 Token keyword = _expectKeyword(Keyword.ENUM); 5322 Token keyword = _expectKeyword(Keyword.ENUM);
5625 SimpleIdentifier name = parseSimpleIdentifier(); 5323 SimpleIdentifier name = parseSimpleIdentifier();
5626 Token leftBracket = null; 5324 Token leftBracket = null;
5627 List<EnumConstantDeclaration> constants = 5325 List<EnumConstantDeclaration> constants =
5628 new List<EnumConstantDeclaration>(); 5326 new List<EnumConstantDeclaration>();
5629 Token rightBracket = null; 5327 Token rightBracket = null;
5630 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { 5328 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
5631 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); 5329 leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
(...skipping 18 matching lines...) Expand all
5650 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET); 5348 leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
5651 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET); 5349 rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
5652 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY); 5350 _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
5653 } 5351 }
5654 return new EnumDeclaration(commentAndMetadata.comment, 5352 return new EnumDeclaration(commentAndMetadata.comment,
5655 commentAndMetadata.metadata, keyword, name, leftBracket, constants, 5353 commentAndMetadata.metadata, keyword, name, leftBracket, constants,
5656 rightBracket); 5354 rightBracket);
5657 } 5355 }
5658 5356
5659 /** 5357 /**
5660 * Parse an equality expression. 5358 * Parse an equality expression. Return the equality expression that was
5359 * parsed.
5661 * 5360 *
5662 * <pre> 5361 * equalityExpression ::=
5663 * equalityExpression ::= 5362 * relationalExpression (equalityOperator relationalExpression)?
5664 * relationalExpression (equalityOperator relationalExpression)? 5363 * | 'super' equalityOperator relationalExpression
5665 * | 'super' equalityOperator relationalExpression
5666 * </pre>
5667 *
5668 * @return the equality expression that was parsed
5669 */ 5364 */
5670 Expression _parseEqualityExpression() { 5365 Expression _parseEqualityExpression() {
5671 Expression expression; 5366 Expression expression;
5672 if (_matchesKeyword(Keyword.SUPER) && 5367 if (_matchesKeyword(Keyword.SUPER) &&
5673 _currentToken.next.type.isEqualityOperator) { 5368 _currentToken.next.type.isEqualityOperator) {
5674 expression = new SuperExpression(getAndAdvance()); 5369 expression = new SuperExpression(getAndAdvance());
5675 } else { 5370 } else {
5676 expression = _parseRelationalExpression(); 5371 expression = _parseRelationalExpression();
5677 } 5372 }
5678 bool leftEqualityExpression = false; 5373 bool leftEqualityExpression = false;
5679 while (_currentToken.type.isEqualityOperator) { 5374 while (_currentToken.type.isEqualityOperator) {
5680 Token operator = getAndAdvance(); 5375 Token operator = getAndAdvance();
5681 if (leftEqualityExpression) { 5376 if (leftEqualityExpression) {
5682 _reportErrorForNode( 5377 _reportErrorForNode(
5683 ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression); 5378 ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression);
5684 } 5379 }
5685 expression = new BinaryExpression( 5380 expression = new BinaryExpression(
5686 expression, operator, _parseRelationalExpression()); 5381 expression, operator, _parseRelationalExpression());
5687 leftEqualityExpression = true; 5382 leftEqualityExpression = true;
5688 } 5383 }
5689 return expression; 5384 return expression;
5690 } 5385 }
5691 5386
5692 /** 5387 /**
5693 * Parse an export directive. 5388 * Parse an export directive. The [commentAndMetadata] is the metadata to be
5389 * associated with the directive. Return the export directive that was parsed.
5694 * 5390 *
5695 * <pre> 5391 * exportDirective ::=
5696 * exportDirective ::= 5392 * metadata 'export' stringLiteral combinator*';'
5697 * metadata 'export' stringLiteral combinator*';'
5698 * </pre>
5699 *
5700 * @param commentAndMetadata the metadata to be associated with the directive
5701 * @return the export directive that was parsed
5702 */ 5393 */
5703 ExportDirective _parseExportDirective(CommentAndMetadata commentAndMetadata) { 5394 ExportDirective _parseExportDirective(CommentAndMetadata commentAndMetadata) {
5704 Token exportKeyword = _expectKeyword(Keyword.EXPORT); 5395 Token exportKeyword = _expectKeyword(Keyword.EXPORT);
5705 StringLiteral libraryUri = _parseUri(); 5396 StringLiteral libraryUri = _parseUri();
5706 List<Combinator> combinators = _parseCombinators(); 5397 List<Combinator> combinators = _parseCombinators();
5707 Token semicolon = _expectSemicolon(); 5398 Token semicolon = _expectSemicolon();
5708 return new ExportDirective(commentAndMetadata.comment, 5399 return new ExportDirective(commentAndMetadata.comment,
5709 commentAndMetadata.metadata, exportKeyword, libraryUri, combinators, 5400 commentAndMetadata.metadata, exportKeyword, libraryUri, combinators,
5710 semicolon); 5401 semicolon);
5711 } 5402 }
5712 5403
5713 /** 5404 /**
5714 * Parse a list of expressions. 5405 * Parse a list of expressions. Return the expression that was parsed.
5715 * 5406 *
5716 * <pre> 5407 * expressionList ::=
5717 * expressionList ::= 5408 * expression (',' expression)*
5718 * expression (',' expression)*
5719 * </pre>
5720 *
5721 * @return the expression that was parsed
5722 */ 5409 */
5723 List<Expression> _parseExpressionList() { 5410 List<Expression> _parseExpressionList() {
5724 List<Expression> expressions = new List<Expression>(); 5411 List<Expression> expressions = new List<Expression>();
5725 expressions.add(parseExpression2()); 5412 expressions.add(parseExpression2());
5726 while (_optional(TokenType.COMMA)) { 5413 while (_optional(TokenType.COMMA)) {
5727 expressions.add(parseExpression2()); 5414 expressions.add(parseExpression2());
5728 } 5415 }
5729 return expressions; 5416 return expressions;
5730 } 5417 }
5731 5418
5732 /** 5419 /**
5733 * Parse the 'final', 'const', 'var' or type preceding a variable declaration. 5420 * Parse the 'final', 'const', 'var' or type preceding a variable declaration.
5421 * The [optional] is `true` if the keyword and type are optional. Return the
5422 * 'final', 'const', 'var' or type that was parsed.
5734 * 5423 *
5735 * <pre> 5424 * finalConstVarOrType ::=
5736 * finalConstVarOrType ::= 5425 * 'final' type?
5737 * | 'final' type? 5426 * | 'const' type?
5738 * | 'const' type? 5427 * | 'var'
5739 * | 'var' 5428 * | type
5740 * | type
5741 * </pre>
5742 *
5743 * @param optional `true` if the keyword and type are optional
5744 * @return the 'final', 'const', 'var' or type that was parsed
5745 */ 5429 */
5746 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { 5430 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) {
5747 Token keyword = null; 5431 Token keyword = null;
5748 TypeName type = null; 5432 TypeName type = null;
5749 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) { 5433 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) {
5750 keyword = getAndAdvance(); 5434 keyword = getAndAdvance();
5751 if (_isTypedIdentifier(_currentToken)) { 5435 if (_isTypedIdentifier(_currentToken)) {
5752 type = parseTypeName(); 5436 type = parseTypeName();
5753 } 5437 }
5754 } else if (_matchesKeyword(Keyword.VAR)) { 5438 } else if (_matchesKeyword(Keyword.VAR)) {
5755 keyword = getAndAdvance(); 5439 keyword = getAndAdvance();
5756 } else { 5440 } else {
5757 if (_isTypedIdentifier(_currentToken)) { 5441 if (_isTypedIdentifier(_currentToken)) {
5758 type = parseReturnType(); 5442 type = parseReturnType();
5759 } else if (!optional) { 5443 } else if (!optional) {
5760 _reportErrorForCurrentToken( 5444 _reportErrorForCurrentToken(
5761 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); 5445 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
5762 } 5446 }
5763 } 5447 }
5764 return new FinalConstVarOrType(keyword, type); 5448 return new FinalConstVarOrType(keyword, type);
5765 } 5449 }
5766 5450
5767 /** 5451 /**
5768 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be 5452 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
5769 * `true`. 5453 * `true`. The [kind] is the kind of parameter being expected based on the
5454 * presence or absence of group delimiters. Return the formal parameter that
5455 * was parsed.
5770 * 5456 *
5771 * <pre> 5457 * defaultFormalParameter ::=
5772 * defaultFormalParameter ::= 5458 * normalFormalParameter ('=' expression)?
5773 * normalFormalParameter ('=' expression)?
5774 * 5459 *
5775 * defaultNamedParameter ::= 5460 * defaultNamedParameter ::=
5776 * normalFormalParameter (':' expression)? 5461 * normalFormalParameter (':' expression)?
5777 * </pre>
5778 *
5779 * @param kind the kind of parameter being expected based on the presence or a bsence of group
5780 * delimiters
5781 * @return the formal parameter that was parsed
5782 */ 5462 */
5783 FormalParameter _parseFormalParameter(ParameterKind kind) { 5463 FormalParameter _parseFormalParameter(ParameterKind kind) {
5784 NormalFormalParameter parameter = parseNormalFormalParameter(); 5464 NormalFormalParameter parameter = parseNormalFormalParameter();
5785 if (_matches(TokenType.EQ)) { 5465 if (_matches(TokenType.EQ)) {
5786 Token seperator = getAndAdvance(); 5466 Token seperator = getAndAdvance();
5787 Expression defaultValue = parseExpression2(); 5467 Expression defaultValue = parseExpression2();
5788 if (kind == ParameterKind.NAMED) { 5468 if (kind == ParameterKind.NAMED) {
5789 _reportErrorForToken( 5469 _reportErrorForToken(
5790 ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER, seperator); 5470 ParserErrorCode.WRONG_SEPARATOR_FOR_NAMED_PARAMETER, seperator);
5791 } else if (kind == ParameterKind.REQUIRED) { 5471 } else if (kind == ParameterKind.REQUIRED) {
(...skipping 15 matching lines...) Expand all
5807 } 5487 }
5808 return new DefaultFormalParameter( 5488 return new DefaultFormalParameter(
5809 parameter, kind, seperator, defaultValue); 5489 parameter, kind, seperator, defaultValue);
5810 } else if (kind != ParameterKind.REQUIRED) { 5490 } else if (kind != ParameterKind.REQUIRED) {
5811 return new DefaultFormalParameter(parameter, kind, null, null); 5491 return new DefaultFormalParameter(parameter, kind, null, null);
5812 } 5492 }
5813 return parameter; 5493 return parameter;
5814 } 5494 }
5815 5495
5816 /** 5496 /**
5817 * Parse a for statement. 5497 * Parse a for statement. Return the for statement that was parsed.
5818 * 5498 *
5819 * <pre> 5499 * forStatement ::=
5820 * forStatement ::= 5500 * 'for' '(' forLoopParts ')' statement
5821 * 'for' '(' forLoopParts ')' statement
5822 * 5501 *
5823 * forLoopParts ::= 5502 * forLoopParts ::=
5824 * forInitializerStatement expression? ';' expressionList? 5503 * forInitializerStatement expression? ';' expressionList?
5825 * | declaredIdentifier 'in' expression 5504 * | declaredIdentifier 'in' expression
5826 * | identifier 'in' expression 5505 * | identifier 'in' expression
5827 * 5506 *
5828 * forInitializerStatement ::= 5507 * forInitializerStatement ::=
5829 * localVariableDeclaration ';' 5508 * localVariableDeclaration ';'
5830 * | expression? ';' 5509 * | expression? ';'
5831 * </pre>
5832 *
5833 * @return the for statement that was parsed
5834 */ 5510 */
5835 Statement _parseForStatement() { 5511 Statement _parseForStatement() {
5836 bool wasInLoop = _inLoop; 5512 bool wasInLoop = _inLoop;
5837 _inLoop = true; 5513 _inLoop = true;
5838 try { 5514 try {
5839 Token awaitKeyword = null; 5515 Token awaitKeyword = null;
5840 if (_matchesString(_AWAIT)) { 5516 if (_matchesString(_AWAIT)) {
5841 awaitKeyword = getAndAdvance(); 5517 awaitKeyword = getAndAdvance();
5842 } 5518 }
5843 Token forKeyword = _expectKeyword(Keyword.FOR); 5519 Token forKeyword = _expectKeyword(Keyword.FOR);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
5930 Statement body = parseStatement2(); 5606 Statement body = parseStatement2();
5931 return new ForStatement(forKeyword, leftParenthesis, variableList, 5607 return new ForStatement(forKeyword, leftParenthesis, variableList,
5932 initialization, leftSeparator, condition, rightSeparator, updaters, 5608 initialization, leftSeparator, condition, rightSeparator, updaters,
5933 rightParenthesis, body); 5609 rightParenthesis, body);
5934 } finally { 5610 } finally {
5935 _inLoop = wasInLoop; 5611 _inLoop = wasInLoop;
5936 } 5612 }
5937 } 5613 }
5938 5614
5939 /** 5615 /**
5940 * Parse a function body. 5616 * Parse a function body. The [mayBeEmpty] is `true` if the function body is
5617 * allowed to be empty. The [emptyErrorCode] is the error code to report if
5618 * function body expected, but not found. The [inExpression] is `true` if the
5619 * function body is being parsed as part of an expression and therefore does
5620 * not have a terminating semicolon. Return the function body that was parsed.
5941 * 5621 *
5942 * <pre> 5622 * functionBody ::=
5943 * functionBody ::= 5623 * '=>' expression ';'
5944 * '=>' expression ';' 5624 * | block
5945 * | block
5946 * 5625 *
5947 * functionExpressionBody ::= 5626 * functionExpressionBody ::=
5948 * '=>' expression 5627 * '=>' expression
5949 * | block 5628 * | block
5950 * </pre>
5951 *
5952 * @param mayBeEmpty `true` if the function body is allowed to be empty
5953 * @param emptyErrorCode the error code to report if function body expected, b ut not found
5954 * @param inExpression `true` if the function body is being parsed as part of an expression
5955 * and therefore does not have a terminating semicolon
5956 * @return the function body that was parsed
5957 */ 5629 */
5958 FunctionBody _parseFunctionBody( 5630 FunctionBody _parseFunctionBody(
5959 bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) { 5631 bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
5960 bool wasInAsync = _inAsync; 5632 bool wasInAsync = _inAsync;
5961 bool wasInGenerator = _inGenerator; 5633 bool wasInGenerator = _inGenerator;
5962 bool wasInLoop = _inLoop; 5634 bool wasInLoop = _inLoop;
5963 bool wasInSwitch = _inSwitch; 5635 bool wasInSwitch = _inSwitch;
5964 _inAsync = false; 5636 _inAsync = false;
5965 _inGenerator = false; 5637 _inGenerator = false;
5966 _inLoop = false; 5638 _inLoop = false;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
6043 } 5715 }
6044 } finally { 5716 } finally {
6045 _inAsync = wasInAsync; 5717 _inAsync = wasInAsync;
6046 _inGenerator = wasInGenerator; 5718 _inGenerator = wasInGenerator;
6047 _inLoop = wasInLoop; 5719 _inLoop = wasInLoop;
6048 _inSwitch = wasInSwitch; 5720 _inSwitch = wasInSwitch;
6049 } 5721 }
6050 } 5722 }
6051 5723
6052 /** 5724 /**
6053 * Parse a function declaration. 5725 * Parse a function declaration. The [commentAndMetadata] is the documentation
5726 * comment and metadata to be associated with the declaration. The
5727 * [externalKeyword] is the 'external' keyword, or `null` if the function is
5728 * not external. The [returnType] is the return type, or `null` if there is no
5729 * return type. The [isStatement] is `true` if the function declaration is
5730 * being parsed as a statement. Return the function declaration that was
5731 * parsed.
6054 * 5732 *
6055 * <pre> 5733 * functionDeclaration ::=
6056 * functionDeclaration ::= 5734 * functionSignature functionBody
6057 * functionSignature functionBody 5735 * | returnType? getOrSet identifier formalParameterList functionBody
6058 * | returnType? getOrSet identifier formalParameterList functionBody
6059 * </pre>
6060 *
6061 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6062 * declaration
6063 * @param externalKeyword the 'external' keyword, or `null` if the function is not external
6064 * @param returnType the return type, or `null` if there is no return type
6065 * @param isStatement `true` if the function declaration is being parsed as a statement
6066 * @return the function declaration that was parsed
6067 */ 5736 */
6068 FunctionDeclaration _parseFunctionDeclaration( 5737 FunctionDeclaration _parseFunctionDeclaration(
6069 CommentAndMetadata commentAndMetadata, Token externalKeyword, 5738 CommentAndMetadata commentAndMetadata, Token externalKeyword,
6070 TypeName returnType) { 5739 TypeName returnType) {
6071 Token keyword = null; 5740 Token keyword = null;
6072 bool isGetter = false; 5741 bool isGetter = false;
6073 if (_matchesKeyword(Keyword.GET) && 5742 if (_matchesKeyword(Keyword.GET) &&
6074 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 5743 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
6075 keyword = getAndAdvance(); 5744 keyword = getAndAdvance();
6076 isGetter = true; 5745 isGetter = true;
(...skipping 26 matching lines...) Expand all
6103 // // TODO(brianwilkerson) Improve this error message. 5772 // // TODO(brianwilkerson) Improve this error message.
6104 // reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme ()); 5773 // reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme ());
6105 // advance(); 5774 // advance();
6106 // } 5775 // }
6107 return new FunctionDeclaration(commentAndMetadata.comment, 5776 return new FunctionDeclaration(commentAndMetadata.comment,
6108 commentAndMetadata.metadata, externalKeyword, returnType, keyword, name, 5777 commentAndMetadata.metadata, externalKeyword, returnType, keyword, name,
6109 new FunctionExpression(parameters, body)); 5778 new FunctionExpression(parameters, body));
6110 } 5779 }
6111 5780
6112 /** 5781 /**
6113 * Parse a function declaration statement. 5782 * Parse a function declaration statement. Return the function declaration
5783 * statement that was parsed.
6114 * 5784 *
6115 * <pre> 5785 * functionDeclarationStatement ::=
6116 * functionDeclarationStatement ::= 5786 * functionSignature functionBody
6117 * functionSignature functionBody
6118 * </pre>
6119 *
6120 * @return the function declaration statement that was parsed
6121 */ 5787 */
6122 Statement _parseFunctionDeclarationStatement() { 5788 Statement _parseFunctionDeclarationStatement() {
6123 Modifiers modifiers = _parseModifiers(); 5789 Modifiers modifiers = _parseModifiers();
6124 _validateModifiersForFunctionDeclarationStatement(modifiers); 5790 _validateModifiersForFunctionDeclarationStatement(modifiers);
6125 return _parseFunctionDeclarationStatementAfterReturnType( 5791 return _parseFunctionDeclarationStatementAfterReturnType(
6126 _parseCommentAndMetadata(), _parseOptionalReturnType()); 5792 _parseCommentAndMetadata(), _parseOptionalReturnType());
6127 } 5793 }
6128 5794
6129 /** 5795 /**
6130 * Parse a function declaration statement. 5796 * Parse a function declaration statement. The [commentAndMetadata] is the
5797 * documentation comment and metadata to be associated with the declaration.
5798 * The [returnType] is the return type, or `null` if there is no return type.
5799 * Return the function declaration statement that was parsed.
6131 * 5800 *
6132 * <pre> 5801 * functionDeclarationStatement ::=
6133 * functionDeclarationStatement ::= 5802 * functionSignature functionBody
6134 * functionSignature functionBody
6135 * </pre>
6136 *
6137 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6138 * declaration
6139 * @param returnType the return type, or `null` if there is no return type
6140 * @return the function declaration statement that was parsed
6141 */ 5803 */
6142 Statement _parseFunctionDeclarationStatementAfterReturnType( 5804 Statement _parseFunctionDeclarationStatementAfterReturnType(
6143 CommentAndMetadata commentAndMetadata, TypeName returnType) { 5805 CommentAndMetadata commentAndMetadata, TypeName returnType) {
6144 FunctionDeclaration declaration = 5806 FunctionDeclaration declaration =
6145 _parseFunctionDeclaration(commentAndMetadata, null, returnType); 5807 _parseFunctionDeclaration(commentAndMetadata, null, returnType);
6146 Token propertyKeyword = declaration.propertyKeyword; 5808 Token propertyKeyword = declaration.propertyKeyword;
6147 if (propertyKeyword != null) { 5809 if (propertyKeyword != null) {
6148 if ((propertyKeyword as KeywordToken).keyword == Keyword.GET) { 5810 if ((propertyKeyword as KeywordToken).keyword == Keyword.GET) {
6149 _reportErrorForToken( 5811 _reportErrorForToken(
6150 ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword); 5812 ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword);
6151 } else { 5813 } else {
6152 _reportErrorForToken( 5814 _reportErrorForToken(
6153 ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword); 5815 ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword);
6154 } 5816 }
6155 } 5817 }
6156 return new FunctionDeclarationStatement(declaration); 5818 return new FunctionDeclarationStatement(declaration);
6157 } 5819 }
6158 5820
6159 /** 5821 /**
6160 * Parse a function type alias. 5822 * Parse a function type alias. The [commentAndMetadata] is the metadata to be
5823 * associated with the member. The [keyword] is the token representing the
5824 * 'typedef' keyword. Return the function type alias that was parsed.
6161 * 5825 *
6162 * <pre> 5826 * functionTypeAlias ::=
6163 * functionTypeAlias ::= 5827 * functionPrefix typeParameterList? formalParameterList ';'
6164 * functionPrefix typeParameterList? formalParameterList ';'
6165 * 5828 *
6166 * functionPrefix ::= 5829 * functionPrefix ::=
6167 * returnType? name 5830 * returnType? name
6168 * </pre>
6169 *
6170 * @param commentAndMetadata the metadata to be associated with the member
6171 * @param keyword the token representing the 'typedef' keyword
6172 * @return the function type alias that was parsed
6173 */ 5831 */
6174 FunctionTypeAlias _parseFunctionTypeAlias( 5832 FunctionTypeAlias _parseFunctionTypeAlias(
6175 CommentAndMetadata commentAndMetadata, Token keyword) { 5833 CommentAndMetadata commentAndMetadata, Token keyword) {
6176 TypeName returnType = null; 5834 TypeName returnType = null;
6177 if (hasReturnTypeInTypeAlias) { 5835 if (hasReturnTypeInTypeAlias) {
6178 returnType = parseReturnType(); 5836 returnType = parseReturnType();
6179 } 5837 }
6180 SimpleIdentifier name = parseSimpleIdentifier(); 5838 SimpleIdentifier name = parseSimpleIdentifier();
6181 TypeParameterList typeParameters = null; 5839 TypeParameterList typeParameters = null;
6182 if (_matches(TokenType.LT)) { 5840 if (_matches(TokenType.LT)) {
(...skipping 23 matching lines...) Expand all
6206 } 5864 }
6207 FormalParameterList parameters = parseFormalParameterList(); 5865 FormalParameterList parameters = parseFormalParameterList();
6208 _validateFormalParameterList(parameters); 5866 _validateFormalParameterList(parameters);
6209 Token semicolon = _expect(TokenType.SEMICOLON); 5867 Token semicolon = _expect(TokenType.SEMICOLON);
6210 return new FunctionTypeAlias(commentAndMetadata.comment, 5868 return new FunctionTypeAlias(commentAndMetadata.comment,
6211 commentAndMetadata.metadata, keyword, returnType, name, typeParameters, 5869 commentAndMetadata.metadata, keyword, returnType, name, typeParameters,
6212 parameters, semicolon); 5870 parameters, semicolon);
6213 } 5871 }
6214 5872
6215 /** 5873 /**
6216 * Parse a getter. 5874 * Parse a getter. The [commentAndMetadata] is the documentation comment and
5875 * metadata to be associated with the declaration. The externalKeyword] is the
5876 * 'external' token. The staticKeyword] is the static keyword, or `null` if
5877 * the getter is not static. The [returnType] the return type that has already
5878 * been parsed, or `null` if there was no return type. Return the getter that
5879 * was parsed.
6217 * 5880 *
6218 * <pre> 5881 * getter ::=
6219 * getter ::= 5882 * getterSignature functionBody?
6220 * getterSignature functionBody?
6221 * 5883 *
6222 * getterSignature ::= 5884 * getterSignature ::=
6223 * 'external'? 'static'? returnType? 'get' identifier 5885 * 'external'? 'static'? returnType? 'get' identifier
6224 * </pre>
6225 *
6226 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6227 * declaration
6228 * @param externalKeyword the 'external' token
6229 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
6230 * @param the return type that has already been parsed, or `null` if there was no return
6231 * type
6232 * @return the getter that was parsed
6233 */ 5886 */
6234 MethodDeclaration _parseGetter(CommentAndMetadata commentAndMetadata, 5887 MethodDeclaration _parseGetter(CommentAndMetadata commentAndMetadata,
6235 Token externalKeyword, Token staticKeyword, TypeName returnType) { 5888 Token externalKeyword, Token staticKeyword, TypeName returnType) {
6236 Token propertyKeyword = _expectKeyword(Keyword.GET); 5889 Token propertyKeyword = _expectKeyword(Keyword.GET);
6237 SimpleIdentifier name = parseSimpleIdentifier(); 5890 SimpleIdentifier name = parseSimpleIdentifier();
6238 if (_matches(TokenType.OPEN_PAREN) && 5891 if (_matches(TokenType.OPEN_PAREN) &&
6239 _tokenMatches(_peek(), TokenType.CLOSE_PAREN)) { 5892 _tokenMatches(_peek(), TokenType.CLOSE_PAREN)) {
6240 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS); 5893 _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
6241 _advance(); 5894 _advance();
6242 _advance(); 5895 _advance();
6243 } 5896 }
6244 FunctionBody body = _parseFunctionBody( 5897 FunctionBody body = _parseFunctionBody(
6245 externalKeyword != null || staticKeyword == null, 5898 externalKeyword != null || staticKeyword == null,
6246 ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false); 5899 ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false);
6247 if (externalKeyword != null && body is! EmptyFunctionBody) { 5900 if (externalKeyword != null && body is! EmptyFunctionBody) {
6248 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY); 5901 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
6249 } 5902 }
6250 return new MethodDeclaration(commentAndMetadata.comment, 5903 return new MethodDeclaration(commentAndMetadata.comment,
6251 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType, 5904 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
6252 propertyKeyword, null, name, null, body); 5905 propertyKeyword, null, name, null, body);
6253 } 5906 }
6254 5907
6255 /** 5908 /**
6256 * Parse a list of identifiers. 5909 * Parse a list of identifiers. Return the list of identifiers that were
5910 * parsed.
6257 * 5911 *
6258 * <pre> 5912 * identifierList ::=
6259 * identifierList ::= 5913 * identifier (',' identifier)*
6260 * identifier (',' identifier)*
6261 * </pre>
6262 *
6263 * @return the list of identifiers that were parsed
6264 */ 5914 */
6265 List<SimpleIdentifier> _parseIdentifierList() { 5915 List<SimpleIdentifier> _parseIdentifierList() {
6266 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>(); 5916 List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
6267 identifiers.add(parseSimpleIdentifier()); 5917 identifiers.add(parseSimpleIdentifier());
6268 while (_matches(TokenType.COMMA)) { 5918 while (_matches(TokenType.COMMA)) {
6269 _advance(); 5919 _advance();
6270 identifiers.add(parseSimpleIdentifier()); 5920 identifiers.add(parseSimpleIdentifier());
6271 } 5921 }
6272 return identifiers; 5922 return identifiers;
6273 } 5923 }
6274 5924
6275 /** 5925 /**
6276 * Parse an if statement. 5926 * Parse an if statement. Return the if statement that was parsed.
6277 * 5927 *
6278 * <pre> 5928 * ifStatement ::=
6279 * ifStatement ::= 5929 * 'if' '(' expression ')' statement ('else' statement)?
6280 * 'if' '(' expression ')' statement ('else' statement)?
6281 * </pre>
6282 *
6283 * @return the if statement that was parsed
6284 */ 5930 */
6285 Statement _parseIfStatement() { 5931 Statement _parseIfStatement() {
6286 Token ifKeyword = _expectKeyword(Keyword.IF); 5932 Token ifKeyword = _expectKeyword(Keyword.IF);
6287 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); 5933 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
6288 Expression condition = parseExpression2(); 5934 Expression condition = parseExpression2();
6289 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); 5935 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
6290 Statement thenStatement = parseStatement2(); 5936 Statement thenStatement = parseStatement2();
6291 Token elseKeyword = null; 5937 Token elseKeyword = null;
6292 Statement elseStatement = null; 5938 Statement elseStatement = null;
6293 if (_matchesKeyword(Keyword.ELSE)) { 5939 if (_matchesKeyword(Keyword.ELSE)) {
6294 elseKeyword = getAndAdvance(); 5940 elseKeyword = getAndAdvance();
6295 elseStatement = parseStatement2(); 5941 elseStatement = parseStatement2();
6296 } 5942 }
6297 return new IfStatement(ifKeyword, leftParenthesis, condition, 5943 return new IfStatement(ifKeyword, leftParenthesis, condition,
6298 rightParenthesis, thenStatement, elseKeyword, elseStatement); 5944 rightParenthesis, thenStatement, elseKeyword, elseStatement);
6299 } 5945 }
6300 5946
6301 /** 5947 /**
6302 * Parse an import directive. 5948 * Parse an import directive. The [commentAndMetadata] is the metadata to be
5949 * associated with the directive. Return the import directive that was parsed.
6303 * 5950 *
6304 * <pre> 5951 * importDirective ::=
6305 * importDirective ::= 5952 * metadata 'import' stringLiteral ('as' identifier)? combinator*';'
6306 * metadata 'import' stringLiteral ('as' identifier)? combinator*';'
6307 * </pre>
6308 *
6309 * @param commentAndMetadata the metadata to be associated with the directive
6310 * @return the import directive that was parsed
6311 */ 5953 */
6312 ImportDirective _parseImportDirective(CommentAndMetadata commentAndMetadata) { 5954 ImportDirective _parseImportDirective(CommentAndMetadata commentAndMetadata) {
6313 Token importKeyword = _expectKeyword(Keyword.IMPORT); 5955 Token importKeyword = _expectKeyword(Keyword.IMPORT);
6314 StringLiteral libraryUri = _parseUri(); 5956 StringLiteral libraryUri = _parseUri();
6315 Token deferredToken = null; 5957 Token deferredToken = null;
6316 Token asToken = null; 5958 Token asToken = null;
6317 SimpleIdentifier prefix = null; 5959 SimpleIdentifier prefix = null;
6318 if (_matchesKeyword(Keyword.DEFERRED)) { 5960 if (_matchesKeyword(Keyword.DEFERRED)) {
6319 deferredToken = getAndAdvance(); 5961 deferredToken = getAndAdvance();
6320 } 5962 }
6321 if (_matchesKeyword(Keyword.AS)) { 5963 if (_matchesKeyword(Keyword.AS)) {
6322 asToken = getAndAdvance(); 5964 asToken = getAndAdvance();
6323 prefix = parseSimpleIdentifier(); 5965 prefix = parseSimpleIdentifier();
6324 } else if (deferredToken != null) { 5966 } else if (deferredToken != null) {
6325 _reportErrorForCurrentToken( 5967 _reportErrorForCurrentToken(
6326 ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT); 5968 ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT);
6327 } 5969 }
6328 List<Combinator> combinators = _parseCombinators(); 5970 List<Combinator> combinators = _parseCombinators();
6329 Token semicolon = _expectSemicolon(); 5971 Token semicolon = _expectSemicolon();
6330 return new ImportDirective(commentAndMetadata.comment, 5972 return new ImportDirective(commentAndMetadata.comment,
6331 commentAndMetadata.metadata, importKeyword, libraryUri, deferredToken, 5973 commentAndMetadata.metadata, importKeyword, libraryUri, deferredToken,
6332 asToken, prefix, combinators, semicolon); 5974 asToken, prefix, combinators, semicolon);
6333 } 5975 }
6334 5976
6335 /** 5977 /**
6336 * Parse a list of initialized identifiers. 5978 * Parse a list of initialized identifiers. The [commentAndMetadata] is the
5979 * documentation comment and metadata to be associated with the declaration.
5980 * The [staticKeyword] is the static keyword, or `null` if the getter is not
5981 * static. The [keyword] is the token representing the 'final', 'const' or
5982 * 'var' keyword, or `null` if there is no keyword. The [type] is the type
5983 * that has already been parsed, or `null` if 'var' was provided. Return the
5984 * getter that was parsed.
6337 * 5985 *
6338 * <pre> 5986 * ?? ::=
6339 * ?? ::= 5987 * 'static'? ('var' | type) initializedIdentifierList ';'
6340 * 'static'? ('var' | type) initializedIdentifierList ';' 5988 * | 'final' type? initializedIdentifierList ';'
6341 * | 'final' type? initializedIdentifierList ';'
6342 * 5989 *
6343 * initializedIdentifierList ::= 5990 * initializedIdentifierList ::=
6344 * initializedIdentifier (',' initializedIdentifier)* 5991 * initializedIdentifier (',' initializedIdentifier)*
6345 * 5992 *
6346 * initializedIdentifier ::= 5993 * initializedIdentifier ::=
6347 * identifier ('=' expression)? 5994 * identifier ('=' expression)?
6348 * </pre>
6349 *
6350 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6351 * declaration
6352 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
6353 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
6354 * there is no keyword
6355 * @param type the type that has already been parsed, or `null` if 'var' was p rovided
6356 * @return the getter that was parsed
6357 */ 5995 */
6358 FieldDeclaration _parseInitializedIdentifierList( 5996 FieldDeclaration _parseInitializedIdentifierList(
6359 CommentAndMetadata commentAndMetadata, Token staticKeyword, Token keyword, 5997 CommentAndMetadata commentAndMetadata, Token staticKeyword, Token keyword,
6360 TypeName type) { 5998 TypeName type) {
6361 VariableDeclarationList fieldList = 5999 VariableDeclarationList fieldList =
6362 _parseVariableDeclarationListAfterType(null, keyword, type); 6000 _parseVariableDeclarationListAfterType(null, keyword, type);
6363 return new FieldDeclaration(commentAndMetadata.comment, 6001 return new FieldDeclaration(commentAndMetadata.comment,
6364 commentAndMetadata.metadata, staticKeyword, fieldList, 6002 commentAndMetadata.metadata, staticKeyword, fieldList,
6365 _expect(TokenType.SEMICOLON)); 6003 _expect(TokenType.SEMICOLON));
6366 } 6004 }
6367 6005
6368 /** 6006 /**
6369 * Parse an instance creation expression. 6007 * Parse an instance creation expression. The [keyword] is the 'new' or
6008 * 'const' keyword that introduces the expression. Return the instance
6009 * creation expression that was parsed.
6370 * 6010 *
6371 * <pre> 6011 * instanceCreationExpression ::=
6372 * instanceCreationExpression ::= 6012 * ('new' | 'const') type ('.' identifier)? argumentList
6373 * ('new' | 'const') type ('.' identifier)? argumentList
6374 * </pre>
6375 *
6376 * @param keyword the 'new' or 'const' keyword that introduces the expression
6377 * @return the instance creation expression that was parsed
6378 */ 6013 */
6379 InstanceCreationExpression _parseInstanceCreationExpression(Token keyword) { 6014 InstanceCreationExpression _parseInstanceCreationExpression(Token keyword) {
6380 ConstructorName constructorName = parseConstructorName(); 6015 ConstructorName constructorName = parseConstructorName();
6381 ArgumentList argumentList = parseArgumentList(); 6016 ArgumentList argumentList = parseArgumentList();
6382 return new InstanceCreationExpression( 6017 return new InstanceCreationExpression(
6383 keyword, constructorName, argumentList); 6018 keyword, constructorName, argumentList);
6384 } 6019 }
6385 6020
6386 /** 6021 /**
6387 * Parse a library directive. 6022 * Parse a library directive. The [commentAndMetadata] is the metadata to be
6023 * associated with the directive. Return the library directive that was
6024 * parsed.
6388 * 6025 *
6389 * <pre> 6026 * libraryDirective ::=
6390 * libraryDirective ::= 6027 * metadata 'library' identifier ';'
6391 * metadata 'library' identifier ';'
6392 * </pre>
6393 *
6394 * @param commentAndMetadata the metadata to be associated with the directive
6395 * @return the library directive that was parsed
6396 */ 6028 */
6397 LibraryDirective _parseLibraryDirective( 6029 LibraryDirective _parseLibraryDirective(
6398 CommentAndMetadata commentAndMetadata) { 6030 CommentAndMetadata commentAndMetadata) {
6399 Token keyword = _expectKeyword(Keyword.LIBRARY); 6031 Token keyword = _expectKeyword(Keyword.LIBRARY);
6400 LibraryIdentifier libraryName = _parseLibraryName( 6032 LibraryIdentifier libraryName = _parseLibraryName(
6401 ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword); 6033 ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword);
6402 Token semicolon = _expect(TokenType.SEMICOLON); 6034 Token semicolon = _expect(TokenType.SEMICOLON);
6403 return new LibraryDirective(commentAndMetadata.comment, 6035 return new LibraryDirective(commentAndMetadata.comment,
6404 commentAndMetadata.metadata, keyword, libraryName, semicolon); 6036 commentAndMetadata.metadata, keyword, libraryName, semicolon);
6405 } 6037 }
6406 6038
6407 /** 6039 /**
6408 * Parse a library name. 6040 * Parse a library name. The [missingNameError] is the error code to be used
6041 * if the library name is missing. The [missingNameToken] is the token
6042 * associated with the error produced if the library name is missing. Return
6043 * the library name that was parsed.
6409 * 6044 *
6410 * <pre> 6045 * libraryName ::=
6411 * libraryName ::= 6046 * libraryIdentifier
6412 * libraryIdentifier
6413 * </pre>
6414 *
6415 * @param missingNameError the error code to be used if the library name is mi ssing
6416 * @param missingNameToken the token associated with the error produced if the library name is
6417 * missing
6418 * @return the library name that was parsed
6419 */ 6047 */
6420 LibraryIdentifier _parseLibraryName( 6048 LibraryIdentifier _parseLibraryName(
6421 ParserErrorCode missingNameError, Token missingNameToken) { 6049 ParserErrorCode missingNameError, Token missingNameToken) {
6422 if (_matchesIdentifier()) { 6050 if (_matchesIdentifier()) {
6423 return parseLibraryIdentifier(); 6051 return parseLibraryIdentifier();
6424 } else if (_matches(TokenType.STRING)) { 6052 } else if (_matches(TokenType.STRING)) {
6425 // TODO(brianwilkerson) Recovery: This should be extended to handle 6053 // TODO(brianwilkerson) Recovery: This should be extended to handle
6426 // arbitrary tokens until we can find a token that can start a compilation 6054 // arbitrary tokens until we can find a token that can start a compilation
6427 // unit member. 6055 // unit member.
6428 StringLiteral string = parseStringLiteral(); 6056 StringLiteral string = parseStringLiteral();
6429 _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string); 6057 _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string);
6430 } else { 6058 } else {
6431 _reportErrorForToken(missingNameError, missingNameToken); 6059 _reportErrorForToken(missingNameError, missingNameToken);
6432 } 6060 }
6433 List<SimpleIdentifier> components = new List<SimpleIdentifier>(); 6061 List<SimpleIdentifier> components = new List<SimpleIdentifier>();
6434 components.add(_createSyntheticIdentifier()); 6062 components.add(_createSyntheticIdentifier());
6435 return new LibraryIdentifier(components); 6063 return new LibraryIdentifier(components);
6436 } 6064 }
6437 6065
6438 /** 6066 /**
6439 * Parse a list literal. 6067 * Parse a list literal. The [modifier] is the 'const' modifier appearing
6068 * before the literal, or `null` if there is no modifier. The [typeArguments]
6069 * is the type arguments appearing before the literal, or `null` if there are
6070 * no type arguments. Return the list literal that was parsed.
6440 * 6071 *
6441 * <pre> 6072 * listLiteral ::=
6442 * listLiteral ::= 6073 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
6443 * 'const'? typeArguments? '[' (expressionList ','?)? ']'
6444 * </pre>
6445 *
6446 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
6447 * no modifier
6448 * @param typeArguments the type arguments appearing before the literal, or `n ull` if there
6449 * are no type arguments
6450 * @return the list literal that was parsed
6451 */ 6074 */
6452 ListLiteral _parseListLiteral( 6075 ListLiteral _parseListLiteral(
6453 Token modifier, TypeArgumentList typeArguments) { 6076 Token modifier, TypeArgumentList typeArguments) {
6454 // may be empty list literal 6077 // may be empty list literal
6455 if (_matches(TokenType.INDEX)) { 6078 if (_matches(TokenType.INDEX)) {
6456 BeginToken leftBracket = _createToken( 6079 BeginToken leftBracket = _createToken(
6457 _currentToken, TokenType.OPEN_SQUARE_BRACKET, isBegin: true); 6080 _currentToken, TokenType.OPEN_SQUARE_BRACKET, isBegin: true);
6458 Token rightBracket = 6081 Token rightBracket =
6459 new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1); 6082 new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
6460 leftBracket.endToken = rightBracket; 6083 leftBracket.endToken = rightBracket;
(...skipping 24 matching lines...) Expand all
6485 } 6108 }
6486 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET); 6109 Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
6487 return new ListLiteral( 6110 return new ListLiteral(
6488 modifier, typeArguments, leftBracket, elements, rightBracket); 6111 modifier, typeArguments, leftBracket, elements, rightBracket);
6489 } finally { 6112 } finally {
6490 _inInitializer = wasInInitializer; 6113 _inInitializer = wasInInitializer;
6491 } 6114 }
6492 } 6115 }
6493 6116
6494 /** 6117 /**
6495 * Parse a list or map literal. 6118 * Parse a list or map literal. The [modifier] is the 'const' modifier
6119 * appearing before the literal, or `null` if there is no modifier. Return the
6120 * list or map literal that was parsed.
6496 * 6121 *
6497 * <pre> 6122 * listOrMapLiteral ::=
6498 * listOrMapLiteral ::= 6123 * listLiteral
6499 * listLiteral 6124 * | mapLiteral
6500 * | mapLiteral
6501 * </pre>
6502 *
6503 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
6504 * no modifier
6505 * @return the list or map literal that was parsed
6506 */ 6125 */
6507 TypedLiteral _parseListOrMapLiteral(Token modifier) { 6126 TypedLiteral _parseListOrMapLiteral(Token modifier) {
6508 TypeArgumentList typeArguments = null; 6127 TypeArgumentList typeArguments = null;
6509 if (_matches(TokenType.LT)) { 6128 if (_matches(TokenType.LT)) {
6510 typeArguments = parseTypeArgumentList(); 6129 typeArguments = parseTypeArgumentList();
6511 } 6130 }
6512 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { 6131 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6513 return _parseMapLiteral(modifier, typeArguments); 6132 return _parseMapLiteral(modifier, typeArguments);
6514 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || 6133 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
6515 _matches(TokenType.INDEX)) { 6134 _matches(TokenType.INDEX)) {
6516 return _parseListLiteral(modifier, typeArguments); 6135 return _parseListLiteral(modifier, typeArguments);
6517 } 6136 }
6518 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL); 6137 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
6519 return new ListLiteral(modifier, typeArguments, 6138 return new ListLiteral(modifier, typeArguments,
6520 _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET), null, 6139 _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET), null,
6521 _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET)); 6140 _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET));
6522 } 6141 }
6523 6142
6524 /** 6143 /**
6525 * Parse a logical and expression. 6144 * Parse a logical and expression. Return the logical and expression that was
6145 * parsed.
6526 * 6146 *
6527 * <pre> 6147 * logicalAndExpression ::=
6528 * logicalAndExpression ::= 6148 * equalityExpression ('&&' equalityExpression)*
6529 * equalityExpression ('&&' equalityExpression)*
6530 * </pre>
6531 *
6532 * @return the logical and expression that was parsed
6533 */ 6149 */
6534 Expression _parseLogicalAndExpression() { 6150 Expression _parseLogicalAndExpression() {
6535 Expression expression = _parseEqualityExpression(); 6151 Expression expression = _parseEqualityExpression();
6536 while (_matches(TokenType.AMPERSAND_AMPERSAND)) { 6152 while (_matches(TokenType.AMPERSAND_AMPERSAND)) {
6537 Token operator = getAndAdvance(); 6153 Token operator = getAndAdvance();
6538 expression = new BinaryExpression( 6154 expression = new BinaryExpression(
6539 expression, operator, _parseEqualityExpression()); 6155 expression, operator, _parseEqualityExpression());
6540 } 6156 }
6541 return expression; 6157 return expression;
6542 } 6158 }
6543 6159
6544 /** 6160 /**
6545 * Parse a map literal. 6161 * Parse a map literal. The [modifier] is the 'const' modifier appearing
6162 * before the literal, or `null` if there is no modifier. The [typeArguments]
6163 * is the type arguments that were declared, or `null` if there are no type
6164 * arguments. Return the map literal that was parsed.
6546 * 6165 *
6547 * <pre> 6166 * mapLiteral ::=
6548 * mapLiteral ::= 6167 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
6549 * 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ',' ?)? '}'
6550 * </pre>
6551 *
6552 * @param modifier the 'const' modifier appearing before the literal, or `null ` if there is
6553 * no modifier
6554 * @param typeArguments the type arguments that were declared, or `null` if th ere are no
6555 * type arguments
6556 * @return the map literal that was parsed
6557 */ 6168 */
6558 MapLiteral _parseMapLiteral(Token modifier, TypeArgumentList typeArguments) { 6169 MapLiteral _parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
6559 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET); 6170 Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
6560 List<MapLiteralEntry> entries = new List<MapLiteralEntry>(); 6171 List<MapLiteralEntry> entries = new List<MapLiteralEntry>();
6561 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { 6172 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6562 return new MapLiteral( 6173 return new MapLiteral(
6563 modifier, typeArguments, leftBracket, entries, getAndAdvance()); 6174 modifier, typeArguments, leftBracket, entries, getAndAdvance());
6564 } 6175 }
6565 bool wasInInitializer = _inInitializer; 6176 bool wasInInitializer = _inInitializer;
6566 _inInitializer = false; 6177 _inInitializer = false;
6567 try { 6178 try {
6568 entries.add(parseMapLiteralEntry()); 6179 entries.add(parseMapLiteralEntry());
6569 while (_optional(TokenType.COMMA)) { 6180 while (_optional(TokenType.COMMA)) {
6570 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { 6181 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6571 return new MapLiteral( 6182 return new MapLiteral(
6572 modifier, typeArguments, leftBracket, entries, getAndAdvance()); 6183 modifier, typeArguments, leftBracket, entries, getAndAdvance());
6573 } 6184 }
6574 entries.add(parseMapLiteralEntry()); 6185 entries.add(parseMapLiteralEntry());
6575 } 6186 }
6576 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); 6187 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
6577 return new MapLiteral( 6188 return new MapLiteral(
6578 modifier, typeArguments, leftBracket, entries, rightBracket); 6189 modifier, typeArguments, leftBracket, entries, rightBracket);
6579 } finally { 6190 } finally {
6580 _inInitializer = wasInInitializer; 6191 _inInitializer = wasInInitializer;
6581 } 6192 }
6582 } 6193 }
6583 6194
6584 /** 6195 /**
6585 * Parse a method declaration. 6196 * Parse a method declaration. The [commentAndMetadata] is the documentation
6197 * comment and metadata to be associated with the declaration. The
6198 * [externalKeyword] is the 'external' token. The [staticKeyword] is the
6199 * static keyword, or `null` if the getter is not static. The [returnType] is
6200 * the return type of the method. The [name] is the name of the method. The
6201 * [parameters] is the parameters to the method. Return the method declaration
6202 * that was parsed.
6586 * 6203 *
6587 * <pre> 6204 * functionDeclaration ::=
6588 * functionDeclaration ::= 6205 * ('external' 'static'?)? functionSignature functionBody
6589 * ('external' 'static'?)? functionSignature functionBody 6206 * | 'external'? functionSignature ';'
6590 * | 'external'? functionSignature ';'
6591 * </pre>
6592 *
6593 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6594 * declaration
6595 * @param externalKeyword the 'external' token
6596 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
6597 * @param returnType the return type of the method
6598 * @param name the name of the method
6599 * @param parameters the parameters to the method
6600 * @return the method declaration that was parsed
6601 */ 6207 */
6602 MethodDeclaration _parseMethodDeclarationAfterParameters( 6208 MethodDeclaration _parseMethodDeclarationAfterParameters(
6603 CommentAndMetadata commentAndMetadata, Token externalKeyword, 6209 CommentAndMetadata commentAndMetadata, Token externalKeyword,
6604 Token staticKeyword, TypeName returnType, SimpleIdentifier name, 6210 Token staticKeyword, TypeName returnType, SimpleIdentifier name,
6605 FormalParameterList parameters) { 6211 FormalParameterList parameters) {
6606 FunctionBody body = _parseFunctionBody( 6212 FunctionBody body = _parseFunctionBody(
6607 externalKeyword != null || staticKeyword == null, 6213 externalKeyword != null || staticKeyword == null,
6608 ParserErrorCode.MISSING_FUNCTION_BODY, false); 6214 ParserErrorCode.MISSING_FUNCTION_BODY, false);
6609 if (externalKeyword != null) { 6215 if (externalKeyword != null) {
6610 if (body is! EmptyFunctionBody) { 6216 if (body is! EmptyFunctionBody) {
6611 _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body); 6217 _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body);
6612 } 6218 }
6613 } else if (staticKeyword != null) { 6219 } else if (staticKeyword != null) {
6614 if (body is EmptyFunctionBody) { 6220 if (body is EmptyFunctionBody) {
6615 _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body); 6221 _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body);
6616 } 6222 }
6617 } 6223 }
6618 return new MethodDeclaration(commentAndMetadata.comment, 6224 return new MethodDeclaration(commentAndMetadata.comment,
6619 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType, 6225 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
6620 null, null, name, parameters, body); 6226 null, null, name, parameters, body);
6621 } 6227 }
6622 6228
6623 /** 6229 /**
6624 * Parse a method declaration. 6230 * Parse a method declaration. The [commentAndMetadata] is the documentation
6231 * comment and metadata to be associated with the declaration. The
6232 * [externalKeyword] is the 'external' token. The [staticKeyword] is the
6233 * static keyword, or `null` if the getter is not static. The [returnType] is
6234 * the return type of the method. Return the method declaration that was
6235 * parsed.
6625 * 6236 *
6626 * <pre> 6237 * functionDeclaration ::=
6627 * functionDeclaration ::= 6238 * 'external'? 'static'? functionSignature functionBody
6628 * 'external'? 'static'? functionSignature functionBody 6239 * | 'external'? functionSignature ';'
6629 * | 'external'? functionSignature ';'
6630 * </pre>
6631 *
6632 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6633 * declaration
6634 * @param externalKeyword the 'external' token
6635 * @param staticKeyword the static keyword, or `null` if the getter is not sta tic
6636 * @param returnType the return type of the method
6637 * @return the method declaration that was parsed
6638 */ 6240 */
6639 MethodDeclaration _parseMethodDeclarationAfterReturnType( 6241 MethodDeclaration _parseMethodDeclarationAfterReturnType(
6640 CommentAndMetadata commentAndMetadata, Token externalKeyword, 6242 CommentAndMetadata commentAndMetadata, Token externalKeyword,
6641 Token staticKeyword, TypeName returnType) { 6243 Token staticKeyword, TypeName returnType) {
6642 SimpleIdentifier methodName = parseSimpleIdentifier(); 6244 SimpleIdentifier methodName = parseSimpleIdentifier();
6643 FormalParameterList parameters; 6245 FormalParameterList parameters;
6644 if (!_matches(TokenType.OPEN_PAREN) && 6246 if (!_matches(TokenType.OPEN_PAREN) &&
6645 (_matches(TokenType.OPEN_CURLY_BRACKET) || 6247 (_matches(TokenType.OPEN_CURLY_BRACKET) ||
6646 _matches(TokenType.FUNCTION))) { 6248 _matches(TokenType.FUNCTION))) {
6647 _reportErrorForToken( 6249 _reportErrorForToken(
6648 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous); 6250 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
6649 parameters = new FormalParameterList( 6251 parameters = new FormalParameterList(
6650 _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null, 6252 _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
6651 _createSyntheticToken(TokenType.CLOSE_PAREN)); 6253 _createSyntheticToken(TokenType.CLOSE_PAREN));
6652 } else { 6254 } else {
6653 parameters = parseFormalParameterList(); 6255 parameters = parseFormalParameterList();
6654 } 6256 }
6655 _validateFormalParameterList(parameters); 6257 _validateFormalParameterList(parameters);
6656 return _parseMethodDeclarationAfterParameters(commentAndMetadata, 6258 return _parseMethodDeclarationAfterParameters(commentAndMetadata,
6657 externalKeyword, staticKeyword, returnType, methodName, parameters); 6259 externalKeyword, staticKeyword, returnType, methodName, parameters);
6658 } 6260 }
6659 6261
6660 /** 6262 /**
6661 * Parse the modifiers preceding a declaration. This method allows the modifie rs to appear in any 6263 * Parse the modifiers preceding a declaration. This method allows the
6662 * order but does generate errors for duplicated modifiers. Checks for other p roblems, such as 6264 * modifiers to appear in any order but does generate errors for duplicated
6663 * having the modifiers appear in the wrong order or specifying both 'const' a nd 'final', are 6265 * modifiers. Checks for other problems, such as having the modifiers appear
6664 * reported in one of the methods whose name is prefixed with `validateModifie rsFor`. 6266 * in the wrong order or specifying both 'const' and 'final', are reported in
6267 * one of the methods whose name is prefixed with `validateModifiersFor`.
6268 * Return the modifiers that were parsed.
6665 * 6269 *
6666 * <pre> 6270 * modifiers ::=
6667 * modifiers ::= 6271 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')*
6668 * ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | ' var')*
6669 * </pre>
6670 *
6671 * @return the modifiers that were parsed
6672 */ 6272 */
6673 Modifiers _parseModifiers() { 6273 Modifiers _parseModifiers() {
6674 Modifiers modifiers = new Modifiers(); 6274 Modifiers modifiers = new Modifiers();
6675 bool progress = true; 6275 bool progress = true;
6676 while (progress) { 6276 while (progress) {
6677 if (_tokenMatches(_peek(), TokenType.PERIOD) || 6277 if (_tokenMatches(_peek(), TokenType.PERIOD) ||
6678 _tokenMatches(_peek(), TokenType.LT) || 6278 _tokenMatches(_peek(), TokenType.LT) ||
6679 _tokenMatches(_peek(), TokenType.OPEN_PAREN)) { 6279 _tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
6680 return modifiers; 6280 return modifiers;
6681 } 6281 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
6742 modifiers.varKeyword = getAndAdvance(); 6342 modifiers.varKeyword = getAndAdvance();
6743 } 6343 }
6744 } else { 6344 } else {
6745 progress = false; 6345 progress = false;
6746 } 6346 }
6747 } 6347 }
6748 return modifiers; 6348 return modifiers;
6749 } 6349 }
6750 6350
6751 /** 6351 /**
6752 * Parse a multiplicative expression. 6352 * Parse a multiplicative expression. Return the multiplicative expression
6353 * that was parsed.
6753 * 6354 *
6754 * <pre> 6355 * multiplicativeExpression ::=
6755 * multiplicativeExpression ::= 6356 * unaryExpression (multiplicativeOperator unaryExpression)*
6756 * unaryExpression (multiplicativeOperator unaryExpression)* 6357 * | 'super' (multiplicativeOperator unaryExpression)+
6757 * | 'super' (multiplicativeOperator unaryExpression)+
6758 * </pre>
6759 *
6760 * @return the multiplicative expression that was parsed
6761 */ 6358 */
6762 Expression _parseMultiplicativeExpression() { 6359 Expression _parseMultiplicativeExpression() {
6763 Expression expression; 6360 Expression expression;
6764 if (_matchesKeyword(Keyword.SUPER) && 6361 if (_matchesKeyword(Keyword.SUPER) &&
6765 _currentToken.next.type.isMultiplicativeOperator) { 6362 _currentToken.next.type.isMultiplicativeOperator) {
6766 expression = new SuperExpression(getAndAdvance()); 6363 expression = new SuperExpression(getAndAdvance());
6767 } else { 6364 } else {
6768 expression = _parseUnaryExpression(); 6365 expression = _parseUnaryExpression();
6769 } 6366 }
6770 while (_currentToken.type.isMultiplicativeOperator) { 6367 while (_currentToken.type.isMultiplicativeOperator) {
6771 Token operator = getAndAdvance(); 6368 Token operator = getAndAdvance();
6772 expression = 6369 expression =
6773 new BinaryExpression(expression, operator, _parseUnaryExpression()); 6370 new BinaryExpression(expression, operator, _parseUnaryExpression());
6774 } 6371 }
6775 return expression; 6372 return expression;
6776 } 6373 }
6777 6374
6778 /** 6375 /**
6779 * Parse a class native clause. 6376 * Parse a class native clause. Return the native clause that was parsed.
6780 * 6377 *
6781 * <pre> 6378 * classNativeClause ::=
6782 * classNativeClause ::= 6379 * 'native' name
6783 * 'native' name
6784 * </pre>
6785 *
6786 * @return the class native clause that was parsed
6787 */ 6380 */
6788 NativeClause _parseNativeClause() { 6381 NativeClause _parseNativeClause() {
6789 Token keyword = getAndAdvance(); 6382 Token keyword = getAndAdvance();
6790 StringLiteral name = parseStringLiteral(); 6383 StringLiteral name = parseStringLiteral();
6791 return new NativeClause(keyword, name); 6384 return new NativeClause(keyword, name);
6792 } 6385 }
6793 6386
6794 /** 6387 /**
6795 * Parse a new expression. 6388 * Parse a new expression. Return the new expression that was parsed.
6796 * 6389 *
6797 * <pre> 6390 * newExpression ::=
6798 * newExpression ::= 6391 * instanceCreationExpression
6799 * instanceCreationExpression
6800 * </pre>
6801 *
6802 * @return the new expression that was parsed
6803 */ 6392 */
6804 InstanceCreationExpression _parseNewExpression() => 6393 InstanceCreationExpression _parseNewExpression() =>
6805 _parseInstanceCreationExpression(_expectKeyword(Keyword.NEW)); 6394 _parseInstanceCreationExpression(_expectKeyword(Keyword.NEW));
6806 6395
6807 /** 6396 /**
6808 * Parse a non-labeled statement. 6397 * Parse a non-labeled statement. Return the non-labeled statement that was
6398 * parsed.
6809 * 6399 *
6810 * <pre> 6400 * nonLabeledStatement ::=
6811 * nonLabeledStatement ::= 6401 * block
6812 * block 6402 * | assertStatement
6813 * | assertStatement 6403 * | breakStatement
6814 * | breakStatement 6404 * | continueStatement
6815 * | continueStatement 6405 * | doStatement
6816 * | doStatement 6406 * | forStatement
6817 * | forStatement 6407 * | ifStatement
6818 * | ifStatement 6408 * | returnStatement
6819 * | returnStatement 6409 * | switchStatement
6820 * | switchStatement 6410 * | tryStatement
6821 * | tryStatement 6411 * | whileStatement
6822 * | whileStatement 6412 * | variableDeclarationList ';'
6823 * | variableDeclarationList ';' 6413 * | expressionStatement
6824 * | expressionStatement 6414 * | functionSignature functionBody
6825 * | functionSignature functionBody
6826 * </pre>
6827 *
6828 * @return the non-labeled statement that was parsed
6829 */ 6415 */
6830 Statement _parseNonLabeledStatement() { 6416 Statement _parseNonLabeledStatement() {
6831 // TODO(brianwilkerson) Pass the comment and metadata on where appropriate. 6417 // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
6832 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 6418 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
6833 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { 6419 if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
6834 if (_tokenMatches(_peek(), TokenType.STRING)) { 6420 if (_tokenMatches(_peek(), TokenType.STRING)) {
6835 Token afterString = _skipStringLiteral(_currentToken.next); 6421 Token afterString = _skipStringLiteral(_currentToken.next);
6836 if (afterString != null && afterString.type == TokenType.COLON) { 6422 if (afterString != null && afterString.type == TokenType.COLON) {
6837 return new ExpressionStatement( 6423 return new ExpressionStatement(
6838 parseExpression2(), _expect(TokenType.SEMICOLON)); 6424 parseExpression2(), _expect(TokenType.SEMICOLON));
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
6974 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { 6560 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
6975 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT); 6561 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
6976 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON)); 6562 return new EmptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
6977 } else { 6563 } else {
6978 return new ExpressionStatement( 6564 return new ExpressionStatement(
6979 parseExpression2(), _expect(TokenType.SEMICOLON)); 6565 parseExpression2(), _expect(TokenType.SEMICOLON));
6980 } 6566 }
6981 } 6567 }
6982 6568
6983 /** 6569 /**
6984 * Parse an operator declaration. 6570 * Parse an operator declaration. The [commentAndMetadata] is the
6571 * documentation comment and metadata to be associated with the declaration.
6572 * The [externalKeyword] is the 'external' token. The [returnType] is the
6573 * return type that has already been parsed, or `null` if there was no return
6574 * type. Return the operator declaration that was parsed.
6985 * 6575 *
6986 * <pre> 6576 * operatorDeclaration ::=
6987 * operatorDeclaration ::= 6577 * operatorSignature (';' | functionBody)
6988 * operatorSignature (';' | functionBody)
6989 * 6578 *
6990 * operatorSignature ::= 6579 * operatorSignature ::=
6991 * 'external'? returnType? 'operator' operator formalParameterList 6580 * 'external'? returnType? 'operator' operator formalParameterList
6992 * </pre>
6993 *
6994 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
6995 * declaration
6996 * @param externalKeyword the 'external' token
6997 * @param the return type that has already been parsed, or `null` if there was no return
6998 * type
6999 * @return the operator declaration that was parsed
7000 */ 6581 */
7001 MethodDeclaration _parseOperator(CommentAndMetadata commentAndMetadata, 6582 MethodDeclaration _parseOperator(CommentAndMetadata commentAndMetadata,
7002 Token externalKeyword, TypeName returnType) { 6583 Token externalKeyword, TypeName returnType) {
7003 Token operatorKeyword; 6584 Token operatorKeyword;
7004 if (_matchesKeyword(Keyword.OPERATOR)) { 6585 if (_matchesKeyword(Keyword.OPERATOR)) {
7005 operatorKeyword = getAndAdvance(); 6586 operatorKeyword = getAndAdvance();
7006 } else { 6587 } else {
7007 _reportErrorForToken( 6588 _reportErrorForToken(
7008 ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken); 6589 ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken);
7009 operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR); 6590 operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR);
(...skipping 20 matching lines...) Expand all
7030 _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false); 6611 _parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
7031 if (externalKeyword != null && body is! EmptyFunctionBody) { 6612 if (externalKeyword != null && body is! EmptyFunctionBody) {
7032 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY); 6613 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
7033 } 6614 }
7034 return new MethodDeclaration(commentAndMetadata.comment, 6615 return new MethodDeclaration(commentAndMetadata.comment,
7035 commentAndMetadata.metadata, externalKeyword, null, returnType, null, 6616 commentAndMetadata.metadata, externalKeyword, null, returnType, null,
7036 operatorKeyword, name, parameters, body); 6617 operatorKeyword, name, parameters, body);
7037 } 6618 }
7038 6619
7039 /** 6620 /**
7040 * Parse a return type if one is given, otherwise return `null` without advanc ing. 6621 * Parse a return type if one is given, otherwise return `null` without
7041 * 6622 * advancing. Return the return type that was parsed.
7042 * @return the return type that was parsed
7043 */ 6623 */
7044 TypeName _parseOptionalReturnType() { 6624 TypeName _parseOptionalReturnType() {
7045 if (_matchesKeyword(Keyword.VOID)) { 6625 if (_matchesKeyword(Keyword.VOID)) {
7046 return parseReturnType(); 6626 return parseReturnType();
7047 } else if (_matchesIdentifier() && 6627 } else if (_matchesIdentifier() &&
7048 !_matchesKeyword(Keyword.GET) && 6628 !_matchesKeyword(Keyword.GET) &&
7049 !_matchesKeyword(Keyword.SET) && 6629 !_matchesKeyword(Keyword.SET) &&
7050 !_matchesKeyword(Keyword.OPERATOR) && 6630 !_matchesKeyword(Keyword.OPERATOR) &&
7051 (_tokenMatchesIdentifier(_peek()) || 6631 (_tokenMatchesIdentifier(_peek()) ||
7052 _tokenMatches(_peek(), TokenType.LT))) { 6632 _tokenMatches(_peek(), TokenType.LT))) {
7053 return parseReturnType(); 6633 return parseReturnType();
7054 } else if (_matchesIdentifier() && 6634 } else if (_matchesIdentifier() &&
7055 _tokenMatches(_peek(), TokenType.PERIOD) && 6635 _tokenMatches(_peek(), TokenType.PERIOD) &&
7056 _tokenMatchesIdentifier(_peekAt(2)) && 6636 _tokenMatchesIdentifier(_peekAt(2)) &&
7057 (_tokenMatchesIdentifier(_peekAt(3)) || 6637 (_tokenMatchesIdentifier(_peekAt(3)) ||
7058 _tokenMatches(_peekAt(3), TokenType.LT))) { 6638 _tokenMatches(_peekAt(3), TokenType.LT))) {
7059 return parseReturnType(); 6639 return parseReturnType();
7060 } 6640 }
7061 return null; 6641 return null;
7062 } 6642 }
7063 6643
7064 /** 6644 /**
7065 * Parse a part or part-of directive. 6645 * Parse a part or part-of directive. The [commentAndMetadata] is the metadata
6646 * to be associated with the directive. Return the part or part-of directive
6647 * that was parsed.
7066 * 6648 *
7067 * <pre> 6649 * partDirective ::=
7068 * partDirective ::= 6650 * metadata 'part' stringLiteral ';'
7069 * metadata 'part' stringLiteral ';'
7070 * 6651 *
7071 * partOfDirective ::= 6652 * partOfDirective ::=
7072 * metadata 'part' 'of' identifier ';' 6653 * metadata 'part' 'of' identifier ';'
7073 * </pre>
7074 *
7075 * @param commentAndMetadata the metadata to be associated with the directive
7076 * @return the part or part-of directive that was parsed
7077 */ 6654 */
7078 Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) { 6655 Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) {
7079 Token partKeyword = _expectKeyword(Keyword.PART); 6656 Token partKeyword = _expectKeyword(Keyword.PART);
7080 if (_matchesString(_OF)) { 6657 if (_matchesString(_OF)) {
7081 Token ofKeyword = getAndAdvance(); 6658 Token ofKeyword = getAndAdvance();
7082 LibraryIdentifier libraryName = _parseLibraryName( 6659 LibraryIdentifier libraryName = _parseLibraryName(
7083 ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword); 6660 ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
7084 Token semicolon = _expect(TokenType.SEMICOLON); 6661 Token semicolon = _expect(TokenType.SEMICOLON);
7085 return new PartOfDirective(commentAndMetadata.comment, 6662 return new PartOfDirective(commentAndMetadata.comment,
7086 commentAndMetadata.metadata, partKeyword, ofKeyword, libraryName, 6663 commentAndMetadata.metadata, partKeyword, ofKeyword, libraryName,
7087 semicolon); 6664 semicolon);
7088 } 6665 }
7089 StringLiteral partUri = _parseUri(); 6666 StringLiteral partUri = _parseUri();
7090 Token semicolon = _expect(TokenType.SEMICOLON); 6667 Token semicolon = _expect(TokenType.SEMICOLON);
7091 return new PartDirective(commentAndMetadata.comment, 6668 return new PartDirective(commentAndMetadata.comment,
7092 commentAndMetadata.metadata, partKeyword, partUri, semicolon); 6669 commentAndMetadata.metadata, partKeyword, partUri, semicolon);
7093 } 6670 }
7094 6671
7095 /** 6672 /**
7096 * Parse a postfix expression. 6673 * Parse a postfix expression. Return the postfix expression that was parsed.
7097 * 6674 *
7098 * <pre> 6675 * postfixExpression ::=
7099 * postfixExpression ::= 6676 * assignableExpression postfixOperator
7100 * assignableExpression postfixOperator 6677 * | primary selector*
7101 * | primary selector*
7102 * 6678 *
7103 * selector ::= 6679 * selector ::=
7104 * assignableSelector 6680 * assignableSelector
7105 * | argumentList 6681 * | argumentList
7106 * </pre>
7107 *
7108 * @return the postfix expression that was parsed
7109 */ 6682 */
7110 Expression _parsePostfixExpression() { 6683 Expression _parsePostfixExpression() {
7111 Expression operand = _parseAssignableExpression(true); 6684 Expression operand = _parseAssignableExpression(true);
7112 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || 6685 if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
7113 _matches(TokenType.PERIOD) || 6686 _matches(TokenType.PERIOD) ||
7114 _matches(TokenType.OPEN_PAREN)) { 6687 _matches(TokenType.OPEN_PAREN)) {
7115 do { 6688 do {
7116 if (_matches(TokenType.OPEN_PAREN)) { 6689 if (_matches(TokenType.OPEN_PAREN)) {
7117 ArgumentList argumentList = parseArgumentList(); 6690 ArgumentList argumentList = parseArgumentList();
7118 if (operand is PropertyAccess) { 6691 if (operand is PropertyAccess) {
(...skipping 13 matching lines...) Expand all
7132 } 6705 }
7133 if (!_currentToken.type.isIncrementOperator) { 6706 if (!_currentToken.type.isIncrementOperator) {
7134 return operand; 6707 return operand;
7135 } 6708 }
7136 _ensureAssignable(operand); 6709 _ensureAssignable(operand);
7137 Token operator = getAndAdvance(); 6710 Token operator = getAndAdvance();
7138 return new PostfixExpression(operand, operator); 6711 return new PostfixExpression(operand, operator);
7139 } 6712 }
7140 6713
7141 /** 6714 /**
7142 * Parse a primary expression. 6715 * Parse a primary expression. Return the primary expression that was parsed.
7143 * 6716 *
7144 * <pre> 6717 * primary ::=
7145 * primary ::= 6718 * thisExpression
7146 * thisExpression 6719 * | 'super' assignableSelector
7147 * | 'super' assignableSelector 6720 * | functionExpression
7148 * | functionExpression 6721 * | literal
7149 * | literal 6722 * | identifier
7150 * | identifier 6723 * | newExpression
7151 * | newExpression 6724 * | constObjectExpression
7152 * | constObjectExpression 6725 * | '(' expression ')'
7153 * | '(' expression ')' 6726 * | argumentDefinitionTest
7154 * | argumentDefinitionTest
7155 * 6727 *
7156 * literal ::= 6728 * literal ::=
7157 * nullLiteral 6729 * nullLiteral
7158 * | booleanLiteral 6730 * | booleanLiteral
7159 * | numericLiteral 6731 * | numericLiteral
7160 * | stringLiteral 6732 * | stringLiteral
7161 * | symbolLiteral 6733 * | symbolLiteral
7162 * | mapLiteral 6734 * | mapLiteral
7163 * | listLiteral 6735 * | listLiteral
7164 * </pre>
7165 *
7166 * @return the primary expression that was parsed
7167 */ 6736 */
7168 Expression _parsePrimaryExpression() { 6737 Expression _parsePrimaryExpression() {
7169 if (_matchesKeyword(Keyword.THIS)) { 6738 if (_matchesKeyword(Keyword.THIS)) {
7170 return new ThisExpression(getAndAdvance()); 6739 return new ThisExpression(getAndAdvance());
7171 } else if (_matchesKeyword(Keyword.SUPER)) { 6740 } else if (_matchesKeyword(Keyword.SUPER)) {
7172 return _parseAssignableSelector( 6741 return _parseAssignableSelector(
7173 new SuperExpression(getAndAdvance()), false); 6742 new SuperExpression(getAndAdvance()), false);
7174 } else if (_matchesKeyword(Keyword.NULL)) { 6743 } else if (_matchesKeyword(Keyword.NULL)) {
7175 return new NullLiteral(getAndAdvance()); 6744 return new NullLiteral(getAndAdvance());
7176 } else if (_matchesKeyword(Keyword.FALSE)) { 6745 } else if (_matchesKeyword(Keyword.FALSE)) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
7263 return _parsePrimaryExpression(); 6832 return _parsePrimaryExpression();
7264 } else if (_matches(TokenType.HASH)) { 6833 } else if (_matches(TokenType.HASH)) {
7265 return _parseSymbolLiteral(); 6834 return _parseSymbolLiteral();
7266 } else { 6835 } else {
7267 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER); 6836 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7268 return _createSyntheticIdentifier(); 6837 return _createSyntheticIdentifier();
7269 } 6838 }
7270 } 6839 }
7271 6840
7272 /** 6841 /**
7273 * Parse a redirecting constructor invocation. 6842 * Parse a redirecting constructor invocation. Return the redirecting
6843 * constructor invocation that was parsed.
7274 * 6844 *
7275 * <pre> 6845 * redirectingConstructorInvocation ::=
7276 * redirectingConstructorInvocation ::= 6846 * 'this' ('.' identifier)? arguments
7277 * 'this' ('.' identifier)? arguments
7278 * </pre>
7279 *
7280 * @return the redirecting constructor invocation that was parsed
7281 */ 6847 */
7282 RedirectingConstructorInvocation _parseRedirectingConstructorInvocation() { 6848 RedirectingConstructorInvocation _parseRedirectingConstructorInvocation() {
7283 Token keyword = _expectKeyword(Keyword.THIS); 6849 Token keyword = _expectKeyword(Keyword.THIS);
7284 Token period = null; 6850 Token period = null;
7285 SimpleIdentifier constructorName = null; 6851 SimpleIdentifier constructorName = null;
7286 if (_matches(TokenType.PERIOD)) { 6852 if (_matches(TokenType.PERIOD)) {
7287 period = getAndAdvance(); 6853 period = getAndAdvance();
7288 constructorName = parseSimpleIdentifier(); 6854 constructorName = parseSimpleIdentifier();
7289 } 6855 }
7290 ArgumentList argumentList = parseArgumentList(); 6856 ArgumentList argumentList = parseArgumentList();
7291 return new RedirectingConstructorInvocation( 6857 return new RedirectingConstructorInvocation(
7292 keyword, period, constructorName, argumentList); 6858 keyword, period, constructorName, argumentList);
7293 } 6859 }
7294 6860
7295 /** 6861 /**
7296 * Parse a relational expression. 6862 * Parse a relational expression. Return the relational expression that was
6863 * parsed.
7297 * 6864 *
7298 * <pre> 6865 * relationalExpression ::=
7299 * relationalExpression ::= 6866 * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperato r bitwiseOrExpression)?
7300 * bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bi twiseOrExpression)? 6867 * | 'super' relationalOperator bitwiseOrExpression
7301 * | 'super' relationalOperator bitwiseOrExpression
7302 * </pre>
7303 *
7304 * @return the relational expression that was parsed
7305 */ 6868 */
7306 Expression _parseRelationalExpression() { 6869 Expression _parseRelationalExpression() {
7307 if (_matchesKeyword(Keyword.SUPER) && 6870 if (_matchesKeyword(Keyword.SUPER) &&
7308 _currentToken.next.type.isRelationalOperator) { 6871 _currentToken.next.type.isRelationalOperator) {
7309 Expression expression = new SuperExpression(getAndAdvance()); 6872 Expression expression = new SuperExpression(getAndAdvance());
7310 Token operator = getAndAdvance(); 6873 Token operator = getAndAdvance();
7311 expression = new BinaryExpression( 6874 expression = new BinaryExpression(
7312 expression, operator, parseBitwiseOrExpression()); 6875 expression, operator, parseBitwiseOrExpression());
7313 return expression; 6876 return expression;
7314 } 6877 }
(...skipping 11 matching lines...) Expand all
7326 expression, isOperator, notOperator, parseTypeName()); 6889 expression, isOperator, notOperator, parseTypeName());
7327 } else if (_currentToken.type.isRelationalOperator) { 6890 } else if (_currentToken.type.isRelationalOperator) {
7328 Token operator = getAndAdvance(); 6891 Token operator = getAndAdvance();
7329 expression = new BinaryExpression( 6892 expression = new BinaryExpression(
7330 expression, operator, parseBitwiseOrExpression()); 6893 expression, operator, parseBitwiseOrExpression());
7331 } 6894 }
7332 return expression; 6895 return expression;
7333 } 6896 }
7334 6897
7335 /** 6898 /**
7336 * Parse a rethrow expression. 6899 * Parse a rethrow expression. Return the rethrow expression that was parsed.
7337 * 6900 *
7338 * <pre> 6901 * rethrowExpression ::=
7339 * rethrowExpression ::= 6902 * 'rethrow'
7340 * 'rethrow'
7341 * </pre>
7342 *
7343 * @return the rethrow expression that was parsed
7344 */ 6903 */
7345 Expression _parseRethrowExpression() => 6904 Expression _parseRethrowExpression() =>
7346 new RethrowExpression(_expectKeyword(Keyword.RETHROW)); 6905 new RethrowExpression(_expectKeyword(Keyword.RETHROW));
7347 6906
7348 /** 6907 /**
7349 * Parse a return statement. 6908 * Parse a return statement. Return the return statement that was parsed.
7350 * 6909 *
7351 * <pre> 6910 * returnStatement ::=
7352 * returnStatement ::= 6911 * 'return' expression? ';'
7353 * 'return' expression? ';'
7354 * </pre>
7355 *
7356 * @return the return statement that was parsed
7357 */ 6912 */
7358 Statement _parseReturnStatement() { 6913 Statement _parseReturnStatement() {
7359 Token returnKeyword = _expectKeyword(Keyword.RETURN); 6914 Token returnKeyword = _expectKeyword(Keyword.RETURN);
7360 if (_matches(TokenType.SEMICOLON)) { 6915 if (_matches(TokenType.SEMICOLON)) {
7361 return new ReturnStatement(returnKeyword, null, getAndAdvance()); 6916 return new ReturnStatement(returnKeyword, null, getAndAdvance());
7362 } 6917 }
7363 Expression expression = parseExpression2(); 6918 Expression expression = parseExpression2();
7364 Token semicolon = _expect(TokenType.SEMICOLON); 6919 Token semicolon = _expect(TokenType.SEMICOLON);
7365 return new ReturnStatement(returnKeyword, expression, semicolon); 6920 return new ReturnStatement(returnKeyword, expression, semicolon);
7366 } 6921 }
7367 6922
7368 /** 6923 /**
7369 * Parse a setter. 6924 * Parse a setter. The [commentAndMetadata] is the documentation comment and
6925 * metadata to be associated with the declaration. The [externalKeyword] is
6926 * the 'external' token. The [staticKeyword] is the static keyword, or `null`
6927 * if the setter is not static. The [returnType] is the return type that has
6928 * already been parsed, or `null` if there was no return type. Return the
6929 * setter that was parsed.
7370 * 6930 *
7371 * <pre> 6931 * setter ::=
7372 * setter ::= 6932 * setterSignature functionBody?
7373 * setterSignature functionBody?
7374 * 6933 *
7375 * setterSignature ::= 6934 * setterSignature ::=
7376 * 'external'? 'static'? returnType? 'set' identifier formalParameterList 6935 * 'external'? 'static'? returnType? 'set' identifier formalParameterL ist
7377 * </pre>
7378 *
7379 * @param commentAndMetadata the documentation comment and metadata to be asso ciated with the
7380 * declaration
7381 * @param externalKeyword the 'external' token
7382 * @param staticKeyword the static keyword, or `null` if the setter is not sta tic
7383 * @param the return type that has already been parsed, or `null` if there was no return
7384 * type
7385 * @return the setter that was parsed
7386 */ 6936 */
7387 MethodDeclaration _parseSetter(CommentAndMetadata commentAndMetadata, 6937 MethodDeclaration _parseSetter(CommentAndMetadata commentAndMetadata,
7388 Token externalKeyword, Token staticKeyword, TypeName returnType) { 6938 Token externalKeyword, Token staticKeyword, TypeName returnType) {
7389 Token propertyKeyword = _expectKeyword(Keyword.SET); 6939 Token propertyKeyword = _expectKeyword(Keyword.SET);
7390 SimpleIdentifier name = parseSimpleIdentifier(); 6940 SimpleIdentifier name = parseSimpleIdentifier();
7391 FormalParameterList parameters = parseFormalParameterList(); 6941 FormalParameterList parameters = parseFormalParameterList();
7392 _validateFormalParameterList(parameters); 6942 _validateFormalParameterList(parameters);
7393 FunctionBody body = _parseFunctionBody( 6943 FunctionBody body = _parseFunctionBody(
7394 externalKeyword != null || staticKeyword == null, 6944 externalKeyword != null || staticKeyword == null,
7395 ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false); 6945 ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false);
7396 if (externalKeyword != null && body is! EmptyFunctionBody) { 6946 if (externalKeyword != null && body is! EmptyFunctionBody) {
7397 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY); 6947 _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
7398 } 6948 }
7399 return new MethodDeclaration(commentAndMetadata.comment, 6949 return new MethodDeclaration(commentAndMetadata.comment,
7400 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType, 6950 commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
7401 propertyKeyword, null, name, parameters, body); 6951 propertyKeyword, null, name, parameters, body);
7402 } 6952 }
7403 6953
7404 /** 6954 /**
7405 * Parse a shift expression. 6955 * Parse a shift expression. Return the shift expression that was parsed.
7406 * 6956 *
7407 * <pre> 6957 * shiftExpression ::=
7408 * shiftExpression ::= 6958 * additiveExpression (shiftOperator additiveExpression)*
7409 * additiveExpression (shiftOperator additiveExpression)* 6959 * | 'super' (shiftOperator additiveExpression)+
7410 * | 'super' (shiftOperator additiveExpression)+
7411 * </pre>
7412 *
7413 * @return the shift expression that was parsed
7414 */ 6960 */
7415 Expression _parseShiftExpression() { 6961 Expression _parseShiftExpression() {
7416 Expression expression; 6962 Expression expression;
7417 if (_matchesKeyword(Keyword.SUPER) && 6963 if (_matchesKeyword(Keyword.SUPER) &&
7418 _currentToken.next.type.isShiftOperator) { 6964 _currentToken.next.type.isShiftOperator) {
7419 expression = new SuperExpression(getAndAdvance()); 6965 expression = new SuperExpression(getAndAdvance());
7420 } else { 6966 } else {
7421 expression = _parseAdditiveExpression(); 6967 expression = _parseAdditiveExpression();
7422 } 6968 }
7423 while (_currentToken.type.isShiftOperator) { 6969 while (_currentToken.type.isShiftOperator) {
7424 Token operator = getAndAdvance(); 6970 Token operator = getAndAdvance();
7425 expression = new BinaryExpression( 6971 expression = new BinaryExpression(
7426 expression, operator, _parseAdditiveExpression()); 6972 expression, operator, _parseAdditiveExpression());
7427 } 6973 }
7428 return expression; 6974 return expression;
7429 } 6975 }
7430 6976
7431 /** 6977 /**
7432 * Parse a list of statements within a switch statement. 6978 * Parse a list of statements within a switch statement. Return the statements
6979 * that were parsed.
7433 * 6980 *
7434 * <pre> 6981 * statements ::=
7435 * statements ::= 6982 * statement*
7436 * statement*
7437 * </pre>
7438 *
7439 * @return the statements that were parsed
7440 */ 6983 */
7441 List<Statement> _parseStatementList() { 6984 List<Statement> _parseStatementList() {
7442 List<Statement> statements = new List<Statement>(); 6985 List<Statement> statements = new List<Statement>();
7443 Token statementStart = _currentToken; 6986 Token statementStart = _currentToken;
7444 while (!_matches(TokenType.EOF) && 6987 while (!_matches(TokenType.EOF) &&
7445 !_matches(TokenType.CLOSE_CURLY_BRACKET) && 6988 !_matches(TokenType.CLOSE_CURLY_BRACKET) &&
7446 !_isSwitchMember()) { 6989 !_isSwitchMember()) {
7447 statements.add(parseStatement2()); 6990 statements.add(parseStatement2());
7448 if (identical(_currentToken, statementStart)) { 6991 if (identical(_currentToken, statementStart)) {
7449 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [ 6992 _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken, [
7450 _currentToken.lexeme 6993 _currentToken.lexeme
7451 ]); 6994 ]);
7452 _advance(); 6995 _advance();
7453 } 6996 }
7454 statementStart = _currentToken; 6997 statementStart = _currentToken;
7455 } 6998 }
7456 return statements; 6999 return statements;
7457 } 7000 }
7458 7001
7459 /** 7002 /**
7460 * Parse a string literal that contains interpolations. 7003 * Parse a string literal that contains interpolations. Return the string
7461 * 7004 * literal that was parsed.
7462 * @return the string literal that was parsed
7463 */ 7005 */
7464 StringInterpolation _parseStringInterpolation(Token string) { 7006 StringInterpolation _parseStringInterpolation(Token string) {
7465 List<InterpolationElement> elements = new List<InterpolationElement>(); 7007 List<InterpolationElement> elements = new List<InterpolationElement>();
7466 bool hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) || 7008 bool hasMore = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
7467 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER); 7009 _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
7468 elements.add(new InterpolationString( 7010 elements.add(new InterpolationString(
7469 string, _computeStringValue(string.lexeme, true, !hasMore))); 7011 string, _computeStringValue(string.lexeme, true, !hasMore)));
7470 while (hasMore) { 7012 while (hasMore) {
7471 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION)) { 7013 if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION)) {
7472 Token openToken = getAndAdvance(); 7014 Token openToken = getAndAdvance();
(...skipping 24 matching lines...) Expand all
7497 elements.add(new InterpolationString( 7039 elements.add(new InterpolationString(
7498 string, _computeStringValue(string.lexeme, false, !hasMore))); 7040 string, _computeStringValue(string.lexeme, false, !hasMore)));
7499 } else { 7041 } else {
7500 hasMore = false; 7042 hasMore = false;
7501 } 7043 }
7502 } 7044 }
7503 return new StringInterpolation(elements); 7045 return new StringInterpolation(elements);
7504 } 7046 }
7505 7047
7506 /** 7048 /**
7507 * Parse a super constructor invocation. 7049 * Parse a super constructor invocation. Return the super constructor
7050 * invocation that was parsed.
7508 * 7051 *
7509 * <pre> 7052 * superConstructorInvocation ::=
7510 * superConstructorInvocation ::= 7053 * 'super' ('.' identifier)? arguments
7511 * 'super' ('.' identifier)? arguments
7512 * </pre>
7513 *
7514 * @return the super constructor invocation that was parsed
7515 */ 7054 */
7516 SuperConstructorInvocation _parseSuperConstructorInvocation() { 7055 SuperConstructorInvocation _parseSuperConstructorInvocation() {
7517 Token keyword = _expectKeyword(Keyword.SUPER); 7056 Token keyword = _expectKeyword(Keyword.SUPER);
7518 Token period = null; 7057 Token period = null;
7519 SimpleIdentifier constructorName = null; 7058 SimpleIdentifier constructorName = null;
7520 if (_matches(TokenType.PERIOD)) { 7059 if (_matches(TokenType.PERIOD)) {
7521 period = getAndAdvance(); 7060 period = getAndAdvance();
7522 constructorName = parseSimpleIdentifier(); 7061 constructorName = parseSimpleIdentifier();
7523 } 7062 }
7524 ArgumentList argumentList = parseArgumentList(); 7063 ArgumentList argumentList = parseArgumentList();
7525 return new SuperConstructorInvocation( 7064 return new SuperConstructorInvocation(
7526 keyword, period, constructorName, argumentList); 7065 keyword, period, constructorName, argumentList);
7527 } 7066 }
7528 7067
7529 /** 7068 /**
7530 * Parse a switch statement. 7069 * Parse a switch statement. Return the switch statement that was parsed.
7531 * 7070 *
7532 * <pre> 7071 * switchStatement ::=
7533 * switchStatement ::= 7072 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
7534 * 'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
7535 * 7073 *
7536 * switchCase ::= 7074 * switchCase ::=
7537 * label* ('case' expression ':') statements 7075 * label* ('case' expression ':') statements
7538 * 7076 *
7539 * defaultCase ::= 7077 * defaultCase ::=
7540 * label* 'default' ':' statements 7078 * label* 'default' ':' statements
7541 * </pre>
7542 *
7543 * @return the switch statement that was parsed
7544 */ 7079 */
7545 SwitchStatement _parseSwitchStatement() { 7080 SwitchStatement _parseSwitchStatement() {
7546 bool wasInSwitch = _inSwitch; 7081 bool wasInSwitch = _inSwitch;
7547 _inSwitch = true; 7082 _inSwitch = true;
7548 try { 7083 try {
7549 HashSet<String> definedLabels = new HashSet<String>(); 7084 HashSet<String> definedLabels = new HashSet<String>();
7550 Token keyword = _expectKeyword(Keyword.SWITCH); 7085 Token keyword = _expectKeyword(Keyword.SWITCH);
7551 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); 7086 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
7552 Expression expression = parseExpression2(); 7087 Expression expression = parseExpression2();
7553 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); 7088 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
7605 } 7140 }
7606 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET); 7141 Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
7607 return new SwitchStatement(keyword, leftParenthesis, expression, 7142 return new SwitchStatement(keyword, leftParenthesis, expression,
7608 rightParenthesis, leftBracket, members, rightBracket); 7143 rightParenthesis, leftBracket, members, rightBracket);
7609 } finally { 7144 } finally {
7610 _inSwitch = wasInSwitch; 7145 _inSwitch = wasInSwitch;
7611 } 7146 }
7612 } 7147 }
7613 7148
7614 /** 7149 /**
7615 * Parse a symbol literal. 7150 * Parse a symbol literal. Return the symbol literal that was parsed.
7616 * 7151 *
7617 * <pre> 7152 * symbolLiteral ::=
7618 * symbolLiteral ::= 7153 * '#' identifier ('.' identifier)*
7619 * '#' identifier ('.' identifier)*
7620 * </pre>
7621 *
7622 * @return the symbol literal that was parsed
7623 */ 7154 */
7624 SymbolLiteral _parseSymbolLiteral() { 7155 SymbolLiteral _parseSymbolLiteral() {
7625 Token poundSign = getAndAdvance(); 7156 Token poundSign = getAndAdvance();
7626 List<Token> components = new List<Token>(); 7157 List<Token> components = new List<Token>();
7627 if (_matchesIdentifier()) { 7158 if (_matchesIdentifier()) {
7628 components.add(getAndAdvance()); 7159 components.add(getAndAdvance());
7629 while (_matches(TokenType.PERIOD)) { 7160 while (_matches(TokenType.PERIOD)) {
7630 _advance(); 7161 _advance();
7631 if (_matchesIdentifier()) { 7162 if (_matchesIdentifier()) {
7632 components.add(getAndAdvance()); 7163 components.add(getAndAdvance());
7633 } else { 7164 } else {
7634 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER); 7165 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7635 components.add(_createSyntheticToken(TokenType.IDENTIFIER)); 7166 components.add(_createSyntheticToken(TokenType.IDENTIFIER));
7636 break; 7167 break;
7637 } 7168 }
7638 } 7169 }
7639 } else if (_currentToken.isOperator) { 7170 } else if (_currentToken.isOperator) {
7640 components.add(getAndAdvance()); 7171 components.add(getAndAdvance());
7641 } else if (_tokenMatchesKeyword(_currentToken, Keyword.VOID)) { 7172 } else if (_tokenMatchesKeyword(_currentToken, Keyword.VOID)) {
7642 components.add(getAndAdvance()); 7173 components.add(getAndAdvance());
7643 } else { 7174 } else {
7644 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER); 7175 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7645 components.add(_createSyntheticToken(TokenType.IDENTIFIER)); 7176 components.add(_createSyntheticToken(TokenType.IDENTIFIER));
7646 } 7177 }
7647 return new SymbolLiteral(poundSign, components); 7178 return new SymbolLiteral(poundSign, components);
7648 } 7179 }
7649 7180
7650 /** 7181 /**
7651 * Parse a throw expression. 7182 * Parse a throw expression. Return the throw expression that was parsed.
7652 * 7183 *
7653 * <pre> 7184 * throwExpression ::=
7654 * throwExpression ::= 7185 * 'throw' expression
7655 * 'throw' expression
7656 * </pre>
7657 *
7658 * @return the throw expression that was parsed
7659 */ 7186 */
7660 Expression _parseThrowExpression() { 7187 Expression _parseThrowExpression() {
7661 Token keyword = _expectKeyword(Keyword.THROW); 7188 Token keyword = _expectKeyword(Keyword.THROW);
7662 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) { 7189 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) {
7663 _reportErrorForToken( 7190 _reportErrorForToken(
7664 ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken); 7191 ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
7665 return new ThrowExpression(keyword, _createSyntheticIdentifier()); 7192 return new ThrowExpression(keyword, _createSyntheticIdentifier());
7666 } 7193 }
7667 Expression expression = parseExpression2(); 7194 Expression expression = parseExpression2();
7668 return new ThrowExpression(keyword, expression); 7195 return new ThrowExpression(keyword, expression);
7669 } 7196 }
7670 7197
7671 /** 7198 /**
7672 * Parse a throw expression. 7199 * Parse a throw expression. Return the throw expression that was parsed.
7673 * 7200 *
7674 * <pre> 7201 * throwExpressionWithoutCascade ::=
7675 * throwExpressionWithoutCascade ::= 7202 * 'throw' expressionWithoutCascade
7676 * 'throw' expressionWithoutCascade
7677 * </pre>
7678 *
7679 * @return the throw expression that was parsed
7680 */ 7203 */
7681 Expression _parseThrowExpressionWithoutCascade() { 7204 Expression _parseThrowExpressionWithoutCascade() {
7682 Token keyword = _expectKeyword(Keyword.THROW); 7205 Token keyword = _expectKeyword(Keyword.THROW);
7683 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) { 7206 if (_matches(TokenType.SEMICOLON) || _matches(TokenType.CLOSE_PAREN)) {
7684 _reportErrorForToken( 7207 _reportErrorForToken(
7685 ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken); 7208 ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
7686 return new ThrowExpression(keyword, _createSyntheticIdentifier()); 7209 return new ThrowExpression(keyword, _createSyntheticIdentifier());
7687 } 7210 }
7688 Expression expression = parseExpressionWithoutCascade(); 7211 Expression expression = parseExpressionWithoutCascade();
7689 return new ThrowExpression(keyword, expression); 7212 return new ThrowExpression(keyword, expression);
7690 } 7213 }
7691 7214
7692 /** 7215 /**
7693 * Parse a try statement. 7216 * Parse a try statement. Return the try statement that was parsed.
7694 * 7217 *
7695 * <pre> 7218 * tryStatement ::=
7696 * tryStatement ::= 7219 * 'try' block (onPart+ finallyPart? | finallyPart)
7697 * 'try' block (onPart+ finallyPart? | finallyPart)
7698 * 7220 *
7699 * onPart ::= 7221 * onPart ::=
7700 * catchPart block 7222 * catchPart block
7701 * | 'on' type catchPart? block 7223 * | 'on' type catchPart? block
7702 * 7224 *
7703 * catchPart ::= 7225 * catchPart ::=
7704 * 'catch' '(' identifier (',' identifier)? ')' 7226 * 'catch' '(' identifier (',' identifier)? ')'
7705 * 7227 *
7706 * finallyPart ::= 7228 * finallyPart ::=
7707 * 'finally' block 7229 * 'finally' block
7708 * </pre>
7709 *
7710 * @return the try statement that was parsed
7711 */ 7230 */
7712 Statement _parseTryStatement() { 7231 Statement _parseTryStatement() {
7713 Token tryKeyword = _expectKeyword(Keyword.TRY); 7232 Token tryKeyword = _expectKeyword(Keyword.TRY);
7714 Block body = parseBlock(); 7233 Block body = parseBlock();
7715 List<CatchClause> catchClauses = new List<CatchClause>(); 7234 List<CatchClause> catchClauses = new List<CatchClause>();
7716 Block finallyClause = null; 7235 Block finallyClause = null;
7717 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) { 7236 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) {
7718 Token onKeyword = null; 7237 Token onKeyword = null;
7719 TypeName exceptionType = null; 7238 TypeName exceptionType = null;
7720 if (_matchesString(_ON)) { 7239 if (_matchesString(_ON)) {
(...skipping 28 matching lines...) Expand all
7749 } else { 7268 } else {
7750 if (catchClauses.isEmpty) { 7269 if (catchClauses.isEmpty) {
7751 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY); 7270 _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY);
7752 } 7271 }
7753 } 7272 }
7754 return new TryStatement( 7273 return new TryStatement(
7755 tryKeyword, body, catchClauses, finallyKeyword, finallyClause); 7274 tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
7756 } 7275 }
7757 7276
7758 /** 7277 /**
7759 * Parse a type alias. 7278 * Parse a type alias. The [commentAndMetadata] is the metadata to be
7279 * associated with the member. Return the type alias that was parsed.
7760 * 7280 *
7761 * <pre> 7281 * typeAlias ::=
7762 * typeAlias ::= 7282 * 'typedef' typeAliasBody
7763 * 'typedef' typeAliasBody
7764 * 7283 *
7765 * typeAliasBody ::= 7284 * typeAliasBody ::=
7766 * classTypeAlias 7285 * classTypeAlias
7767 * | functionTypeAlias 7286 * | functionTypeAlias
7768 * 7287 *
7769 * classTypeAlias ::= 7288 * classTypeAlias ::=
7770 * identifier typeParameters? '=' 'abstract'? mixinApplication 7289 * identifier typeParameters? '=' 'abstract'? mixinApplication
7771 * 7290 *
7772 * mixinApplication ::= 7291 * mixinApplication ::=
7773 * qualified withClause implementsClause? ';' 7292 * qualified withClause implementsClause? ';'
7774 * 7293 *
7775 * functionTypeAlias ::= 7294 * functionTypeAlias ::=
7776 * functionPrefix typeParameterList? formalParameterList ';' 7295 * functionPrefix typeParameterList? formalParameterList ';'
7777 * 7296 *
7778 * functionPrefix ::= 7297 * functionPrefix ::=
7779 * returnType? name 7298 * returnType? name
7780 * </pre>
7781 *
7782 * @param commentAndMetadata the metadata to be associated with the member
7783 * @return the type alias that was parsed
7784 */ 7299 */
7785 TypeAlias _parseTypeAlias(CommentAndMetadata commentAndMetadata) { 7300 TypeAlias _parseTypeAlias(CommentAndMetadata commentAndMetadata) {
7786 Token keyword = _expectKeyword(Keyword.TYPEDEF); 7301 Token keyword = _expectKeyword(Keyword.TYPEDEF);
7787 if (_matchesIdentifier()) { 7302 if (_matchesIdentifier()) {
7788 Token next = _peek(); 7303 Token next = _peek();
7789 if (_tokenMatches(next, TokenType.LT)) { 7304 if (_tokenMatches(next, TokenType.LT)) {
7790 next = _skipTypeParameterList(next); 7305 next = _skipTypeParameterList(next);
7791 if (next != null && _tokenMatches(next, TokenType.EQ)) { 7306 if (next != null && _tokenMatches(next, TokenType.EQ)) {
7792 TypeAlias typeAlias = 7307 TypeAlias typeAlias =
7793 _parseClassTypeAlias(commentAndMetadata, null, keyword); 7308 _parseClassTypeAlias(commentAndMetadata, null, keyword);
7794 _reportErrorForToken( 7309 _reportErrorForToken(
7795 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); 7310 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword);
7796 return typeAlias; 7311 return typeAlias;
7797 } 7312 }
7798 } else if (_tokenMatches(next, TokenType.EQ)) { 7313 } else if (_tokenMatches(next, TokenType.EQ)) {
7799 TypeAlias typeAlias = 7314 TypeAlias typeAlias =
7800 _parseClassTypeAlias(commentAndMetadata, null, keyword); 7315 _parseClassTypeAlias(commentAndMetadata, null, keyword);
7801 _reportErrorForToken( 7316 _reportErrorForToken(
7802 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); 7317 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword);
7803 return typeAlias; 7318 return typeAlias;
7804 } 7319 }
7805 } 7320 }
7806 return _parseFunctionTypeAlias(commentAndMetadata, keyword); 7321 return _parseFunctionTypeAlias(commentAndMetadata, keyword);
7807 } 7322 }
7808 7323
7809 /** 7324 /**
7810 * Parse a unary expression. 7325 * Parse a unary expression. Return the unary expression that was parsed.
7811 * 7326 *
7812 * <pre> 7327 * unaryExpression ::=
7813 * unaryExpression ::= 7328 * prefixOperator unaryExpression
7814 * prefixOperator unaryExpression 7329 * | awaitExpression
7815 * | awaitExpression 7330 * | postfixExpression
7816 * | postfixExpression 7331 * | unaryOperator 'super'
7817 * | unaryOperator 'super' 7332 * | '-' 'super'
7818 * | '-' 'super' 7333 * | incrementOperator assignableExpression
7819 * | incrementOperator assignableExpression
7820 * </pre>
7821 *
7822 * @return the unary expression that was parsed
7823 */ 7334 */
7824 Expression _parseUnaryExpression() { 7335 Expression _parseUnaryExpression() {
7825 if (_matches(TokenType.MINUS) || 7336 if (_matches(TokenType.MINUS) ||
7826 _matches(TokenType.BANG) || 7337 _matches(TokenType.BANG) ||
7827 _matches(TokenType.TILDE)) { 7338 _matches(TokenType.TILDE)) {
7828 Token operator = getAndAdvance(); 7339 Token operator = getAndAdvance();
7829 if (_matchesKeyword(Keyword.SUPER)) { 7340 if (_matchesKeyword(Keyword.SUPER)) {
7830 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) || 7341 if (_tokenMatches(_peek(), TokenType.OPEN_SQUARE_BRACKET) ||
7831 _tokenMatches(_peek(), TokenType.PERIOD)) { 7342 _tokenMatches(_peek(), TokenType.PERIOD)) {
7832 // "prefixOperator unaryExpression" 7343 // "prefixOperator unaryExpression"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
7875 } else if (_matches(TokenType.PLUS)) { 7386 } else if (_matches(TokenType.PLUS)) {
7876 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER); 7387 _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
7877 return _createSyntheticIdentifier(); 7388 return _createSyntheticIdentifier();
7878 } else if (_inAsync && _matchesString(_AWAIT)) { 7389 } else if (_inAsync && _matchesString(_AWAIT)) {
7879 return _parseAwaitExpression(); 7390 return _parseAwaitExpression();
7880 } 7391 }
7881 return _parsePostfixExpression(); 7392 return _parsePostfixExpression();
7882 } 7393 }
7883 7394
7884 /** 7395 /**
7885 * Parse a string literal representing a URI. 7396 * Parse a string literal representing a URI. Return the string literal that
7397 * was parsed.
7886 */ 7398 */
7887 StringLiteral _parseUri() { 7399 StringLiteral _parseUri() {
7888 bool iskeywordAfterUri(Token token) => token.lexeme == Keyword.AS.syntax || 7400 bool iskeywordAfterUri(Token token) => token.lexeme == Keyword.AS.syntax ||
7889 token.lexeme == _HIDE || 7401 token.lexeme == _HIDE ||
7890 token.lexeme == _SHOW; 7402 token.lexeme == _SHOW;
7891 if (!_matches(TokenType.STRING) && 7403 if (!_matches(TokenType.STRING) &&
7892 !_matches(TokenType.SEMICOLON) && 7404 !_matches(TokenType.SEMICOLON) &&
7893 !iskeywordAfterUri(_currentToken)) { 7405 !iskeywordAfterUri(_currentToken)) {
7894 // Attempt to recover in the case where the URI was not enclosed in 7406 // Attempt to recover in the case where the URI was not enclosed in
7895 // quotes. 7407 // quotes.
(...skipping 29 matching lines...) Expand all
7925 _reportErrorForToken( 7437 _reportErrorForToken(
7926 ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken); 7438 ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken);
7927 _currentToken = endToken.next; 7439 _currentToken = endToken.next;
7928 return new SimpleStringLiteral(newToken, value); 7440 return new SimpleStringLiteral(newToken, value);
7929 } 7441 }
7930 } 7442 }
7931 return parseStringLiteral(); 7443 return parseStringLiteral();
7932 } 7444 }
7933 7445
7934 /** 7446 /**
7935 * Parse a variable declaration. 7447 * Parse a variable declaration. Return the variable declaration that was
7448 * parsed.
7936 * 7449 *
7937 * <pre> 7450 * variableDeclaration ::=
7938 * variableDeclaration ::= 7451 * identifier ('=' expression)?
7939 * identifier ('=' expression)?
7940 * </pre>
7941 *
7942 * @return the variable declaration that was parsed
7943 */ 7452 */
7944 VariableDeclaration _parseVariableDeclaration() { 7453 VariableDeclaration _parseVariableDeclaration() {
7945 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); 7454 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata();
7946 SimpleIdentifier name = parseSimpleIdentifier(); 7455 SimpleIdentifier name = parseSimpleIdentifier();
7947 Token equals = null; 7456 Token equals = null;
7948 Expression initializer = null; 7457 Expression initializer = null;
7949 if (_matches(TokenType.EQ)) { 7458 if (_matches(TokenType.EQ)) {
7950 equals = getAndAdvance(); 7459 equals = getAndAdvance();
7951 initializer = parseExpression2(); 7460 initializer = parseExpression2();
7952 } 7461 }
7953 return new VariableDeclaration(commentAndMetadata.comment, 7462 return new VariableDeclaration(commentAndMetadata.comment,
7954 commentAndMetadata.metadata, name, equals, initializer); 7463 commentAndMetadata.metadata, name, equals, initializer);
7955 } 7464 }
7956 7465
7957 /** 7466 /**
7958 * Parse a variable declaration list. 7467 * Parse a variable declaration list. The [commentAndMetadata] is the metadata
7468 * to be associated with the variable declaration list. Return the variable
7469 * declaration list that was parsed.
7959 * 7470 *
7960 * <pre> 7471 * variableDeclarationList ::=
7961 * variableDeclarationList ::= 7472 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
7962 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
7963 * </pre>
7964 *
7965 * @param commentAndMetadata the metadata to be associated with the variable d eclaration list
7966 * @return the variable declaration list that was parsed
7967 */ 7473 */
7968 VariableDeclarationList _parseVariableDeclarationListAfterMetadata( 7474 VariableDeclarationList _parseVariableDeclarationListAfterMetadata(
7969 CommentAndMetadata commentAndMetadata) { 7475 CommentAndMetadata commentAndMetadata) {
7970 FinalConstVarOrType holder = _parseFinalConstVarOrType(false); 7476 FinalConstVarOrType holder = _parseFinalConstVarOrType(false);
7971 return _parseVariableDeclarationListAfterType( 7477 return _parseVariableDeclarationListAfterType(
7972 commentAndMetadata, holder.keyword, holder.type); 7478 commentAndMetadata, holder.keyword, holder.type);
7973 } 7479 }
7974 7480
7975 /** 7481 /**
7976 * Parse a variable declaration list. 7482 * Parse a variable declaration list. The [commentAndMetadata] is the metadata
7483 * to be associated with the variable declaration list, or `null` if there is
7484 * no attempt at parsing the comment and metadata. The [keyword] is the token
7485 * representing the 'final', 'const' or 'var' keyword, or `null` if there is
7486 * no keyword. The [type] is the type of the variables in the list. Return the
7487 * variable declaration list that was parsed.
7977 * 7488 *
7978 * <pre> 7489 * variableDeclarationList ::=
7979 * variableDeclarationList ::= 7490 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
7980 * finalConstVarOrType variableDeclaration (',' variableDeclaration)*
7981 * </pre>
7982 *
7983 * @param commentAndMetadata the metadata to be associated with the variable d eclaration list, or
7984 * `null` if there is no attempt at parsing the comment and metadata
7985 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
7986 * there is no keyword
7987 * @param type the type of the variables in the list
7988 * @return the variable declaration list that was parsed
7989 */ 7491 */
7990 VariableDeclarationList _parseVariableDeclarationListAfterType( 7492 VariableDeclarationList _parseVariableDeclarationListAfterType(
7991 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) { 7493 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
7992 if (type != null && 7494 if (type != null &&
7993 keyword != null && 7495 keyword != null &&
7994 _tokenMatchesKeyword(keyword, Keyword.VAR)) { 7496 _tokenMatchesKeyword(keyword, Keyword.VAR)) {
7995 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword); 7497 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword);
7996 } 7498 }
7997 List<VariableDeclaration> variables = new List<VariableDeclaration>(); 7499 List<VariableDeclaration> variables = new List<VariableDeclaration>();
7998 variables.add(_parseVariableDeclaration()); 7500 variables.add(_parseVariableDeclaration());
7999 while (_matches(TokenType.COMMA)) { 7501 while (_matches(TokenType.COMMA)) {
8000 _advance(); 7502 _advance();
8001 variables.add(_parseVariableDeclaration()); 7503 variables.add(_parseVariableDeclaration());
8002 } 7504 }
8003 return new VariableDeclarationList( 7505 return new VariableDeclarationList(
8004 commentAndMetadata != null ? commentAndMetadata.comment : null, 7506 commentAndMetadata != null ? commentAndMetadata.comment : null,
8005 commentAndMetadata != null ? commentAndMetadata.metadata : null, 7507 commentAndMetadata != null ? commentAndMetadata.metadata : null,
8006 keyword, type, variables); 7508 keyword, type, variables);
8007 } 7509 }
8008 7510
8009 /** 7511 /**
8010 * Parse a variable declaration statement. 7512 * Parse a variable declaration statement. The [commentAndMetadata] is the
7513 * metadata to be associated with the variable declaration statement, or
7514 * `null` if there is no attempt at parsing the comment and metadata. Return
7515 * the variable declaration statement that was parsed.
8011 * 7516 *
8012 * <pre> 7517 * variableDeclarationStatement ::=
8013 * variableDeclarationStatement ::= 7518 * variableDeclarationList ';'
8014 * variableDeclarationList ';'
8015 * </pre>
8016 *
8017 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
8018 * statement, or `null` if there is no attempt at parsing the comment and metadata
8019 * @return the variable declaration statement that was parsed
8020 */ 7519 */
8021 VariableDeclarationStatement _parseVariableDeclarationStatementAfterMetadata( 7520 VariableDeclarationStatement _parseVariableDeclarationStatementAfterMetadata(
8022 CommentAndMetadata commentAndMetadata) { 7521 CommentAndMetadata commentAndMetadata) {
8023 // Token startToken = currentToken; 7522 // Token startToken = currentToken;
8024 VariableDeclarationList variableList = 7523 VariableDeclarationList variableList =
8025 _parseVariableDeclarationListAfterMetadata(commentAndMetadata); 7524 _parseVariableDeclarationListAfterMetadata(commentAndMetadata);
8026 // if (!matches(TokenType.SEMICOLON)) { 7525 // if (!matches(TokenType.SEMICOLON)) {
8027 // if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken .getNext())) { 7526 // if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken .getNext())) {
8028 // // TODO(brianwilkerson) This appears to be of the form "var type v ariable". We should do 7527 // // TODO(brianwilkerson) This appears to be of the form "var type v ariable". We should do
8029 // // a better job of recovering in this case. 7528 // // a better job of recovering in this case.
8030 // } 7529 // }
8031 // } 7530 // }
8032 Token semicolon = _expect(TokenType.SEMICOLON); 7531 Token semicolon = _expect(TokenType.SEMICOLON);
8033 return new VariableDeclarationStatement(variableList, semicolon); 7532 return new VariableDeclarationStatement(variableList, semicolon);
8034 } 7533 }
8035 7534
8036 /** 7535 /**
8037 * Parse a variable declaration statement. 7536 * Parse a variable declaration statement. The [commentAndMetadata] is the
7537 * metadata to be associated with the variable declaration statement, or
7538 * `null` if there is no attempt at parsing the comment and metadata. The
7539 * [keyword] is the token representing the 'final', 'const' or 'var' keyword,
7540 * or `null` if there is no keyword. The [type] is the type of the variables
7541 * in the list. Return the variable declaration statement that was parsed.
8038 * 7542 *
8039 * <pre> 7543 * variableDeclarationStatement ::=
8040 * variableDeclarationStatement ::= 7544 * variableDeclarationList ';'
8041 * variableDeclarationList ';'
8042 * </pre>
8043 *
8044 * @param commentAndMetadata the metadata to be associated with the variable d eclaration
8045 * statement, or `null` if there is no attempt at parsing the comment and metadata
8046 * @param keyword the token representing the 'final', 'const' or 'var' keyword , or `null` if
8047 * there is no keyword
8048 * @param type the type of the variables in the list
8049 * @return the variable declaration statement that was parsed
8050 */ 7545 */
8051 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType( 7546 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(
8052 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) { 7547 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
8053 VariableDeclarationList variableList = 7548 VariableDeclarationList variableList =
8054 _parseVariableDeclarationListAfterType( 7549 _parseVariableDeclarationListAfterType(
8055 commentAndMetadata, keyword, type); 7550 commentAndMetadata, keyword, type);
8056 Token semicolon = _expect(TokenType.SEMICOLON); 7551 Token semicolon = _expect(TokenType.SEMICOLON);
8057 return new VariableDeclarationStatement(variableList, semicolon); 7552 return new VariableDeclarationStatement(variableList, semicolon);
8058 } 7553 }
8059 7554
8060 /** 7555 /**
8061 * Parse a while statement. 7556 * Parse a while statement. Return the while statement that was parsed.
8062 * 7557 *
8063 * <pre> 7558 * whileStatement ::=
8064 * whileStatement ::= 7559 * 'while' '(' expression ')' statement
8065 * 'while' '(' expression ')' statement
8066 * </pre>
8067 *
8068 * @return the while statement that was parsed
8069 */ 7560 */
8070 Statement _parseWhileStatement() { 7561 Statement _parseWhileStatement() {
8071 bool wasInLoop = _inLoop; 7562 bool wasInLoop = _inLoop;
8072 _inLoop = true; 7563 _inLoop = true;
8073 try { 7564 try {
8074 Token keyword = _expectKeyword(Keyword.WHILE); 7565 Token keyword = _expectKeyword(Keyword.WHILE);
8075 Token leftParenthesis = _expect(TokenType.OPEN_PAREN); 7566 Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
8076 Expression condition = parseExpression2(); 7567 Expression condition = parseExpression2();
8077 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN); 7568 Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
8078 Statement body = parseStatement2(); 7569 Statement body = parseStatement2();
8079 return new WhileStatement( 7570 return new WhileStatement(
8080 keyword, leftParenthesis, condition, rightParenthesis, body); 7571 keyword, leftParenthesis, condition, rightParenthesis, body);
8081 } finally { 7572 } finally {
8082 _inLoop = wasInLoop; 7573 _inLoop = wasInLoop;
8083 } 7574 }
8084 } 7575 }
8085 7576
8086 /** 7577 /**
8087 * Parse a yield statement. 7578 * Parse a yield statement. Return the yield statement that was parsed.
8088 * 7579 *
8089 * <pre> 7580 * yieldStatement ::=
8090 * yieldStatement ::= 7581 * 'yield' '*'? expression ';'
8091 * 'yield' '*'? expression ';'
8092 * </pre>
8093 *
8094 * @return the yield statement that was parsed
8095 */ 7582 */
8096 YieldStatement _parseYieldStatement() { 7583 YieldStatement _parseYieldStatement() {
8097 Token yieldToken = getAndAdvance(); 7584 Token yieldToken = getAndAdvance();
8098 Token star = null; 7585 Token star = null;
8099 if (_matches(TokenType.STAR)) { 7586 if (_matches(TokenType.STAR)) {
8100 star = getAndAdvance(); 7587 star = getAndAdvance();
8101 } 7588 }
8102 Expression expression = parseExpression2(); 7589 Expression expression = parseExpression2();
8103 Token semicolon = _expect(TokenType.SEMICOLON); 7590 Token semicolon = _expect(TokenType.SEMICOLON);
8104 return new YieldStatement(yieldToken, star, expression, semicolon); 7591 return new YieldStatement(yieldToken, star, expression, semicolon);
8105 } 7592 }
8106 7593
8107 /** 7594 /**
8108 * Return the token that is immediately after the current token. This is equiv alent to 7595 * Return the token that is immediately after the current token. This is
8109 * [peekAt]. 7596 * equivalent to [_peekAt](1).
8110 *
8111 * @return the token that is immediately after the current token
8112 */ 7597 */
8113 Token _peek() => _currentToken.next; 7598 Token _peek() => _currentToken.next;
8114 7599
8115 /** 7600 /**
8116 * Return the token that is the given distance after the current token. 7601 * Return the token that is the given [distance] after the current token,
8117 * 7602 * where the distance is the number of tokens to look ahead. A distance of `0`
8118 * @param distance the number of tokens to look ahead, where `0` is the curren t token, 7603 * is the current token, `1` is the next token, etc.
8119 * `1` is the next token, etc.
8120 * @return the token that is the given distance after the current token
8121 */ 7604 */
8122 Token _peekAt(int distance) { 7605 Token _peekAt(int distance) {
8123 Token token = _currentToken; 7606 Token token = _currentToken;
8124 for (int i = 0; i < distance; i++) { 7607 for (int i = 0; i < distance; i++) {
8125 token = token.next; 7608 token = token.next;
8126 } 7609 }
8127 return token; 7610 return token;
8128 } 7611 }
8129 7612
8130 /** 7613 /**
8131 * Report the given [AnalysisError]. 7614 * Report the given [error].
8132 *
8133 * @param error the error to be reported
8134 */ 7615 */
8135 void _reportError(AnalysisError error) { 7616 void _reportError(AnalysisError error) {
8136 if (_errorListenerLock != 0) { 7617 if (_errorListenerLock != 0) {
8137 return; 7618 return;
8138 } 7619 }
8139 _errorListener.onError(error); 7620 _errorListener.onError(error);
8140 } 7621 }
8141 7622
8142 /** 7623 /**
8143 * Report an error with the given error code and arguments. 7624 * Report an error with the given [errorCode] and [arguments] associated with
8144 * 7625 * the current token.
8145 * @param errorCode the error code of the error to be reported
8146 * @param arguments the arguments to the error, used to compose the error mess age
8147 */ 7626 */
8148 void _reportErrorForCurrentToken(ParserErrorCode errorCode, 7627 void _reportErrorForCurrentToken(ParserErrorCode errorCode,
8149 [List<Object> arguments]) { 7628 [List<Object> arguments]) {
8150 _reportErrorForToken(errorCode, _currentToken, arguments); 7629 _reportErrorForToken(errorCode, _currentToken, arguments);
8151 } 7630 }
8152 7631
8153 /** 7632 /**
8154 * Report an error with the given error code and arguments. 7633 * Report an error with the given [errorCode] and [arguments] associated with
8155 * 7634 * the given [node].
8156 * @param errorCode the error code of the error to be reported
8157 * @param node the node specifying the location of the error
8158 * @param arguments the arguments to the error, used to compose the error mess age
8159 */ 7635 */
8160 void _reportErrorForNode(ParserErrorCode errorCode, AstNode node, 7636 void _reportErrorForNode(ParserErrorCode errorCode, AstNode node,
8161 [List<Object> arguments]) { 7637 [List<Object> arguments]) {
8162 _reportError(new AnalysisError.con2( 7638 _reportError(new AnalysisError.con2(
8163 _source, node.offset, node.length, errorCode, arguments)); 7639 _source, node.offset, node.length, errorCode, arguments));
8164 } 7640 }
8165 7641
8166 /** 7642 /**
8167 * Report an error with the given error code and arguments. 7643 * Report an error with the given [errorCode] and [arguments] associated with
8168 * 7644 * the given [token].
8169 * @param errorCode the error code of the error to be reported
8170 * @param token the token specifying the location of the error
8171 * @param arguments the arguments to the error, used to compose the error mess age
8172 */ 7645 */
8173 void _reportErrorForToken(ErrorCode errorCode, Token token, 7646 void _reportErrorForToken(ErrorCode errorCode, Token token,
8174 [List<Object> arguments]) { 7647 [List<Object> arguments]) {
8175 if (token.type == TokenType.EOF) { 7648 if (token.type == TokenType.EOF) {
8176 token = token.previous; 7649 token = token.previous;
8177 } 7650 }
8178 _reportError(new AnalysisError.con2(_source, token.offset, 7651 _reportError(new AnalysisError.con2(_source, token.offset,
8179 math.max(token.length, 1), errorCode, arguments)); 7652 math.max(token.length, 1), errorCode, arguments));
8180 } 7653 }
8181 7654
8182 /** 7655 /**
8183 * Skips a block with all containing blocks. 7656 * Skips a block with all containing blocks.
8184 */ 7657 */
8185 void _skipBlock() { 7658 void _skipBlock() {
8186 Token endToken = (_currentToken as BeginToken).endToken; 7659 Token endToken = (_currentToken as BeginToken).endToken;
8187 if (endToken == null) { 7660 if (endToken == null) {
8188 endToken = _currentToken.next; 7661 endToken = _currentToken.next;
8189 while (!identical(endToken, _currentToken)) { 7662 while (!identical(endToken, _currentToken)) {
8190 _currentToken = endToken; 7663 _currentToken = endToken;
8191 endToken = _currentToken.next; 7664 endToken = _currentToken.next;
8192 } 7665 }
8193 _reportErrorForToken( 7666 _reportErrorForToken(
8194 ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, ["}"]); 7667 ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, ["}"]);
8195 } else { 7668 } else {
8196 _currentToken = endToken.next; 7669 _currentToken = endToken.next;
8197 } 7670 }
8198 } 7671 }
8199 7672
8200 /** 7673 /**
8201 * Parse the 'final', 'const', 'var' or type preceding a variable declaration, starting at the 7674 * Parse the 'final', 'const', 'var' or type preceding a variable declaration,
8202 * given token, without actually creating a type or changing the current token . Return the token 7675 * starting at the given token, without actually creating a type or changing
8203 * following the type that was parsed, or `null` if the given token is not the first token 7676 * the current token. Return the token following the type that was parsed, or
8204 * in a valid type. 7677 * `null` if the given token is not the first token in a valid type. The
7678 * [startToken] is the token at which parsing is to begin. Return the token
7679 * following the type that was parsed.
8205 * 7680 *
8206 * <pre>
8207 * finalConstVarOrType ::= 7681 * finalConstVarOrType ::=
8208 * | 'final' type? 7682 * | 'final' type?
8209 * | 'const' type? 7683 * | 'const' type?
8210 * | 'var' 7684 * | 'var'
8211 * | type 7685 * | type
8212 * </pre>
8213 *
8214 * @param startToken the token at which parsing is to begin
8215 * @return the token following the type that was parsed
8216 */ 7686 */
8217 Token _skipFinalConstVarOrType(Token startToken) { 7687 Token _skipFinalConstVarOrType(Token startToken) {
8218 if (_tokenMatchesKeyword(startToken, Keyword.FINAL) || 7688 if (_tokenMatchesKeyword(startToken, Keyword.FINAL) ||
8219 _tokenMatchesKeyword(startToken, Keyword.CONST)) { 7689 _tokenMatchesKeyword(startToken, Keyword.CONST)) {
8220 Token next = startToken.next; 7690 Token next = startToken.next;
8221 if (_tokenMatchesIdentifier(next)) { 7691 if (_tokenMatchesIdentifier(next)) {
8222 Token next2 = next.next; 7692 Token next2 = next.next;
8223 // "Type parameter" or "Type<" or "prefix.Type" 7693 // "Type parameter" or "Type<" or "prefix.Type"
8224 if (_tokenMatchesIdentifier(next2) || 7694 if (_tokenMatchesIdentifier(next2) ||
8225 _tokenMatches(next2, TokenType.LT) || 7695 _tokenMatches(next2, TokenType.LT) ||
(...skipping 15 matching lines...) Expand all
8241 (_tokenMatchesIdentifier(next.next.next) || 7711 (_tokenMatchesIdentifier(next.next.next) ||
8242 _tokenMatches(next.next.next, TokenType.LT) || 7712 _tokenMatches(next.next.next, TokenType.LT) ||
8243 _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) { 7713 _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) {
8244 return _skipReturnType(startToken); 7714 return _skipReturnType(startToken);
8245 } 7715 }
8246 } 7716 }
8247 return null; 7717 return null;
8248 } 7718 }
8249 7719
8250 /** 7720 /**
8251 * Parse a list of formal parameters, starting at the given token, without act ually creating a 7721 * Parse a list of formal parameters, starting at the [startToken], without
8252 * formal parameter list or changing the current token. Return the token follo wing the formal 7722 * actually creating a formal parameter list or changing the current token.
8253 * parameter list that was parsed, or `null` if the given token is not the fir st token in a 7723 * Return the token following the formal parameter list that was parsed, or
8254 * valid list of formal parameter. 7724 * `null` if the given token is not the first token in a valid list of formal
7725 * parameter.
8255 * 7726 *
8256 * Note that unlike other skip methods, this method uses a heuristic. In the w orst case, the 7727 * Note that unlike other skip methods, this method uses a heuristic. In the
8257 * parameters could be prefixed by metadata, which would require us to be able to skip arbitrary 7728 * worst case, the parameters could be prefixed by metadata, which would
8258 * expressions. Rather than duplicate the logic of most of the parse methods w e simply look for 7729 * require us to be able to skip arbitrary expressions. Rather than duplicate
8259 * something that is likely to be a list of parameters and then skip to return ing the token after 7730 * the logic of most of the parse methods we simply look for something that is
8260 * the closing parenthesis. 7731 * likely to be a list of parameters and then skip to returning the token
7732 * after the closing parenthesis.
8261 * 7733 *
8262 * This method must be kept in sync with [parseFormalParameterList]. 7734 * This method must be kept in sync with [parseFormalParameterList].
8263 * 7735 *
8264 * <pre> 7736 * formalParameterList ::=
8265 * formalParameterList ::= 7737 * '(' ')'
8266 * '(' ')' 7738 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
8267 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' 7739 * | '(' optionalFormalParameters ')'
8268 * | '(' optionalFormalParameters ')'
8269 * 7740 *
8270 * normalFormalParameters ::= 7741 * normalFormalParameters ::=
8271 * normalFormalParameter (',' normalFormalParameter)* 7742 * normalFormalParameter (',' normalFormalParameter)*
8272 * 7743 *
8273 * optionalFormalParameters ::= 7744 * optionalFormalParameters ::=
8274 * optionalPositionalFormalParameters 7745 * optionalPositionalFormalParameters
8275 * | namedFormalParameters 7746 * | namedFormalParameters
8276 * 7747 *
8277 * optionalPositionalFormalParameters ::= 7748 * optionalPositionalFormalParameters ::=
8278 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']' 7749 * '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
8279 * 7750 *
8280 * namedFormalParameters ::= 7751 * namedFormalParameters ::=
8281 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}' 7752 * '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
8282 * </pre>
8283 *
8284 * @param startToken the token at which parsing is to begin
8285 * @return the token following the formal parameter list that was parsed
8286 */ 7753 */
8287 Token _skipFormalParameterList(Token startToken) { 7754 Token _skipFormalParameterList(Token startToken) {
8288 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) { 7755 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
8289 return null; 7756 return null;
8290 } 7757 }
8291 Token next = startToken.next; 7758 Token next = startToken.next;
8292 if (_tokenMatches(next, TokenType.CLOSE_PAREN)) { 7759 if (_tokenMatches(next, TokenType.CLOSE_PAREN)) {
8293 return next.next; 7760 return next.next;
8294 } 7761 }
8295 // 7762 //
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8327 if (afterType == null) { 7794 if (afterType == null) {
8328 return null; 7795 return null;
8329 } 7796 }
8330 if (_skipSimpleIdentifier(afterType) == null) { 7797 if (_skipSimpleIdentifier(afterType) == null) {
8331 return null; 7798 return null;
8332 } 7799 }
8333 return _skipPastMatchingToken(startToken); 7800 return _skipPastMatchingToken(startToken);
8334 } 7801 }
8335 7802
8336 /** 7803 /**
8337 * If the given token is a begin token with an associated end token, then retu rn the token 7804 * If the [startToken] is a begin token with an associated end token, then
8338 * following the end token. Otherwise, return `null`. 7805 * return the token following the end token. Otherwise, return `null`.
8339 *
8340 * @param startToken the token that is assumed to be a being token
8341 * @return the token following the matching end token
8342 */ 7806 */
8343 Token _skipPastMatchingToken(Token startToken) { 7807 Token _skipPastMatchingToken(Token startToken) {
8344 if (startToken is! BeginToken) { 7808 if (startToken is! BeginToken) {
8345 return null; 7809 return null;
8346 } 7810 }
8347 Token closeParen = (startToken as BeginToken).endToken; 7811 Token closeParen = (startToken as BeginToken).endToken;
8348 if (closeParen == null) { 7812 if (closeParen == null) {
8349 return null; 7813 return null;
8350 } 7814 }
8351 return closeParen.next; 7815 return closeParen.next;
8352 } 7816 }
8353 7817
8354 /** 7818 /**
8355 * Parse a prefixed identifier, starting at the given token, without actually creating a prefixed 7819 * Parse a prefixed identifier, starting at the [startToken], without actually
8356 * identifier or changing the current token. Return the token following the pr efixed identifier 7820 * creating a prefixed identifier or changing the current token. Return the
8357 * that was parsed, or `null` if the given token is not the first token in a v alid prefixed 7821 * token following the prefixed identifier that was parsed, or `null` if the
8358 * identifier. 7822 * given token is not the first token in a valid prefixed identifier.
8359 * 7823 *
8360 * This method must be kept in sync with [parsePrefixedIdentifier]. 7824 * This method must be kept in sync with [parsePrefixedIdentifier].
8361 * 7825 *
8362 * <pre> 7826 * prefixedIdentifier ::=
8363 * prefixedIdentifier ::= 7827 * identifier ('.' identifier)?
8364 * identifier ('.' identifier)?
8365 * </pre>
8366 *
8367 * @param startToken the token at which parsing is to begin
8368 * @return the token following the prefixed identifier that was parsed
8369 */ 7828 */
8370 Token _skipPrefixedIdentifier(Token startToken) { 7829 Token _skipPrefixedIdentifier(Token startToken) {
8371 Token token = _skipSimpleIdentifier(startToken); 7830 Token token = _skipSimpleIdentifier(startToken);
8372 if (token == null) { 7831 if (token == null) {
8373 return null; 7832 return null;
8374 } else if (!_tokenMatches(token, TokenType.PERIOD)) { 7833 } else if (!_tokenMatches(token, TokenType.PERIOD)) {
8375 return token; 7834 return token;
8376 } 7835 }
8377 return _skipSimpleIdentifier(token.next); 7836 return _skipSimpleIdentifier(token.next);
8378 } 7837 }
8379 7838
8380 /** 7839 /**
8381 * Parse a return type, starting at the given token, without actually creating a return type or 7840 * Parse a return type, starting at the [startToken], without actually
8382 * changing the current token. Return the token following the return type that was parsed, or 7841 * creating a return type or changing the current token. Return the token
8383 * `null` if the given token is not the first token in a valid return type. 7842 * following the return type that was parsed, or `null` if the given token is
7843 * not the first token in a valid return type.
8384 * 7844 *
8385 * This method must be kept in sync with [parseReturnType]. 7845 * This method must be kept in sync with [parseReturnType].
8386 * 7846 *
8387 * <pre> 7847 * returnType ::=
8388 * returnType ::= 7848 * 'void'
8389 * 'void' 7849 * | type
8390 * | type
8391 * </pre>
8392 *
8393 * @param startToken the token at which parsing is to begin
8394 * @return the token following the return type that was parsed
8395 */ 7850 */
8396 Token _skipReturnType(Token startToken) { 7851 Token _skipReturnType(Token startToken) {
8397 if (_tokenMatchesKeyword(startToken, Keyword.VOID)) { 7852 if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
8398 return startToken.next; 7853 return startToken.next;
8399 } else { 7854 } else {
8400 return _skipTypeName(startToken); 7855 return _skipTypeName(startToken);
8401 } 7856 }
8402 } 7857 }
8403 7858
8404 /** 7859 /**
8405 * Parse a simple identifier, starting at the given token, without actually cr eating a simple 7860 * Parse a simple identifier, starting at the [startToken], without actually
8406 * identifier or changing the current token. Return the token following the si mple identifier that 7861 * creating a simple identifier or changing the current token. Return the
8407 * was parsed, or `null` if the given token is not the first token in a valid simple 7862 * token following the simple identifier that was parsed, or `null` if the
8408 * identifier. 7863 * given token is not the first token in a valid simple identifier.
8409 * 7864 *
8410 * This method must be kept in sync with [parseSimpleIdentifier]. 7865 * This method must be kept in sync with [parseSimpleIdentifier].
8411 * 7866 *
8412 * <pre> 7867 * identifier ::=
8413 * identifier ::= 7868 * IDENTIFIER
8414 * IDENTIFIER
8415 * </pre>
8416 *
8417 * @param startToken the token at which parsing is to begin
8418 * @return the token following the simple identifier that was parsed
8419 */ 7869 */
8420 Token _skipSimpleIdentifier(Token startToken) { 7870 Token _skipSimpleIdentifier(Token startToken) {
8421 if (_tokenMatches(startToken, TokenType.IDENTIFIER) || 7871 if (_tokenMatches(startToken, TokenType.IDENTIFIER) ||
8422 (_tokenMatches(startToken, TokenType.KEYWORD) && 7872 (_tokenMatches(startToken, TokenType.KEYWORD) &&
8423 (startToken as KeywordToken).keyword.isPseudoKeyword)) { 7873 (startToken as KeywordToken).keyword.isPseudoKeyword)) {
8424 return startToken.next; 7874 return startToken.next;
8425 } 7875 }
8426 return null; 7876 return null;
8427 } 7877 }
8428 7878
8429 /** 7879 /**
8430 * Parse a string literal that contains interpolations, starting at the given token, without 7880 * Parse a string literal that contains interpolations, starting at the
8431 * actually creating a string literal or changing the current token. Return th e token following 7881 * [startToken], without actually creating a string literal or changing the
8432 * the string literal that was parsed, or `null` if the given token is not the first token 7882 * current token. Return the token following the string literal that was
8433 * in a valid string literal. 7883 * parsed, or `null` if the given token is not the first token in a valid
7884 * string literal.
8434 * 7885 *
8435 * This method must be kept in sync with [parseStringInterpolation]. 7886 * This method must be kept in sync with [parseStringInterpolation].
8436 *
8437 * @param startToken the token at which parsing is to begin
8438 * @return the string literal that was parsed
8439 */ 7887 */
8440 Token _skipStringInterpolation(Token startToken) { 7888 Token _skipStringInterpolation(Token startToken) {
8441 Token token = startToken; 7889 Token token = startToken;
8442 TokenType type = token.type; 7890 TokenType type = token.type;
8443 while (type == TokenType.STRING_INTERPOLATION_EXPRESSION || 7891 while (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
8444 type == TokenType.STRING_INTERPOLATION_IDENTIFIER) { 7892 type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
8445 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) { 7893 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
8446 token = token.next; 7894 token = token.next;
8447 type = token.type; 7895 type = token.type;
8448 // 7896 //
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8480 type = token.type; 7928 type = token.type;
8481 if (type == TokenType.STRING) { 7929 if (type == TokenType.STRING) {
8482 token = token.next; 7930 token = token.next;
8483 type = token.type; 7931 type = token.type;
8484 } 7932 }
8485 } 7933 }
8486 return token; 7934 return token;
8487 } 7935 }
8488 7936
8489 /** 7937 /**
8490 * Parse a string literal, starting at the given token, without actually creat ing a string literal 7938 * Parse a string literal, starting at the [startToken], without actually
8491 * or changing the current token. Return the token following the string litera l that was parsed, 7939 * creating a string literal or changing the current token. Return the token
8492 * or `null` if the given token is not the first token in a valid string liter al. 7940 * following the string literal that was parsed, or `null` if the given token
7941 * is not the first token in a valid string literal.
8493 * 7942 *
8494 * This method must be kept in sync with [parseStringLiteral]. 7943 * This method must be kept in sync with [parseStringLiteral].
8495 * 7944 *
8496 * <pre> 7945 * stringLiteral ::=
8497 * stringLiteral ::= 7946 * MULTI_LINE_STRING+
8498 * MULTI_LINE_STRING+ 7947 * | SINGLE_LINE_STRING+
8499 * | SINGLE_LINE_STRING+
8500 * </pre>
8501 *
8502 * @param startToken the token at which parsing is to begin
8503 * @return the token following the string literal that was parsed
8504 */ 7948 */
8505 Token _skipStringLiteral(Token startToken) { 7949 Token _skipStringLiteral(Token startToken) {
8506 Token token = startToken; 7950 Token token = startToken;
8507 while (token != null && _tokenMatches(token, TokenType.STRING)) { 7951 while (token != null && _tokenMatches(token, TokenType.STRING)) {
8508 token = token.next; 7952 token = token.next;
8509 TokenType type = token.type; 7953 TokenType type = token.type;
8510 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION || 7954 if (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
8511 type == TokenType.STRING_INTERPOLATION_IDENTIFIER) { 7955 type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
8512 token = _skipStringInterpolation(token); 7956 token = _skipStringInterpolation(token);
8513 } 7957 }
8514 } 7958 }
8515 if (identical(token, startToken)) { 7959 if (identical(token, startToken)) {
8516 return null; 7960 return null;
8517 } 7961 }
8518 return token; 7962 return token;
8519 } 7963 }
8520 7964
8521 /** 7965 /**
8522 * Parse a list of type arguments, starting at the given token, without actual ly creating a type argument list 7966 * Parse a list of type arguments, starting at the [startToken], without
8523 * or changing the current token. Return the token following the type argument list that was parsed, 7967 * actually creating a type argument list or changing the current token.
8524 * or `null` if the given token is not the first token in a valid type argumen t list. 7968 * Return the token following the type argument list that was parsed, or
7969 * `null` if the given token is not the first token in a valid type argument
7970 * list.
8525 * 7971 *
8526 * This method must be kept in sync with [parseTypeArgumentList]. 7972 * This method must be kept in sync with [parseTypeArgumentList].
8527 * 7973 *
8528 * <pre> 7974 * typeArguments ::=
8529 * typeArguments ::= 7975 * '<' typeList '>'
8530 * '<' typeList '>'
8531 * 7976 *
8532 * typeList ::= 7977 * typeList ::=
8533 * type (',' type)* 7978 * type (',' type)*
8534 * </pre>
8535 *
8536 * @param startToken the token at which parsing is to begin
8537 * @return the token following the type argument list that was parsed
8538 */ 7979 */
8539 Token _skipTypeArgumentList(Token startToken) { 7980 Token _skipTypeArgumentList(Token startToken) {
8540 Token token = startToken; 7981 Token token = startToken;
8541 if (!_tokenMatches(token, TokenType.LT)) { 7982 if (!_tokenMatches(token, TokenType.LT)) {
8542 return null; 7983 return null;
8543 } 7984 }
8544 token = _skipTypeName(token.next); 7985 token = _skipTypeName(token.next);
8545 if (token == null) { 7986 if (token == null) {
8546 return null; 7987 return null;
8547 } 7988 }
8548 while (_tokenMatches(token, TokenType.COMMA)) { 7989 while (_tokenMatches(token, TokenType.COMMA)) {
8549 token = _skipTypeName(token.next); 7990 token = _skipTypeName(token.next);
8550 if (token == null) { 7991 if (token == null) {
8551 return null; 7992 return null;
8552 } 7993 }
8553 } 7994 }
8554 if (token.type == TokenType.GT) { 7995 if (token.type == TokenType.GT) {
8555 return token.next; 7996 return token.next;
8556 } else if (token.type == TokenType.GT_GT) { 7997 } else if (token.type == TokenType.GT_GT) {
8557 Token second = new Token(TokenType.GT, token.offset + 1); 7998 Token second = new Token(TokenType.GT, token.offset + 1);
8558 second.setNextWithoutSettingPrevious(token.next); 7999 second.setNextWithoutSettingPrevious(token.next);
8559 return second; 8000 return second;
8560 } 8001 }
8561 return null; 8002 return null;
8562 } 8003 }
8563 8004
8564 /** 8005 /**
8565 * Parse a type name, starting at the given token, without actually creating a type name or 8006 * Parse a type name, starting at the [startToken], without actually creating
8566 * changing the current token. Return the token following the type name that w as parsed, or 8007 * a type name or changing the current token. Return the token following the
8567 * `null` if the given token is not the first token in a valid type name. 8008 * type name that was parsed, or `null` if the given token is not the first
8009 * token in a valid type name.
8568 * 8010 *
8569 * This method must be kept in sync with [parseTypeName]. 8011 * This method must be kept in sync with [parseTypeName].
8570 * 8012 *
8571 * <pre> 8013 * type ::=
8572 * type ::= 8014 * qualified typeArguments?
8573 * qualified typeArguments?
8574 * </pre>
8575 *
8576 * @param startToken the token at which parsing is to begin
8577 * @return the token following the type name that was parsed
8578 */ 8015 */
8579 Token _skipTypeName(Token startToken) { 8016 Token _skipTypeName(Token startToken) {
8580 Token token = _skipPrefixedIdentifier(startToken); 8017 Token token = _skipPrefixedIdentifier(startToken);
8581 if (token == null) { 8018 if (token == null) {
8582 return null; 8019 return null;
8583 } 8020 }
8584 if (_tokenMatches(token, TokenType.LT)) { 8021 if (_tokenMatches(token, TokenType.LT)) {
8585 token = _skipTypeArgumentList(token); 8022 token = _skipTypeArgumentList(token);
8586 } 8023 }
8587 return token; 8024 return token;
8588 } 8025 }
8589 8026
8590 /** 8027 /**
8591 * Parse a list of type parameters, starting at the given token, without actua lly creating a type 8028 * Parse a list of type parameters, starting at the [startToken], without
8592 * parameter list or changing the current token. Return the token following th e type parameter 8029 * actually creating a type parameter list or changing the current token.
8593 * list that was parsed, or `null` if the given token is not the first token i n a valid type 8030 * Return the token following the type parameter list that was parsed, or
8594 * parameter list. 8031 * `null` if the given token is not the first token in a valid type parameter
8032 * list.
8595 * 8033 *
8596 * This method must be kept in sync with [parseTypeParameterList]. 8034 * This method must be kept in sync with [parseTypeParameterList].
8597 * 8035 *
8598 * <pre> 8036 * typeParameterList ::=
8599 * typeParameterList ::= 8037 * '<' typeParameter (',' typeParameter)* '>'
8600 * '<' typeParameter (',' typeParameter)* '>'
8601 * </pre>
8602 *
8603 * @param startToken the token at which parsing is to begin
8604 * @return the token following the type parameter list that was parsed
8605 */ 8038 */
8606 Token _skipTypeParameterList(Token startToken) { 8039 Token _skipTypeParameterList(Token startToken) {
8607 if (!_tokenMatches(startToken, TokenType.LT)) { 8040 if (!_tokenMatches(startToken, TokenType.LT)) {
8608 return null; 8041 return null;
8609 } 8042 }
8610 // 8043 //
8611 // We can't skip a type parameter because it can be preceeded by metadata, 8044 // We can't skip a type parameter because it can be preceeded by metadata,
8612 // so we just assume that everything before the matching end token is valid. 8045 // so we just assume that everything before the matching end token is valid.
8613 // 8046 //
8614 int depth = 1; 8047 int depth = 1;
(...skipping 23 matching lines...) Expand all
8638 return fakeEquals; 8071 return fakeEquals;
8639 } 8072 }
8640 depth -= 2; 8073 depth -= 2;
8641 } 8074 }
8642 next = next.next; 8075 next = next.next;
8643 } 8076 }
8644 return next; 8077 return next;
8645 } 8078 }
8646 8079
8647 /** 8080 /**
8648 * Return `true` if the given token has the given type. 8081 * Return `true` if the given [token] has the given [type].
8649 *
8650 * @param token the token being tested
8651 * @param type the type of token that is being tested for
8652 * @return `true` if the given token has the given type
8653 */ 8082 */
8654 bool _tokenMatches(Token token, TokenType type) => token.type == type; 8083 bool _tokenMatches(Token token, TokenType type) => token.type == type;
8655 8084
8656 /** 8085 /**
8657 * Return `true` if the given token is a valid identifier. Valid identifiers i nclude 8086 * Return `true` if the given [token] is a valid identifier. Valid identifiers
8658 * built-in identifiers (pseudo-keywords). 8087 * include built-in identifiers (pseudo-keywords).
8659 *
8660 * @return `true` if the given token is a valid identifier
8661 */ 8088 */
8662 bool _tokenMatchesIdentifier(Token token) => 8089 bool _tokenMatchesIdentifier(Token token) =>
8663 _tokenMatches(token, TokenType.IDENTIFIER) || 8090 _tokenMatches(token, TokenType.IDENTIFIER) ||
8664 (_tokenMatches(token, TokenType.KEYWORD) && 8091 (_tokenMatches(token, TokenType.KEYWORD) &&
8665 (token as KeywordToken).keyword.isPseudoKeyword); 8092 (token as KeywordToken).keyword.isPseudoKeyword);
8666 8093
8667 /** 8094 /**
8668 * Return `true` if the given token matches the given keyword. 8095 * Return `true` if the given [token] matches the given [keyword].
8669 *
8670 * @param token the token being tested
8671 * @param keyword the keyword that is being tested for
8672 * @return `true` if the given token matches the given keyword
8673 */ 8096 */
8674 bool _tokenMatchesKeyword(Token token, Keyword keyword) => 8097 bool _tokenMatchesKeyword(Token token, Keyword keyword) =>
8675 token.type == TokenType.KEYWORD && 8098 token.type == TokenType.KEYWORD &&
8676 (token as KeywordToken).keyword == keyword; 8099 (token as KeywordToken).keyword == keyword;
8677 8100
8678 /** 8101 /**
8679 * Return `true` if the given token matches the given identifier. 8102 * Return `true` if the given [token] matches the given [identifier].
8680 *
8681 * @param token the token being tested
8682 * @param identifier the identifier that can optionally appear in the current location
8683 * @return `true` if the current token matches the given identifier
8684 */ 8103 */
8685 bool _tokenMatchesString(Token token, String identifier) => 8104 bool _tokenMatchesString(Token token, String identifier) =>
8686 token.type == TokenType.IDENTIFIER && token.lexeme == identifier; 8105 token.type == TokenType.IDENTIFIER && token.lexeme == identifier;
8687 8106
8688 /** 8107 /**
8689 * Translate the characters at the given [index] in the given [lexeme], 8108 * Translate the characters at the given [index] in the given [lexeme],
8690 * appending the translated character to the given [buffer]. The index is 8109 * appending the translated character to the given [buffer]. The index is
8691 * assumed to be valid. 8110 * assumed to be valid.
8692 */ 8111 */
8693 int _translateCharacter(StringBuffer buffer, String lexeme, int index) { 8112 int _translateCharacter(StringBuffer buffer, String lexeme, int index) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
8831 */ 8250 */
8832 void _unlockErrorListener() { 8251 void _unlockErrorListener() {
8833 if (_errorListenerLock == 0) { 8252 if (_errorListenerLock == 0) {
8834 throw new IllegalStateException( 8253 throw new IllegalStateException(
8835 "Attempt to unlock not locked error listener."); 8254 "Attempt to unlock not locked error listener.");
8836 } 8255 }
8837 _errorListenerLock--; 8256 _errorListenerLock--;
8838 } 8257 }
8839 8258
8840 /** 8259 /**
8841 * Validate that the given parameter list does not contain any field initializ ers. 8260 * Validate that the given [parameterList] does not contain any field
8842 * 8261 * initializers.
8843 * @param parameterList the parameter list to be validated
8844 */ 8262 */
8845 void _validateFormalParameterList(FormalParameterList parameterList) { 8263 void _validateFormalParameterList(FormalParameterList parameterList) {
8846 for (FormalParameter parameter in parameterList.parameters) { 8264 for (FormalParameter parameter in parameterList.parameters) {
8847 if (parameter is FieldFormalParameter) { 8265 if (parameter is FieldFormalParameter) {
8848 _reportErrorForNode( 8266 _reportErrorForNode(
8849 ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 8267 ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
8850 parameter.identifier); 8268 parameter.identifier);
8851 } 8269 }
8852 } 8270 }
8853 } 8271 }
8854 8272
8855 /** 8273 /**
8856 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract' 8274 * Validate that the given set of [modifiers] is appropriate for a class and
8857 * keyword if there is one. 8275 * return the 'abstract' keyword if there is one.
8858 *
8859 * @param modifiers the modifiers being validated
8860 */ 8276 */
8861 Token _validateModifiersForClass(Modifiers modifiers) { 8277 Token _validateModifiersForClass(Modifiers modifiers) {
8862 _validateModifiersForTopLevelDeclaration(modifiers); 8278 _validateModifiersForTopLevelDeclaration(modifiers);
8863 if (modifiers.constKeyword != null) { 8279 if (modifiers.constKeyword != null) {
8864 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword); 8280 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
8865 } 8281 }
8866 if (modifiers.externalKeyword != null) { 8282 if (modifiers.externalKeyword != null) {
8867 _reportErrorForToken( 8283 _reportErrorForToken(
8868 ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword); 8284 ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword);
8869 } 8285 }
8870 if (modifiers.finalKeyword != null) { 8286 if (modifiers.finalKeyword != null) {
8871 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword); 8287 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
8872 } 8288 }
8873 if (modifiers.varKeyword != null) { 8289 if (modifiers.varKeyword != null) {
8874 _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword); 8290 _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword);
8875 } 8291 }
8876 return modifiers.abstractKeyword; 8292 return modifiers.abstractKeyword;
8877 } 8293 }
8878 8294
8879 /** 8295 /**
8880 * Validate that the given set of modifiers is appropriate for a constructor a nd return the 8296 * Validate that the given set of [modifiers] is appropriate for a constructor
8881 * 'const' keyword if there is one. 8297 * and return the 'const' keyword if there is one.
8882 *
8883 * @param modifiers the modifiers being validated
8884 * @return the 'const' or 'final' keyword associated with the constructor
8885 */ 8298 */
8886 Token _validateModifiersForConstructor(Modifiers modifiers) { 8299 Token _validateModifiersForConstructor(Modifiers modifiers) {
8887 if (modifiers.abstractKeyword != null) { 8300 if (modifiers.abstractKeyword != null) {
8888 _reportErrorForToken( 8301 _reportErrorForToken(
8889 ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abstractKeyword); 8302 ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abstractKeyword);
8890 } 8303 }
8891 if (modifiers.finalKeyword != null) { 8304 if (modifiers.finalKeyword != null) {
8892 _reportErrorForToken( 8305 _reportErrorForToken(
8893 ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword); 8306 ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword);
8894 } 8307 }
(...skipping 17 matching lines...) Expand all
8912 if (externalKeyword != null && 8325 if (externalKeyword != null &&
8913 factoryKeyword != null && 8326 factoryKeyword != null &&
8914 factoryKeyword.offset < externalKeyword.offset) { 8327 factoryKeyword.offset < externalKeyword.offset) {
8915 _reportErrorForToken( 8328 _reportErrorForToken(
8916 ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword); 8329 ParserErrorCode.EXTERNAL_AFTER_FACTORY, externalKeyword);
8917 } 8330 }
8918 return constKeyword; 8331 return constKeyword;
8919 } 8332 }
8920 8333
8921 /** 8334 /**
8922 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract' 8335 * Validate that the given set of [modifiers] is appropriate for a class and
8923 * keyword if there is one. 8336 * return the 'abstract' keyword if there is one.
8924 *
8925 * @param modifiers the modifiers being validated
8926 */ 8337 */
8927 void _validateModifiersForEnum(Modifiers modifiers) { 8338 void _validateModifiersForEnum(Modifiers modifiers) {
8928 _validateModifiersForTopLevelDeclaration(modifiers); 8339 _validateModifiersForTopLevelDeclaration(modifiers);
8929 if (modifiers.abstractKeyword != null) { 8340 if (modifiers.abstractKeyword != null) {
8930 _reportErrorForToken( 8341 _reportErrorForToken(
8931 ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyword); 8342 ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyword);
8932 } 8343 }
8933 if (modifiers.constKeyword != null) { 8344 if (modifiers.constKeyword != null) {
8934 _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword); 8345 _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword);
8935 } 8346 }
8936 if (modifiers.externalKeyword != null) { 8347 if (modifiers.externalKeyword != null) {
8937 _reportErrorForToken( 8348 _reportErrorForToken(
8938 ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyword); 8349 ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyword);
8939 } 8350 }
8940 if (modifiers.finalKeyword != null) { 8351 if (modifiers.finalKeyword != null) {
8941 _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword); 8352 _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword);
8942 } 8353 }
8943 if (modifiers.varKeyword != null) { 8354 if (modifiers.varKeyword != null) {
8944 _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword); 8355 _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword);
8945 } 8356 }
8946 } 8357 }
8947 8358
8948 /** 8359 /**
8949 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final', 8360 * Validate that the given set of [modifiers] is appropriate for a field and
8950 * 'const' or 'var' keyword if there is one. 8361 * return the 'final', 'const' or 'var' keyword if there is one.
8951 *
8952 * @param modifiers the modifiers being validated
8953 * @return the 'final', 'const' or 'var' keyword associated with the field
8954 */ 8362 */
8955 Token _validateModifiersForField(Modifiers modifiers) { 8363 Token _validateModifiersForField(Modifiers modifiers) {
8956 if (modifiers.abstractKeyword != null) { 8364 if (modifiers.abstractKeyword != null) {
8957 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER); 8365 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
8958 } 8366 }
8959 if (modifiers.externalKeyword != null) { 8367 if (modifiers.externalKeyword != null) {
8960 _reportErrorForToken( 8368 _reportErrorForToken(
8961 ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword); 8369 ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
8962 } 8370 }
8963 if (modifiers.factoryKeyword != null) { 8371 if (modifiers.factoryKeyword != null) {
(...skipping 23 matching lines...) Expand all
8987 } 8395 }
8988 } else if (varKeyword != null && 8396 } else if (varKeyword != null &&
8989 staticKeyword != null && 8397 staticKeyword != null &&
8990 varKeyword.offset < staticKeyword.offset) { 8398 varKeyword.offset < staticKeyword.offset) {
8991 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword); 8399 _reportErrorForToken(ParserErrorCode.STATIC_AFTER_VAR, staticKeyword);
8992 } 8400 }
8993 return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]); 8401 return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
8994 } 8402 }
8995 8403
8996 /** 8404 /**
8997 * Validate that the given set of modifiers is appropriate for a local functio n. 8405 * Validate that the given set of [modifiers] is appropriate for a local
8998 * 8406 * function.
8999 * @param modifiers the modifiers being validated
9000 */ 8407 */
9001 void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) { 8408 void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
9002 if (modifiers.abstractKeyword != null || 8409 if (modifiers.abstractKeyword != null ||
9003 modifiers.constKeyword != null || 8410 modifiers.constKeyword != null ||
9004 modifiers.externalKeyword != null || 8411 modifiers.externalKeyword != null ||
9005 modifiers.factoryKeyword != null || 8412 modifiers.factoryKeyword != null ||
9006 modifiers.finalKeyword != null || 8413 modifiers.finalKeyword != null ||
9007 modifiers.staticKeyword != null || 8414 modifiers.staticKeyword != null ||
9008 modifiers.varKeyword != null) { 8415 modifiers.varKeyword != null) {
9009 _reportErrorForCurrentToken( 8416 _reportErrorForCurrentToken(
9010 ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER); 8417 ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER);
9011 } 8418 }
9012 } 8419 }
9013 8420
9014 /** 8421 /**
9015 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method. 8422 * Validate that the given set of [modifiers] is appropriate for a getter,
9016 * 8423 * setter, or method.
9017 * @param modifiers the modifiers being validated
9018 */ 8424 */
9019 void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) { 8425 void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
9020 if (modifiers.abstractKeyword != null) { 8426 if (modifiers.abstractKeyword != null) {
9021 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER); 8427 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
9022 } 8428 }
9023 if (modifiers.constKeyword != null) { 8429 if (modifiers.constKeyword != null) {
9024 _reportErrorForToken( 8430 _reportErrorForToken(
9025 ParserErrorCode.CONST_METHOD, modifiers.constKeyword); 8431 ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
9026 } 8432 }
9027 if (modifiers.factoryKeyword != null) { 8433 if (modifiers.factoryKeyword != null) {
(...skipping 12 matching lines...) Expand all
9040 Token staticKeyword = modifiers.staticKeyword; 8446 Token staticKeyword = modifiers.staticKeyword;
9041 if (externalKeyword != null && 8447 if (externalKeyword != null &&
9042 staticKeyword != null && 8448 staticKeyword != null &&
9043 staticKeyword.offset < externalKeyword.offset) { 8449 staticKeyword.offset < externalKeyword.offset) {
9044 _reportErrorForToken( 8450 _reportErrorForToken(
9045 ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeyword); 8451 ParserErrorCode.EXTERNAL_AFTER_STATIC, externalKeyword);
9046 } 8452 }
9047 } 8453 }
9048 8454
9049 /** 8455 /**
9050 * Validate that the given set of modifiers is appropriate for a getter, sette r, or method. 8456 * Validate that the given set of [modifiers] is appropriate for a getter,
9051 * 8457 * setter, or method.
9052 * @param modifiers the modifiers being validated
9053 */ 8458 */
9054 void _validateModifiersForOperator(Modifiers modifiers) { 8459 void _validateModifiersForOperator(Modifiers modifiers) {
9055 if (modifiers.abstractKeyword != null) { 8460 if (modifiers.abstractKeyword != null) {
9056 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER); 8461 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
9057 } 8462 }
9058 if (modifiers.constKeyword != null) { 8463 if (modifiers.constKeyword != null) {
9059 _reportErrorForToken( 8464 _reportErrorForToken(
9060 ParserErrorCode.CONST_METHOD, modifiers.constKeyword); 8465 ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
9061 } 8466 }
9062 if (modifiers.factoryKeyword != null) { 8467 if (modifiers.factoryKeyword != null) {
9063 _reportErrorForToken( 8468 _reportErrorForToken(
9064 ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword); 8469 ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
9065 } 8470 }
9066 if (modifiers.finalKeyword != null) { 8471 if (modifiers.finalKeyword != null) {
9067 _reportErrorForToken( 8472 _reportErrorForToken(
9068 ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword); 8473 ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
9069 } 8474 }
9070 if (modifiers.staticKeyword != null) { 8475 if (modifiers.staticKeyword != null) {
9071 _reportErrorForToken( 8476 _reportErrorForToken(
9072 ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword); 8477 ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword);
9073 } 8478 }
9074 if (modifiers.varKeyword != null) { 8479 if (modifiers.varKeyword != null) {
9075 _reportErrorForToken( 8480 _reportErrorForToken(
9076 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword); 8481 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
9077 } 8482 }
9078 } 8483 }
9079 8484
9080 /** 8485 /**
9081 * Validate that the given set of modifiers is appropriate for a top-level dec laration. 8486 * Validate that the given set of [modifiers] is appropriate for a top-level
9082 * 8487 * declaration.
9083 * @param modifiers the modifiers being validated
9084 */ 8488 */
9085 void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) { 8489 void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
9086 if (modifiers.factoryKeyword != null) { 8490 if (modifiers.factoryKeyword != null) {
9087 _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 8491 _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION,
9088 modifiers.factoryKeyword); 8492 modifiers.factoryKeyword);
9089 } 8493 }
9090 if (modifiers.staticKeyword != null) { 8494 if (modifiers.staticKeyword != null) {
9091 _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 8495 _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION,
9092 modifiers.staticKeyword); 8496 modifiers.staticKeyword);
9093 } 8497 }
9094 } 8498 }
9095 8499
9096 /** 8500 /**
9097 * Validate that the given set of modifiers is appropriate for a top-level fun ction. 8501 * Validate that the given set of [modifiers] is appropriate for a top-level
9098 * 8502 * function.
9099 * @param modifiers the modifiers being validated
9100 */ 8503 */
9101 void _validateModifiersForTopLevelFunction(Modifiers modifiers) { 8504 void _validateModifiersForTopLevelFunction(Modifiers modifiers) {
9102 _validateModifiersForTopLevelDeclaration(modifiers); 8505 _validateModifiersForTopLevelDeclaration(modifiers);
9103 if (modifiers.abstractKeyword != null) { 8506 if (modifiers.abstractKeyword != null) {
9104 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION); 8507 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION);
9105 } 8508 }
9106 if (modifiers.constKeyword != null) { 8509 if (modifiers.constKeyword != null) {
9107 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword); 8510 _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
9108 } 8511 }
9109 if (modifiers.finalKeyword != null) { 8512 if (modifiers.finalKeyword != null) {
9110 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword); 8513 _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
9111 } 8514 }
9112 if (modifiers.varKeyword != null) { 8515 if (modifiers.varKeyword != null) {
9113 _reportErrorForToken( 8516 _reportErrorForToken(
9114 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword); 8517 ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
9115 } 8518 }
9116 } 8519 }
9117 8520
9118 /** 8521 /**
9119 * Validate that the given set of modifiers is appropriate for a field and ret urn the 'final', 8522 * Validate that the given set of [modifiers] is appropriate for a field and
9120 * 'const' or 'var' keyword if there is one. 8523 * return the 'final', 'const' or 'var' keyword if there is one.
9121 *
9122 * @param modifiers the modifiers being validated
9123 * @return the 'final', 'const' or 'var' keyword associated with the field
9124 */ 8524 */
9125 Token _validateModifiersForTopLevelVariable(Modifiers modifiers) { 8525 Token _validateModifiersForTopLevelVariable(Modifiers modifiers) {
9126 _validateModifiersForTopLevelDeclaration(modifiers); 8526 _validateModifiersForTopLevelDeclaration(modifiers);
9127 if (modifiers.abstractKeyword != null) { 8527 if (modifiers.abstractKeyword != null) {
9128 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE); 8528 _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE);
9129 } 8529 }
9130 if (modifiers.externalKeyword != null) { 8530 if (modifiers.externalKeyword != null) {
9131 _reportErrorForToken( 8531 _reportErrorForToken(
9132 ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword); 8532 ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
9133 } 8533 }
9134 Token constKeyword = modifiers.constKeyword; 8534 Token constKeyword = modifiers.constKeyword;
9135 Token finalKeyword = modifiers.finalKeyword; 8535 Token finalKeyword = modifiers.finalKeyword;
9136 Token varKeyword = modifiers.varKeyword; 8536 Token varKeyword = modifiers.varKeyword;
9137 if (constKeyword != null) { 8537 if (constKeyword != null) {
9138 if (finalKeyword != null) { 8538 if (finalKeyword != null) {
9139 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword); 8539 _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
9140 } 8540 }
9141 if (varKeyword != null) { 8541 if (varKeyword != null) {
9142 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword); 8542 _reportErrorForToken(ParserErrorCode.CONST_AND_VAR, varKeyword);
9143 } 8543 }
9144 } else if (finalKeyword != null) { 8544 } else if (finalKeyword != null) {
9145 if (varKeyword != null) { 8545 if (varKeyword != null) {
9146 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword); 8546 _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
9147 } 8547 }
9148 } 8548 }
9149 return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]); 8549 return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
9150 } 8550 }
9151 8551
9152 /** 8552 /**
9153 * Validate that the given set of modifiers is appropriate for a class and ret urn the 'abstract' 8553 * Validate that the given set of [modifiers] is appropriate for a class and
9154 * keyword if there is one. 8554 * return the 'abstract' keyword if there is one.
9155 *
9156 * @param modifiers the modifiers being validated
9157 */ 8555 */
9158 void _validateModifiersForTypedef(Modifiers modifiers) { 8556 void _validateModifiersForTypedef(Modifiers modifiers) {
9159 _validateModifiersForTopLevelDeclaration(modifiers); 8557 _validateModifiersForTopLevelDeclaration(modifiers);
9160 if (modifiers.abstractKeyword != null) { 8558 if (modifiers.abstractKeyword != null) {
9161 _reportErrorForToken( 8559 _reportErrorForToken(
9162 ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword); 8560 ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword);
9163 } 8561 }
9164 if (modifiers.constKeyword != null) { 8562 if (modifiers.constKeyword != null) {
9165 _reportErrorForToken( 8563 _reportErrorForToken(
9166 ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword); 8564 ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword);
9167 } 8565 }
9168 if (modifiers.externalKeyword != null) { 8566 if (modifiers.externalKeyword != null) {
9169 _reportErrorForToken( 8567 _reportErrorForToken(
9170 ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword); 8568 ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword);
9171 } 8569 }
9172 if (modifiers.finalKeyword != null) { 8570 if (modifiers.finalKeyword != null) {
9173 _reportErrorForToken( 8571 _reportErrorForToken(
9174 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword); 8572 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword);
9175 } 8573 }
9176 if (modifiers.varKeyword != null) { 8574 if (modifiers.varKeyword != null) {
9177 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword); 8575 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword);
9178 } 8576 }
9179 } 8577 }
9180 } 8578 }
9181 /** 8579 /**
9182 * Instances of the class `SyntheticKeywordToken` implement a synthetic keyword token. 8580 * A synthetic keyword token.
9183 */ 8581 */
9184 class Parser_SyntheticKeywordToken extends KeywordToken { 8582 class Parser_SyntheticKeywordToken extends KeywordToken {
9185 /** 8583 /**
9186 * Initialize a newly created token to represent the given keyword. 8584 * Initialize a newly created token to represent the given [keyword] at the
9187 * 8585 * given [offset].
9188 * @param keyword the keyword being represented by this token
9189 * @param offset the offset from the beginning of the file to the first charac ter in the token
9190 */ 8586 */
9191 Parser_SyntheticKeywordToken(Keyword keyword, int offset) 8587 Parser_SyntheticKeywordToken(Keyword keyword, int offset)
9192 : super(keyword, offset); 8588 : super(keyword, offset);
9193 8589
9194 @override 8590 @override
9195 int get length => 0; 8591 int get length => 0;
9196 8592
9197 @override 8593 @override
9198 Token copy() => new Parser_SyntheticKeywordToken(keyword, offset); 8594 Token copy() => new Parser_SyntheticKeywordToken(keyword, offset);
9199 } 8595 }
9200 8596
9201 /** 8597 /**
9202 * The enumeration `ParserErrorCode` defines the error codes used for errors 8598 * The error codes used for errors detected by the parser. The convention for
9203 * detected by the parser. The convention for this class is for the name of the 8599 * this class is for the name of the error code to indicate the problem that
9204 * error code to indicate the problem that caused the error to be generated and 8600 * caused the error to be generated and for the error message to explain what
9205 * for the error message to explain what is wrong and, when appropriate, how the 8601 * is wrong and, when appropriate, how the problem can be corrected.
9206 * problem can be corrected.
9207 */ 8602 */
9208 class ParserErrorCode extends ErrorCode { 8603 class ParserErrorCode extends ErrorCode {
9209 static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode( 8604 static const ParserErrorCode ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
9210 'ABSTRACT_CLASS_MEMBER', 8605 'ABSTRACT_CLASS_MEMBER',
9211 "Members of classes cannot be declared to be 'abstract'"); 8606 "Members of classes cannot be declared to be 'abstract'");
9212 8607
9213 static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode( 8608 static const ParserErrorCode ABSTRACT_ENUM = const ParserErrorCode(
9214 'ABSTRACT_ENUM', "Enums cannot be declared to be 'abstract'"); 8609 'ABSTRACT_ENUM', "Enums cannot be declared to be 'abstract'");
9215 8610
9216 static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode( 8611 static const ParserErrorCode ABSTRACT_STATIC_METHOD = const ParserErrorCode(
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
9813 : super(name, message, correction); 9208 : super(name, message, correction);
9814 9209
9815 @override 9210 @override
9816 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; 9211 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
9817 9212
9818 @override 9213 @override
9819 ErrorType get type => ErrorType.SYNTACTIC_ERROR; 9214 ErrorType get type => ErrorType.SYNTACTIC_ERROR;
9820 } 9215 }
9821 9216
9822 /** 9217 /**
9823 * Instances of the class `ResolutionCopier` copies resolution information from one AST 9218 * An object that copies resolution information from one AST structure to
9824 * structure to another as long as the structures of the corresponding children of a pair of nodes 9219 * another as long as the structures of the corresponding children of a pair of
9825 * are the same. 9220 * nodes are the same.
9826 */ 9221 */
9827 class ResolutionCopier implements AstVisitor<bool> { 9222 class ResolutionCopier implements AstVisitor<bool> {
9828 /** 9223 /**
9829 * The AST node with which the node being visited is to be compared. This is o nly valid at the 9224 * The AST node with which the node being visited is to be compared. This is
9830 * beginning of each visit method (until [isEqualNodes] is invoked). 9225 * only valid at the beginning of each visit method (until [isEqualNodes] is
9226 * invoked).
9831 */ 9227 */
9832 AstNode _toNode; 9228 AstNode _toNode;
9833 9229
9834 @override 9230 @override
9835 bool visitAdjacentStrings(AdjacentStrings node) { 9231 bool visitAdjacentStrings(AdjacentStrings node) {
9836 AdjacentStrings toNode = this._toNode as AdjacentStrings; 9232 AdjacentStrings toNode = this._toNode as AdjacentStrings;
9837 return _isEqualNodeLists(node.strings, toNode.strings); 9233 return _isEqualNodeLists(node.strings, toNode.strings);
9838 } 9234 }
9839 9235
9840 @override 9236 @override
(...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after
11027 _isEqualNodes(node.expression, toNode.expression), 10423 _isEqualNodes(node.expression, toNode.expression),
11028 _isEqualTokens(node.semicolon, toNode.semicolon)); 10424 _isEqualTokens(node.semicolon, toNode.semicolon));
11029 } 10425 }
11030 10426
11031 /** 10427 /**
11032 * Return `true` if all of the parameters are `true`. 10428 * Return `true` if all of the parameters are `true`.
11033 */ 10429 */
11034 bool _and(bool b1, bool b2, [bool b3 = true, bool b4 = true, bool b5 = true, 10430 bool _and(bool b1, bool b2, [bool b3 = true, bool b4 = true, bool b5 = true,
11035 bool b6 = true, bool b7 = true, bool b8 = true, bool b9 = true, 10431 bool b6 = true, bool b7 = true, bool b8 = true, bool b9 = true,
11036 bool b10 = true, bool b11 = true, bool b12 = true, bool b13 = true]) { 10432 bool b10 = true, bool b11 = true, bool b12 = true, bool b13 = true]) {
10433 // TODO(brianwilkerson) Inline this method.
11037 return b1 && 10434 return b1 &&
11038 b2 && 10435 b2 &&
11039 b3 && 10436 b3 &&
11040 b4 && 10437 b4 &&
11041 b5 && 10438 b5 &&
11042 b6 && 10439 b6 &&
11043 b7 && 10440 b7 &&
11044 b8 && 10441 b8 &&
11045 b9 && 10442 b9 &&
11046 b10 && 10443 b10 &&
11047 b11 && 10444 b11 &&
11048 b12 && 10445 b12 &&
11049 b13; 10446 b13;
11050 } 10447 }
11051 10448
11052 /** 10449 /**
11053 * Return `true` if the given lists of AST nodes have the same size and corres ponding 10450 * Return `true` if the [first] and [second] lists of AST nodes have the same
11054 * elements are equal. 10451 * size and corresponding elements are equal.
11055 *
11056 * @param first the first node being compared
11057 * @param second the second node being compared
11058 * @return `true` if the given AST nodes have the same size and corresponding elements are
11059 * equal
11060 */ 10452 */
11061 bool _isEqualNodeLists(NodeList first, NodeList second) { 10453 bool _isEqualNodeLists(NodeList first, NodeList second) {
11062 if (first == null) { 10454 if (first == null) {
11063 return second == null; 10455 return second == null;
11064 } else if (second == null) { 10456 } else if (second == null) {
11065 return false; 10457 return false;
11066 } 10458 }
11067 int size = first.length; 10459 int size = first.length;
11068 if (second.length != size) { 10460 if (second.length != size) {
11069 return false; 10461 return false;
11070 } 10462 }
11071 bool equal = true; 10463 bool equal = true;
11072 for (int i = 0; i < size; i++) { 10464 for (int i = 0; i < size; i++) {
11073 if (!_isEqualNodes(first[i], second[i])) { 10465 if (!_isEqualNodes(first[i], second[i])) {
11074 equal = false; 10466 equal = false;
11075 } 10467 }
11076 } 10468 }
11077 return equal; 10469 return equal;
11078 } 10470 }
11079 10471
11080 /** 10472 /**
11081 * Return `true` if the given AST nodes have the same structure. As a side-eff ect, if the 10473 * Return `true` if the [fromNode] and [toNode] have the same structure. As a
11082 * nodes do have the same structure, any resolution data from the first node w ill be copied to the 10474 * side-effect, if the nodes do have the same structure, any resolution data
11083 * second node. 10475 * from the first node will be copied to the second node.
11084 *
11085 * @param fromNode the node from which resolution information will be copied
11086 * @param toNode the node to which resolution information will be copied
11087 * @return `true` if the given AST nodes have the same structure
11088 */ 10476 */
11089 bool _isEqualNodes(AstNode fromNode, AstNode toNode) { 10477 bool _isEqualNodes(AstNode fromNode, AstNode toNode) {
11090 if (fromNode == null) { 10478 if (fromNode == null) {
11091 return toNode == null; 10479 return toNode == null;
11092 } else if (toNode == null) { 10480 } else if (toNode == null) {
11093 return false; 10481 return false;
11094 } else if (fromNode.runtimeType == toNode.runtimeType) { 10482 } else if (fromNode.runtimeType == toNode.runtimeType) {
11095 this._toNode = toNode; 10483 this._toNode = toNode;
11096 return fromNode.accept(this); 10484 return fromNode.accept(this);
11097 } 10485 }
(...skipping 10 matching lines...) Expand all
11108 Expression target = toNode.target; 10496 Expression target = toNode.target;
11109 if (fromNode.runtimeType == target.runtimeType) { 10497 if (fromNode.runtimeType == target.runtimeType) {
11110 this._toNode = target; 10498 this._toNode = target;
11111 return fromNode.accept(this); 10499 return fromNode.accept(this);
11112 } 10500 }
11113 } 10501 }
11114 return false; 10502 return false;
11115 } 10503 }
11116 10504
11117 /** 10505 /**
11118 * Return `true` if the given arrays of tokens have the same length and corres ponding 10506 * Return `true` if the [first] and [second] arrays of tokens have the same
11119 * elements are equal. 10507 * length and corresponding elements are equal.
11120 *
11121 * @param first the first node being compared
11122 * @param second the second node being compared
11123 * @return `true` if the given arrays of tokens have the same length and corre sponding
11124 * elements are equal
11125 */ 10508 */
11126 bool _isEqualTokenLists(List<Token> first, List<Token> second) { 10509 bool _isEqualTokenLists(List<Token> first, List<Token> second) {
11127 int length = first.length; 10510 int length = first.length;
11128 if (second.length != length) { 10511 if (second.length != length) {
11129 return false; 10512 return false;
11130 } 10513 }
11131 for (int i = 0; i < length; i++) { 10514 for (int i = 0; i < length; i++) {
11132 if (!_isEqualTokens(first[i], second[i])) { 10515 if (!_isEqualTokens(first[i], second[i])) {
11133 return false; 10516 return false;
11134 } 10517 }
11135 } 10518 }
11136 return true; 10519 return true;
11137 } 10520 }
11138 10521
11139 /** 10522 /**
11140 * Return `true` if the given tokens have the same structure. 10523 * Return `true` if the [first] and [second] tokens have the same structure.
11141 *
11142 * @param first the first node being compared
11143 * @param second the second node being compared
11144 * @return `true` if the given tokens have the same structure
11145 */ 10524 */
11146 bool _isEqualTokens(Token first, Token second) { 10525 bool _isEqualTokens(Token first, Token second) {
11147 if (first == null) { 10526 if (first == null) {
11148 return second == null; 10527 return second == null;
11149 } else if (second == null) { 10528 } else if (second == null) {
11150 return false; 10529 return false;
11151 } 10530 }
11152 return first.lexeme == second.lexeme; 10531 return first.lexeme == second.lexeme;
11153 } 10532 }
11154 10533
11155 /** 10534 /**
11156 * Copy resolution data from one node to another. 10535 * Copy resolution data from the [fromNode] to the [toNode].
11157 *
11158 * @param fromNode the node from which resolution information will be copied
11159 * @param toNode the node to which resolution information will be copied
11160 */ 10536 */
11161 static void copyResolutionData(AstNode fromNode, AstNode toNode) { 10537 static void copyResolutionData(AstNode fromNode, AstNode toNode) {
11162 ResolutionCopier copier = new ResolutionCopier(); 10538 ResolutionCopier copier = new ResolutionCopier();
11163 copier._isEqualNodes(fromNode, toNode); 10539 copier._isEqualNodes(fromNode, toNode);
11164 } 10540 }
11165 } 10541 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698