OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 analyzer.parser; | 5 library analyzer.parser; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import "dart:math" as math; | 8 import "dart:math" as math; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 344 |
345 /** | 345 /** |
346 * Return `true` if the current token is the first token of a return type that | 346 * Return `true` if the current token is the first token of a return type that |
347 * is followed by an identifier, possibly followed by a list of type | 347 * is followed by an identifier, possibly followed by a list of type |
348 * parameters, followed by a left-parenthesis. This is used by | 348 * parameters, followed by a left-parenthesis. This is used by |
349 * [parseTypeAlias] to determine whether or not to parse a return type. | 349 * [parseTypeAlias] to determine whether or not to parse a return type. |
350 */ | 350 */ |
351 bool get hasReturnTypeInTypeAlias { | 351 bool get hasReturnTypeInTypeAlias { |
352 // TODO(brianwilkerson) This is too expensive as implemented and needs to be | 352 // TODO(brianwilkerson) This is too expensive as implemented and needs to be |
353 // re-implemented or removed. | 353 // re-implemented or removed. |
354 Token next = skipTypeAnnotation(_currentToken); | 354 Token next = skipReturnType(_currentToken); |
355 if (next == null) { | 355 if (next == null) { |
356 return false; | 356 return false; |
357 } | 357 } |
358 return _tokenMatchesIdentifier(next); | 358 return _tokenMatchesIdentifier(next); |
359 } | 359 } |
360 | 360 |
361 /** | 361 /** |
362 * Set whether the parser is to parse the async support. | 362 * Set whether the parser is to parse the async support. |
363 * | 363 * |
364 * Support for removing the 'async' library has been removed. | 364 * Support for removing the 'async' library has been removed. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 _currentToken = _currentToken.next; | 442 _currentToken = _currentToken.next; |
443 return token; | 443 return token; |
444 } | 444 } |
445 | 445 |
446 /** | 446 /** |
447 * Return `true` if the current token appears to be the beginning of a | 447 * Return `true` if the current token appears to be the beginning of a |
448 * function declaration. | 448 * function declaration. |
449 */ | 449 */ |
450 bool isFunctionDeclaration() { | 450 bool isFunctionDeclaration() { |
451 Keyword keyword = _currentToken.keyword; | 451 Keyword keyword = _currentToken.keyword; |
452 Token afterReturnType = skipTypeWithoutFunction(_currentToken); | 452 if (keyword == Keyword.VOID) { |
| 453 return true; |
| 454 } |
| 455 Token afterReturnType = skipTypeName(_currentToken); |
453 if (afterReturnType != null && | 456 if (afterReturnType != null && |
454 _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) { | 457 _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) { |
455 afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType); | 458 afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType); |
456 } | 459 } |
457 if (afterReturnType == null) { | 460 if (afterReturnType == null) { |
458 // There was no return type, but it is optional, so go back to where we | 461 // There was no return type, but it is optional, so go back to where we |
459 // started. | 462 // started. |
460 afterReturnType = _currentToken; | 463 afterReturnType = _currentToken; |
461 } | 464 } |
462 Token afterIdentifier = skipSimpleIdentifier(afterReturnType); | 465 Token afterIdentifier = skipSimpleIdentifier(afterReturnType); |
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 ])) { | 1321 ])) { |
1319 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 1322 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
1320 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, | 1323 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, |
1321 modifiers.externalKeyword, modifiers.staticKeyword, returnType); | 1324 modifiers.externalKeyword, modifiers.staticKeyword, returnType); |
1322 } else if (_matchesIdentifier() && | 1325 } else if (_matchesIdentifier() && |
1323 _peek().matchesAny(const <TokenType>[ | 1326 _peek().matchesAny(const <TokenType>[ |
1324 TokenType.EQ, | 1327 TokenType.EQ, |
1325 TokenType.COMMA, | 1328 TokenType.COMMA, |
1326 TokenType.SEMICOLON | 1329 TokenType.SEMICOLON |
1327 ])) { | 1330 ])) { |
| 1331 if (returnType is! GenericFunctionType) { |
| 1332 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 1333 } |
1328 return parseInitializedIdentifierList( | 1334 return parseInitializedIdentifierList( |
1329 commentAndMetadata, | 1335 commentAndMetadata, |
1330 modifiers.staticKeyword, | 1336 modifiers.staticKeyword, |
1331 modifiers.covariantKeyword, | 1337 modifiers.covariantKeyword, |
1332 _validateModifiersForField(modifiers), | 1338 _validateModifiersForField(modifiers), |
1333 returnType); | 1339 returnType); |
1334 } else { | 1340 } else { |
1335 // | 1341 // |
1336 // We have found an error of some kind. Try to recover. | 1342 // We have found an error of some kind. Try to recover. |
1337 // | 1343 // |
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2124 ])) { | 2130 ])) { |
2125 _validateModifiersForTopLevelFunction(modifiers); | 2131 _validateModifiersForTopLevelFunction(modifiers); |
2126 return parseFunctionDeclaration( | 2132 return parseFunctionDeclaration( |
2127 commentAndMetadata, modifiers.externalKeyword, returnType); | 2133 commentAndMetadata, modifiers.externalKeyword, returnType); |
2128 } else if (_matchesIdentifier() && | 2134 } else if (_matchesIdentifier() && |
2129 next.matchesAny(const <TokenType>[ | 2135 next.matchesAny(const <TokenType>[ |
2130 TokenType.EQ, | 2136 TokenType.EQ, |
2131 TokenType.COMMA, | 2137 TokenType.COMMA, |
2132 TokenType.SEMICOLON | 2138 TokenType.SEMICOLON |
2133 ])) { | 2139 ])) { |
| 2140 if (returnType is! GenericFunctionType) { |
| 2141 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 2142 } |
2134 return astFactory.topLevelVariableDeclaration( | 2143 return astFactory.topLevelVariableDeclaration( |
2135 commentAndMetadata.comment, | 2144 commentAndMetadata.comment, |
2136 commentAndMetadata.metadata, | 2145 commentAndMetadata.metadata, |
2137 parseVariableDeclarationListAfterType(null, | 2146 parseVariableDeclarationListAfterType(null, |
2138 _validateModifiersForTopLevelVariable(modifiers), returnType), | 2147 _validateModifiersForTopLevelVariable(modifiers), returnType), |
2139 _expect(TokenType.SEMICOLON)); | 2148 _expect(TokenType.SEMICOLON)); |
2140 } else { | 2149 } else { |
2141 // | 2150 // |
2142 // We have found an error of some kind. Try to recover. | 2151 // We have found an error of some kind. Try to recover. |
2143 // | 2152 // |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2201 _reportErrorForCurrentToken( | 2210 _reportErrorForCurrentToken( |
2202 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); | 2211 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); |
2203 } | 2212 } |
2204 return astFactory.topLevelVariableDeclaration( | 2213 return astFactory.topLevelVariableDeclaration( |
2205 commentAndMetadata.comment, | 2214 commentAndMetadata.comment, |
2206 commentAndMetadata.metadata, | 2215 commentAndMetadata.metadata, |
2207 parseVariableDeclarationListAfterType( | 2216 parseVariableDeclarationListAfterType( |
2208 null, _validateModifiersForTopLevelVariable(modifiers), null), | 2217 null, _validateModifiersForTopLevelVariable(modifiers), null), |
2209 _expect(TokenType.SEMICOLON)); | 2218 _expect(TokenType.SEMICOLON)); |
2210 } | 2219 } |
2211 TypeAnnotation returnType = parseTypeAnnotation(false); | 2220 TypeAnnotation returnType = parseReturnType(false); |
2212 keyword = _currentToken.keyword; | 2221 keyword = _currentToken.keyword; |
2213 next = _peek(); | 2222 next = _peek(); |
2214 if ((keyword == Keyword.GET || keyword == Keyword.SET) && | 2223 if ((keyword == Keyword.GET || keyword == Keyword.SET) && |
2215 _tokenMatchesIdentifier(next)) { | 2224 _tokenMatchesIdentifier(next)) { |
2216 _validateModifiersForTopLevelFunction(modifiers); | 2225 _validateModifiersForTopLevelFunction(modifiers); |
2217 return parseFunctionDeclaration( | 2226 return parseFunctionDeclaration( |
2218 commentAndMetadata, modifiers.externalKeyword, returnType); | 2227 commentAndMetadata, modifiers.externalKeyword, returnType); |
2219 } else if (keyword == Keyword.OPERATOR && _isOperator(next)) { | 2228 } else if (keyword == Keyword.OPERATOR && _isOperator(next)) { |
2220 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken); | 2229 _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken); |
2221 return _convertToFunctionDeclaration(_parseOperatorAfterKeyword( | 2230 return _convertToFunctionDeclaration(_parseOperatorAfterKeyword( |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2876 } | 2885 } |
2877 } else if (keyword == Keyword.VAR) { | 2886 } else if (keyword == Keyword.VAR) { |
2878 keywordToken = getAndAdvance(); | 2887 keywordToken = getAndAdvance(); |
2879 // Support `var/*=T*/ x;` | 2888 // Support `var/*=T*/ x;` |
2880 type = _parseOptionalTypeNameComment(); | 2889 type = _parseOptionalTypeNameComment(); |
2881 if (type != null) { | 2890 if (type != null) { |
2882 // Clear the keyword to prevent an error. | 2891 // Clear the keyword to prevent an error. |
2883 keywordToken = null; | 2892 keywordToken = null; |
2884 } | 2893 } |
2885 } else if (_isTypedIdentifier(_currentToken)) { | 2894 } else if (_isTypedIdentifier(_currentToken)) { |
2886 type = parseTypeAnnotation(false); | 2895 type = parseReturnType(false); |
2887 } else if (inFunctionType && _matchesIdentifier()) { | 2896 } else if (inFunctionType && _matchesIdentifier()) { |
2888 type = parseTypeAnnotation(false); | 2897 type = parseTypeAnnotation(false); |
2889 } else if (!optional) { | 2898 } else if (!optional) { |
2890 // If there is a valid type immediately following an unexpected token, | 2899 // If there is a valid type immediately following an unexpected token, |
2891 // then report and skip the unexpected token. | 2900 // then report and skip the unexpected token. |
2892 Token next = _peek(); | 2901 Token next = _peek(); |
2893 Keyword nextKeyword = next.keyword; | 2902 Keyword nextKeyword = next.keyword; |
2894 if (nextKeyword == Keyword.FINAL || | 2903 if (nextKeyword == Keyword.FINAL || |
2895 nextKeyword == Keyword.CONST || | 2904 nextKeyword == Keyword.CONST || |
2896 nextKeyword == Keyword.VAR || | 2905 nextKeyword == Keyword.VAR || |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3398 * Parse the portion of a generic function type following the [returnType]. | 3407 * Parse the portion of a generic function type following the [returnType]. |
3399 * | 3408 * |
3400 * functionType ::= | 3409 * functionType ::= |
3401 * returnType? 'Function' typeParameters? parameterTypeList | 3410 * returnType? 'Function' typeParameters? parameterTypeList |
3402 * parameterTypeList ::= | 3411 * parameterTypeList ::= |
3403 * '(' ')' | | 3412 * '(' ')' | |
3404 * | '(' normalParameterTypes ','? ')' | | 3413 * | '(' normalParameterTypes ','? ')' | |
3405 * | '(' normalParameterTypes ',' optionalParameterTypes ')' | | 3414 * | '(' normalParameterTypes ',' optionalParameterTypes ')' | |
3406 * | '(' optionalParameterTypes ')' | 3415 * | '(' optionalParameterTypes ')' |
3407 * normalParameterTypes ::= | 3416 * normalParameterTypes ::= |
3408 * normalParameterType (',' normalParameterType)* | 3417 * normalParameterType (',' normalParameterType)* |
3409 * normalParameterType ::= | 3418 * normalParameterType ::= |
3410 * type | typedIdentifier | 3419 * type | typedIdentifier |
3411 * optionalParameterTypes ::= | 3420 * optionalParameterTypes ::= |
3412 * optionalPositionalParameterTypes | namedParameterTypes | 3421 * optionalPositionalParameterTypes | namedParameterTypes |
3413 * optionalPositionalParameterTypes ::= | 3422 * optionalPositionalParameterTypes ::= |
3414 * '[' normalParameterTypes ','? ']' | 3423 * '[' normalParameterTypes ','? ']' |
3415 * namedParameterTypes ::= | 3424 * namedParameterTypes ::= |
3416 * '{' typedIdentifier (',' typedIdentifier)* ','? '}' | 3425 * '{' typedIdentifier (',' typedIdentifier)* ','? '}' |
3417 * typedIdentifier ::= | 3426 * typedIdentifier ::= |
3418 * type identifier | 3427 * type identifier |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4121 TokenType.LT | 4130 TokenType.LT |
4122 ])) { | 4131 ])) { |
4123 return _parseFunctionDeclarationStatementAfterReturnType( | 4132 return _parseFunctionDeclarationStatementAfterReturnType( |
4124 commentAndMetadata, returnType); | 4133 commentAndMetadata, returnType); |
4125 } else if (_matchesIdentifier() && | 4134 } else if (_matchesIdentifier() && |
4126 next.matchesAny(const <TokenType>[ | 4135 next.matchesAny(const <TokenType>[ |
4127 TokenType.EQ, | 4136 TokenType.EQ, |
4128 TokenType.COMMA, | 4137 TokenType.COMMA, |
4129 TokenType.SEMICOLON | 4138 TokenType.SEMICOLON |
4130 ])) { | 4139 ])) { |
| 4140 if (returnType is! GenericFunctionType) { |
| 4141 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 4142 } |
4131 return _parseVariableDeclarationStatementAfterType( | 4143 return _parseVariableDeclarationStatementAfterType( |
4132 commentAndMetadata, null, returnType); | 4144 commentAndMetadata, null, returnType); |
4133 } else { | 4145 } else { |
4134 // | 4146 // |
4135 // We have found an error of some kind. Try to recover. | 4147 // We have found an error of some kind. Try to recover. |
4136 // | 4148 // |
4137 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { | 4149 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
4138 // | 4150 // |
4139 // We appear to have found an incomplete statement at the end of a | 4151 // We appear to have found an incomplete statement at the end of a |
4140 // block. Parse it as a variable declaration. | 4152 // block. Parse it as a variable declaration. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4198 TokenType.LT | 4210 TokenType.LT |
4199 ])) { | 4211 ])) { |
4200 return _parseFunctionDeclarationStatementAfterReturnType( | 4212 return _parseFunctionDeclarationStatementAfterReturnType( |
4201 commentAndMetadata, returnType); | 4213 commentAndMetadata, returnType); |
4202 } else if (_matchesIdentifier() && | 4214 } else if (_matchesIdentifier() && |
4203 next.matchesAny(const <TokenType>[ | 4215 next.matchesAny(const <TokenType>[ |
4204 TokenType.EQ, | 4216 TokenType.EQ, |
4205 TokenType.COMMA, | 4217 TokenType.COMMA, |
4206 TokenType.SEMICOLON | 4218 TokenType.SEMICOLON |
4207 ])) { | 4219 ])) { |
| 4220 if (returnType is! GenericFunctionType) { |
| 4221 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 4222 } |
4208 return _parseVariableDeclarationStatementAfterType( | 4223 return _parseVariableDeclarationStatementAfterType( |
4209 commentAndMetadata, null, returnType); | 4224 commentAndMetadata, null, returnType); |
4210 } else { | 4225 } else { |
4211 // | 4226 // |
4212 // We have found an error of some kind. Try to recover. | 4227 // We have found an error of some kind. Try to recover. |
4213 // | 4228 // |
4214 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { | 4229 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
4215 // | 4230 // |
4216 // We appear to have found an incomplete statement at the end of a | 4231 // We appear to have found an incomplete statement at the end of a |
4217 // block. Parse it as a variable declaration. | 4232 // block. Parse it as a variable declaration. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4343 identifier: identifier, | 4358 identifier: identifier, |
4344 typeParameters: typeParameters, | 4359 typeParameters: typeParameters, |
4345 parameters: parameters); | 4360 parameters: parameters); |
4346 } | 4361 } |
4347 } else if (typeParameters != null) { | 4362 } else if (typeParameters != null) { |
4348 // TODO(brianwilkerson) Report an error. It looks like a function-typed | 4363 // TODO(brianwilkerson) Report an error. It looks like a function-typed |
4349 // parameter with no parameter list. | 4364 // parameter with no parameter list. |
4350 //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.
endToken); | 4365 //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.
endToken); |
4351 } | 4366 } |
4352 TypeAnnotation type = holder.type; | 4367 TypeAnnotation type = holder.type; |
4353 if (type != null && | 4368 if (type != null) { |
4354 holder.keyword != null && | 4369 if (type is TypeName && |
4355 _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) { | 4370 _tokenMatchesKeyword(type.name.beginToken, Keyword.VOID)) { |
4356 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword); | 4371 _reportErrorForToken( |
| 4372 ParserErrorCode.VOID_PARAMETER, type.name.beginToken); |
| 4373 } else if (holder.keyword != null && |
| 4374 _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) { |
| 4375 _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword); |
| 4376 } |
4357 } | 4377 } |
4358 if (thisKeyword != null) { | 4378 if (thisKeyword != null) { |
4359 // TODO(brianwilkerson) If there are type parameters but no parameters, | 4379 // TODO(brianwilkerson) If there are type parameters but no parameters, |
4360 // should we create a synthetic empty parameter list here so we can | 4380 // should we create a synthetic empty parameter list here so we can |
4361 // capture the type parameters? | 4381 // capture the type parameters? |
4362 return astFactory.fieldFormalParameter2( | 4382 return astFactory.fieldFormalParameter2( |
4363 comment: commentAndMetadata.comment, | 4383 comment: commentAndMetadata.comment, |
4364 metadata: commentAndMetadata.metadata, | 4384 metadata: commentAndMetadata.metadata, |
4365 covariantKeyword: covariantKeyword, | 4385 covariantKeyword: covariantKeyword, |
4366 keyword: holder.keyword, | 4386 keyword: holder.keyword, |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4674 Expression expression = astFactory.superExpression(getAndAdvance()); | 4694 Expression expression = astFactory.superExpression(getAndAdvance()); |
4675 Token operator = getAndAdvance(); | 4695 Token operator = getAndAdvance(); |
4676 return astFactory.binaryExpression( | 4696 return astFactory.binaryExpression( |
4677 expression, operator, parseBitwiseOrExpression()); | 4697 expression, operator, parseBitwiseOrExpression()); |
4678 } | 4698 } |
4679 Expression expression = parseBitwiseOrExpression(); | 4699 Expression expression = parseBitwiseOrExpression(); |
4680 Keyword keyword = _currentToken.keyword; | 4700 Keyword keyword = _currentToken.keyword; |
4681 if (keyword == Keyword.AS) { | 4701 if (keyword == Keyword.AS) { |
4682 Token asOperator = getAndAdvance(); | 4702 Token asOperator = getAndAdvance(); |
4683 return astFactory.asExpression( | 4703 return astFactory.asExpression( |
4684 expression, asOperator, parseTypeNotVoid(true)); | 4704 expression, asOperator, parseTypeAnnotation(true)); |
4685 } else if (keyword == Keyword.IS) { | 4705 } else if (keyword == Keyword.IS) { |
4686 Token isOperator = getAndAdvance(); | 4706 Token isOperator = getAndAdvance(); |
4687 Token notOperator = null; | 4707 Token notOperator = null; |
4688 if (_matches(TokenType.BANG)) { | 4708 if (_matches(TokenType.BANG)) { |
4689 notOperator = getAndAdvance(); | 4709 notOperator = getAndAdvance(); |
4690 } | 4710 } |
4691 TypeAnnotation type = parseTypeNotVoid(true); | 4711 TypeAnnotation type = parseTypeAnnotation(true); |
4692 return astFactory.isExpression(expression, isOperator, notOperator, type); | 4712 return astFactory.isExpression(expression, isOperator, notOperator, type); |
4693 } else if (_currentToken.type.isRelationalOperator) { | 4713 } else if (_currentToken.type.isRelationalOperator) { |
4694 Token operator = getAndAdvance(); | 4714 Token operator = getAndAdvance(); |
4695 return astFactory.binaryExpression( | 4715 return astFactory.binaryExpression( |
4696 expression, operator, parseBitwiseOrExpression()); | 4716 expression, operator, parseBitwiseOrExpression()); |
4697 } | 4717 } |
4698 return expression; | 4718 return expression; |
4699 } | 4719 } |
4700 | 4720 |
4701 /** | 4721 /** |
(...skipping 19 matching lines...) Expand all Loading... |
4721 Token returnKeyword = getAndAdvance(); | 4741 Token returnKeyword = getAndAdvance(); |
4722 if (_matches(TokenType.SEMICOLON)) { | 4742 if (_matches(TokenType.SEMICOLON)) { |
4723 return astFactory.returnStatement(returnKeyword, null, getAndAdvance()); | 4743 return astFactory.returnStatement(returnKeyword, null, getAndAdvance()); |
4724 } | 4744 } |
4725 Expression expression = parseExpression2(); | 4745 Expression expression = parseExpression2(); |
4726 Token semicolon = _expect(TokenType.SEMICOLON); | 4746 Token semicolon = _expect(TokenType.SEMICOLON); |
4727 return astFactory.returnStatement(returnKeyword, expression, semicolon); | 4747 return astFactory.returnStatement(returnKeyword, expression, semicolon); |
4728 } | 4748 } |
4729 | 4749 |
4730 /** | 4750 /** |
| 4751 * Parse a return type. Return the return type that was parsed. |
| 4752 * |
| 4753 * returnType ::= |
| 4754 * 'void' |
| 4755 * | type |
| 4756 */ |
| 4757 TypeAnnotation parseReturnType(bool inExpression) { |
| 4758 if (_currentToken.keyword == Keyword.VOID) { |
| 4759 if (_atGenericFunctionTypeAfterReturnType(_peek())) { |
| 4760 return parseTypeAnnotation(false); |
| 4761 } else { |
| 4762 return astFactory.typeName( |
| 4763 astFactory.simpleIdentifier(getAndAdvance()), null); |
| 4764 } |
| 4765 } else { |
| 4766 return parseTypeAnnotation(inExpression); |
| 4767 } |
| 4768 } |
| 4769 |
| 4770 /** |
4731 * Parse a setter. The [commentAndMetadata] is the documentation comment and | 4771 * Parse a setter. The [commentAndMetadata] is the documentation comment and |
4732 * metadata to be associated with the declaration. The [externalKeyword] is | 4772 * metadata to be associated with the declaration. The [externalKeyword] is |
4733 * the 'external' token. The [staticKeyword] is the static keyword, or `null` | 4773 * the 'external' token. The [staticKeyword] is the static keyword, or `null` |
4734 * if the setter is not static. The [returnType] is the return type that has | 4774 * if the setter is not static. The [returnType] is the return type that has |
4735 * already been parsed, or `null` if there was no return type. Return the | 4775 * already been parsed, or `null` if there was no return type. Return the |
4736 * setter that was parsed. | 4776 * setter that was parsed. |
4737 * | 4777 * |
4738 * This method assumes that the current token matches `Keyword.SET`. | 4778 * This method assumes that the current token matches `Keyword.SET`. |
4739 * | 4779 * |
4740 * setter ::= | 4780 * setter ::= |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5083 Statement parseTryStatement() { | 5123 Statement parseTryStatement() { |
5084 Token tryKeyword = getAndAdvance(); | 5124 Token tryKeyword = getAndAdvance(); |
5085 Block body = _parseBlockChecked(); | 5125 Block body = _parseBlockChecked(); |
5086 List<CatchClause> catchClauses = <CatchClause>[]; | 5126 List<CatchClause> catchClauses = <CatchClause>[]; |
5087 Block finallyClause = null; | 5127 Block finallyClause = null; |
5088 while (_matchesKeyword(Keyword.ON) || _matchesKeyword(Keyword.CATCH)) { | 5128 while (_matchesKeyword(Keyword.ON) || _matchesKeyword(Keyword.CATCH)) { |
5089 Token onKeyword = null; | 5129 Token onKeyword = null; |
5090 TypeName exceptionType = null; | 5130 TypeName exceptionType = null; |
5091 if (_matchesKeyword(Keyword.ON)) { | 5131 if (_matchesKeyword(Keyword.ON)) { |
5092 onKeyword = getAndAdvance(); | 5132 onKeyword = getAndAdvance(); |
5093 exceptionType = parseTypeNotVoid(false); | 5133 exceptionType = parseTypeAnnotation(false); |
5094 } | 5134 } |
5095 Token catchKeyword = null; | 5135 Token catchKeyword = null; |
5096 Token leftParenthesis = null; | 5136 Token leftParenthesis = null; |
5097 SimpleIdentifier exceptionParameter = null; | 5137 SimpleIdentifier exceptionParameter = null; |
5098 Token comma = null; | 5138 Token comma = null; |
5099 SimpleIdentifier stackTraceParameter = null; | 5139 SimpleIdentifier stackTraceParameter = null; |
5100 Token rightParenthesis = null; | 5140 Token rightParenthesis = null; |
5101 if (_matchesKeyword(Keyword.CATCH)) { | 5141 if (_matchesKeyword(Keyword.CATCH)) { |
5102 catchKeyword = getAndAdvance(); | 5142 catchKeyword = getAndAdvance(); |
5103 leftParenthesis = _expect(TokenType.OPEN_PAREN); | 5143 leftParenthesis = _expect(TokenType.OPEN_PAREN); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5174 * Parse a type. | 5214 * Parse a type. |
5175 * | 5215 * |
5176 * type ::= | 5216 * type ::= |
5177 * typeWithoutFunction | 5217 * typeWithoutFunction |
5178 * | functionType | 5218 * | functionType |
5179 */ | 5219 */ |
5180 TypeAnnotation parseTypeAnnotation(bool inExpression) { | 5220 TypeAnnotation parseTypeAnnotation(bool inExpression) { |
5181 TypeAnnotation type = null; | 5221 TypeAnnotation type = null; |
5182 if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | 5222 if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
5183 // Generic function type with no return type. | 5223 // Generic function type with no return type. |
5184 type = parseGenericFunctionTypeAfterReturnType(null); | |
5185 } else { | |
5186 type = parseTypeWithoutFunction(inExpression); | |
5187 } | |
5188 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | |
5189 type = parseGenericFunctionTypeAfterReturnType(type); | |
5190 } | |
5191 return type; | |
5192 } | |
5193 | |
5194 /** | |
5195 * Parse a type which is not `void`. | |
5196 * | |
5197 * typeNotVoid ::= | |
5198 * functionType | |
5199 * | typeNotVoidWithoutFunction | |
5200 */ | |
5201 TypeAnnotation parseTypeNotVoid(bool inExpression) { | |
5202 TypeAnnotation type = null; | |
5203 if (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | |
5204 // Generic function type with no return type. | |
5205 type = parseGenericFunctionTypeAfterReturnType(null); | 5224 type = parseGenericFunctionTypeAfterReturnType(null); |
5206 } else if (_currentToken.keyword == Keyword.VOID && | 5225 } else if (_currentToken.keyword == Keyword.VOID && |
5207 _atGenericFunctionTypeAfterReturnType(_currentToken.next)) { | 5226 _atGenericFunctionTypeAfterReturnType(_currentToken.next)) { |
5208 type = astFactory.typeName( | 5227 type = astFactory.typeName( |
5209 astFactory.simpleIdentifier(getAndAdvance()), null); | 5228 astFactory.simpleIdentifier(getAndAdvance()), null); |
5210 } else { | 5229 } else { |
5211 type = parseTypeName(inExpression); | 5230 type = parseTypeName(inExpression); |
5212 } | 5231 } |
5213 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { | 5232 while (_atGenericFunctionTypeAfterReturnType(_currentToken)) { |
5214 type = parseGenericFunctionTypeAfterReturnType(type); | 5233 type = parseGenericFunctionTypeAfterReturnType(type); |
5215 } | 5234 } |
5216 return type; | 5235 return type; |
5217 } | 5236 } |
5218 | 5237 |
5219 /** | 5238 /** |
5220 * Parse a type which is not a function type. | |
5221 * | |
5222 * typeWithoutFunction ::= | |
5223 * `void` | |
5224 * | typeNotVoidWithoutFunction | |
5225 */ | |
5226 TypeAnnotation parseTypeWithoutFunction(bool inExpression) { | |
5227 if (_currentToken.keyword == Keyword.VOID) { | |
5228 return astFactory.typeName( | |
5229 astFactory.simpleIdentifier(getAndAdvance()), null); | |
5230 } else { | |
5231 return parseTypeName(inExpression); | |
5232 } | |
5233 } | |
5234 | |
5235 /** | |
5236 * Parse a list of type arguments. Return the type argument list that was | 5239 * Parse a list of type arguments. Return the type argument list that was |
5237 * parsed. | 5240 * parsed. |
5238 * | 5241 * |
5239 * This method assumes that the current token matches `TokenType.LT`. | 5242 * This method assumes that the current token matches `TokenType.LT`. |
5240 * | 5243 * |
5241 * typeArguments ::= | 5244 * typeArguments ::= |
5242 * '<' typeList '>' | 5245 * '<' typeList '>' |
5243 * | 5246 * |
5244 * typeList ::= | 5247 * typeList ::= |
5245 * type (',' type)* | 5248 * type (',' type)* |
5246 */ | 5249 */ |
5247 TypeArgumentList parseTypeArgumentList() { | 5250 TypeArgumentList parseTypeArgumentList() { |
5248 Token leftBracket = getAndAdvance(); | 5251 Token leftBracket = getAndAdvance(); |
5249 List<TypeAnnotation> arguments = <TypeAnnotation>[ | 5252 List<TypeAnnotation> arguments = <TypeAnnotation>[ |
5250 parseTypeAnnotation(false) | 5253 parseTypeAnnotation(false) |
5251 ]; | 5254 ]; |
5252 while (_optional(TokenType.COMMA)) { | 5255 while (_optional(TokenType.COMMA)) { |
5253 arguments.add(parseTypeAnnotation(false)); | 5256 arguments.add(parseTypeAnnotation(false)); |
5254 } | 5257 } |
5255 Token rightBracket = _expectGt(); | 5258 Token rightBracket = _expectGt(); |
5256 return astFactory.typeArgumentList(leftBracket, arguments, rightBracket); | 5259 return astFactory.typeArgumentList(leftBracket, arguments, rightBracket); |
5257 } | 5260 } |
5258 | 5261 |
5259 /** | 5262 /** |
5260 * Parse a type which is not void and is not a function type. Return the type | 5263 * Parse a type name. Return the type name that was parsed. |
5261 * that was parsed. | |
5262 * | 5264 * |
5263 * typeNotVoidWithoutFunction ::= | 5265 * type ::= |
5264 * qualified typeArguments? | 5266 * qualified typeArguments? |
5265 */ | 5267 */ |
5266 // TODO(eernst): Rename this to `parseTypeNotVoidWithoutFunction`? | |
5267 // Apparently, it was named `parseTypeName` before type arguments existed. | |
5268 TypeName parseTypeName(bool inExpression) { | 5268 TypeName parseTypeName(bool inExpression) { |
5269 TypeName realType = _parseTypeName(inExpression); | 5269 TypeName realType = _parseTypeName(inExpression); |
5270 // If this is followed by a generic method type comment, allow the comment | 5270 // If this is followed by a generic method type comment, allow the comment |
5271 // type to replace the real type name. | 5271 // type to replace the real type name. |
5272 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to | 5272 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to |
5273 // only work inside generic methods? | 5273 // only work inside generic methods? |
5274 TypeName typeFromComment = _parseOptionalTypeNameComment(); | 5274 TypeName typeFromComment = _parseOptionalTypeNameComment(); |
5275 return typeFromComment ?? realType; | 5275 return typeFromComment ?? realType; |
5276 } | 5276 } |
5277 | 5277 |
5278 /** | 5278 /** |
5279 * Parse a type parameter. Return the type parameter that was parsed. | 5279 * Parse a type parameter. Return the type parameter that was parsed. |
5280 * | 5280 * |
5281 * typeParameter ::= | 5281 * typeParameter ::= |
5282 * metadata name ('extends' bound)? | 5282 * metadata name ('extends' bound)? |
5283 */ | 5283 */ |
5284 TypeParameter parseTypeParameter() { | 5284 TypeParameter parseTypeParameter() { |
5285 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); | 5285 CommentAndMetadata commentAndMetadata = parseCommentAndMetadata(); |
5286 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); | 5286 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); |
5287 if (_matches(TokenType.QUESTION)) { | 5287 if (_matches(TokenType.QUESTION)) { |
5288 _reportErrorForCurrentToken(ParserErrorCode.NULLABLE_TYPE_PARAMETER); | 5288 _reportErrorForCurrentToken(ParserErrorCode.NULLABLE_TYPE_PARAMETER); |
5289 _advance(); | 5289 _advance(); |
5290 } | 5290 } |
5291 if (_matchesKeyword(Keyword.EXTENDS)) { | 5291 if (_matchesKeyword(Keyword.EXTENDS)) { |
5292 Token keyword = getAndAdvance(); | 5292 Token keyword = getAndAdvance(); |
5293 TypeAnnotation bound = parseTypeNotVoid(false); | 5293 TypeAnnotation bound = parseTypeAnnotation(false); |
5294 return astFactory.typeParameter(commentAndMetadata.comment, | 5294 return astFactory.typeParameter(commentAndMetadata.comment, |
5295 commentAndMetadata.metadata, name, keyword, bound); | 5295 commentAndMetadata.metadata, name, keyword, bound); |
5296 } | 5296 } |
5297 return astFactory.typeParameter(commentAndMetadata.comment, | 5297 return astFactory.typeParameter(commentAndMetadata.comment, |
5298 commentAndMetadata.metadata, name, null, null); | 5298 commentAndMetadata.metadata, name, null, null); |
5299 } | 5299 } |
5300 | 5300 |
5301 /** | 5301 /** |
5302 * Parse a list of type parameters. Return the list of type parameters that | 5302 * Parse a list of type parameters. Return the list of type parameters that |
5303 * were parsed. | 5303 * were parsed. |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5614 _tokenMatches(token, TokenType.COMMA)) { | 5614 _tokenMatches(token, TokenType.COMMA)) { |
5615 // If the `id.` is followed by something that cannot produce a valid | 5615 // If the `id.` is followed by something that cannot produce a valid |
5616 // structure then assume this is a prefixed identifier but missing the | 5616 // structure then assume this is a prefixed identifier but missing the |
5617 // trailing identifier | 5617 // trailing identifier |
5618 return token; | 5618 return token; |
5619 } | 5619 } |
5620 return null; | 5620 return null; |
5621 } | 5621 } |
5622 | 5622 |
5623 /** | 5623 /** |
| 5624 * Parse a return type, starting at the [startToken], without actually |
| 5625 * creating a return type or changing the current token. Return the token |
| 5626 * following the return type that was parsed, or `null` if the given token is |
| 5627 * not the first token in a valid return type. |
| 5628 * |
| 5629 * This method must be kept in sync with [parseReturnType]. |
| 5630 * |
| 5631 * returnType ::= |
| 5632 * 'void' |
| 5633 * | type |
| 5634 */ |
| 5635 Token skipReturnType(Token startToken) { |
| 5636 if (_tokenMatchesKeyword(startToken, Keyword.VOID)) { |
| 5637 if (_atGenericFunctionTypeAfterReturnType(_peek())) { |
| 5638 return skipTypeAnnotation(startToken); |
| 5639 } |
| 5640 return startToken.next; |
| 5641 } else { |
| 5642 return skipTypeAnnotation(startToken); |
| 5643 } |
| 5644 } |
| 5645 |
| 5646 /** |
5624 * Parse a simple identifier, starting at the [startToken], without actually | 5647 * Parse a simple identifier, starting at the [startToken], without actually |
5625 * creating a simple identifier or changing the current token. Return the | 5648 * creating a simple identifier or changing the current token. Return the |
5626 * token following the simple identifier that was parsed, or `null` if the | 5649 * token following the simple identifier that was parsed, or `null` if the |
5627 * given token is not the first token in a valid simple identifier. | 5650 * given token is not the first token in a valid simple identifier. |
5628 * | 5651 * |
5629 * This method must be kept in sync with [parseSimpleIdentifier]. | 5652 * This method must be kept in sync with [parseSimpleIdentifier]. |
5630 * | 5653 * |
5631 * identifier ::= | 5654 * identifier ::= |
5632 * IDENTIFIER | 5655 * IDENTIFIER |
5633 */ | 5656 */ |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5671 * Parse a type annotation, starting at the [startToken], without actually | 5694 * Parse a type annotation, starting at the [startToken], without actually |
5672 * creating a type annotation or changing the current token. Return the token | 5695 * creating a type annotation or changing the current token. Return the token |
5673 * following the type annotation that was parsed, or `null` if the given token | 5696 * following the type annotation that was parsed, or `null` if the given token |
5674 * is not the first token in a valid type annotation. | 5697 * is not the first token in a valid type annotation. |
5675 * | 5698 * |
5676 * This method must be kept in sync with [parseTypeAnnotation]. | 5699 * This method must be kept in sync with [parseTypeAnnotation]. |
5677 */ | 5700 */ |
5678 Token skipTypeAnnotation(Token startToken) { | 5701 Token skipTypeAnnotation(Token startToken) { |
5679 Token next = null; | 5702 Token next = null; |
5680 if (_atGenericFunctionTypeAfterReturnType(startToken)) { | 5703 if (_atGenericFunctionTypeAfterReturnType(startToken)) { |
5681 // Generic function type with no return type. | |
5682 next = skipGenericFunctionTypeAfterReturnType(startToken); | 5704 next = skipGenericFunctionTypeAfterReturnType(startToken); |
| 5705 } else if (startToken.keyword == Keyword.VOID && |
| 5706 _atGenericFunctionTypeAfterReturnType(startToken.next)) { |
| 5707 next = startToken.next; |
5683 } else { | 5708 } else { |
5684 next = skipTypeWithoutFunction(startToken); | 5709 next = skipTypeName(startToken); |
5685 } | 5710 } |
5686 while (next != null && _atGenericFunctionTypeAfterReturnType(next)) { | 5711 while (next != null && _atGenericFunctionTypeAfterReturnType(next)) { |
5687 next = skipGenericFunctionTypeAfterReturnType(next); | 5712 next = skipGenericFunctionTypeAfterReturnType(next); |
5688 } | 5713 } |
5689 return next; | 5714 return next; |
5690 } | 5715 } |
5691 | 5716 |
5692 /** | 5717 /** |
5693 * Parse a typeWithoutFunction, starting at the [startToken], without actually | |
5694 * creating a TypeAnnotation or changing the current token. Return the token | |
5695 * following the typeWithoutFunction that was parsed, or `null` if the given | |
5696 * token is not the first token in a valid typeWithoutFunction. | |
5697 * | |
5698 * This method must be kept in sync with [parseTypeWithoutFunction]. | |
5699 */ | |
5700 Token skipTypeWithoutFunction(Token startToken) { | |
5701 if (startToken.keyword == Keyword.VOID) { | |
5702 return startToken.next; | |
5703 } else { | |
5704 return skipTypeName(startToken); | |
5705 } | |
5706 } | |
5707 | |
5708 /** | |
5709 * Parse a list of type arguments, starting at the [startToken], without | 5718 * Parse a list of type arguments, starting at the [startToken], without |
5710 * actually creating a type argument list or changing the current token. | 5719 * actually creating a type argument list or changing the current token. |
5711 * Return the token following the type argument list that was parsed, or | 5720 * Return the token following the type argument list that was parsed, or |
5712 * `null` if the given token is not the first token in a valid type argument | 5721 * `null` if the given token is not the first token in a valid type argument |
5713 * list. | 5722 * list. |
5714 * | 5723 * |
5715 * This method must be kept in sync with [parseTypeArgumentList]. | 5724 * This method must be kept in sync with [parseTypeArgumentList]. |
5716 * | 5725 * |
5717 * typeArguments ::= | 5726 * typeArguments ::= |
5718 * '<' typeList '>' | 5727 * '<' typeList '>' |
5719 * | 5728 * |
5720 * typeList ::= | 5729 * typeList ::= |
5721 * type (',' type)* | 5730 * type (',' type)* |
5722 */ | 5731 */ |
5723 Token skipTypeArgumentList(Token startToken) { | 5732 Token skipTypeArgumentList(Token startToken) { |
5724 Token token = startToken; | 5733 Token token = startToken; |
5725 if (!_tokenMatches(token, TokenType.LT) && | 5734 if (!_tokenMatches(token, TokenType.LT) && |
5726 !_injectGenericCommentTypeList()) { | 5735 !_injectGenericCommentTypeList()) { |
5727 return null; | 5736 return null; |
5728 } | 5737 } |
5729 token = skipTypeAnnotation(token.next); | 5738 token = skipTypeName(token.next); |
5730 if (token == null) { | 5739 if (token == null) { |
5731 // If the start token '<' is followed by '>' | 5740 // If the start token '<' is followed by '>' |
5732 // then assume this should be type argument list but is missing a type | 5741 // then assume this should be type argument list but is missing a type |
5733 token = startToken.next; | 5742 token = startToken.next; |
5734 if (_tokenMatches(token, TokenType.GT)) { | 5743 if (_tokenMatches(token, TokenType.GT)) { |
5735 return token.next; | 5744 return token.next; |
5736 } | 5745 } |
5737 return null; | 5746 return null; |
5738 } | 5747 } |
5739 while (_tokenMatches(token, TokenType.COMMA)) { | 5748 while (_tokenMatches(token, TokenType.COMMA)) { |
5740 token = skipTypeAnnotation(token.next); | 5749 token = skipTypeName(token.next); |
5741 if (token == null) { | 5750 if (token == null) { |
5742 return null; | 5751 return null; |
5743 } | 5752 } |
5744 } | 5753 } |
5745 if (token.type == TokenType.GT) { | 5754 if (token.type == TokenType.GT) { |
5746 return token.next; | 5755 return token.next; |
5747 } else if (token.type == TokenType.GT_GT) { | 5756 } else if (token.type == TokenType.GT_GT) { |
5748 Token second = new Token(TokenType.GT, token.offset + 1); | 5757 Token second = new Token(TokenType.GT, token.offset + 1); |
5749 second.setNextWithoutSettingPrevious(token.next); | 5758 second.setNextWithoutSettingPrevious(token.next); |
5750 return second; | 5759 return second; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5917 ((keyword == Keyword.GET || keyword == Keyword.SET) && | 5926 ((keyword == Keyword.GET || keyword == Keyword.SET) && |
5918 _tokenMatchesIdentifier(next)) || | 5927 _tokenMatchesIdentifier(next)) || |
5919 (keyword == Keyword.OPERATOR && _isOperator(next))) { | 5928 (keyword == Keyword.OPERATOR && _isOperator(next))) { |
5920 // This looks like the start of a function | 5929 // This looks like the start of a function |
5921 return true; | 5930 return true; |
5922 } else if (_matchesIdentifier()) { | 5931 } else if (_matchesIdentifier()) { |
5923 if (nextType == TokenType.OPEN_PAREN) { | 5932 if (nextType == TokenType.OPEN_PAREN) { |
5924 // This looks like the start of a function | 5933 // This looks like the start of a function |
5925 return true; | 5934 return true; |
5926 } | 5935 } |
5927 Token token = skipTypeAnnotation(_currentToken); | 5936 Token token = skipReturnType(_currentToken); |
5928 if (token == null) { | 5937 if (token == null) { |
5929 return false; | 5938 return false; |
5930 } | 5939 } |
5931 // TODO(brianwilkerson) This looks wrong; should we be checking 'token'? | 5940 // TODO(brianwilkerson) This looks wrong; should we be checking 'token'? |
5932 if (keyword == Keyword.GET || | 5941 if (keyword == Keyword.GET || |
5933 keyword == Keyword.SET || | 5942 keyword == Keyword.SET || |
5934 (keyword == Keyword.OPERATOR && _isOperator(next)) || | 5943 (keyword == Keyword.OPERATOR && _isOperator(next)) || |
5935 _matchesIdentifier()) { | 5944 _matchesIdentifier()) { |
5936 return true; | 5945 return true; |
5937 } | 5946 } |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6305 bool _isPeekGenericTypeParametersAndOpenParen() { | 6314 bool _isPeekGenericTypeParametersAndOpenParen() { |
6306 Token token = _skipTypeParameterList(_peek()); | 6315 Token token = _skipTypeParameterList(_peek()); |
6307 return token != null && _tokenMatches(token, TokenType.OPEN_PAREN); | 6316 return token != null && _tokenMatches(token, TokenType.OPEN_PAREN); |
6308 } | 6317 } |
6309 | 6318 |
6310 /** | 6319 /** |
6311 * Return `true` if the [startToken] appears to be the first token of a type | 6320 * Return `true` if the [startToken] appears to be the first token of a type |
6312 * name that is followed by a variable or field formal parameter. | 6321 * name that is followed by a variable or field formal parameter. |
6313 */ | 6322 */ |
6314 bool _isTypedIdentifier(Token startToken) { | 6323 bool _isTypedIdentifier(Token startToken) { |
6315 Token token = skipTypeAnnotation(startToken); | 6324 Token token = skipReturnType(startToken); |
6316 if (token == null) { | 6325 if (token == null) { |
6317 return false; | 6326 return false; |
6318 } else if (_tokenMatchesIdentifier(token)) { | 6327 } else if (_tokenMatchesIdentifier(token)) { |
6319 return true; | 6328 return true; |
6320 } else if (_tokenMatchesKeyword(token, Keyword.THIS) && | 6329 } else if (_tokenMatchesKeyword(token, Keyword.THIS) && |
6321 _tokenMatches(token.next, TokenType.PERIOD) && | 6330 _tokenMatches(token.next, TokenType.PERIOD) && |
6322 _tokenMatchesIdentifier(token.next.next)) { | 6331 _tokenMatchesIdentifier(token.next.next)) { |
6323 return true; | 6332 return true; |
| 6333 } else if (_tokenMatchesKeyword(startToken, Keyword.VOID)) { |
| 6334 // The keyword 'void' isn't a valid identifier, so it should be assumed to |
| 6335 // be a type name. |
| 6336 return true; |
6324 } else if (startToken.next != token && | 6337 } else if (startToken.next != token && |
6325 !_tokenMatches(token, TokenType.OPEN_PAREN)) { | 6338 !_tokenMatches(token, TokenType.OPEN_PAREN)) { |
6326 // The type is more than a simple identifier, so it should be assumed to | 6339 // The type is more than a simple identifier, so it should be assumed to |
6327 // be a type name. | 6340 // be a type name. |
6328 return true; | 6341 return true; |
6329 } | 6342 } |
6330 return false; | 6343 return false; |
6331 } | 6344 } |
6332 | 6345 |
6333 /** | 6346 /** |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7003 * functionTypeAlias ::= | 7016 * functionTypeAlias ::= |
7004 * functionPrefix typeParameterList? formalParameterList ';' | 7017 * functionPrefix typeParameterList? formalParameterList ';' |
7005 * | 7018 * |
7006 * functionPrefix ::= | 7019 * functionPrefix ::= |
7007 * returnType? name | 7020 * returnType? name |
7008 */ | 7021 */ |
7009 FunctionTypeAlias _parseFunctionTypeAlias( | 7022 FunctionTypeAlias _parseFunctionTypeAlias( |
7010 CommentAndMetadata commentAndMetadata, Token keyword) { | 7023 CommentAndMetadata commentAndMetadata, Token keyword) { |
7011 TypeAnnotation returnType = null; | 7024 TypeAnnotation returnType = null; |
7012 if (hasReturnTypeInTypeAlias) { | 7025 if (hasReturnTypeInTypeAlias) { |
7013 returnType = parseTypeAnnotation(false); | 7026 returnType = parseReturnType(false); |
7014 } | 7027 } |
7015 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); | 7028 SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true); |
7016 TypeParameterList typeParameters = null; | 7029 TypeParameterList typeParameters = null; |
7017 if (_matches(TokenType.LT)) { | 7030 if (_matches(TokenType.LT)) { |
7018 typeParameters = parseTypeParameterList(); | 7031 typeParameters = parseTypeParameterList(); |
7019 } | 7032 } |
7020 TokenType type = _currentToken.type; | 7033 TokenType type = _currentToken.type; |
7021 if (type == TokenType.SEMICOLON || type == TokenType.EOF) { | 7034 if (type == TokenType.SEMICOLON || type == TokenType.EOF) { |
7022 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS); | 7035 _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS); |
7023 FormalParameterList parameters = astFactory.formalParameterList( | 7036 FormalParameterList parameters = astFactory.formalParameterList( |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7318 (_tokenMatchesIdentifier(next) || | 7331 (_tokenMatchesIdentifier(next) || |
7319 _tokenMatches(next, TokenType.LT))) { | 7332 _tokenMatches(next, TokenType.LT))) { |
7320 Token afterTypeParameters = _skipTypeParameterList(next); | 7333 Token afterTypeParameters = _skipTypeParameterList(next); |
7321 if (afterTypeParameters != null && | 7334 if (afterTypeParameters != null && |
7322 _tokenMatches(afterTypeParameters, TokenType.OPEN_PAREN)) { | 7335 _tokenMatches(afterTypeParameters, TokenType.OPEN_PAREN)) { |
7323 // If the identifier is followed by type parameters and a parenthesis, | 7336 // If the identifier is followed by type parameters and a parenthesis, |
7324 // then the identifier is the name of a generic method, not a return | 7337 // then the identifier is the name of a generic method, not a return |
7325 // type. | 7338 // type. |
7326 return null; | 7339 return null; |
7327 } | 7340 } |
7328 return parseTypeAnnotation(false); | 7341 return parseReturnType(false); |
7329 } | 7342 } |
7330 Token next2 = next.next; | 7343 Token next2 = next.next; |
7331 Token next3 = next2.next; | 7344 Token next3 = next2.next; |
7332 if (_tokenMatches(next, TokenType.PERIOD) && | 7345 if (_tokenMatches(next, TokenType.PERIOD) && |
7333 _tokenMatchesIdentifier(next2) && | 7346 _tokenMatchesIdentifier(next2) && |
7334 (_tokenMatchesIdentifier(next3) || | 7347 (_tokenMatchesIdentifier(next3) || |
7335 _tokenMatches(next3, TokenType.LT))) { | 7348 _tokenMatches(next3, TokenType.LT))) { |
7336 return parseTypeAnnotation(false); | 7349 return parseReturnType(false); |
7337 } | 7350 } |
7338 } | 7351 } |
7339 return null; | 7352 return null; |
7340 } | 7353 } |
7341 | 7354 |
7342 /** | 7355 /** |
7343 * Parse a [TypeArgumentList] if present, otherwise return null. | 7356 * Parse a [TypeArgumentList] if present, otherwise return null. |
7344 * This also supports the comment form, if enabled: `/*<T>*/` | 7357 * This also supports the comment form, if enabled: `/*<T>*/` |
7345 */ | 7358 */ |
7346 TypeArgumentList _parseOptionalTypeArguments() { | 7359 TypeArgumentList _parseOptionalTypeArguments() { |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7871 } else if (_tokenMatchesIdentifier(startToken)) { | 7884 } else if (_tokenMatchesIdentifier(startToken)) { |
7872 Token next = startToken.next; | 7885 Token next = startToken.next; |
7873 if (_tokenMatchesIdentifier(next) || | 7886 if (_tokenMatchesIdentifier(next) || |
7874 _tokenMatches(next, TokenType.LT) || | 7887 _tokenMatches(next, TokenType.LT) || |
7875 _tokenMatchesKeyword(next, Keyword.THIS) || | 7888 _tokenMatchesKeyword(next, Keyword.THIS) || |
7876 (_tokenMatches(next, TokenType.PERIOD) && | 7889 (_tokenMatches(next, TokenType.PERIOD) && |
7877 _tokenMatchesIdentifier(next.next) && | 7890 _tokenMatchesIdentifier(next.next) && |
7878 (_tokenMatchesIdentifier(next.next.next) || | 7891 (_tokenMatchesIdentifier(next.next.next) || |
7879 _tokenMatches(next.next.next, TokenType.LT) || | 7892 _tokenMatches(next.next.next, TokenType.LT) || |
7880 _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) { | 7893 _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) { |
7881 return skipTypeAnnotation(startToken); | 7894 return skipReturnType(startToken); |
7882 } | 7895 } |
7883 } | 7896 } |
7884 return null; | 7897 return null; |
7885 } | 7898 } |
7886 | 7899 |
7887 /** | 7900 /** |
7888 * Parse a list of formal parameters, starting at the [startToken], without | 7901 * Parse a list of formal parameters, starting at the [startToken], without |
7889 * actually creating a formal parameter list or changing the current token. | 7902 * actually creating a formal parameter list or changing the current token. |
7890 * Return the token following the formal parameter list that was parsed, or | 7903 * Return the token following the formal parameter list that was parsed, or |
7891 * `null` if the given token is not the first token in a valid list of formal | 7904 * `null` if the given token is not the first token in a valid list of formal |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8648 } | 8661 } |
8649 } | 8662 } |
8650 } | 8663 } |
8651 | 8664 |
8652 /** | 8665 /** |
8653 * Instances of this class are thrown when the parser detects that AST has | 8666 * Instances of this class are thrown when the parser detects that AST has |
8654 * too many nested expressions to be parsed safely and avoid possibility of | 8667 * too many nested expressions to be parsed safely and avoid possibility of |
8655 * [StackOverflowError] in the parser or during later analysis. | 8668 * [StackOverflowError] in the parser or during later analysis. |
8656 */ | 8669 */ |
8657 class _TooDeepTreeError {} | 8670 class _TooDeepTreeError {} |
OLD | NEW |