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