Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: pkg/analyzer/lib/src/generated/parser.dart

Issue 2817753002: More parser fixes for generic function types (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/parser_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/parser_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698