OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 fasta.parser.parser; | 5 library fasta.parser.parser; |
6 | 6 |
7 import '../fasta_codes.dart' | 7 import '../fasta_codes.dart' |
8 show | 8 show |
9 FastaCode, | 9 FastaCode, |
10 FastaMessage, | 10 FastaMessage, |
11 codeAbstractNotSync, | 11 codeAbstractNotSync, |
12 codeAsciiControlCharacter, | 12 codeAsciiControlCharacter, |
| 13 codeAssertAsExpression, |
| 14 codeAssertExtraneousArgument, |
13 codeAsyncAsIdentifier, | 15 codeAsyncAsIdentifier, |
14 codeAwaitAsIdentifier, | 16 codeAwaitAsIdentifier, |
15 codeAwaitForNotAsync, | 17 codeAwaitForNotAsync, |
16 codeAwaitNotAsync, | 18 codeAwaitNotAsync, |
17 codeBuiltInIdentifierAsType, | 19 codeBuiltInIdentifierAsType, |
18 codeBuiltInIdentifierInDeclaration, | 20 codeBuiltInIdentifierInDeclaration, |
19 codeEmptyNamedParameterList, | 21 codeEmptyNamedParameterList, |
20 codeEmptyOptionalParameterList, | 22 codeEmptyOptionalParameterList, |
21 codeEncoding, | 23 codeEncoding, |
22 codeExpectedBlockToSkip, | 24 codeExpectedBlockToSkip, |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 /// An instance field in a class. | 153 /// An instance field in a class. |
152 NonStaticField, | 154 NonStaticField, |
153 | 155 |
154 /// A static field in a class. | 156 /// A static field in a class. |
155 StaticField, | 157 StaticField, |
156 | 158 |
157 /// A top-level field. | 159 /// A top-level field. |
158 TopLevelField, | 160 TopLevelField, |
159 } | 161 } |
160 | 162 |
| 163 /// Syntactic forms of `assert`. |
| 164 /// |
| 165 /// An assertion can legally occur as a statement. However, assertions are also |
| 166 /// experimentally allowed in initializers. For improved error recovery, we |
| 167 /// also attempt to parse asserts as expressions. |
| 168 enum Assert { |
| 169 Expression, |
| 170 Initializer, |
| 171 Statement, |
| 172 } |
| 173 |
161 /// An event generating parser of Dart programs. This parser expects all tokens | 174 /// An event generating parser of Dart programs. This parser expects all tokens |
162 /// in a linked list (aka a token stream). | 175 /// in a linked list (aka a token stream). |
163 /// | 176 /// |
164 /// The class [Scanner] is used to generate a token stream. See the file | 177 /// The class [Scanner] is used to generate a token stream. See the file |
165 /// [scanner.dart](../scanner.dart). | 178 /// [scanner.dart](../scanner.dart). |
166 /// | 179 /// |
167 /// Subclasses of the class [Listener] are used to listen to events. | 180 /// Subclasses of the class [Listener] are used to listen to events. |
168 /// | 181 /// |
169 /// Most methods of this class belong in one of three major categories: parse | 182 /// Most methods of this class belong in one of three major categories: parse |
170 /// methods, peek methods, and skip methods. Parse methods all have the prefix | 183 /// methods, peek methods, and skip methods. Parse methods all have the prefix |
(...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 } | 1567 } |
1555 | 1568 |
1556 Token parseInitializers(Token token) { | 1569 Token parseInitializers(Token token) { |
1557 Token begin = token; | 1570 Token begin = token; |
1558 listener.beginInitializers(begin); | 1571 listener.beginInitializers(begin); |
1559 expect(':', token); | 1572 expect(':', token); |
1560 int count = 0; | 1573 int count = 0; |
1561 bool old = mayParseFunctionExpressions; | 1574 bool old = mayParseFunctionExpressions; |
1562 mayParseFunctionExpressions = false; | 1575 mayParseFunctionExpressions = false; |
1563 do { | 1576 do { |
1564 token = token.next; | 1577 token = parseInitializer(token.next); |
1565 listener.beginInitializer(token); | |
1566 token = parseExpression(token); | |
1567 listener.endInitializer(token); | |
1568 ++count; | 1578 ++count; |
1569 } while (optional(',', token)); | 1579 } while (optional(',', token)); |
1570 mayParseFunctionExpressions = old; | 1580 mayParseFunctionExpressions = old; |
1571 listener.endInitializers(count, begin, token); | 1581 listener.endInitializers(count, begin, token); |
1572 return token; | 1582 return token; |
1573 } | 1583 } |
1574 | 1584 |
| 1585 Token parseInitializer(Token token) { |
| 1586 listener.beginInitializer(token); |
| 1587 if (optional('assert', token)) { |
| 1588 token = parseAssert(token, Assert.Initializer); |
| 1589 } else { |
| 1590 token = parseExpression(token); |
| 1591 } |
| 1592 listener.endInitializer(token); |
| 1593 return token; |
| 1594 } |
| 1595 |
1575 Token parseLiteralStringOrRecoverExpression(Token token) { | 1596 Token parseLiteralStringOrRecoverExpression(Token token) { |
1576 if (identical(token.kind, STRING_TOKEN)) { | 1597 if (identical(token.kind, STRING_TOKEN)) { |
1577 return parseLiteralString(token); | 1598 return parseLiteralString(token); |
1578 } else { | 1599 } else { |
1579 reportRecoverableErrorCodeWithToken(token, codeExpectedString); | 1600 reportRecoverableErrorCodeWithToken(token, codeExpectedString); |
1580 return parseRecoverExpression(token); | 1601 return parseRecoverExpression( |
| 1602 token, codeExpectedString.format(uri, token.charOffset, token)); |
1581 } | 1603 } |
1582 } | 1604 } |
1583 | 1605 |
1584 Token expectSemicolon(Token token) { | 1606 Token expectSemicolon(Token token) { |
1585 return expect(';', token); | 1607 return expect(';', token); |
1586 } | 1608 } |
1587 | 1609 |
1588 bool isModifier(Token token) => modifierOrder(token) < 127; | 1610 bool isModifier(Token token) => modifierOrder(token) < 127; |
1589 | 1611 |
1590 /// Provides a partial order on modifiers. | 1612 /// Provides a partial order on modifiers. |
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2679 BeginToken begin = token; | 2701 BeginToken begin = token; |
2680 token = (begin.endGroup != null) ? begin.endGroup : token; | 2702 token = (begin.endGroup != null) ? begin.endGroup : token; |
2681 } else if (token is ErrorToken) { | 2703 } else if (token is ErrorToken) { |
2682 reportErrorToken(token, false).next; | 2704 reportErrorToken(token, false).next; |
2683 } | 2705 } |
2684 token = token.next; | 2706 token = token.next; |
2685 } | 2707 } |
2686 return token; | 2708 return token; |
2687 } | 2709 } |
2688 | 2710 |
2689 Token parseRecoverExpression(Token token) => parseExpression(token); | 2711 Token parseRecoverExpression(Token token, FastaMessage message) => |
| 2712 parseExpression(token); |
2690 | 2713 |
2691 int expressionDepth = 0; | 2714 int expressionDepth = 0; |
2692 Token parseExpression(Token token) { | 2715 Token parseExpression(Token token) { |
2693 if (expressionDepth++ > 500) { | 2716 if (expressionDepth++ > 500) { |
2694 // This happens in degenerate programs, for example, with a lot of nested | 2717 // This happens in degenerate programs, for example, with a lot of nested |
2695 // list literals. This is provoked by, for examaple, the language test | 2718 // list literals. This is provoked by, for examaple, the language test |
2696 // deep_nesting1_negative_test. | 2719 // deep_nesting1_negative_test. |
2697 return reportUnrecoverableErrorCode(token, codeStackOverflow).next; | 2720 return reportUnrecoverableErrorCode(token, codeStackOverflow).next; |
2698 } | 2721 } |
2699 listener.beginExpression(token); | 2722 listener.beginExpression(token); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2908 return parseSuperExpression(token, context); | 2931 return parseSuperExpression(token, context); |
2909 } else if (identical(value, "new")) { | 2932 } else if (identical(value, "new")) { |
2910 return parseNewExpression(token); | 2933 return parseNewExpression(token); |
2911 } else if (identical(value, "const")) { | 2934 } else if (identical(value, "const")) { |
2912 return parseConstExpression(token); | 2935 return parseConstExpression(token); |
2913 } else if (identical(value, "void")) { | 2936 } else if (identical(value, "void")) { |
2914 return parseFunctionExpression(token); | 2937 return parseFunctionExpression(token); |
2915 } else if (!inPlainSync && | 2938 } else if (!inPlainSync && |
2916 (identical(value, "yield") || identical(value, "async"))) { | 2939 (identical(value, "yield") || identical(value, "async"))) { |
2917 return expressionExpected(token); | 2940 return expressionExpected(token); |
| 2941 } else if (identical(value, "assert")) { |
| 2942 return parseAssert(token, Assert.Expression); |
2918 } else if (token.isIdentifier) { | 2943 } else if (token.isIdentifier) { |
2919 return parseSendOrFunctionLiteral(token, context); | 2944 return parseSendOrFunctionLiteral(token, context); |
2920 } else { | 2945 } else { |
2921 return expressionExpected(token); | 2946 return expressionExpected(token); |
2922 } | 2947 } |
2923 } else if (kind == OPEN_PAREN_TOKEN) { | 2948 } else if (kind == OPEN_PAREN_TOKEN) { |
2924 return parseParenthesizedExpressionOrFunctionLiteral(token); | 2949 return parseParenthesizedExpressionOrFunctionLiteral(token); |
2925 } else if (kind == OPEN_SQUARE_BRACKET_TOKEN || optional('[]', token)) { | 2950 } else if (kind == OPEN_SQUARE_BRACKET_TOKEN || optional('[]', token)) { |
2926 listener.handleNoTypeArguments(token); | 2951 listener.handleNoTypeArguments(token); |
2927 return parseLiteralListSuffix(token, null); | 2952 return parseLiteralListSuffix(token, null); |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3766 token = token.next; | 3791 token = token.next; |
3767 bool hasTarget = false; | 3792 bool hasTarget = false; |
3768 if (token.isIdentifier) { | 3793 if (token.isIdentifier) { |
3769 token = parseIdentifier(token, IdentifierContext.labelReference); | 3794 token = parseIdentifier(token, IdentifierContext.labelReference); |
3770 hasTarget = true; | 3795 hasTarget = true; |
3771 } | 3796 } |
3772 listener.handleBreakStatement(hasTarget, breakKeyword, token); | 3797 listener.handleBreakStatement(hasTarget, breakKeyword, token); |
3773 return expectSemicolon(token); | 3798 return expectSemicolon(token); |
3774 } | 3799 } |
3775 | 3800 |
3776 Token parseAssertStatement(Token token) { | 3801 Token parseAssert(Token token, Assert kind) { |
| 3802 listener.beginAssert(token, kind); |
3777 Token assertKeyword = token; | 3803 Token assertKeyword = token; |
3778 Token commaToken = null; | 3804 Token commaToken = null; |
3779 token = expect('assert', token); | 3805 token = expect('assert', token); |
3780 Token leftParenthesis = token; | 3806 Token leftParenthesis = token; |
3781 token = expect('(', token); | 3807 token = expect('(', token); |
3782 bool old = mayParseFunctionExpressions; | 3808 bool old = mayParseFunctionExpressions; |
3783 mayParseFunctionExpressions = true; | 3809 mayParseFunctionExpressions = true; |
3784 token = parseExpression(token); | 3810 token = parseExpression(token); |
3785 if (optional(',', token)) { | 3811 if (optional(',', token)) { |
3786 commaToken = token; | 3812 commaToken = token; |
3787 token = token.next; | 3813 token = token.next; |
3788 token = parseExpression(token); | 3814 token = parseExpression(token); |
3789 } | 3815 } |
| 3816 if (optional(',', token)) { |
| 3817 Token firstExtra = token.next; |
| 3818 while (optional(',', token)) { |
| 3819 token = token.next; |
| 3820 Token begin = token; |
| 3821 token = parseExpression(token); |
| 3822 listener.handleExtraneousExpression( |
| 3823 begin, codeAssertExtraneousArgument.format(uri, token.charOffset)); |
| 3824 } |
| 3825 reportRecoverableErrorCode(firstExtra, codeAssertExtraneousArgument); |
| 3826 } |
3790 Token rightParenthesis = token; | 3827 Token rightParenthesis = token; |
3791 token = expect(')', token); | 3828 token = expect(')', token); |
3792 mayParseFunctionExpressions = old; | 3829 mayParseFunctionExpressions = old; |
3793 listener.handleAssertStatement( | 3830 listener.endAssert(assertKeyword, kind, leftParenthesis, commaToken, |
3794 assertKeyword, leftParenthesis, commaToken, rightParenthesis, token); | 3831 rightParenthesis, token); |
| 3832 if (kind == Assert.Expression) { |
| 3833 reportRecoverableErrorCode(assertKeyword, codeAssertAsExpression); |
| 3834 } |
| 3835 return token; |
| 3836 } |
| 3837 |
| 3838 Token parseAssertStatement(Token token) { |
| 3839 token = parseAssert(token, Assert.Statement); |
3795 return expectSemicolon(token); | 3840 return expectSemicolon(token); |
3796 } | 3841 } |
3797 | 3842 |
3798 Token parseContinueStatement(Token token) { | 3843 Token parseContinueStatement(Token token) { |
3799 assert(optional('continue', token)); | 3844 assert(optional('continue', token)); |
3800 Token continueKeyword = token; | 3845 Token continueKeyword = token; |
3801 token = token.next; | 3846 token = token.next; |
3802 bool hasTarget = false; | 3847 bool hasTarget = false; |
3803 if (token.isIdentifier) { | 3848 if (token.isIdentifier) { |
3804 token = parseIdentifier(token, IdentifierContext.labelReference); | 3849 token = parseIdentifier(token, IdentifierContext.labelReference); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3907 return reportUnrecoverableError( | 3952 return reportUnrecoverableError( |
3908 token, () => code.format(uri, token.charOffset, string)); | 3953 token, () => code.format(uri, token.charOffset, string)); |
3909 } | 3954 } |
3910 } | 3955 } |
3911 | 3956 |
3912 typedef FastaMessage NoArgument(Uri uri, int charOffset); | 3957 typedef FastaMessage NoArgument(Uri uri, int charOffset); |
3913 | 3958 |
3914 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); | 3959 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); |
3915 | 3960 |
3916 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); | 3961 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); |
OLD | NEW |