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

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

Issue 2969053002: Implement type variables on old style function-typed formal parameters. (Closed)
Patch Set: Add comment. Created 3 years, 5 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' show FastaCode, FastaMessage; 7 import '../fasta_codes.dart' show FastaCode, FastaMessage;
8 8
9 import '../fasta_codes.dart' as fasta; 9 import '../fasta_codes.dart' as fasta;
10 10
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 56
57 import 'listener.dart' show Listener; 57 import 'listener.dart' show Listener;
58 58
59 import 'identifier_context.dart' show IdentifierContext; 59 import 'identifier_context.dart' show IdentifierContext;
60 60
61 /// Returns true if [token] is the symbol or keyword [value]. 61 /// Returns true if [token] is the symbol or keyword [value].
62 bool optional(String value, Token token) { 62 bool optional(String value, Token token) {
63 return identical(value, token.stringValue); 63 return identical(value, token.stringValue);
64 } 64 }
65 65
66 // TODO(ahe): Convert this to an enum.
66 class FormalParameterType { 67 class FormalParameterType {
67 final String type; 68 final String type;
68 const FormalParameterType(this.type); 69
70 final TypeContinuation typeContinuation;
71
72 const FormalParameterType(this.type, this.typeContinuation);
73
69 bool get isRequired => this == REQUIRED; 74 bool get isRequired => this == REQUIRED;
75
70 bool get isPositional => this == POSITIONAL; 76 bool get isPositional => this == POSITIONAL;
77
71 bool get isNamed => this == NAMED; 78 bool get isNamed => this == NAMED;
72 static final REQUIRED = const FormalParameterType('required'); 79
73 static final POSITIONAL = const FormalParameterType('positional'); 80 static final REQUIRED = const FormalParameterType(
74 static final NAMED = const FormalParameterType('named'); 81 'required', TypeContinuation.NormalFormalParameter);
82
83 static final POSITIONAL = const FormalParameterType(
84 'positional', TypeContinuation.OptionalPositionalFormalParameter);
85
86 static final NAMED =
87 const FormalParameterType('named', TypeContinuation.NamedFormalParameter);
75 } 88 }
76 89
77 enum MemberKind { 90 enum MemberKind {
78 /// A catch block, not a real member. 91 /// A catch block, not a real member.
79 Catch, 92 Catch,
80 93
81 /// A factory 94 /// A factory
82 Factory, 95 Factory,
83 96
84 /// Old-style typedef. 97 /// Old-style typedef.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 /// Indicates that a type may follow. If the following matches one of these 147 /// Indicates that a type may follow. If the following matches one of these
135 /// productions, it is parsed as a type: 148 /// productions, it is parsed as a type:
136 /// 149 ///
137 /// - `'void'` 150 /// - `'void'`
138 /// - `'Function' ( '(' | '<' )` 151 /// - `'Function' ( '(' | '<' )`
139 /// - `identifier ('.' identifier)? ('<' ... '>')? identifer` 152 /// - `identifier ('.' identifier)? ('<' ... '>')? identifer`
140 /// 153 ///
141 /// Otherwise, do nothing. 154 /// Otherwise, do nothing.
142 Optional, 155 Optional,
143 156
157 /// Same as [Optional], but we have seen `var`.
158 OptionalAfterVar,
159
144 /// Indicates that the keyword `typedef` has just been seen, and the parser 160 /// Indicates that the keyword `typedef` has just been seen, and the parser
145 /// should parse the following as a type unless it is followed by `=`. 161 /// should parse the following as a type unless it is followed by `=`.
146 Typedef, 162 Typedef,
147 163
148 /// Indicates that what follows is either a local declaration or an 164 /// Indicates that what follows is either a local declaration or an
149 /// expression. 165 /// expression.
150 ExpressionStatementOrDeclaration, 166 ExpressionStatementOrDeclaration,
151 167
152 /// Indicates that the keyword `const` has just been seen, and what follows 168 /// Indicates that the keyword `const` has just been seen, and what follows
153 /// may be a local variable declaration or an expression. 169 /// may be a local variable declaration or an expression.
154 ExpressionStatementOrConstDeclaration, 170 ExpressionStatementOrConstDeclaration,
155 171
156 /// Indicates that the parser is parsing an expression and has just seen an 172 /// Indicates that the parser is parsing an expression and has just seen an
157 /// identifier. 173 /// identifier.
158 SendOrFunctionLiteral, 174 SendOrFunctionLiteral,
159 175
160 /// Indicates that the parser has just parsed `for '('` and is looking to 176 /// Indicates that the parser has just parsed `for '('` and is looking to
161 /// parse a variable declaration or expression. 177 /// parse a variable declaration or expression.
162 VariablesDeclarationOrExpression, 178 VariablesDeclarationOrExpression,
179
180 /// Indicates that an optional type followed by a normal formal parameter is
181 /// expected.
182 NormalFormalParameter,
183
184 /// Indicates that an optional type followed by an optional positional formal
185 /// parameter is expected.
186 OptionalPositionalFormalParameter,
187
188 /// Indicates that an optional type followed by a named formal parameter is
189 /// expected.
190 NamedFormalParameter,
191
192 /// Same as [NormalFormalParameter], but we have seen `var`.
193 NormalFormalParameterAfterVar,
194
195 /// Same as [OptionalPositionalFormalParameter], but we have seen `var`.
196 OptionalPositionalFormalParameterAfterVar,
197
198 /// Same as [NamedFormalParameter], but we have seen `var`.
199 NamedFormalParameterAfterVar,
163 } 200 }
164 201
165 /// An event generating parser of Dart programs. This parser expects all tokens 202 /// An event generating parser of Dart programs. This parser expects all tokens
166 /// in a linked list (aka a token stream). 203 /// in a linked list (aka a token stream).
167 /// 204 ///
168 /// The class [Scanner] is used to generate a token stream. See the file 205 /// The class [Scanner] is used to generate a token stream. See the file
169 /// [scanner.dart](../scanner.dart). 206 /// [scanner.dart](../scanner.dart).
170 /// 207 ///
171 /// Subclasses of the class [Listener] are used to listen to events. 208 /// Subclasses of the class [Listener] are used to listen to events.
172 /// 209 ///
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 IdentifierContext.partNameContinuation); 583 IdentifierContext.partNameContinuation);
547 } else { 584 } else {
548 token = parseLiteralStringOrRecoverExpression(token); 585 token = parseLiteralStringOrRecoverExpression(token);
549 } 586 }
550 Token semicolon = token; 587 Token semicolon = token;
551 token = expect(';', token); 588 token = expect(';', token);
552 listener.endPartOf(partKeyword, semicolon, hasName); 589 listener.endPartOf(partKeyword, semicolon, hasName);
553 return token; 590 return token;
554 } 591 }
555 592
556 Token parseMetadataStar(Token token, {bool forParameter: false}) { 593 Token parseMetadataStar(Token token,
594 // TODO(ahe): Remove [forParameter].
595 {bool forParameter: false}) {
557 token = listener.injectGenericCommentTypeAssign(token); 596 token = listener.injectGenericCommentTypeAssign(token);
558 listener.beginMetadataStar(token); 597 listener.beginMetadataStar(token);
559 int count = 0; 598 int count = 0;
560 while (optional('@', token)) { 599 while (optional('@', token)) {
561 token = parseMetadata(token); 600 token = parseMetadata(token);
562 count++; 601 count++;
563 } 602 }
564 listener.endMetadataStar(count, forParameter); 603 listener.endMetadataStar(count, forParameter);
565 return token; 604 return token;
566 } 605 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind); 722 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind);
684 } while (optional(',', token)); 723 } while (optional(',', token));
685 listener.endFormalParameters(parameterCount, begin, token, kind); 724 listener.endFormalParameters(parameterCount, begin, token, kind);
686 return expect(')', token); 725 return expect(')', token);
687 } 726 }
688 727
689 Token parseFormalParameter( 728 Token parseFormalParameter(
690 Token token, FormalParameterType parameterKind, MemberKind memberKind) { 729 Token token, FormalParameterType parameterKind, MemberKind memberKind) {
691 token = parseMetadataStar(token, forParameter: true); 730 token = parseMetadataStar(token, forParameter: true);
692 listener.beginFormalParameter(token, memberKind); 731 listener.beginFormalParameter(token, memberKind);
693
694 bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType;
695 token = parseModifiers(token, memberKind, parameterKind: parameterKind); 732 token = parseModifiers(token, memberKind, parameterKind: parameterKind);
696 bool isNamedParameter = parameterKind == FormalParameterType.NAMED;
697
698 Token thisKeyword = null;
699 Token nameToken;
700 if (inFunctionType) {
701 if (isNamedParameter || token.isIdentifier) {
702 nameToken = token;
703 token = parseIdentifier(
704 token, IdentifierContext.formalParameterDeclaration);
705 } else {
706 listener.handleNoName(token);
707 }
708 } else {
709 if (optional('this', token)) {
710 thisKeyword = token;
711 token = expect('.', token.next);
712 nameToken = token;
713 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
714 } else {
715 nameToken = token;
716 token = parseIdentifier(
717 token, IdentifierContext.formalParameterDeclaration);
718 }
719 }
720 if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
721 reportRecoverableErrorCode(nameToken, fasta.codePrivateNamedParameter);
722 }
723
724 token = listener.injectGenericCommentTypeList(token);
725 if (optional('(', token)) {
726 Token inlineFunctionTypeStart = token;
727 listener.beginFunctionTypedFormalParameter(token);
728 listener.handleNoTypeVariables(token);
729 token = parseFormalParameters(token, MemberKind.FunctionTypedParameter);
730 listener.endFunctionTypedFormalParameter(thisKeyword, parameterKind);
731 // Generalized function types don't allow inline function types.
732 // The following isn't allowed:
733 // int Function(int bar(String x)).
734 if (memberKind == MemberKind.GeneralizedFunctionType) {
735 reportRecoverableErrorCode(
736 inlineFunctionTypeStart, fasta.codeInvalidInlineFunctionType);
737 }
738 } else if (optional('<', token)) {
739 Token inlineFunctionTypeStart = token;
740 listener.beginFunctionTypedFormalParameter(token);
741 token = parseTypeVariablesOpt(token);
742 token = parseFormalParameters(token, MemberKind.FunctionTypedParameter);
743 listener.endFunctionTypedFormalParameter(thisKeyword, parameterKind);
744 // Generalized function types don't allow inline function types.
745 // The following isn't allowed:
746 // int Function(int bar(String x)).
747 if (memberKind == MemberKind.GeneralizedFunctionType) {
748 reportRecoverableErrorCode(
749 inlineFunctionTypeStart, fasta.codeInvalidInlineFunctionType);
750 }
751 }
752 String value = token.stringValue;
753 if ((identical('=', value)) || (identical(':', value))) {
754 Token equal = token;
755 token = parseExpression(token.next);
756 listener.handleValuedFormalParameter(equal, token);
757 if (parameterKind.isRequired) {
758 reportRecoverableErrorCode(
759 equal, fasta.codeRequiredParameterWithDefault);
760 } else if (parameterKind.isPositional && identical(':', value)) {
761 reportRecoverableErrorCode(
762 equal, fasta.codePositionalParameterWithEquals);
763 } else if (inFunctionType ||
764 memberKind == MemberKind.FunctionTypeAlias ||
765 memberKind == MemberKind.FunctionTypedParameter) {
766 reportRecoverableErrorCode(
767 equal.next, fasta.codeFunctionTypeDefaultValue);
768 }
769 } else {
770 listener.handleFormalParameterWithoutValue(token);
771 }
772 listener.endFormalParameter(
773 thisKeyword, nameToken, parameterKind, memberKind);
774 return token; 733 return token;
775 } 734 }
776 735
777 Token parseOptionalFormalParameters( 736 Token parseOptionalFormalParameters(
778 Token token, bool isNamed, MemberKind kind) { 737 Token token, bool isNamed, MemberKind kind) {
779 Token begin = token; 738 Token begin = token;
780 listener.beginOptionalFormalParameters(begin); 739 listener.beginOptionalFormalParameters(begin);
781 assert((isNamed && optional('{', token)) || optional('[', token)); 740 assert((isNamed && optional('{', token)) || optional('[', token));
782 int parameterCount = 0; 741 int parameterCount = 0;
783 do { 742 do {
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 return optional('Function', token) && 1079 return optional('Function', token) &&
1121 (optional('<', token.next) || optional('(', token.next)); 1080 (optional('<', token.next) || optional('(', token.next));
1122 } 1081 }
1123 1082
1124 /// Parse a type, if it is appropriate to do so. 1083 /// Parse a type, if it is appropriate to do so.
1125 /// 1084 ///
1126 /// If this method can parse a type, it will return the next (non-null) token 1085 /// If this method can parse a type, it will return the next (non-null) token
1127 /// after the type. Otherwise, it returns null. 1086 /// after the type. Otherwise, it returns null.
1128 Token parseType(Token token, 1087 Token parseType(Token token,
1129 [TypeContinuation continuation = TypeContinuation.Required, 1088 [TypeContinuation continuation = TypeContinuation.Required,
1130 IdentifierContext continuationContext]) { 1089 IdentifierContext continuationContext,
1090 MemberKind memberKind]) {
1131 /// Returns the close brace, bracket, or parenthesis of [left]. For '<', it 1091 /// Returns the close brace, bracket, or parenthesis of [left]. For '<', it
1132 /// may return null. 1092 /// may return null.
1133 Token getClose(BeginToken left) => left.endToken; 1093 Token getClose(BeginToken left) => left.endToken;
1134 1094
1095 /// True if we've seen the `var` keyword.
1096 bool hasVar = false;
1097
1135 /// Where the type begins. 1098 /// Where the type begins.
1136 Token begin; 1099 Token begin;
1137 1100
1138 /// Non-null if 'void' is the first token. 1101 /// Non-null if 'void' is the first token.
1139 Token voidToken; 1102 Token voidToken;
1140 1103
1141 /// True if the tokens at [begin] looks like a type. 1104 /// True if the tokens at [begin] looks like a type.
1142 bool looksLikeType = false; 1105 bool looksLikeType = false;
1143 1106
1144 /// True if a type that could be a return type for a generalized function 1107 /// True if a type that could be a return type for a generalized function
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 token = token.next; 1240 token = token.next;
1278 if (optional("<", token)) { 1241 if (optional("<", token)) {
1279 // Skip type parameters, they were parsed above. 1242 // Skip type parameters, they were parsed above.
1280 token = getClose(token).next; 1243 token = getClose(token).next;
1281 } 1244 }
1282 token = 1245 token =
1283 parseFormalParameters(token, MemberKind.GeneralizedFunctionType); 1246 parseFormalParameters(token, MemberKind.GeneralizedFunctionType);
1284 listener.endFunctionType(functionToken, token); 1247 listener.endFunctionType(functionToken, token);
1285 } 1248 }
1286 1249
1250 if (hasVar) {
1251 reportRecoverableErrorCode(begin, fasta.codeTypeAfterVar);
1252 }
1253
1287 return token; 1254 return token;
1288 } 1255 }
1289 1256
1290 /// Returns true if [kind] is '=', ';', or ',', that is, if [kind] could be 1257 /// Returns true if [kind] is '=', ';', or ',', that is, if [kind] could be
1291 /// the end of a variable declaration. 1258 /// the end of a variable declaration.
1292 bool looksLikeVariableDeclarationEnd(int kind) { 1259 bool looksLikeVariableDeclarationEnd(int kind) {
1293 return EQ_TOKEN == kind || SEMICOLON_TOKEN == kind || COMMA_TOKEN == kind; 1260 return EQ_TOKEN == kind || SEMICOLON_TOKEN == kind || COMMA_TOKEN == kind;
1294 } 1261 }
1295 1262
1296 /// Returns true if [token] could be the start of a function body. 1263 /// Returns true if [token] could be the start of a function body.
1297 bool looksLikeFunctionBody(Token token) { 1264 bool looksLikeFunctionBody(Token token) {
1298 return optional('{', token) || 1265 return optional('{', token) ||
1299 optional('=>', token) || 1266 optional('=>', token) ||
1300 optional('async', token) || 1267 optional('async', token) ||
1301 optional('sync', token); 1268 optional('sync', token);
1302 } 1269 }
1303 1270
1271 FormalParameterType parameterKind;
1304 switch (continuation) { 1272 switch (continuation) {
1305 case TypeContinuation.Required: 1273 case TypeContinuation.Required:
1306 return commitType(); 1274 return commitType();
1307 1275
1308 optional: 1276 optional:
1309 case TypeContinuation.Optional: 1277 case TypeContinuation.Optional:
1310 if (looksLikeType) { 1278 if (looksLikeType) {
1311 if (functionTypes > 0) { 1279 if (functionTypes > 0) {
1312 return commitType(); // Parse function type. 1280 return commitType(); // Parse function type.
1313 } 1281 }
1314 if (voidToken != null) { 1282 if (voidToken != null) {
1315 listener.handleVoidKeyword(voidToken); 1283 listener.handleVoidKeyword(voidToken);
1316 return voidToken.next; 1284 return voidToken.next;
1317 } 1285 }
1318 if (token.isIdentifier || optional('this', token)) { 1286 if (token.isIdentifier || optional('this', token)) {
1319 return commitType(); // Parse type. 1287 return commitType(); // Parse type.
1320 } 1288 }
1321 } 1289 }
1322 listener.handleNoType(begin); 1290 listener.handleNoType(begin);
1323 return begin; 1291 return begin;
1324 1292
1293 case TypeContinuation.OptionalAfterVar:
1294 hasVar = true;
1295 continue optional;
1296
1325 case TypeContinuation.Typedef: 1297 case TypeContinuation.Typedef:
1326 if (optional('=', token)) { 1298 if (optional('=', token)) {
1327 return null; // This isn't a type, it's a new-style typedef. 1299 return null; // This isn't a type, it's a new-style typedef.
1328 } 1300 }
1329 continue optional; 1301 continue optional;
1330 1302
1331 case TypeContinuation.ExpressionStatementOrDeclaration: 1303 case TypeContinuation.ExpressionStatementOrDeclaration:
1332 assert(begin.isIdentifier || identical(begin.stringValue, 'void')); 1304 assert(begin.isIdentifier || identical(begin.stringValue, 'void'));
1333 if (!inPlainSync && optional("await", begin)) { 1305 if (!inPlainSync && optional("await", begin)) {
1334 return parseExpressionStatement(begin); 1306 return parseExpressionStatement(begin);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 1397
1426 case TypeContinuation.VariablesDeclarationOrExpression: 1398 case TypeContinuation.VariablesDeclarationOrExpression:
1427 if (looksLikeType && 1399 if (looksLikeType &&
1428 token.isIdentifier && 1400 token.isIdentifier &&
1429 isOneOf4(token.next, '=', ';', ',', 'in')) { 1401 isOneOf4(token.next, '=', ';', ',', 'in')) {
1430 // TODO(ahe): Generate type events and call 1402 // TODO(ahe): Generate type events and call
1431 // parseVariablesDeclarationNoSemicolonRest instead. 1403 // parseVariablesDeclarationNoSemicolonRest instead.
1432 return parseVariablesDeclarationNoSemicolon(begin); 1404 return parseVariablesDeclarationNoSemicolon(begin);
1433 } 1405 }
1434 return parseExpression(begin); 1406 return parseExpression(begin);
1407
1408 case TypeContinuation.NormalFormalParameter:
1409 case TypeContinuation.NormalFormalParameterAfterVar:
1410 parameterKind = FormalParameterType.REQUIRED;
1411 hasVar = continuation == TypeContinuation.NormalFormalParameterAfterVar;
1412 continue handleParameters;
1413
1414 case TypeContinuation.OptionalPositionalFormalParameter:
1415 case TypeContinuation.OptionalPositionalFormalParameterAfterVar:
1416 parameterKind = FormalParameterType.POSITIONAL;
1417 hasVar = continuation ==
1418 TypeContinuation.OptionalPositionalFormalParameterAfterVar;
1419 continue handleParameters;
1420
1421 case TypeContinuation.NamedFormalParameterAfterVar:
1422 hasVar = true;
1423 continue handleParameters;
1424
1425 handleParameters:
1426 case TypeContinuation.NamedFormalParameter:
1427 parameterKind ??= FormalParameterType.NAMED;
1428 bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType;
1429 bool isNamedParameter = parameterKind == FormalParameterType.NAMED;
1430
1431 bool untyped = false;
1432 if (!looksLikeType || optional("this", begin)) {
1433 untyped = true;
1434 token = begin;
1435 }
1436
1437 Token thisKeyword;
1438 Token nameToken = token;
1439 IdentifierContext nameContext =
1440 IdentifierContext.formalParameterDeclaration;
1441 token = token.next;
1442 if (inFunctionType) {
1443 if (isNamedParameter || nameToken.isIdentifier) {
1444 nameContext = IdentifierContext.formalParameterDeclaration;
1445 } else {
1446 // No name required in a function type.
1447 nameContext = null;
1448 token = nameToken;
1449 }
1450 } else if (optional('this', nameToken)) {
1451 thisKeyword = nameToken;
1452 token = expect('.', token);
1453 nameToken = token;
1454 nameContext = IdentifierContext.fieldInitializer;
1455 token = token.next;
1456 } else if (!nameToken.isIdentifier) {
1457 untyped = true;
1458 nameToken = begin;
1459 token = nameToken.next;
1460 }
1461 if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
1462 // TODO(ahe): Move this to after commiting the type.
1463 reportRecoverableErrorCode(
1464 nameToken, fasta.codePrivateNamedParameter);
1465 }
1466
1467 token = listener.injectGenericCommentTypeList(token);
1468
1469 Token inlineFunctionTypeStart;
1470 if (optional("<", token)) {
1471 Token closer = getClose(token);
1472 if (closer != null) {
1473 if (optional("(", closer.next)) {
1474 inlineFunctionTypeStart = token;
1475 token = token.next;
1476 }
1477 }
1478 } else if (optional("(", token)) {
1479 inlineFunctionTypeStart = token;
1480 token = getClose(token).next;
1481 }
1482
1483 if (inlineFunctionTypeStart != null) {
1484 token = parseTypeVariablesOpt(inlineFunctionTypeStart);
1485 listener.beginFunctionTypedFormalParameter(inlineFunctionTypeStart);
1486 if (!untyped) {
1487 if (voidToken != null) {
1488 listener.handleVoidKeyword(voidToken);
1489 } else {
1490 Token saved = token;
1491 commitType();
1492 token = saved;
1493 }
1494 } else {
1495 listener.handleNoType(begin);
1496 }
1497 token =
1498 parseFormalParameters(token, MemberKind.FunctionTypedParameter);
1499 listener.endFunctionTypedFormalParameter();
1500
1501 // Generalized function types don't allow inline function types.
1502 // The following isn't allowed:
1503 // int Function(int bar(String x)).
1504 if (memberKind == MemberKind.GeneralizedFunctionType) {
1505 reportRecoverableErrorCode(
1506 inlineFunctionTypeStart, fasta.codeInvalidInlineFunctionType);
1507 }
1508 } else if (untyped) {
1509 listener.handleNoType(begin);
1510 } else {
1511 Token saved = token;
1512 commitType();
1513 token = saved;
1514 }
1515
1516 if (nameContext != null) {
1517 parseIdentifier(nameToken, nameContext);
1518 } else {
1519 listener.handleNoName(nameToken);
1520 }
1521
1522 String value = token.stringValue;
1523 if ((identical('=', value)) || (identical(':', value))) {
1524 Token equal = token;
1525 token = parseExpression(token.next);
1526 listener.handleValuedFormalParameter(equal, token);
1527 if (parameterKind.isRequired) {
1528 reportRecoverableErrorCode(
1529 equal, fasta.codeRequiredParameterWithDefault);
1530 } else if (parameterKind.isPositional && identical(':', value)) {
1531 reportRecoverableErrorCode(
1532 equal, fasta.codePositionalParameterWithEquals);
1533 } else if (inFunctionType ||
1534 memberKind == MemberKind.FunctionTypeAlias ||
1535 memberKind == MemberKind.FunctionTypedParameter) {
1536 reportRecoverableErrorCode(
1537 equal.next, fasta.codeFunctionTypeDefaultValue);
1538 }
1539 } else {
1540 listener.handleFormalParameterWithoutValue(token);
1541 }
1542 listener.endFormalParameter(
1543 thisKeyword, nameToken, parameterKind, memberKind);
1544
1545 return token;
1435 } 1546 }
1436 1547
1437 throw "Internal error: Unhandled continuation '$continuation'."; 1548 throw "Internal error: Unhandled continuation '$continuation'.";
1438 } 1549 }
1439 1550
1440 Token parseTypeArgumentsOpt(Token token) { 1551 Token parseTypeArgumentsOpt(Token token) {
1441 return parseStuff( 1552 return parseStuff(
1442 token, 1553 token,
1443 (t) => listener.beginTypeArguments(t), 1554 (t) => listener.beginTypeArguments(t),
1444 (t) => parseType(t), 1555 (t) => parseType(t),
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1557 for (Token modifier in modifiers) { 1668 for (Token modifier in modifiers) {
1558 if (optional("var", modifier) || 1669 if (optional("var", modifier) ||
1559 optional("final", modifier) || 1670 optional("final", modifier) ||
1560 optional("const", modifier)) { 1671 optional("const", modifier)) {
1561 varFinalOrConst = modifier; 1672 varFinalOrConst = modifier;
1562 break; 1673 break;
1563 } 1674 }
1564 } 1675 }
1565 Token token = parseModifiers(start, 1676 Token token = parseModifiers(start,
1566 isTopLevel ? MemberKind.TopLevelField : MemberKind.NonStaticField, 1677 isTopLevel ? MemberKind.TopLevelField : MemberKind.NonStaticField,
1567 isVariable: true); 1678 isVarAllowed: true);
1568 1679
1569 if (token != name) { 1680 if (token != name) {
1570 reportRecoverableErrorCodeWithToken(token, fasta.codeExtraneousModifier); 1681 reportRecoverableErrorCodeWithToken(token, fasta.codeExtraneousModifier);
1571 token = name; 1682 token = name;
1572 } 1683 }
1573 1684
1574 IdentifierContext context = isTopLevel 1685 IdentifierContext context = isTopLevel
1575 ? IdentifierContext.topLevelVariableDeclaration 1686 ? IdentifierContext.topLevelVariableDeclaration
1576 : IdentifierContext.fieldDeclaration; 1687 : IdentifierContext.fieldDeclaration;
1577 token = parseIdentifier(token, context); 1688 token = parseIdentifier(token, context);
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1912 } 2023 }
1913 2024
1914 /// This method is used in most locations where modifiers can occur. However, 2025 /// This method is used in most locations where modifiers can occur. However,
1915 /// it isn't used when parsing a class or when parsing the modifiers of a 2026 /// it isn't used when parsing a class or when parsing the modifiers of a
1916 /// member function (non-local), but is used when parsing their formal 2027 /// member function (non-local), but is used when parsing their formal
1917 /// parameters. 2028 /// parameters.
1918 /// 2029 ///
1919 /// When parsing the formal parameters of any function, [parameterKind] is 2030 /// When parsing the formal parameters of any function, [parameterKind] is
1920 /// non-null. 2031 /// non-null.
1921 Token parseModifiers(Token token, MemberKind memberKind, 2032 Token parseModifiers(Token token, MemberKind memberKind,
1922 {FormalParameterType parameterKind, bool isVariable: false}) { 2033 {FormalParameterType parameterKind, bool isVarAllowed: false}) {
1923 bool returnTypeAllowed =
1924 !isVariable && memberKind != MemberKind.GeneralizedFunctionType;
1925 bool typeRequired =
1926 isVariable || memberKind == MemberKind.GeneralizedFunctionType;
1927 int count = 0; 2034 int count = 0;
1928 2035
1929 int currentOrder = -1; 2036 int currentOrder = -1;
1930 bool hasVar = false; 2037 TypeContinuation typeContinuation = parameterKind?.typeContinuation;
2038
1931 while (token.kind == KEYWORD_TOKEN) { 2039 while (token.kind == KEYWORD_TOKEN) {
1932 if (token.type.isPseudo) { 2040 if (token.type.isPseudo) {
1933 // A pseudo keyword is never a modifier. 2041 // A pseudo keyword is never a modifier.
1934 break; 2042 break;
1935 } 2043 }
1936 if (token.type.isBuiltIn) { 2044 if (token.type.isBuiltIn) {
1937 // A built-in identifier can only be a modifier as long as it is 2045 // A built-in identifier can only be a modifier as long as it is
1938 // followed by another modifier or an identifier. Otherwise, it is the 2046 // followed by another modifier or an identifier. Otherwise, it is the
1939 // identifier. 2047 // identifier.
1940 if (token.next.kind != KEYWORD_TOKEN && !token.next.isIdentifier) { 2048 if (token.next.kind != KEYWORD_TOKEN && !token.next.isIdentifier) {
1941 break; 2049 break;
1942 } 2050 }
1943 } 2051 }
1944 int order = modifierOrder(token); 2052 int order = modifierOrder(token);
1945 if (order < 3) { 2053 if (order < 3) {
1946 // `abstract` isn't parsed with this method. 2054 // `abstract` isn't parsed with this method.
1947 if (order > currentOrder) { 2055 if (order > currentOrder) {
1948 currentOrder = order; 2056 currentOrder = order;
1949 if (optional("var", token)) { 2057 if (optional("var", token)) {
1950 if (!isVariable && parameterKind == null) { 2058 if (!isVarAllowed && parameterKind == null) {
1951 reportRecoverableErrorCodeWithToken( 2059 reportRecoverableErrorCodeWithToken(
1952 token, fasta.codeExtraneousModifier); 2060 token, fasta.codeExtraneousModifier);
1953 } 2061 }
1954 hasVar = true; 2062 switch (typeContinuation ?? TypeContinuation.Required) {
1955 typeRequired = false; 2063 case TypeContinuation.NormalFormalParameter:
2064 typeContinuation =
2065 TypeContinuation.NormalFormalParameterAfterVar;
2066 break;
2067
2068 case TypeContinuation.OptionalPositionalFormalParameter:
2069 typeContinuation =
2070 TypeContinuation.OptionalPositionalFormalParameterAfterVar;
2071 break;
2072
2073 case TypeContinuation.NamedFormalParameter:
2074 typeContinuation =
2075 TypeContinuation.NamedFormalParameterAfterVar;
2076 break;
2077
2078 default:
2079 typeContinuation = TypeContinuation.OptionalAfterVar;
2080 break;
2081 }
1956 } else if (optional("final", token)) { 2082 } else if (optional("final", token)) {
1957 if (!isVariable && parameterKind == null) { 2083 if (!isVarAllowed && parameterKind == null) {
1958 reportRecoverableErrorCodeWithToken( 2084 reportRecoverableErrorCodeWithToken(
1959 token, fasta.codeExtraneousModifier); 2085 token, fasta.codeExtraneousModifier);
1960 } 2086 }
1961 typeRequired = false; 2087 typeContinuation ??= TypeContinuation.Optional;
1962 } else if (optional("const", token)) { 2088 } else if (optional("const", token)) {
1963 if (!isVariable) { 2089 if (!isVarAllowed) {
1964 reportRecoverableErrorCodeWithToken( 2090 reportRecoverableErrorCodeWithToken(
1965 token, fasta.codeExtraneousModifier); 2091 token, fasta.codeExtraneousModifier);
1966 } 2092 }
1967 typeRequired = false; 2093 typeContinuation ??= TypeContinuation.Optional;
1968 } else if (optional("static", token)) { 2094 } else if (optional("static", token)) {
1969 if (parameterKind != null) { 2095 if (parameterKind != null) {
1970 reportRecoverableErrorCodeWithToken( 2096 reportRecoverableErrorCodeWithToken(
1971 token, fasta.codeExtraneousModifier); 2097 token, fasta.codeExtraneousModifier);
1972 } else if (memberKind == MemberKind.NonStaticMethod) { 2098 } else if (memberKind == MemberKind.NonStaticMethod) {
1973 memberKind = MemberKind.StaticMethod; 2099 memberKind = MemberKind.StaticMethod;
1974 } else if (memberKind == MemberKind.NonStaticField) { 2100 } else if (memberKind == MemberKind.NonStaticField) {
1975 memberKind = MemberKind.StaticField; 2101 memberKind = MemberKind.StaticField;
1976 } else { 2102 } else {
1977 reportRecoverableErrorCodeWithToken( 2103 reportRecoverableErrorCodeWithToken(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2014 reportRecoverableErrorCodeWithToken( 2140 reportRecoverableErrorCodeWithToken(
2015 token, fasta.codeExtraneousModifier); 2141 token, fasta.codeExtraneousModifier);
2016 token = token.next; 2142 token = token.next;
2017 } 2143 }
2018 } else { 2144 } else {
2019 break; 2145 break;
2020 } 2146 }
2021 } 2147 }
2022 listener.handleModifiers(count); 2148 listener.handleModifiers(count);
2023 2149
2024 Token beforeType = token; 2150 typeContinuation ??=
2025 token = parseType( 2151 (isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType)
2026 token, 2152 ? TypeContinuation.Required
2027 returnTypeAllowed || !typeRequired 2153 : TypeContinuation.Optional;
2028 ? TypeContinuation.Optional 2154
2029 : TypeContinuation.Required); 2155 token = parseType(token, typeContinuation, null, memberKind);
2030 if (typeRequired && beforeType == token) {
2031 reportRecoverableErrorCode(token, fasta.codeTypeRequired);
2032 }
2033 if (hasVar && beforeType != token) {
2034 reportRecoverableErrorCode(beforeType, fasta.codeTypeAfterVar);
2035 }
2036 return token; 2156 return token;
2037 } 2157 }
2038 2158
2039 Token skipClassBody(Token token) { 2159 Token skipClassBody(Token token) {
2040 if (!optional('{', token)) { 2160 if (!optional('{', token)) {
2041 return reportUnrecoverableErrorCodeWithToken( 2161 return reportUnrecoverableErrorCodeWithToken(
2042 token, fasta.codeExpectedClassBodyToSkip) 2162 token, fasta.codeExpectedClassBodyToSkip)
2043 .next; 2163 .next;
2044 } 2164 }
2045 BeginToken beginGroupToken = token; 2165 BeginToken beginGroupToken = token;
(...skipping 1446 matching lines...) Expand 10 before | Expand all | Expand 10 after
3492 Token token, bool endWithSemicolon) { 3612 Token token, bool endWithSemicolon) {
3493 token = parseMetadataStar(token); 3613 token = parseMetadataStar(token);
3494 3614
3495 // If the next token has a type substitution comment /*=T*/, then 3615 // If the next token has a type substitution comment /*=T*/, then
3496 // the current 'var' token should be repealed and replaced. 3616 // the current 'var' token should be repealed and replaced.
3497 if (optional('var', token)) { 3617 if (optional('var', token)) {
3498 token = 3618 token =
3499 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next); 3619 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next);
3500 } 3620 }
3501 3621
3502 token = parseModifiers(token, MemberKind.Local, isVariable: true); 3622 token = parseModifiers(token, MemberKind.Local, isVarAllowed: true);
3503 return parseVariablesDeclarationMaybeSemicolonRest(token, endWithSemicolon); 3623 return parseVariablesDeclarationMaybeSemicolonRest(token, endWithSemicolon);
3504 } 3624 }
3505 3625
3506 Token parseVariablesDeclarationMaybeSemicolonRest( 3626 Token parseVariablesDeclarationMaybeSemicolonRest(
3507 Token token, bool endWithSemicolon) { 3627 Token token, bool endWithSemicolon) {
3508 int count = 1; 3628 int count = 1;
3509 listener.beginVariablesDeclaration(token); 3629 listener.beginVariablesDeclaration(token);
3510 token = parseOptionallyInitializedIdentifier(token); 3630 token = parseOptionallyInitializedIdentifier(token);
3511 while (optional(',', token)) { 3631 while (optional(',', token)) {
3512 token = parseOptionallyInitializedIdentifier(token.next); 3632 token = parseOptionallyInitializedIdentifier(token.next);
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
4029 return reportUnrecoverableError( 4149 return reportUnrecoverableError(
4030 token, () => code.format(uri, token.charOffset, string)); 4150 token, () => code.format(uri, token.charOffset, string));
4031 } 4151 }
4032 } 4152 }
4033 4153
4034 typedef FastaMessage NoArgument(Uri uri, int charOffset); 4154 typedef FastaMessage NoArgument(Uri uri, int charOffset);
4035 4155
4036 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); 4156 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
4037 4157
4038 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); 4158 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