| 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 Code, Message, Template; | 7 import '../fasta_codes.dart' show Code, Message, Template; |
| 8 | 8 |
| 9 import '../fasta_codes.dart' as fasta; | 9 import '../fasta_codes.dart' as fasta; |
| 10 | 10 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 PERIOD_TOKEN, | 45 PERIOD_TOKEN, |
| 46 SEMICOLON_TOKEN, | 46 SEMICOLON_TOKEN, |
| 47 STRING_INTERPOLATION_IDENTIFIER_TOKEN, | 47 STRING_INTERPOLATION_IDENTIFIER_TOKEN, |
| 48 STRING_INTERPOLATION_TOKEN, | 48 STRING_INTERPOLATION_TOKEN, |
| 49 STRING_TOKEN; | 49 STRING_TOKEN; |
| 50 | 50 |
| 51 import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET; | 51 import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET; |
| 52 | 52 |
| 53 import '../util/link.dart' show Link; | 53 import '../util/link.dart' show Link; |
| 54 | 54 |
| 55 import 'assert.dart' show Assert; |
| 56 |
| 55 import 'async_modifier.dart' show AsyncModifier; | 57 import 'async_modifier.dart' show AsyncModifier; |
| 56 | 58 |
| 59 import 'formal_parameter_kind.dart' |
| 60 show |
| 61 FormalParameterKind, |
| 62 isMandatoryFormalParameterKind, |
| 63 isOptionalPositionalFormalParameterKind; |
| 64 |
| 65 import 'identifier_context.dart' show IdentifierContext; |
| 66 |
| 57 import 'listener.dart' show Listener; | 67 import 'listener.dart' show Listener; |
| 58 | 68 |
| 59 import 'identifier_context.dart' show IdentifierContext; | 69 import 'member_kind.dart' show MemberKind; |
| 60 | 70 |
| 61 /// Returns true if [token] is the symbol or keyword [value]. | 71 import 'type_continuation.dart' |
| 62 bool optional(String value, Token token) { | 72 show TypeContinuation, typeContiunationFromFormalParameterKind; |
| 63 return identical(value, token.stringValue); | |
| 64 } | |
| 65 | 73 |
| 66 // TODO(ahe): Convert this to an enum. | 74 import 'util.dart' show optional; |
| 67 class FormalParameterType { | |
| 68 final String type; | |
| 69 | |
| 70 final TypeContinuation typeContinuation; | |
| 71 | |
| 72 const FormalParameterType(this.type, this.typeContinuation); | |
| 73 | |
| 74 bool get isRequired => this == REQUIRED; | |
| 75 | |
| 76 bool get isPositional => this == POSITIONAL; | |
| 77 | |
| 78 bool get isNamed => this == NAMED; | |
| 79 | |
| 80 static final REQUIRED = const FormalParameterType( | |
| 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); | |
| 88 } | |
| 89 | |
| 90 enum MemberKind { | |
| 91 /// A catch block, not a real member. | |
| 92 Catch, | |
| 93 | |
| 94 /// A factory | |
| 95 Factory, | |
| 96 | |
| 97 /// Old-style typedef. | |
| 98 FunctionTypeAlias, | |
| 99 | |
| 100 /// Old-style function-typed parameter, not a real member. | |
| 101 FunctionTypedParameter, | |
| 102 | |
| 103 /// A generalized function type, not a real member. | |
| 104 GeneralizedFunctionType, | |
| 105 | |
| 106 /// A local function. | |
| 107 Local, | |
| 108 | |
| 109 /// A non-static method in a class (including constructors). | |
| 110 NonStaticMethod, | |
| 111 | |
| 112 /// A static method in a class. | |
| 113 StaticMethod, | |
| 114 | |
| 115 /// A top-level method. | |
| 116 TopLevelMethod, | |
| 117 | |
| 118 /// An instance field in a class. | |
| 119 NonStaticField, | |
| 120 | |
| 121 /// A static field in a class. | |
| 122 StaticField, | |
| 123 | |
| 124 /// A top-level field. | |
| 125 TopLevelField, | |
| 126 } | |
| 127 | |
| 128 /// Syntactic forms of `assert`. | |
| 129 /// | |
| 130 /// An assertion can legally occur as a statement. However, assertions are also | |
| 131 /// experimentally allowed in initializers. For improved error recovery, we | |
| 132 /// also attempt to parse asserts as expressions. | |
| 133 enum Assert { | |
| 134 Expression, | |
| 135 Initializer, | |
| 136 Statement, | |
| 137 } | |
| 138 | |
| 139 /// Indication of how the parser should continue after (attempting) to parse a | |
| 140 /// type. | |
| 141 /// | |
| 142 /// Depending on the continuation, the parser may not parse a type at all. | |
| 143 enum TypeContinuation { | |
| 144 /// Indicates that a type is unconditionally expected. | |
| 145 Required, | |
| 146 | |
| 147 /// Indicates that a type may follow. If the following matches one of these | |
| 148 /// productions, it is parsed as a type: | |
| 149 /// | |
| 150 /// - `'void'` | |
| 151 /// - `'Function' ( '(' | '<' )` | |
| 152 /// - `identifier ('.' identifier)? ('<' ... '>')? identifer` | |
| 153 /// | |
| 154 /// Otherwise, do nothing. | |
| 155 Optional, | |
| 156 | |
| 157 /// Same as [Optional], but we have seen `var`. | |
| 158 OptionalAfterVar, | |
| 159 | |
| 160 /// Indicates that the keyword `typedef` has just been seen, and the parser | |
| 161 /// should parse the following as a type unless it is followed by `=`. | |
| 162 Typedef, | |
| 163 | |
| 164 /// Indicates that what follows is either a local declaration or an | |
| 165 /// expression. | |
| 166 ExpressionStatementOrDeclaration, | |
| 167 | |
| 168 /// Indicates that the keyword `const` has just been seen, and what follows | |
| 169 /// may be a local variable declaration or an expression. | |
| 170 ExpressionStatementOrConstDeclaration, | |
| 171 | |
| 172 /// Indicates that the parser is parsing an expression and has just seen an | |
| 173 /// identifier. | |
| 174 SendOrFunctionLiteral, | |
| 175 | |
| 176 /// Indicates that the parser has just parsed `for '('` and is looking to | |
| 177 /// parse a variable declaration or expression. | |
| 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, | |
| 200 } | |
| 201 | 75 |
| 202 /// An event generating parser of Dart programs. This parser expects all tokens | 76 /// An event generating parser of Dart programs. This parser expects all tokens |
| 203 /// in a linked list (aka a token stream). | 77 /// in a linked list (aka a token stream). |
| 204 /// | 78 /// |
| 205 /// The class [Scanner] is used to generate a token stream. See the file | 79 /// The class [Scanner] is used to generate a token stream. See the file |
| 206 /// [scanner.dart](../scanner.dart). | 80 /// [scanner.dart](../scanner.dart). |
| 207 /// | 81 /// |
| 208 /// Subclasses of the class [Listener] are used to listen to events. | 82 /// Subclasses of the class [Listener] are used to listen to events. |
| 209 /// | 83 /// |
| 210 /// Most methods of this class belong in one of three major categories: parse | 84 /// Most methods of this class belong in one of three major categories: parse |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 break; | 586 break; |
| 713 } else if (identical(value, '{')) { | 587 } else if (identical(value, '{')) { |
| 714 token = parseOptionalFormalParameters(token, true, kind); | 588 token = parseOptionalFormalParameters(token, true, kind); |
| 715 break; | 589 break; |
| 716 } else if (identical(value, '[]')) { | 590 } else if (identical(value, '[]')) { |
| 717 --parameterCount; | 591 --parameterCount; |
| 718 reportRecoverableError(token, fasta.messageEmptyOptionalParameterList); | 592 reportRecoverableError(token, fasta.messageEmptyOptionalParameterList); |
| 719 token = token.next; | 593 token = token.next; |
| 720 break; | 594 break; |
| 721 } | 595 } |
| 722 token = parseFormalParameter(token, FormalParameterType.REQUIRED, kind); | 596 token = parseFormalParameter(token, FormalParameterKind.mandatory, kind); |
| 723 } while (optional(',', token)); | 597 } while (optional(',', token)); |
| 724 listener.endFormalParameters(parameterCount, begin, token, kind); | 598 listener.endFormalParameters(parameterCount, begin, token, kind); |
| 725 return expect(')', token); | 599 return expect(')', token); |
| 726 } | 600 } |
| 727 | 601 |
| 728 Token parseFormalParameter( | 602 Token parseFormalParameter( |
| 729 Token token, FormalParameterType parameterKind, MemberKind memberKind) { | 603 Token token, FormalParameterKind parameterKind, MemberKind memberKind) { |
| 730 token = parseMetadataStar(token, forParameter: true); | 604 token = parseMetadataStar(token, forParameter: true); |
| 731 listener.beginFormalParameter(token, memberKind); | 605 listener.beginFormalParameter(token, memberKind); |
| 732 token = parseModifiers(token, memberKind, parameterKind: parameterKind); | 606 token = parseModifiers(token, memberKind, parameterKind: parameterKind); |
| 733 return token; | 607 return token; |
| 734 } | 608 } |
| 735 | 609 |
| 736 Token parseOptionalFormalParameters( | 610 Token parseOptionalFormalParameters( |
| 737 Token token, bool isNamed, MemberKind kind) { | 611 Token token, bool isNamed, MemberKind kind) { |
| 738 Token begin = token; | 612 Token begin = token; |
| 739 listener.beginOptionalFormalParameters(begin); | 613 listener.beginOptionalFormalParameters(begin); |
| 740 assert((isNamed && optional('{', token)) || optional('[', token)); | 614 assert((isNamed && optional('{', token)) || optional('[', token)); |
| 741 int parameterCount = 0; | 615 int parameterCount = 0; |
| 742 do { | 616 do { |
| 743 token = token.next; | 617 token = token.next; |
| 744 if (isNamed && optional('}', token)) { | 618 if (isNamed && optional('}', token)) { |
| 745 break; | 619 break; |
| 746 } else if (!isNamed && optional(']', token)) { | 620 } else if (!isNamed && optional(']', token)) { |
| 747 break; | 621 break; |
| 748 } | 622 } |
| 749 var type = | 623 var type = isNamed |
| 750 isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; | 624 ? FormalParameterKind.optionalNamed |
| 625 : FormalParameterKind.optionalPositional; |
| 751 token = parseFormalParameter(token, type, kind); | 626 token = parseFormalParameter(token, type, kind); |
| 752 ++parameterCount; | 627 ++parameterCount; |
| 753 } while (optional(',', token)); | 628 } while (optional(',', token)); |
| 754 if (parameterCount == 0) { | 629 if (parameterCount == 0) { |
| 755 reportRecoverableError( | 630 reportRecoverableError( |
| 756 token, | 631 token, |
| 757 isNamed | 632 isNamed |
| 758 ? fasta.messageEmptyNamedParameterList | 633 ? fasta.messageEmptyNamedParameterList |
| 759 : fasta.messageEmptyOptionalParameterList); | 634 : fasta.messageEmptyOptionalParameterList); |
| 760 } | 635 } |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 } | 1136 } |
| 1262 | 1137 |
| 1263 /// Returns true if [token] could be the start of a function body. | 1138 /// Returns true if [token] could be the start of a function body. |
| 1264 bool looksLikeFunctionBody(Token token) { | 1139 bool looksLikeFunctionBody(Token token) { |
| 1265 return optional('{', token) || | 1140 return optional('{', token) || |
| 1266 optional('=>', token) || | 1141 optional('=>', token) || |
| 1267 optional('async', token) || | 1142 optional('async', token) || |
| 1268 optional('sync', token); | 1143 optional('sync', token); |
| 1269 } | 1144 } |
| 1270 | 1145 |
| 1271 FormalParameterType parameterKind; | 1146 FormalParameterKind parameterKind; |
| 1272 switch (continuation) { | 1147 switch (continuation) { |
| 1273 case TypeContinuation.Required: | 1148 case TypeContinuation.Required: |
| 1274 return commitType(); | 1149 return commitType(); |
| 1275 | 1150 |
| 1276 optional: | 1151 optional: |
| 1277 case TypeContinuation.Optional: | 1152 case TypeContinuation.Optional: |
| 1278 if (looksLikeType) { | 1153 if (looksLikeType) { |
| 1279 if (functionTypes > 0) { | 1154 if (functionTypes > 0) { |
| 1280 return commitType(); // Parse function type. | 1155 return commitType(); // Parse function type. |
| 1281 } | 1156 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 token.isIdentifier && | 1275 token.isIdentifier && |
| 1401 isOneOf4(token.next, '=', ';', ',', 'in')) { | 1276 isOneOf4(token.next, '=', ';', ',', 'in')) { |
| 1402 // TODO(ahe): Generate type events and call | 1277 // TODO(ahe): Generate type events and call |
| 1403 // parseVariablesDeclarationNoSemicolonRest instead. | 1278 // parseVariablesDeclarationNoSemicolonRest instead. |
| 1404 return parseVariablesDeclarationNoSemicolon(begin); | 1279 return parseVariablesDeclarationNoSemicolon(begin); |
| 1405 } | 1280 } |
| 1406 return parseExpression(begin); | 1281 return parseExpression(begin); |
| 1407 | 1282 |
| 1408 case TypeContinuation.NormalFormalParameter: | 1283 case TypeContinuation.NormalFormalParameter: |
| 1409 case TypeContinuation.NormalFormalParameterAfterVar: | 1284 case TypeContinuation.NormalFormalParameterAfterVar: |
| 1410 parameterKind = FormalParameterType.REQUIRED; | 1285 parameterKind = FormalParameterKind.mandatory; |
| 1411 hasVar = continuation == TypeContinuation.NormalFormalParameterAfterVar; | 1286 hasVar = continuation == TypeContinuation.NormalFormalParameterAfterVar; |
| 1412 continue handleParameters; | 1287 continue handleParameters; |
| 1413 | 1288 |
| 1414 case TypeContinuation.OptionalPositionalFormalParameter: | 1289 case TypeContinuation.OptionalPositionalFormalParameter: |
| 1415 case TypeContinuation.OptionalPositionalFormalParameterAfterVar: | 1290 case TypeContinuation.OptionalPositionalFormalParameterAfterVar: |
| 1416 parameterKind = FormalParameterType.POSITIONAL; | 1291 parameterKind = FormalParameterKind.optionalPositional; |
| 1417 hasVar = continuation == | 1292 hasVar = continuation == |
| 1418 TypeContinuation.OptionalPositionalFormalParameterAfterVar; | 1293 TypeContinuation.OptionalPositionalFormalParameterAfterVar; |
| 1419 continue handleParameters; | 1294 continue handleParameters; |
| 1420 | 1295 |
| 1421 case TypeContinuation.NamedFormalParameterAfterVar: | 1296 case TypeContinuation.NamedFormalParameterAfterVar: |
| 1422 hasVar = true; | 1297 hasVar = true; |
| 1423 continue handleParameters; | 1298 continue handleParameters; |
| 1424 | 1299 |
| 1425 handleParameters: | 1300 handleParameters: |
| 1426 case TypeContinuation.NamedFormalParameter: | 1301 case TypeContinuation.NamedFormalParameter: |
| 1427 parameterKind ??= FormalParameterType.NAMED; | 1302 parameterKind ??= FormalParameterKind.optionalNamed; |
| 1428 bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType; | 1303 bool inFunctionType = memberKind == MemberKind.GeneralizedFunctionType; |
| 1429 bool isNamedParameter = parameterKind == FormalParameterType.NAMED; | 1304 bool isNamedParameter = |
| 1305 parameterKind == FormalParameterKind.optionalNamed; |
| 1430 | 1306 |
| 1431 bool untyped = false; | 1307 bool untyped = false; |
| 1432 if (!looksLikeType || optional("this", begin)) { | 1308 if (!looksLikeType || optional("this", begin)) { |
| 1433 untyped = true; | 1309 untyped = true; |
| 1434 token = begin; | 1310 token = begin; |
| 1435 } | 1311 } |
| 1436 | 1312 |
| 1437 Token thisKeyword; | 1313 Token thisKeyword; |
| 1438 Token nameToken = token; | 1314 Token nameToken = token; |
| 1439 IdentifierContext nameContext = | 1315 IdentifierContext nameContext = |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 parseIdentifier(nameToken, nameContext); | 1392 parseIdentifier(nameToken, nameContext); |
| 1517 } else { | 1393 } else { |
| 1518 listener.handleNoName(nameToken); | 1394 listener.handleNoName(nameToken); |
| 1519 } | 1395 } |
| 1520 | 1396 |
| 1521 String value = token.stringValue; | 1397 String value = token.stringValue; |
| 1522 if ((identical('=', value)) || (identical(':', value))) { | 1398 if ((identical('=', value)) || (identical(':', value))) { |
| 1523 Token equal = token; | 1399 Token equal = token; |
| 1524 token = parseExpression(token.next); | 1400 token = parseExpression(token.next); |
| 1525 listener.handleValuedFormalParameter(equal, token); | 1401 listener.handleValuedFormalParameter(equal, token); |
| 1526 if (parameterKind.isRequired) { | 1402 if (isMandatoryFormalParameterKind(parameterKind)) { |
| 1527 reportRecoverableError( | 1403 reportRecoverableError( |
| 1528 equal, fasta.messageRequiredParameterWithDefault); | 1404 equal, fasta.messageRequiredParameterWithDefault); |
| 1529 } else if (parameterKind.isPositional && identical(':', value)) { | 1405 } else if (isOptionalPositionalFormalParameterKind(parameterKind) && |
| 1406 identical(':', value)) { |
| 1530 reportRecoverableError( | 1407 reportRecoverableError( |
| 1531 equal, fasta.messagePositionalParameterWithEquals); | 1408 equal, fasta.messagePositionalParameterWithEquals); |
| 1532 } else if (inFunctionType || | 1409 } else if (inFunctionType || |
| 1533 memberKind == MemberKind.FunctionTypeAlias || | 1410 memberKind == MemberKind.FunctionTypeAlias || |
| 1534 memberKind == MemberKind.FunctionTypedParameter) { | 1411 memberKind == MemberKind.FunctionTypedParameter) { |
| 1535 reportRecoverableError( | 1412 reportRecoverableError( |
| 1536 equal.next, fasta.messageFunctionTypeDefaultValue); | 1413 equal.next, fasta.messageFunctionTypeDefaultValue); |
| 1537 } | 1414 } |
| 1538 } else { | 1415 } else { |
| 1539 listener.handleFormalParameterWithoutValue(token); | 1416 listener.handleFormalParameterWithoutValue(token); |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2024 } | 1901 } |
| 2025 | 1902 |
| 2026 /// This method is used in most locations where modifiers can occur. However, | 1903 /// This method is used in most locations where modifiers can occur. However, |
| 2027 /// it isn't used when parsing a class or when parsing the modifiers of a | 1904 /// it isn't used when parsing a class or when parsing the modifiers of a |
| 2028 /// member function (non-local), but is used when parsing their formal | 1905 /// member function (non-local), but is used when parsing their formal |
| 2029 /// parameters. | 1906 /// parameters. |
| 2030 /// | 1907 /// |
| 2031 /// When parsing the formal parameters of any function, [parameterKind] is | 1908 /// When parsing the formal parameters of any function, [parameterKind] is |
| 2032 /// non-null. | 1909 /// non-null. |
| 2033 Token parseModifiers(Token token, MemberKind memberKind, | 1910 Token parseModifiers(Token token, MemberKind memberKind, |
| 2034 {FormalParameterType parameterKind, bool isVarAllowed: false}) { | 1911 {FormalParameterKind parameterKind, bool isVarAllowed: false}) { |
| 2035 int count = 0; | 1912 int count = 0; |
| 2036 | 1913 |
| 2037 int currentOrder = -1; | 1914 int currentOrder = -1; |
| 2038 TypeContinuation typeContinuation = parameterKind?.typeContinuation; | 1915 TypeContinuation typeContinuation = |
| 1916 typeContiunationFromFormalParameterKind(parameterKind); |
| 2039 | 1917 |
| 2040 while (token.kind == KEYWORD_TOKEN) { | 1918 while (token.kind == KEYWORD_TOKEN) { |
| 2041 if (token.type.isPseudo) { | 1919 if (token.type.isPseudo) { |
| 2042 // A pseudo keyword is never a modifier. | 1920 // A pseudo keyword is never a modifier. |
| 2043 break; | 1921 break; |
| 2044 } | 1922 } |
| 2045 if (token.type.isBuiltIn) { | 1923 if (token.type.isBuiltIn) { |
| 2046 // A built-in identifier can only be a modifier as long as it is | 1924 // A built-in identifier can only be a modifier as long as it is |
| 2047 // followed by another modifier or an identifier. Otherwise, it is the | 1925 // followed by another modifier or an identifier. Otherwise, it is the |
| 2048 // identifier. | 1926 // identifier. |
| (...skipping 2086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4135 } | 4013 } |
| 4136 | 4014 |
| 4137 Token reportUnexpectedToken(Token token) { | 4015 Token reportUnexpectedToken(Token token) { |
| 4138 return reportUnrecoverableErrorWithToken( | 4016 return reportUnrecoverableErrorWithToken( |
| 4139 token, fasta.templateUnexpectedToken); | 4017 token, fasta.templateUnexpectedToken); |
| 4140 } | 4018 } |
| 4141 } | 4019 } |
| 4142 | 4020 |
| 4143 // TODO(ahe): Remove when analyzer supports generalized function syntax. | 4021 // TODO(ahe): Remove when analyzer supports generalized function syntax. |
| 4144 typedef _MessageWithArgument<T> = Message Function(T); | 4022 typedef _MessageWithArgument<T> = Message Function(T); |
| OLD | NEW |