| 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 |