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 |