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

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2930673002: Implement initializer asserts. (Closed)
Patch Set: Address comments and tweak error recovery. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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);
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/parser/listener.dart ('k') | pkg/front_end/lib/src/fasta/source/outline_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698