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 library analyzer.src.generated.parser; | 5 library analyzer.src.generated.parser; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import "dart:math" as math; | 8 import "dart:math" as math; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 new MethodTrampoline(0, (Parser target) => target.parseReturnType()), | 83 new MethodTrampoline(0, (Parser target) => target.parseReturnType()), |
84 'parseSimpleIdentifier_0': new MethodTrampoline( | 84 'parseSimpleIdentifier_0': new MethodTrampoline( |
85 0, (Parser target) => target.parseSimpleIdentifier()), | 85 0, (Parser target) => target.parseSimpleIdentifier()), |
86 'parseStatement_0': | 86 'parseStatement_0': |
87 new MethodTrampoline(0, (Parser target) => target.parseStatement2()), | 87 new MethodTrampoline(0, (Parser target) => target.parseStatement2()), |
88 'parseStringLiteral_0': | 88 'parseStringLiteral_0': |
89 new MethodTrampoline(0, (Parser target) => target.parseStringLiteral()), | 89 new MethodTrampoline(0, (Parser target) => target.parseStringLiteral()), |
90 'parseTypeArgumentList_0': new MethodTrampoline( | 90 'parseTypeArgumentList_0': new MethodTrampoline( |
91 0, (Parser target) => target.parseTypeArgumentList()), | 91 0, (Parser target) => target.parseTypeArgumentList()), |
92 'parseTypeName_0': | 92 'parseTypeName_0': |
93 new MethodTrampoline(0, (Parser target) => target.parseTypeName()), | 93 new MethodTrampoline(0, (Parser target) => target.parseTypeName(false)), |
94 'parseTypeParameter_0': | 94 'parseTypeParameter_0': |
95 new MethodTrampoline(0, (Parser target) => target.parseTypeParameter()), | 95 new MethodTrampoline(0, (Parser target) => target.parseTypeParameter()), |
96 'parseTypeParameterList_0': new MethodTrampoline( | 96 'parseTypeParameterList_0': new MethodTrampoline( |
97 0, (Parser target) => target.parseTypeParameterList()), | 97 0, (Parser target) => target.parseTypeParameterList()), |
98 'parseWithClause_0': | 98 'parseWithClause_0': |
99 new MethodTrampoline(0, (Parser target) => target.parseWithClause()), | 99 new MethodTrampoline(0, (Parser target) => target.parseWithClause()), |
100 'advance_0': new MethodTrampoline(0, (Parser target) => target._advance()), | 100 'advance_0': new MethodTrampoline(0, (Parser target) => target._advance()), |
101 'appendScalarValue_5': new MethodTrampoline( | 101 'appendScalarValue_5': new MethodTrampoline( |
102 5, | 102 5, |
103 (Parser target, arg0, arg1, arg2, arg3, arg4) => | 103 (Parser target, arg0, arg1, arg2, arg3, arg4) => |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 */ | 676 */ |
677 int _errorListenerLock = 0; | 677 int _errorListenerLock = 0; |
678 | 678 |
679 /** | 679 /** |
680 * A flag indicating whether the parser is to parse asserts in the initializer | 680 * A flag indicating whether the parser is to parse asserts in the initializer |
681 * list of a constructor. | 681 * list of a constructor. |
682 */ | 682 */ |
683 bool _enableAssertInitializer = false; | 683 bool _enableAssertInitializer = false; |
684 | 684 |
685 /** | 685 /** |
| 686 * A flag indicating whether the parser is to parse the non-nullable modifier |
| 687 * in type names. |
| 688 */ |
| 689 bool _enableNnbd = false; |
| 690 |
| 691 /** |
686 * A flag indicating whether the parser is to parse the async support. | 692 * A flag indicating whether the parser is to parse the async support. |
687 */ | 693 */ |
688 bool _parseAsync = true; | 694 bool _parseAsync = true; |
689 | 695 |
690 /** | 696 /** |
691 * A flag indicating whether parser is to parse function bodies. | 697 * A flag indicating whether parser is to parse function bodies. |
692 */ | 698 */ |
693 bool _parseFunctionBodies = true; | 699 bool _parseFunctionBodies = true; |
694 | 700 |
695 /** | 701 /** |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 | 763 |
758 /** | 764 /** |
759 * Set whether the parser is to parse asserts in the initializer list of a | 765 * Set whether the parser is to parse asserts in the initializer list of a |
760 * constructor to match the given [enable] flag. | 766 * constructor to match the given [enable] flag. |
761 */ | 767 */ |
762 void set enableAssertInitializer(bool enable) { | 768 void set enableAssertInitializer(bool enable) { |
763 _enableAssertInitializer = enable; | 769 _enableAssertInitializer = enable; |
764 } | 770 } |
765 | 771 |
766 /** | 772 /** |
| 773 * Return `true` if the parser is to parse the non-nullable modifier in type |
| 774 * names. |
| 775 */ |
| 776 bool get enableNnbd => _enableNnbd; |
| 777 |
| 778 /** |
| 779 * Set whether the parser is to parse the non-nullable modifier in type names |
| 780 * to match the given [enable] flag. |
| 781 */ |
| 782 void set enableNnbd(bool enable) { |
| 783 _enableNnbd = enable; |
| 784 } |
| 785 |
| 786 /** |
767 * Return `true` if the current token is the first token of a return type that | 787 * Return `true` if the current token is the first token of a return type that |
768 * is followed by an identifier, possibly followed by a list of type | 788 * is followed by an identifier, possibly followed by a list of type |
769 * parameters, followed by a left-parenthesis. This is used by | 789 * parameters, followed by a left-parenthesis. This is used by |
770 * [_parseTypeAlias] to determine whether or not to parse a return type. | 790 * [_parseTypeAlias] to determine whether or not to parse a return type. |
771 */ | 791 */ |
772 @deprecated | 792 @deprecated |
773 bool get hasReturnTypeInTypeAlias { | 793 bool get hasReturnTypeInTypeAlias { |
774 Token next = _skipReturnType(_currentToken); | 794 Token next = _skipReturnType(_currentToken); |
775 if (next == null) { | 795 if (next == null) { |
776 return false; | 796 return false; |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 } | 1534 } |
1515 | 1535 |
1516 /** | 1536 /** |
1517 * Parse the name of a constructor. Return the constructor name that was | 1537 * Parse the name of a constructor. Return the constructor name that was |
1518 * parsed. | 1538 * parsed. |
1519 * | 1539 * |
1520 * constructorName: | 1540 * constructorName: |
1521 * type ('.' identifier)? | 1541 * type ('.' identifier)? |
1522 */ | 1542 */ |
1523 ConstructorName parseConstructorName() { | 1543 ConstructorName parseConstructorName() { |
1524 TypeName type = parseTypeName(); | 1544 TypeName type = parseTypeName(false); |
1525 Token period = null; | 1545 Token period = null; |
1526 SimpleIdentifier name = null; | 1546 SimpleIdentifier name = null; |
1527 if (_matches(TokenType.PERIOD)) { | 1547 if (_matches(TokenType.PERIOD)) { |
1528 period = getAndAdvance(); | 1548 period = getAndAdvance(); |
1529 name = parseSimpleIdentifier(); | 1549 name = parseSimpleIdentifier(); |
1530 } | 1550 } |
1531 return new ConstructorName(type, period, name); | 1551 return new ConstructorName(type, period, name); |
1532 } | 1552 } |
1533 | 1553 |
1534 /** | 1554 /** |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1630 * Parse a class extends clause. Return the class extends clause that was | 1650 * Parse a class extends clause. Return the class extends clause that was |
1631 * parsed. | 1651 * parsed. |
1632 * | 1652 * |
1633 * This method assumes that the current token matches `Keyword.EXTENDS`. | 1653 * This method assumes that the current token matches `Keyword.EXTENDS`. |
1634 * | 1654 * |
1635 * classExtendsClause ::= | 1655 * classExtendsClause ::= |
1636 * 'extends' type | 1656 * 'extends' type |
1637 */ | 1657 */ |
1638 ExtendsClause parseExtendsClause() { | 1658 ExtendsClause parseExtendsClause() { |
1639 Token keyword = getAndAdvance(); | 1659 Token keyword = getAndAdvance(); |
1640 TypeName superclass = parseTypeName(); | 1660 TypeName superclass = parseTypeName(false); |
1641 return new ExtendsClause(keyword, superclass); | 1661 return new ExtendsClause(keyword, superclass); |
1642 } | 1662 } |
1643 | 1663 |
1644 /** | 1664 /** |
1645 * Parse a list of formal parameters. Return the formal parameters that were | 1665 * Parse a list of formal parameters. Return the formal parameters that were |
1646 * parsed. | 1666 * parsed. |
1647 * | 1667 * |
1648 * formalParameterList ::= | 1668 * formalParameterList ::= |
1649 * '(' ')' | 1669 * '(' ')' |
1650 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' | 1670 * | '(' normalFormalParameters (',' optionalFormalParameters)? ')' |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1711 * Parse an implements clause. Return the implements clause that was parsed. | 1731 * Parse an implements clause. Return the implements clause that was parsed. |
1712 * | 1732 * |
1713 * This method assumes that the current token matches `Keyword.IMPLEMENTS`. | 1733 * This method assumes that the current token matches `Keyword.IMPLEMENTS`. |
1714 * | 1734 * |
1715 * implementsClause ::= | 1735 * implementsClause ::= |
1716 * 'implements' type (',' type)* | 1736 * 'implements' type (',' type)* |
1717 */ | 1737 */ |
1718 ImplementsClause parseImplementsClause() { | 1738 ImplementsClause parseImplementsClause() { |
1719 Token keyword = getAndAdvance(); | 1739 Token keyword = getAndAdvance(); |
1720 List<TypeName> interfaces = <TypeName>[]; | 1740 List<TypeName> interfaces = <TypeName>[]; |
1721 interfaces.add(parseTypeName()); | 1741 interfaces.add(parseTypeName(false)); |
1722 while (_optional(TokenType.COMMA)) { | 1742 while (_optional(TokenType.COMMA)) { |
1723 interfaces.add(parseTypeName()); | 1743 interfaces.add(parseTypeName(false)); |
1724 } | 1744 } |
1725 return new ImplementsClause(keyword, interfaces); | 1745 return new ImplementsClause(keyword, interfaces); |
1726 } | 1746 } |
1727 | 1747 |
1728 /** | 1748 /** |
1729 * Parse a label. Return the label that was parsed. | 1749 * Parse a label. Return the label that was parsed. |
1730 * | 1750 * |
1731 * This method assumes that the current token matches an identifier and that | 1751 * This method assumes that the current token matches an identifier and that |
1732 * the following token matches `TokenType.COLON`. | 1752 * the following token matches `TokenType.COLON`. |
1733 * | 1753 * |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 } | 1835 } |
1816 SimpleIdentifier identifier = parseSimpleIdentifier(); | 1836 SimpleIdentifier identifier = parseSimpleIdentifier(); |
1817 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); | 1837 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
1818 if (_matches(TokenType.OPEN_PAREN)) { | 1838 if (_matches(TokenType.OPEN_PAREN)) { |
1819 FormalParameterList parameters = _parseFormalParameterListUnchecked(); | 1839 FormalParameterList parameters = _parseFormalParameterListUnchecked(); |
1820 if (thisKeyword == null) { | 1840 if (thisKeyword == null) { |
1821 if (holder.keyword != null) { | 1841 if (holder.keyword != null) { |
1822 _reportErrorForToken( | 1842 _reportErrorForToken( |
1823 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); | 1843 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); |
1824 } | 1844 } |
| 1845 Token question = null; |
| 1846 if (enableNnbd && _matches(TokenType.QUESTION)) { |
| 1847 question = getAndAdvance(); |
| 1848 } |
1825 return new FunctionTypedFormalParameter( | 1849 return new FunctionTypedFormalParameter( |
1826 commentAndMetadata.comment, | 1850 commentAndMetadata.comment, |
1827 commentAndMetadata.metadata, | 1851 commentAndMetadata.metadata, |
1828 holder.type, | 1852 holder.type, |
1829 new SimpleIdentifier(identifier.token, isDeclaration: true), | 1853 new SimpleIdentifier(identifier.token, isDeclaration: true), |
1830 typeParameters, | 1854 typeParameters, |
1831 parameters); | 1855 parameters, |
| 1856 question: question); |
1832 } else { | 1857 } else { |
1833 return new FieldFormalParameter( | 1858 return new FieldFormalParameter( |
1834 commentAndMetadata.comment, | 1859 commentAndMetadata.comment, |
1835 commentAndMetadata.metadata, | 1860 commentAndMetadata.metadata, |
1836 holder.keyword, | 1861 holder.keyword, |
1837 holder.type, | 1862 holder.type, |
1838 thisKeyword, | 1863 thisKeyword, |
1839 period, | 1864 period, |
1840 identifier, | 1865 identifier, |
1841 typeParameters, | 1866 typeParameters, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1894 * Parse a return type. Return the return type that was parsed. | 1919 * Parse a return type. Return the return type that was parsed. |
1895 * | 1920 * |
1896 * returnType ::= | 1921 * returnType ::= |
1897 * 'void' | 1922 * 'void' |
1898 * | type | 1923 * | type |
1899 */ | 1924 */ |
1900 TypeName parseReturnType() { | 1925 TypeName parseReturnType() { |
1901 if (_currentToken.keyword == Keyword.VOID) { | 1926 if (_currentToken.keyword == Keyword.VOID) { |
1902 return new TypeName(new SimpleIdentifier(getAndAdvance()), null); | 1927 return new TypeName(new SimpleIdentifier(getAndAdvance()), null); |
1903 } else { | 1928 } else { |
1904 return parseTypeName(); | 1929 return parseTypeName(false); |
1905 } | 1930 } |
1906 } | 1931 } |
1907 | 1932 |
1908 /** | 1933 /** |
1909 * Parse a simple identifier. Return the simple identifier that was parsed. | 1934 * Parse a simple identifier. Return the simple identifier that was parsed. |
1910 * | 1935 * |
1911 * identifier ::= | 1936 * identifier ::= |
1912 * IDENTIFIER | 1937 * IDENTIFIER |
1913 */ | 1938 */ |
1914 SimpleIdentifier parseSimpleIdentifier({bool isDeclaration: false}) { | 1939 SimpleIdentifier parseSimpleIdentifier({bool isDeclaration: false}) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 * This method assumes that the current token matches `TokenType.LT`. | 2009 * This method assumes that the current token matches `TokenType.LT`. |
1985 * | 2010 * |
1986 * typeArguments ::= | 2011 * typeArguments ::= |
1987 * '<' typeList '>' | 2012 * '<' typeList '>' |
1988 * | 2013 * |
1989 * typeList ::= | 2014 * typeList ::= |
1990 * type (',' type)* | 2015 * type (',' type)* |
1991 */ | 2016 */ |
1992 TypeArgumentList parseTypeArgumentList() { | 2017 TypeArgumentList parseTypeArgumentList() { |
1993 Token leftBracket = getAndAdvance(); | 2018 Token leftBracket = getAndAdvance(); |
1994 List<TypeName> arguments = <TypeName>[parseTypeName()]; | 2019 List<TypeName> arguments = <TypeName>[parseTypeName(false)]; |
1995 while (_optional(TokenType.COMMA)) { | 2020 while (_optional(TokenType.COMMA)) { |
1996 arguments.add(parseTypeName()); | 2021 arguments.add(parseTypeName(false)); |
1997 } | 2022 } |
1998 Token rightBracket = _expectGt(); | 2023 Token rightBracket = _expectGt(); |
1999 return new TypeArgumentList(leftBracket, arguments, rightBracket); | 2024 return new TypeArgumentList(leftBracket, arguments, rightBracket); |
2000 } | 2025 } |
2001 | 2026 |
2002 /** | 2027 /** |
2003 * Parse a type name. Return the type name that was parsed. | 2028 * Parse a type name. Return the type name that was parsed. |
2004 * | 2029 * |
2005 * type ::= | 2030 * type ::= |
2006 * qualified typeArguments? | 2031 * qualified typeArguments? |
2007 */ | 2032 */ |
2008 TypeName parseTypeName() { | 2033 TypeName parseTypeName(bool inExpression) { |
2009 TypeName realType = _parseTypeName(); | 2034 TypeName realType = _parseTypeName(inExpression); |
2010 // If this is followed by a generic method type comment, allow the comment | 2035 // If this is followed by a generic method type comment, allow the comment |
2011 // type to replace the real type name. | 2036 // type to replace the real type name. |
2012 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to | 2037 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to |
2013 // only work inside generic methods? | 2038 // only work inside generic methods? |
2014 TypeName typeFromComment = _parseOptionalTypeNameComment(); | 2039 TypeName typeFromComment = _parseOptionalTypeNameComment(); |
2015 return typeFromComment ?? realType; | 2040 return typeFromComment ?? realType; |
2016 } | 2041 } |
2017 | 2042 |
2018 /** | 2043 /** |
2019 * Parse a type parameter. Return the type parameter that was parsed. | 2044 * Parse a type parameter. Return the type parameter that was parsed. |
2020 * | 2045 * |
2021 * typeParameter ::= | 2046 * typeParameter ::= |
2022 * metadata name ('extends' bound)? | 2047 * metadata name ('extends' bound)? |
2023 */ | 2048 */ |
2024 TypeParameter parseTypeParameter() { | 2049 TypeParameter parseTypeParameter() { |
2025 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); | 2050 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
2026 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); | 2051 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); |
2027 if (_matchesKeyword(Keyword.EXTENDS)) { | 2052 if (_matchesKeyword(Keyword.EXTENDS)) { |
2028 Token keyword = getAndAdvance(); | 2053 Token keyword = getAndAdvance(); |
2029 TypeName bound = parseTypeName(); | 2054 TypeName bound = parseTypeName(false); |
2030 return new TypeParameter(commentAndMetadata.comment, | 2055 return new TypeParameter(commentAndMetadata.comment, |
2031 commentAndMetadata.metadata, name, keyword, bound); | 2056 commentAndMetadata.metadata, name, keyword, bound); |
2032 } | 2057 } |
2033 return new TypeParameter(commentAndMetadata.comment, | 2058 return new TypeParameter(commentAndMetadata.comment, |
2034 commentAndMetadata.metadata, name, null, null); | 2059 commentAndMetadata.metadata, name, null, null); |
2035 } | 2060 } |
2036 | 2061 |
2037 /** | 2062 /** |
2038 * Parse a list of type parameters. Return the list of type parameters that | 2063 * Parse a list of type parameters. Return the list of type parameters that |
2039 * were parsed. | 2064 * were parsed. |
(...skipping 16 matching lines...) Expand all Loading... |
2056 /** | 2081 /** |
2057 * Parse a with clause. Return the with clause that was parsed. | 2082 * Parse a with clause. Return the with clause that was parsed. |
2058 * | 2083 * |
2059 * This method assumes that the current token matches `Keyword.WITH`. | 2084 * This method assumes that the current token matches `Keyword.WITH`. |
2060 * | 2085 * |
2061 * withClause ::= | 2086 * withClause ::= |
2062 * 'with' typeName (',' typeName)* | 2087 * 'with' typeName (',' typeName)* |
2063 */ | 2088 */ |
2064 WithClause parseWithClause() { | 2089 WithClause parseWithClause() { |
2065 Token withKeyword = getAndAdvance(); | 2090 Token withKeyword = getAndAdvance(); |
2066 List<TypeName> types = <TypeName>[parseTypeName()]; | 2091 List<TypeName> types = <TypeName>[parseTypeName(false)]; |
2067 while (_optional(TokenType.COMMA)) { | 2092 while (_optional(TokenType.COMMA)) { |
2068 types.add(parseTypeName()); | 2093 types.add(parseTypeName(false)); |
2069 } | 2094 } |
2070 return new WithClause(withKeyword, types); | 2095 return new WithClause(withKeyword, types); |
2071 } | 2096 } |
2072 | 2097 |
2073 /** | 2098 /** |
2074 * Advance to the next token in the token stream. | 2099 * Advance to the next token in the token stream. |
2075 */ | 2100 */ |
2076 void _advance() { | 2101 void _advance() { |
2077 _currentToken = _currentToken.next; | 2102 _currentToken = _currentToken.next; |
2078 } | 2103 } |
(...skipping 15 matching lines...) Expand all Loading... |
2094 return; | 2119 return; |
2095 } | 2120 } |
2096 if (scalarValue < Character.MAX_VALUE) { | 2121 if (scalarValue < Character.MAX_VALUE) { |
2097 buffer.writeCharCode(scalarValue); | 2122 buffer.writeCharCode(scalarValue); |
2098 } else { | 2123 } else { |
2099 buffer.write(Character.toChars(scalarValue)); | 2124 buffer.write(Character.toChars(scalarValue)); |
2100 } | 2125 } |
2101 } | 2126 } |
2102 | 2127 |
2103 /** | 2128 /** |
| 2129 * Clone all token starting from the given [token] up to the end of the token |
| 2130 * stream, and return the first token in the new token stream. |
| 2131 */ |
| 2132 Token _cloneTokens(Token token) { |
| 2133 if (token == null) { |
| 2134 return null; |
| 2135 } |
| 2136 token = token is CommentToken ? token.parent : token; |
| 2137 Token head = new Token(TokenType.EOF, -1); |
| 2138 head.setNext(head); |
| 2139 Token current = head; |
| 2140 while (token.type != TokenType.EOF) { |
| 2141 Token clone = token.copy(); |
| 2142 current.setNext(clone); |
| 2143 current = clone; |
| 2144 token = token.next; |
| 2145 } |
| 2146 Token tail = new Token(TokenType.EOF, 0); |
| 2147 tail.setNext(tail); |
| 2148 current.setNext(tail); |
| 2149 return head.next; |
| 2150 } |
| 2151 |
| 2152 /** |
2104 * Return the content of a string with the given literal representation. The | 2153 * Return the content of a string with the given literal representation. The |
2105 * [lexeme] is the literal representation of the string. The flag [isFirst] is | 2154 * [lexeme] is the literal representation of the string. The flag [isFirst] is |
2106 * `true` if this is the first token in a string literal. The flag [isLast] is | 2155 * `true` if this is the first token in a string literal. The flag [isLast] is |
2107 * `true` if this is the last token in a string literal. | 2156 * `true` if this is the last token in a string literal. |
2108 */ | 2157 */ |
2109 String _computeStringValue(String lexeme, bool isFirst, bool isLast) { | 2158 String _computeStringValue(String lexeme, bool isFirst, bool isLast) { |
2110 StringLexemeHelper helper = new StringLexemeHelper(lexeme, isFirst, isLast); | 2159 StringLexemeHelper helper = new StringLexemeHelper(lexeme, isFirst, isLast); |
2111 int start = helper.start; | 2160 int start = helper.start; |
2112 int end = helper.end; | 2161 int end = helper.end; |
2113 bool stringEndsAfterStart = end >= start; | 2162 bool stringEndsAfterStart = end >= start; |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2490 lastToken = lastToken.next; | 2539 lastToken = lastToken.next; |
2491 } | 2540 } |
2492 // Inject these new tokens into the stream. | 2541 // Inject these new tokens into the stream. |
2493 Token previous = _currentToken.previous; | 2542 Token previous = _currentToken.previous; |
2494 lastToken.setNext(_currentToken); | 2543 lastToken.setNext(_currentToken); |
2495 previous.setNext(firstToken); | 2544 previous.setNext(firstToken); |
2496 _currentToken = firstToken; | 2545 _currentToken = firstToken; |
2497 } | 2546 } |
2498 | 2547 |
2499 /** | 2548 /** |
| 2549 * Return `true` if the current token could be the question mark in a |
| 2550 * condition expression. The current token is assumed to be a question mark. |
| 2551 */ |
| 2552 bool _isConditionalOperator() { |
| 2553 void parseOperation(Parser parser) { |
| 2554 parser.parseExpressionWithoutCascade(); |
| 2555 } |
| 2556 |
| 2557 Token token = _skip(_currentToken.next, parseOperation); |
| 2558 if (token == null || !_tokenMatches(token, TokenType.COLON)) { |
| 2559 return false; |
| 2560 } |
| 2561 token = _skip(token.next, parseOperation); |
| 2562 return token != null; |
| 2563 } |
| 2564 |
| 2565 /** |
2500 * Return `true` if the current token appears to be the beginning of a | 2566 * Return `true` if the current token appears to be the beginning of a |
2501 * function declaration. | 2567 * function declaration. |
2502 */ | 2568 */ |
2503 bool _isFunctionDeclaration() { | 2569 bool _isFunctionDeclaration() { |
2504 Keyword keyword = _currentToken.keyword; | 2570 Keyword keyword = _currentToken.keyword; |
2505 if (keyword == Keyword.VOID) { | 2571 if (keyword == Keyword.VOID) { |
2506 return true; | 2572 return true; |
2507 } | 2573 } |
2508 Token afterReturnType = _skipTypeName(_currentToken); | 2574 Token afterReturnType = _skipTypeName(_currentToken); |
2509 if (afterReturnType == null) { | 2575 if (afterReturnType == null) { |
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3500 * mixinApplication ::= | 3566 * mixinApplication ::= |
3501 * type withClause implementsClause? ';' | 3567 * type withClause implementsClause? ';' |
3502 */ | 3568 */ |
3503 ClassTypeAlias _parseClassTypeAliasAfterName( | 3569 ClassTypeAlias _parseClassTypeAliasAfterName( |
3504 CommentAndMetadata commentAndMetadata, | 3570 CommentAndMetadata commentAndMetadata, |
3505 Token abstractKeyword, | 3571 Token abstractKeyword, |
3506 Token classKeyword, | 3572 Token classKeyword, |
3507 SimpleIdentifier className, | 3573 SimpleIdentifier className, |
3508 TypeParameterList typeParameters) { | 3574 TypeParameterList typeParameters) { |
3509 Token equals = _expect(TokenType.EQ); | 3575 Token equals = _expect(TokenType.EQ); |
3510 TypeName superclass = parseTypeName(); | 3576 TypeName superclass = parseTypeName(false); |
3511 WithClause withClause = null; | 3577 WithClause withClause = null; |
3512 if (_matchesKeyword(Keyword.WITH)) { | 3578 if (_matchesKeyword(Keyword.WITH)) { |
3513 withClause = parseWithClause(); | 3579 withClause = parseWithClause(); |
3514 } else { | 3580 } else { |
3515 _reportErrorForCurrentToken( | 3581 _reportErrorForCurrentToken( |
3516 ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.syntax]); | 3582 ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.syntax]); |
3517 } | 3583 } |
3518 ImplementsClause implementsClause = null; | 3584 ImplementsClause implementsClause = null; |
3519 if (_matchesKeyword(Keyword.IMPLEMENTS)) { | 3585 if (_matchesKeyword(Keyword.IMPLEMENTS)) { |
3520 implementsClause = parseImplementsClause(); | 3586 implementsClause = parseImplementsClause(); |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4573 * | 'var' | 4639 * | 'var' |
4574 * | type | 4640 * | type |
4575 */ | 4641 */ |
4576 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { | 4642 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { |
4577 Token keywordToken = null; | 4643 Token keywordToken = null; |
4578 TypeName type = null; | 4644 TypeName type = null; |
4579 Keyword keyword = _currentToken.keyword; | 4645 Keyword keyword = _currentToken.keyword; |
4580 if (keyword == Keyword.FINAL || keyword == Keyword.CONST) { | 4646 if (keyword == Keyword.FINAL || keyword == Keyword.CONST) { |
4581 keywordToken = getAndAdvance(); | 4647 keywordToken = getAndAdvance(); |
4582 if (_isTypedIdentifier(_currentToken)) { | 4648 if (_isTypedIdentifier(_currentToken)) { |
4583 type = parseTypeName(); | 4649 type = parseTypeName(false); |
4584 } else { | 4650 } else { |
4585 // Support `final/*=T*/ x;` | 4651 // Support `final/*=T*/ x;` |
4586 type = _parseOptionalTypeNameComment(); | 4652 type = _parseOptionalTypeNameComment(); |
4587 } | 4653 } |
4588 } else if (keyword == Keyword.VAR) { | 4654 } else if (keyword == Keyword.VAR) { |
4589 keywordToken = getAndAdvance(); | 4655 keywordToken = getAndAdvance(); |
4590 // Support `var/*=T*/ x;` | 4656 // Support `var/*=T*/ x;` |
4591 type = _parseOptionalTypeNameComment(); | 4657 type = _parseOptionalTypeNameComment(); |
4592 if (type != null) { | 4658 if (type != null) { |
4593 // Clear the keyword to prevent an error. | 4659 // Clear the keyword to prevent an error. |
(...skipping 1616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6210 */ | 6276 */ |
6211 TypeArgumentList _parseOptionalTypeArguments() { | 6277 TypeArgumentList _parseOptionalTypeArguments() { |
6212 if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) { | 6278 if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) { |
6213 return parseTypeArgumentList(); | 6279 return parseTypeArgumentList(); |
6214 } | 6280 } |
6215 return null; | 6281 return null; |
6216 } | 6282 } |
6217 | 6283 |
6218 TypeName _parseOptionalTypeNameComment() { | 6284 TypeName _parseOptionalTypeNameComment() { |
6219 if (_injectGenericCommentTypeAssign()) { | 6285 if (_injectGenericCommentTypeAssign()) { |
6220 return _parseTypeName(); | 6286 return _parseTypeName(false); |
6221 } | 6287 } |
6222 return null; | 6288 return null; |
6223 } | 6289 } |
6224 | 6290 |
6225 /** | 6291 /** |
6226 * Parse a part directive. The [commentAndMetadata] is the metadata to be | 6292 * Parse a part directive. The [commentAndMetadata] is the metadata to be |
6227 * associated with the directive. Return the part or part-of directive that | 6293 * associated with the directive. Return the part or part-of directive that |
6228 * was parsed. | 6294 * was parsed. |
6229 * | 6295 * |
6230 * This method assumes that the current token matches `Keyword.PART`. | 6296 * This method assumes that the current token matches `Keyword.PART`. |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6548 _currentToken.next.type.isRelationalOperator) { | 6614 _currentToken.next.type.isRelationalOperator) { |
6549 Expression expression = new SuperExpression(getAndAdvance()); | 6615 Expression expression = new SuperExpression(getAndAdvance()); |
6550 Token operator = getAndAdvance(); | 6616 Token operator = getAndAdvance(); |
6551 return new BinaryExpression( | 6617 return new BinaryExpression( |
6552 expression, operator, parseBitwiseOrExpression()); | 6618 expression, operator, parseBitwiseOrExpression()); |
6553 } | 6619 } |
6554 Expression expression = parseBitwiseOrExpression(); | 6620 Expression expression = parseBitwiseOrExpression(); |
6555 Keyword keyword = _currentToken.keyword; | 6621 Keyword keyword = _currentToken.keyword; |
6556 if (keyword == Keyword.AS) { | 6622 if (keyword == Keyword.AS) { |
6557 Token asOperator = getAndAdvance(); | 6623 Token asOperator = getAndAdvance(); |
6558 return new AsExpression(expression, asOperator, parseTypeName()); | 6624 return new AsExpression(expression, asOperator, parseTypeName(true)); |
6559 } else if (keyword == Keyword.IS) { | 6625 } else if (keyword == Keyword.IS) { |
6560 Token isOperator = getAndAdvance(); | 6626 Token isOperator = getAndAdvance(); |
6561 Token notOperator = null; | 6627 Token notOperator = null; |
6562 if (_matches(TokenType.BANG)) { | 6628 if (_matches(TokenType.BANG)) { |
6563 notOperator = getAndAdvance(); | 6629 notOperator = getAndAdvance(); |
6564 } | 6630 } |
6565 return new IsExpression( | 6631 return new IsExpression( |
6566 expression, isOperator, notOperator, parseTypeName()); | 6632 expression, isOperator, notOperator, parseTypeName(true)); |
6567 } else if (_currentToken.type.isRelationalOperator) { | 6633 } else if (_currentToken.type.isRelationalOperator) { |
6568 Token operator = getAndAdvance(); | 6634 Token operator = getAndAdvance(); |
6569 return new BinaryExpression( | 6635 return new BinaryExpression( |
6570 expression, operator, parseBitwiseOrExpression()); | 6636 expression, operator, parseBitwiseOrExpression()); |
6571 } | 6637 } |
6572 return expression; | 6638 return expression; |
6573 } | 6639 } |
6574 | 6640 |
6575 /** | 6641 /** |
6576 * Parse a rethrow expression. Return the rethrow expression that was parsed. | 6642 * Parse a rethrow expression. Return the rethrow expression that was parsed. |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6995 Statement _parseTryStatement() { | 7061 Statement _parseTryStatement() { |
6996 Token tryKeyword = getAndAdvance(); | 7062 Token tryKeyword = getAndAdvance(); |
6997 Block body = _parseBlockChecked(); | 7063 Block body = _parseBlockChecked(); |
6998 List<CatchClause> catchClauses = <CatchClause>[]; | 7064 List<CatchClause> catchClauses = <CatchClause>[]; |
6999 Block finallyClause = null; | 7065 Block finallyClause = null; |
7000 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) { | 7066 while (_matchesString(_ON) || _matchesKeyword(Keyword.CATCH)) { |
7001 Token onKeyword = null; | 7067 Token onKeyword = null; |
7002 TypeName exceptionType = null; | 7068 TypeName exceptionType = null; |
7003 if (_matchesString(_ON)) { | 7069 if (_matchesString(_ON)) { |
7004 onKeyword = getAndAdvance(); | 7070 onKeyword = getAndAdvance(); |
7005 exceptionType = parseTypeName(); | 7071 exceptionType = parseTypeName(false); |
7006 } | 7072 } |
7007 Token catchKeyword = null; | 7073 Token catchKeyword = null; |
7008 Token leftParenthesis = null; | 7074 Token leftParenthesis = null; |
7009 SimpleIdentifier exceptionParameter = null; | 7075 SimpleIdentifier exceptionParameter = null; |
7010 Token comma = null; | 7076 Token comma = null; |
7011 SimpleIdentifier stackTraceParameter = null; | 7077 SimpleIdentifier stackTraceParameter = null; |
7012 Token rightParenthesis = null; | 7078 Token rightParenthesis = null; |
7013 if (_matchesKeyword(Keyword.CATCH)) { | 7079 if (_matchesKeyword(Keyword.CATCH)) { |
7014 catchKeyword = getAndAdvance(); | 7080 catchKeyword = getAndAdvance(); |
7015 leftParenthesis = _expect(TokenType.OPEN_PAREN); | 7081 leftParenthesis = _expect(TokenType.OPEN_PAREN); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7085 TypeAlias typeAlias = | 7151 TypeAlias typeAlias = |
7086 _parseClassTypeAlias(commentAndMetadata, null, keyword); | 7152 _parseClassTypeAlias(commentAndMetadata, null, keyword); |
7087 _reportErrorForToken( | 7153 _reportErrorForToken( |
7088 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); | 7154 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); |
7089 return typeAlias; | 7155 return typeAlias; |
7090 } | 7156 } |
7091 } | 7157 } |
7092 return _parseFunctionTypeAlias(commentAndMetadata, keyword); | 7158 return _parseFunctionTypeAlias(commentAndMetadata, keyword); |
7093 } | 7159 } |
7094 | 7160 |
7095 TypeName _parseTypeName() { | 7161 TypeName _parseTypeName(bool inExpression) { |
7096 Identifier typeName; | 7162 Identifier typeName; |
7097 if (_matchesIdentifier()) { | 7163 if (_matchesIdentifier()) { |
7098 typeName = _parsePrefixedIdentifierUnchecked(); | 7164 typeName = _parsePrefixedIdentifierUnchecked(); |
7099 } else if (_matchesKeyword(Keyword.VAR)) { | 7165 } else if (_matchesKeyword(Keyword.VAR)) { |
7100 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); | 7166 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); |
7101 typeName = new SimpleIdentifier(getAndAdvance()); | 7167 typeName = new SimpleIdentifier(getAndAdvance()); |
7102 } else { | 7168 } else { |
7103 typeName = _createSyntheticIdentifier(); | 7169 typeName = _createSyntheticIdentifier(); |
7104 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); | 7170 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); |
7105 } | 7171 } |
7106 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); | 7172 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
7107 return new TypeName(typeName, typeArguments); | 7173 Token question = null; |
| 7174 if (enableNnbd && _matches(TokenType.QUESTION)) { |
| 7175 if (!inExpression || !_isConditionalOperator()) { |
| 7176 question = getAndAdvance(); |
| 7177 } |
| 7178 } |
| 7179 return new TypeName(typeName, typeArguments, question: question); |
7108 } | 7180 } |
7109 | 7181 |
7110 /** | 7182 /** |
7111 * Parse a type name. Return the type name that was parsed. | 7183 * Parse a type name. Return the type name that was parsed. |
7112 * | 7184 * |
7113 * This method assumes that the current token is an identifier. | 7185 * This method assumes that the current token is an identifier. |
7114 * | 7186 * |
7115 * type ::= | 7187 * type ::= |
7116 * qualified typeArguments? | 7188 * qualified typeArguments? |
7117 */ | 7189 */ |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7509 new Scanner(null, new SubSequenceReader(code, offset), listener); | 7581 new Scanner(null, new SubSequenceReader(code, offset), listener); |
7510 scanner.setSourceStart(1, 1); | 7582 scanner.setSourceStart(1, 1); |
7511 Token firstToken = scanner.tokenize(); | 7583 Token firstToken = scanner.tokenize(); |
7512 if (listener.errorReported) { | 7584 if (listener.errorReported) { |
7513 return null; | 7585 return null; |
7514 } | 7586 } |
7515 return firstToken; | 7587 return firstToken; |
7516 } | 7588 } |
7517 | 7589 |
7518 /** | 7590 /** |
| 7591 * Execute the given [parseOperation] in a temporary parser whose current |
| 7592 * token has been set to the given [startToken]. If the parse does not |
| 7593 * generate any errors or exceptions, then return the token following the |
| 7594 * matching portion of the token stream. Otherwise, return `null`. |
| 7595 * |
| 7596 * Note: This is an extremely inefficient way of testing whether the tokens in |
| 7597 * the token stream match a given production. It should not be used for |
| 7598 * production code. |
| 7599 */ |
| 7600 Token _skip(Token startToken, parseOperation(Parser parser)) { |
| 7601 BooleanErrorListener listener = new BooleanErrorListener(); |
| 7602 Parser parser = new Parser(_source, listener); |
| 7603 parser._currentToken = _cloneTokens(startToken); |
| 7604 parser._enableAssertInitializer = _enableAssertInitializer; |
| 7605 parser._enableNnbd = _enableNnbd; |
| 7606 parser._inAsync = _inAsync; |
| 7607 parser._inGenerator = _inGenerator; |
| 7608 parser._inInitializer = _inInitializer; |
| 7609 parser._inLoop = _inLoop; |
| 7610 parser._inSwitch = _inSwitch; |
| 7611 parser._parseAsync = _parseAsync; |
| 7612 parser._parseFunctionBodies = _parseFunctionBodies; |
| 7613 try { |
| 7614 parseOperation(parser); |
| 7615 } catch (exception) { |
| 7616 return null; |
| 7617 } |
| 7618 if (listener.errorReported) { |
| 7619 return null; |
| 7620 } |
| 7621 return parser._currentToken; |
| 7622 } |
| 7623 |
| 7624 /** |
7519 * Skips a block with all containing blocks. | 7625 * Skips a block with all containing blocks. |
7520 */ | 7626 */ |
7521 void _skipBlock() { | 7627 void _skipBlock() { |
7522 Token endToken = (_currentToken as BeginToken).endToken; | 7628 Token endToken = (_currentToken as BeginToken).endToken; |
7523 if (endToken == null) { | 7629 if (endToken == null) { |
7524 endToken = _currentToken.next; | 7630 endToken = _currentToken.next; |
7525 while (!identical(endToken, _currentToken)) { | 7631 while (!identical(endToken, _currentToken)) { |
7526 _currentToken = endToken; | 7632 _currentToken = endToken; |
7527 endToken = _currentToken.next; | 7633 endToken = _currentToken.next; |
7528 } | 7634 } |
(...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9084 */ | 9190 */ |
9085 const ParserErrorCode(String name, String message, [String correction]) | 9191 const ParserErrorCode(String name, String message, [String correction]) |
9086 : super(name, message, correction); | 9192 : super(name, message, correction); |
9087 | 9193 |
9088 @override | 9194 @override |
9089 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; | 9195 ErrorSeverity get errorSeverity => ErrorSeverity.ERROR; |
9090 | 9196 |
9091 @override | 9197 @override |
9092 ErrorType get type => ErrorType.SYNTACTIC_ERROR; | 9198 ErrorType get type => ErrorType.SYNTACTIC_ERROR; |
9093 } | 9199 } |
OLD | NEW |