| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |