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.src.generated.parser; | 5 library analyzer.src.generated.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 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 /** | 417 /** |
418 * Return `true` if the current token appears to be the beginning of a | 418 * Return `true` if the current token appears to be the beginning of a |
419 * function declaration. | 419 * function declaration. |
420 */ | 420 */ |
421 bool isFunctionDeclaration() { | 421 bool isFunctionDeclaration() { |
422 Keyword keyword = _currentToken.keyword; | 422 Keyword keyword = _currentToken.keyword; |
423 if (keyword == Keyword.VOID) { | 423 if (keyword == Keyword.VOID) { |
424 return true; | 424 return true; |
425 } | 425 } |
426 Token afterReturnType = skipTypeName(_currentToken); | 426 Token afterReturnType = skipTypeName(_currentToken); |
| 427 if (afterReturnType != null && |
| 428 _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) { |
| 429 afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType); |
| 430 } |
427 if (afterReturnType == null) { | 431 if (afterReturnType == null) { |
428 // There was no return type, but it is optional, so go back to where we | 432 // There was no return type, but it is optional, so go back to where we |
429 // started. | 433 // started. |
430 afterReturnType = _currentToken; | 434 afterReturnType = _currentToken; |
431 } | 435 } |
432 Token afterIdentifier = skipSimpleIdentifier(afterReturnType); | 436 Token afterIdentifier = skipSimpleIdentifier(afterReturnType); |
433 if (afterIdentifier == null) { | 437 if (afterIdentifier == null) { |
434 // It's possible that we parsed the function name as if it were a type | 438 // It's possible that we parsed the function name as if it were a type |
435 // name, so see whether it makes sense if we assume that there is no type. | 439 // name, so see whether it makes sense if we assume that there is no type. |
436 afterIdentifier = skipSimpleIdentifier(_currentToken); | 440 afterIdentifier = skipSimpleIdentifier(_currentToken); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 // We know that we have an identifier, and need to see whether it might be | 535 // We know that we have an identifier, and need to see whether it might be |
532 // a type name. | 536 // a type name. |
533 if (_currentToken.type != TokenType.IDENTIFIER) { | 537 if (_currentToken.type != TokenType.IDENTIFIER) { |
534 allowAdditionalTokens = false; | 538 allowAdditionalTokens = false; |
535 } | 539 } |
536 Token token = skipTypeName(_currentToken); | 540 Token token = skipTypeName(_currentToken); |
537 if (token == null) { | 541 if (token == null) { |
538 // There was no type name, so this can't be a declaration. | 542 // There was no type name, so this can't be a declaration. |
539 return false; | 543 return false; |
540 } | 544 } |
| 545 if (_tokenMatchesKeyword(token, Keyword.FUNCTION)) { |
| 546 token = skipGenericFunctionTypeAfterReturnType(token); |
| 547 } |
541 if (token.type != TokenType.IDENTIFIER) { | 548 if (token.type != TokenType.IDENTIFIER) { |
542 allowAdditionalTokens = false; | 549 allowAdditionalTokens = false; |
543 } | 550 } |
544 token = skipSimpleIdentifier(token); | 551 token = skipSimpleIdentifier(token); |
545 if (token == null) { | 552 if (token == null) { |
546 return false; | 553 return false; |
547 } | 554 } |
548 TokenType type = token.type; | 555 TokenType type = token.type; |
549 // Usual cases in valid code: | 556 // Usual cases in valid code: |
550 // String v = ''; | 557 // String v = ''; |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1265 } else if (_matchesIdentifier() && | 1272 } else if (_matchesIdentifier() && |
1266 _peek().matchesAny(const <TokenType>[ | 1273 _peek().matchesAny(const <TokenType>[ |
1267 TokenType.OPEN_PAREN, | 1274 TokenType.OPEN_PAREN, |
1268 TokenType.OPEN_CURLY_BRACKET, | 1275 TokenType.OPEN_CURLY_BRACKET, |
1269 TokenType.FUNCTION, | 1276 TokenType.FUNCTION, |
1270 TokenType.LT | 1277 TokenType.LT |
1271 ])) { | 1278 ])) { |
1272 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 1279 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
1273 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, | 1280 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, |
1274 modifiers.externalKeyword, modifiers.staticKeyword, returnType); | 1281 modifiers.externalKeyword, modifiers.staticKeyword, returnType); |
| 1282 } else if (_matchesIdentifier() && |
| 1283 _peek().matchesAny(const <TokenType>[ |
| 1284 TokenType.EQ, |
| 1285 TokenType.COMMA, |
| 1286 TokenType.SEMICOLON |
| 1287 ])) { |
| 1288 if (returnType is! GenericFunctionType) { |
| 1289 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 1290 } |
| 1291 return parseInitializedIdentifierList( |
| 1292 commentAndMetadata, |
| 1293 modifiers.staticKeyword, |
| 1294 modifiers.covariantKeyword, |
| 1295 _validateModifiersForField(modifiers), |
| 1296 returnType); |
1275 } else { | 1297 } else { |
1276 // | 1298 // |
1277 // We have found an error of some kind. Try to recover. | 1299 // We have found an error of some kind. Try to recover. |
1278 // | 1300 // |
1279 if (_matchesIdentifier()) { | |
1280 if (_peek().matchesAny(const <TokenType>[ | |
1281 TokenType.EQ, | |
1282 TokenType.COMMA, | |
1283 TokenType.SEMICOLON | |
1284 ])) { | |
1285 // | |
1286 // We appear to have a variable declaration with a type of "void". | |
1287 // | |
1288 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); | |
1289 return parseInitializedIdentifierList( | |
1290 commentAndMetadata, | |
1291 modifiers.staticKeyword, | |
1292 modifiers.covariantKeyword, | |
1293 _validateModifiersForField(modifiers), | |
1294 returnType); | |
1295 } | |
1296 } | |
1297 if (_isOperator(_currentToken)) { | 1301 if (_isOperator(_currentToken)) { |
1298 // | 1302 // |
1299 // We appear to have found an operator declaration without the | 1303 // We appear to have found an operator declaration without the |
1300 // 'operator' keyword. | 1304 // 'operator' keyword. |
1301 // | 1305 // |
1302 _validateModifiersForOperator(modifiers); | 1306 _validateModifiersForOperator(modifiers); |
1303 return parseOperator( | 1307 return parseOperator( |
1304 commentAndMetadata, modifiers.externalKeyword, returnType); | 1308 commentAndMetadata, modifiers.externalKeyword, returnType); |
1305 } | 1309 } |
1306 _reportErrorForToken( | 1310 _reportErrorForToken( |
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2071 } else if (_matchesIdentifier() && | 2075 } else if (_matchesIdentifier() && |
2072 next.matchesAny(const <TokenType>[ | 2076 next.matchesAny(const <TokenType>[ |
2073 TokenType.OPEN_PAREN, | 2077 TokenType.OPEN_PAREN, |
2074 TokenType.OPEN_CURLY_BRACKET, | 2078 TokenType.OPEN_CURLY_BRACKET, |
2075 TokenType.FUNCTION, | 2079 TokenType.FUNCTION, |
2076 TokenType.LT | 2080 TokenType.LT |
2077 ])) { | 2081 ])) { |
2078 _validateModifiersForTopLevelFunction(modifiers); | 2082 _validateModifiersForTopLevelFunction(modifiers); |
2079 return parseFunctionDeclaration( | 2083 return parseFunctionDeclaration( |
2080 commentAndMetadata, modifiers.externalKeyword, returnType); | 2084 commentAndMetadata, modifiers.externalKeyword, returnType); |
| 2085 } else if (_matchesIdentifier() && |
| 2086 next.matchesAny(const <TokenType>[ |
| 2087 TokenType.EQ, |
| 2088 TokenType.COMMA, |
| 2089 TokenType.SEMICOLON |
| 2090 ])) { |
| 2091 if (returnType is! GenericFunctionType) { |
| 2092 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 2093 } |
| 2094 return astFactory.topLevelVariableDeclaration( |
| 2095 commentAndMetadata.comment, |
| 2096 commentAndMetadata.metadata, |
| 2097 parseVariableDeclarationListAfterType( |
| 2098 null, _validateModifiersForTopLevelVariable(modifiers), null), |
| 2099 _expect(TokenType.SEMICOLON)); |
2081 } else { | 2100 } else { |
2082 // | 2101 // |
2083 // We have found an error of some kind. Try to recover. | 2102 // We have found an error of some kind. Try to recover. |
2084 // | 2103 // |
2085 if (_matchesIdentifier()) { | |
2086 if (next.matchesAny(const <TokenType>[ | |
2087 TokenType.EQ, | |
2088 TokenType.COMMA, | |
2089 TokenType.SEMICOLON | |
2090 ])) { | |
2091 // | |
2092 // We appear to have a variable declaration with a type of "void". | |
2093 // | |
2094 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); | |
2095 return astFactory.topLevelVariableDeclaration( | |
2096 commentAndMetadata.comment, | |
2097 commentAndMetadata.metadata, | |
2098 parseVariableDeclarationListAfterType(null, | |
2099 _validateModifiersForTopLevelVariable(modifiers), null), | |
2100 _expect(TokenType.SEMICOLON)); | |
2101 } | |
2102 } | |
2103 _reportErrorForToken( | 2104 _reportErrorForToken( |
2104 ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken); | 2105 ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken); |
2105 return null; | 2106 return null; |
2106 } | 2107 } |
2107 } else if ((keyword == Keyword.GET || keyword == Keyword.SET) && | 2108 } else if ((keyword == Keyword.GET || keyword == Keyword.SET) && |
2108 _tokenMatchesIdentifier(next)) { | 2109 _tokenMatchesIdentifier(next)) { |
2109 _validateModifiersForTopLevelFunction(modifiers); | 2110 _validateModifiersForTopLevelFunction(modifiers); |
2110 return parseFunctionDeclaration( | 2111 return parseFunctionDeclaration( |
2111 commentAndMetadata, modifiers.externalKeyword, null); | 2112 commentAndMetadata, modifiers.externalKeyword, null); |
2112 } else if (keyword == Keyword.OPERATOR && _isOperator(next)) { | 2113 } else if (keyword == Keyword.OPERATOR && _isOperator(next)) { |
(...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4131 Token next = _currentToken.next; | 4132 Token next = _currentToken.next; |
4132 if (_matchesIdentifier() && | 4133 if (_matchesIdentifier() && |
4133 next.matchesAny(const <TokenType>[ | 4134 next.matchesAny(const <TokenType>[ |
4134 TokenType.OPEN_PAREN, | 4135 TokenType.OPEN_PAREN, |
4135 TokenType.OPEN_CURLY_BRACKET, | 4136 TokenType.OPEN_CURLY_BRACKET, |
4136 TokenType.FUNCTION, | 4137 TokenType.FUNCTION, |
4137 TokenType.LT | 4138 TokenType.LT |
4138 ])) { | 4139 ])) { |
4139 return _parseFunctionDeclarationStatementAfterReturnType( | 4140 return _parseFunctionDeclarationStatementAfterReturnType( |
4140 commentAndMetadata, returnType); | 4141 commentAndMetadata, returnType); |
| 4142 } else if (_matchesIdentifier() && |
| 4143 next.matchesAny(const <TokenType>[ |
| 4144 TokenType.EQ, |
| 4145 TokenType.COMMA, |
| 4146 TokenType.SEMICOLON |
| 4147 ])) { |
| 4148 if (returnType is! GenericFunctionType) { |
| 4149 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); |
| 4150 } |
| 4151 return _parseVariableDeclarationStatementAfterType( |
| 4152 commentAndMetadata, null, returnType); |
4141 } else { | 4153 } else { |
4142 // | 4154 // |
4143 // We have found an error of some kind. Try to recover. | 4155 // We have found an error of some kind. Try to recover. |
4144 // | 4156 // |
4145 if (_matchesIdentifier()) { | 4157 if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { |
4146 if (next.matchesAny(const <TokenType>[ | |
4147 TokenType.EQ, | |
4148 TokenType.COMMA, | |
4149 TokenType.SEMICOLON | |
4150 ])) { | |
4151 // | |
4152 // We appear to have a variable declaration with a type of "void". | |
4153 // | |
4154 _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType); | |
4155 return parseVariableDeclarationStatementAfterMetadata( | |
4156 commentAndMetadata); | |
4157 } | |
4158 } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) { | |
4159 // | 4158 // |
4160 // We appear to have found an incomplete statement at the end of a | 4159 // We appear to have found an incomplete statement at the end of a |
4161 // block. Parse it as a variable declaration. | 4160 // block. Parse it as a variable declaration. |
4162 // | 4161 // |
4163 return _parseVariableDeclarationStatementAfterType( | 4162 return _parseVariableDeclarationStatementAfterType( |
4164 commentAndMetadata, null, returnType); | 4163 commentAndMetadata, null, returnType); |
4165 } | 4164 } |
4166 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT); | 4165 _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT); |
4167 // TODO(brianwilkerson) Recover from this error. | 4166 // TODO(brianwilkerson) Recover from this error. |
4168 return astFactory | 4167 return astFactory |
(...skipping 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5477 * actually creating a formal parameter list or changing the current token. | 5476 * actually creating a formal parameter list or changing the current token. |
5478 * Return the token following the parameter list that was parsed, or `null` | 5477 * Return the token following the parameter list that was parsed, or `null` |
5479 * if the given token is not the first token in a valid parameter list. | 5478 * if the given token is not the first token in a valid parameter list. |
5480 * | 5479 * |
5481 * This method must be kept in sync with [parseFormalParameterList]. | 5480 * This method must be kept in sync with [parseFormalParameterList]. |
5482 */ | 5481 */ |
5483 Token skipFormalParameterList(Token startToken) { | 5482 Token skipFormalParameterList(Token startToken) { |
5484 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) { | 5483 if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) { |
5485 return null; | 5484 return null; |
5486 } | 5485 } |
5487 return (startToken as BeginToken).endToken; | 5486 return (startToken as BeginToken).endToken.next; |
5488 } | 5487 } |
5489 | 5488 |
5490 /** | 5489 /** |
5491 * Parse the portion of a generic function type after the return type, | 5490 * Parse the portion of a generic function type after the return type, |
5492 * starting at the [startToken], without actually creating a generic function | 5491 * starting at the [startToken], without actually creating a generic function |
5493 * type or changing the current token. Return the token following the generic | 5492 * type or changing the current token. Return the token following the generic |
5494 * function type that was parsed, or `null` if the given token is not the | 5493 * function type that was parsed, or `null` if the given token is not the |
5495 * first token in a valid generic function type. | 5494 * first token in a valid generic function type. |
5496 * | 5495 * |
5497 * This method must be kept in sync with | 5496 * This method must be kept in sync with |
(...skipping 2092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7590 * metadata to be associated with the variable declaration statement, or | 7589 * metadata to be associated with the variable declaration statement, or |
7591 * `null` if there is no attempt at parsing the comment and metadata. The | 7590 * `null` if there is no attempt at parsing the comment and metadata. The |
7592 * [keyword] is the token representing the 'final', 'const' or 'var' keyword, | 7591 * [keyword] is the token representing the 'final', 'const' or 'var' keyword, |
7593 * or `null` if there is no keyword. The [type] is the type of the variables | 7592 * or `null` if there is no keyword. The [type] is the type of the variables |
7594 * in the list. Return the variable declaration statement that was parsed. | 7593 * in the list. Return the variable declaration statement that was parsed. |
7595 * | 7594 * |
7596 * variableDeclarationStatement ::= | 7595 * variableDeclarationStatement ::= |
7597 * variableDeclarationList ';' | 7596 * variableDeclarationList ';' |
7598 */ | 7597 */ |
7599 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType( | 7598 VariableDeclarationStatement _parseVariableDeclarationStatementAfterType( |
7600 CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) { | 7599 CommentAndMetadata commentAndMetadata, |
| 7600 Token keyword, |
| 7601 TypeAnnotation type) { |
7601 VariableDeclarationList variableList = | 7602 VariableDeclarationList variableList = |
7602 parseVariableDeclarationListAfterType( | 7603 parseVariableDeclarationListAfterType( |
7603 commentAndMetadata, keyword, type); | 7604 commentAndMetadata, keyword, type); |
7604 Token semicolon = _expect(TokenType.SEMICOLON); | 7605 Token semicolon = _expect(TokenType.SEMICOLON); |
7605 return astFactory.variableDeclarationStatement(variableList, semicolon); | 7606 return astFactory.variableDeclarationStatement(variableList, semicolon); |
7606 } | 7607 } |
7607 | 7608 |
7608 /** | 7609 /** |
7609 * Return the token that is immediately after the current token. This is | 7610 * Return the token that is immediately after the current token. This is |
7610 * equivalent to [_peekAt](1). | 7611 * equivalent to [_peekAt](1). |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8557 } | 8558 } |
8558 if (modifiers.finalKeyword != null) { | 8559 if (modifiers.finalKeyword != null) { |
8559 _reportErrorForToken( | 8560 _reportErrorForToken( |
8560 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword); | 8561 ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword); |
8561 } | 8562 } |
8562 if (modifiers.varKeyword != null) { | 8563 if (modifiers.varKeyword != null) { |
8563 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword); | 8564 _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword); |
8564 } | 8565 } |
8565 } | 8566 } |
8566 } | 8567 } |
OLD | NEW |