| 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' 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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); |
| OLD | NEW |