| 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 engine.parser; | 5 library engine.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 'ast.dart'; | 10 import 'ast.dart'; |
| (...skipping 2105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2116 * initializer, with no intervening parens, braces, or brackets. | 2116 * initializer, with no intervening parens, braces, or brackets. |
| 2117 */ | 2117 */ |
| 2118 bool _inInitializer = false; | 2118 bool _inInitializer = false; |
| 2119 | 2119 |
| 2120 /** | 2120 /** |
| 2121 * A flag indicating whether the parser is to parse generic method syntax. | 2121 * A flag indicating whether the parser is to parse generic method syntax. |
| 2122 */ | 2122 */ |
| 2123 bool parseGenericMethods = false; | 2123 bool parseGenericMethods = false; |
| 2124 | 2124 |
| 2125 /** | 2125 /** |
| 2126 * A flag indicating whether to parse generic method comments, of the form |
| 2127 * `/*=T*/` and `/*<T>*/`. |
| 2128 */ |
| 2129 bool parseGenericMethodComments = false; |
| 2130 |
| 2131 /** |
| 2126 * Initialize a newly created parser to parse the content of the given | 2132 * Initialize a newly created parser to parse the content of the given |
| 2127 * [_source] and to report any errors that are found to the given | 2133 * [_source] and to report any errors that are found to the given |
| 2128 * [_errorListener]. | 2134 * [_errorListener]. |
| 2129 */ | 2135 */ |
| 2130 Parser(this._source, this._errorListener); | 2136 Parser(this._source, this._errorListener); |
| 2131 | 2137 |
| 2132 void set currentToken(Token currentToken) { | 2138 void set currentToken(Token currentToken) { |
| 2133 this._currentToken = currentToken; | 2139 this._currentToken = currentToken; |
| 2134 } | 2140 } |
| 2135 | 2141 |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2507 return _parseConstructor( | 2513 return _parseConstructor( |
| 2508 commentAndMetadata, | 2514 commentAndMetadata, |
| 2509 modifiers.externalKeyword, | 2515 modifiers.externalKeyword, |
| 2510 _validateModifiersForConstructor(modifiers), | 2516 _validateModifiersForConstructor(modifiers), |
| 2511 modifiers.factoryKeyword, | 2517 modifiers.factoryKeyword, |
| 2512 parseSimpleIdentifier(), | 2518 parseSimpleIdentifier(), |
| 2513 getAndAdvance(), | 2519 getAndAdvance(), |
| 2514 parseSimpleIdentifier(), | 2520 parseSimpleIdentifier(), |
| 2515 parseFormalParameterList()); | 2521 parseFormalParameterList()); |
| 2516 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 2522 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 2523 TypeName returnType = _parseOptionalTypeNameComment(); |
| 2517 SimpleIdentifier methodName = parseSimpleIdentifier(); | 2524 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 2525 TypeParameterList typeParameters = _parseGenericCommentTypeParameters(); |
| 2518 FormalParameterList parameters = parseFormalParameterList(); | 2526 FormalParameterList parameters = parseFormalParameterList(); |
| 2519 if (_matches(TokenType.COLON) || | 2527 if (_matches(TokenType.COLON) || |
| 2520 modifiers.factoryKeyword != null || | 2528 modifiers.factoryKeyword != null || |
| 2521 methodName.name == className) { | 2529 methodName.name == className) { |
| 2522 return _parseConstructor( | 2530 return _parseConstructor( |
| 2523 commentAndMetadata, | 2531 commentAndMetadata, |
| 2524 modifiers.externalKeyword, | 2532 modifiers.externalKeyword, |
| 2525 _validateModifiersForConstructor(modifiers), | 2533 _validateModifiersForConstructor(modifiers), |
| 2526 modifiers.factoryKeyword, | 2534 modifiers.factoryKeyword, |
| 2527 methodName, | 2535 methodName, |
| 2528 null, | 2536 null, |
| 2529 null, | 2537 null, |
| 2530 parameters); | 2538 parameters); |
| 2531 } | 2539 } |
| 2532 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 2540 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2533 _validateFormalParameterList(parameters); | 2541 _validateFormalParameterList(parameters); |
| 2534 return _parseMethodDeclarationAfterParameters( | 2542 return _parseMethodDeclarationAfterParameters( |
| 2535 commentAndMetadata, | 2543 commentAndMetadata, |
| 2536 modifiers.externalKeyword, | 2544 modifiers.externalKeyword, |
| 2537 modifiers.staticKeyword, | 2545 modifiers.staticKeyword, |
| 2538 null, | 2546 returnType, |
| 2539 methodName, | 2547 methodName, |
| 2540 null, | 2548 typeParameters, |
| 2541 parameters); | 2549 parameters); |
| 2542 } else if (_peek() | 2550 } else if (_peek() |
| 2543 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) { | 2551 .matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) { |
| 2544 if (modifiers.constKeyword == null && | 2552 if (modifiers.constKeyword == null && |
| 2545 modifiers.finalKeyword == null && | 2553 modifiers.finalKeyword == null && |
| 2546 modifiers.varKeyword == null) { | 2554 modifiers.varKeyword == null) { |
| 2547 _reportErrorForCurrentToken( | 2555 _reportErrorForCurrentToken( |
| 2548 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); | 2556 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); |
| 2549 } | 2557 } |
| 2550 return _parseInitializedIdentifierList(commentAndMetadata, | 2558 return _parseInitializedIdentifierList(commentAndMetadata, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2610 return _parseInitializedIdentifierList( | 2618 return _parseInitializedIdentifierList( |
| 2611 commentAndMetadata, | 2619 commentAndMetadata, |
| 2612 modifiers.staticKeyword, | 2620 modifiers.staticKeyword, |
| 2613 _validateModifiersForField(modifiers), | 2621 _validateModifiersForField(modifiers), |
| 2614 type); | 2622 type); |
| 2615 } finally { | 2623 } finally { |
| 2616 _unlockErrorListener(); | 2624 _unlockErrorListener(); |
| 2617 } | 2625 } |
| 2618 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 2626 } else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 2619 SimpleIdentifier methodName = parseSimpleIdentifier(); | 2627 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 2628 TypeParameterList typeParameters = _parseGenericCommentTypeParameters(); |
| 2620 FormalParameterList parameters = parseFormalParameterList(); | 2629 FormalParameterList parameters = parseFormalParameterList(); |
| 2621 if (methodName.name == className) { | 2630 if (methodName.name == className) { |
| 2622 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type); | 2631 _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type); |
| 2623 return _parseConstructor( | 2632 return _parseConstructor( |
| 2624 commentAndMetadata, | 2633 commentAndMetadata, |
| 2625 modifiers.externalKeyword, | 2634 modifiers.externalKeyword, |
| 2626 _validateModifiersForConstructor(modifiers), | 2635 _validateModifiersForConstructor(modifiers), |
| 2627 modifiers.factoryKeyword, | 2636 modifiers.factoryKeyword, |
| 2628 methodName, | 2637 methodName, |
| 2629 null, | 2638 null, |
| 2630 null, | 2639 null, |
| 2631 parameters); | 2640 parameters); |
| 2632 } | 2641 } |
| 2633 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 2642 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2634 _validateFormalParameterList(parameters); | 2643 _validateFormalParameterList(parameters); |
| 2635 return _parseMethodDeclarationAfterParameters( | 2644 return _parseMethodDeclarationAfterParameters( |
| 2636 commentAndMetadata, | 2645 commentAndMetadata, |
| 2637 modifiers.externalKeyword, | 2646 modifiers.externalKeyword, |
| 2638 modifiers.staticKeyword, | 2647 modifiers.staticKeyword, |
| 2639 type, | 2648 type, |
| 2640 methodName, | 2649 methodName, |
| 2641 null, | 2650 typeParameters, |
| 2642 parameters); | 2651 parameters); |
| 2643 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) { | 2652 } else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) { |
| 2644 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, | 2653 return _parseMethodDeclarationAfterReturnType(commentAndMetadata, |
| 2645 modifiers.externalKeyword, modifiers.staticKeyword, type); | 2654 modifiers.externalKeyword, modifiers.staticKeyword, type); |
| 2646 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) { | 2655 } else if (_tokenMatches(_peek(), TokenType.OPEN_CURLY_BRACKET)) { |
| 2647 // We have found "TypeName identifier {", and are guessing that this is a | 2656 // We have found "TypeName identifier {", and are guessing that this is a |
| 2648 // getter without the keyword 'get'. | 2657 // getter without the keyword 'get'. |
| 2649 _validateModifiersForGetterOrSetterOrMethod(modifiers); | 2658 _validateModifiersForGetterOrSetterOrMethod(modifiers); |
| 2650 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET); | 2659 _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET); |
| 2651 _currentToken = _injectToken( | 2660 _currentToken = _injectToken( |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3128 } | 3137 } |
| 3129 | 3138 |
| 3130 /** | 3139 /** |
| 3131 * Parse a function expression. Return the function expression that was | 3140 * Parse a function expression. Return the function expression that was |
| 3132 * parsed. | 3141 * parsed. |
| 3133 * | 3142 * |
| 3134 * functionExpression ::= | 3143 * functionExpression ::= |
| 3135 * typeParameters? formalParameterList functionExpressionBody | 3144 * typeParameters? formalParameterList functionExpressionBody |
| 3136 */ | 3145 */ |
| 3137 FunctionExpression parseFunctionExpression() { | 3146 FunctionExpression parseFunctionExpression() { |
| 3138 TypeParameterList typeParameters = null; | 3147 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 3139 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 3140 typeParameters = parseTypeParameterList(); | |
| 3141 } | |
| 3142 FormalParameterList parameters = parseFormalParameterList(); | 3148 FormalParameterList parameters = parseFormalParameterList(); |
| 3143 _validateFormalParameterList(parameters); | 3149 _validateFormalParameterList(parameters); |
| 3144 FunctionBody body = | 3150 FunctionBody body = |
| 3145 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true); | 3151 _parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true); |
| 3146 return new FunctionExpression(typeParameters, parameters, body); | 3152 return new FunctionExpression(typeParameters, parameters, body); |
| 3147 } | 3153 } |
| 3148 | 3154 |
| 3149 /** | 3155 /** |
| 3150 * Parse an if-null expression. Return the if-null expression that was | 3156 * Parse an if-null expression. Return the if-null expression that was |
| 3151 * parsed. | 3157 * parsed. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3258 NormalFormalParameter parseNormalFormalParameter() { | 3264 NormalFormalParameter parseNormalFormalParameter() { |
| 3259 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); | 3265 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| 3260 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); | 3266 FinalConstVarOrType holder = _parseFinalConstVarOrType(true); |
| 3261 Token thisKeyword = null; | 3267 Token thisKeyword = null; |
| 3262 Token period = null; | 3268 Token period = null; |
| 3263 if (_matchesKeyword(Keyword.THIS)) { | 3269 if (_matchesKeyword(Keyword.THIS)) { |
| 3264 thisKeyword = getAndAdvance(); | 3270 thisKeyword = getAndAdvance(); |
| 3265 period = _expect(TokenType.PERIOD); | 3271 period = _expect(TokenType.PERIOD); |
| 3266 } | 3272 } |
| 3267 SimpleIdentifier identifier = parseSimpleIdentifier(); | 3273 SimpleIdentifier identifier = parseSimpleIdentifier(); |
| 3268 TypeParameterList typeParameters = null; | 3274 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 3269 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 3270 typeParameters = parseTypeParameterList(); | |
| 3271 } | |
| 3272 if (_matches(TokenType.OPEN_PAREN)) { | 3275 if (_matches(TokenType.OPEN_PAREN)) { |
| 3273 FormalParameterList parameters = parseFormalParameterList(); | 3276 FormalParameterList parameters = parseFormalParameterList(); |
| 3274 if (thisKeyword == null) { | 3277 if (thisKeyword == null) { |
| 3275 if (holder.keyword != null) { | 3278 if (holder.keyword != null) { |
| 3276 _reportErrorForToken( | 3279 _reportErrorForToken( |
| 3277 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); | 3280 ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword); |
| 3278 } | 3281 } |
| 3279 return new FunctionTypedFormalParameter( | 3282 return new FunctionTypedFormalParameter( |
| 3280 commentAndMetadata.comment, | 3283 commentAndMetadata.comment, |
| 3281 commentAndMetadata.metadata, | 3284 commentAndMetadata.metadata, |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3469 return new TypeArgumentList(leftBracket, arguments, rightBracket); | 3472 return new TypeArgumentList(leftBracket, arguments, rightBracket); |
| 3470 } | 3473 } |
| 3471 | 3474 |
| 3472 /** | 3475 /** |
| 3473 * Parse a type name. Return the type name that was parsed. | 3476 * Parse a type name. Return the type name that was parsed. |
| 3474 * | 3477 * |
| 3475 * type ::= | 3478 * type ::= |
| 3476 * qualified typeArguments? | 3479 * qualified typeArguments? |
| 3477 */ | 3480 */ |
| 3478 TypeName parseTypeName() { | 3481 TypeName parseTypeName() { |
| 3479 Identifier typeName; | 3482 TypeName realType = _parseTypeName(); |
| 3480 if (_matchesKeyword(Keyword.VAR)) { | 3483 // If this is followed by a generic method type comment, allow the comment |
| 3481 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); | 3484 // type to replace the real type name. |
| 3482 typeName = new SimpleIdentifier(getAndAdvance()); | 3485 // TODO(jmesserly): this feels like a big hammer. Can we restrict it to |
| 3483 } else if (_matchesIdentifier()) { | 3486 // only work inside generic methods? |
| 3484 typeName = parsePrefixedIdentifier(); | 3487 TypeName typeComment = _parseOptionalTypeNameComment(); |
| 3485 } else { | 3488 return typeComment ?? realType; |
| 3486 typeName = _createSyntheticIdentifier(); | |
| 3487 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); | |
| 3488 } | |
| 3489 TypeArgumentList typeArguments = null; | |
| 3490 if (_matches(TokenType.LT)) { | |
| 3491 typeArguments = parseTypeArgumentList(); | |
| 3492 } | |
| 3493 return new TypeName(typeName, typeArguments); | |
| 3494 } | 3489 } |
| 3495 | 3490 |
| 3496 /** | 3491 /** |
| 3497 * Parse a type parameter. Return the type parameter that was parsed. | 3492 * Parse a type parameter. Return the type parameter that was parsed. |
| 3498 * | 3493 * |
| 3499 * typeParameter ::= | 3494 * typeParameter ::= |
| 3500 * metadata name ('extends' bound)? | 3495 * metadata name ('extends' bound)? |
| 3501 */ | 3496 */ |
| 3502 TypeParameter parseTypeParameter() { | 3497 TypeParameter parseTypeParameter() { |
| 3503 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); | 3498 CommentAndMetadata commentAndMetadata = _parseCommentAndMetadata(); |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3902 * either the given token is not a begin token or it does not have an end | 3897 * either the given token is not a begin token or it does not have an end |
| 3903 * token associated with it. | 3898 * token associated with it. |
| 3904 */ | 3899 */ |
| 3905 Token _getEndToken(Token beginToken) { | 3900 Token _getEndToken(Token beginToken) { |
| 3906 if (beginToken is BeginToken) { | 3901 if (beginToken is BeginToken) { |
| 3907 return beginToken.endToken; | 3902 return beginToken.endToken; |
| 3908 } | 3903 } |
| 3909 return null; | 3904 return null; |
| 3910 } | 3905 } |
| 3911 | 3906 |
| 3907 bool _injectGenericComment(TokenType type, int prefixLen) { |
| 3908 if (parseGenericMethodComments) { |
| 3909 CommentToken t = _currentToken.precedingComments; |
| 3910 for (; t != null; t = t.next) { |
| 3911 if (t.type == type) { |
| 3912 String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2); |
| 3913 Token list = _scanGenericMethodComment(comment, t.offset + prefixLen); |
| 3914 if (list != null) { |
| 3915 // Insert the tokens into the stream. |
| 3916 _injectTokenList(list); |
| 3917 return true; |
| 3918 } |
| 3919 } |
| 3920 } |
| 3921 } |
| 3922 return false; |
| 3923 } |
| 3924 |
| 3925 /** |
| 3926 * Matches a generic comment type substitution and injects it into the token |
| 3927 * stream. Returns true if a match was injected, otherwise false. |
| 3928 * |
| 3929 * These comments are of the form `/*=T*/`, in other words, a [TypeName] |
| 3930 * inside a slash-star comment, preceded by equals sign. |
| 3931 */ |
| 3932 bool _injectGenericCommentTypeAssign() { |
| 3933 return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_ASSIGN, 3); |
| 3934 } |
| 3935 |
| 3936 /** |
| 3937 * Matches a generic comment type parameters and injects them into the token |
| 3938 * stream. Returns true if a match was injected, otherwise false. |
| 3939 * |
| 3940 * These comments are of the form `/*<K, V>*/`, in other words, a |
| 3941 * [TypeParameterList] or [TypeArgumentList] inside a slash-star comment. |
| 3942 */ |
| 3943 bool _injectGenericCommentTypeList() { |
| 3944 return _injectGenericComment(TokenType.GENERIC_METHOD_TYPE_LIST, 2); |
| 3945 } |
| 3946 |
| 3912 /** | 3947 /** |
| 3913 * Inject the given [token] into the token stream immediately before the | 3948 * Inject the given [token] into the token stream immediately before the |
| 3914 * current token. | 3949 * current token. |
| 3915 */ | 3950 */ |
| 3916 Token _injectToken(Token token) { | 3951 Token _injectToken(Token token) { |
| 3917 Token previous = _currentToken.previous; | 3952 Token previous = _currentToken.previous; |
| 3918 token.setNext(_currentToken); | 3953 token.setNext(_currentToken); |
| 3919 previous.setNext(token); | 3954 previous.setNext(token); |
| 3920 return token; | 3955 return token; |
| 3921 } | 3956 } |
| 3922 | 3957 |
| 3958 void _injectTokenList(Token firstToken) { |
| 3959 // Scanner creates a cyclic EOF token. |
| 3960 Token lastToken = firstToken; |
| 3961 while (lastToken.next.type != TokenType.EOF) { |
| 3962 lastToken = lastToken.next; |
| 3963 } |
| 3964 // Inject these new tokens into the stream. |
| 3965 Token previous = _currentToken.previous; |
| 3966 lastToken.setNext(_currentToken); |
| 3967 previous.setNext(firstToken); |
| 3968 _currentToken = firstToken; |
| 3969 } |
| 3970 |
| 3923 /** | 3971 /** |
| 3924 * Return `true` if the current token appears to be the beginning of a | 3972 * Return `true` if the current token appears to be the beginning of a |
| 3925 * function declaration. | 3973 * function declaration. |
| 3926 */ | 3974 */ |
| 3927 bool _isFunctionDeclaration() { | 3975 bool _isFunctionDeclaration() { |
| 3928 if (_matchesKeyword(Keyword.VOID)) { | 3976 if (_matchesKeyword(Keyword.VOID)) { |
| 3929 return true; | 3977 return true; |
| 3930 } | 3978 } |
| 3931 Token afterReturnType = _skipTypeName(_currentToken); | 3979 Token afterReturnType = _skipTypeName(_currentToken); |
| 3932 if (afterReturnType == null) { | 3980 if (afterReturnType == null) { |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4354 } | 4402 } |
| 4355 // | 4403 // |
| 4356 // A primary expression can start with an identifier. We resolve the | 4404 // A primary expression can start with an identifier. We resolve the |
| 4357 // ambiguity by determining whether the primary consists of anything other | 4405 // ambiguity by determining whether the primary consists of anything other |
| 4358 // than an identifier and/or is followed by an assignableSelector. | 4406 // than an identifier and/or is followed by an assignableSelector. |
| 4359 // | 4407 // |
| 4360 Expression expression = _parsePrimaryExpression(); | 4408 Expression expression = _parsePrimaryExpression(); |
| 4361 bool isOptional = primaryAllowed || expression is SimpleIdentifier; | 4409 bool isOptional = primaryAllowed || expression is SimpleIdentifier; |
| 4362 while (true) { | 4410 while (true) { |
| 4363 while (_isLikelyParameterList()) { | 4411 while (_isLikelyParameterList()) { |
| 4364 TypeArgumentList typeArguments = null; | 4412 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
| 4365 if (_matches(TokenType.LT)) { | |
| 4366 typeArguments = parseTypeArgumentList(); | |
| 4367 } | |
| 4368 ArgumentList argumentList = parseArgumentList(); | 4413 ArgumentList argumentList = parseArgumentList(); |
| 4369 if (expression is SimpleIdentifier) { | 4414 if (expression is SimpleIdentifier) { |
| 4370 expression = new MethodInvocation(null, null, | 4415 expression = new MethodInvocation(null, null, |
| 4371 expression as SimpleIdentifier, typeArguments, argumentList); | 4416 expression as SimpleIdentifier, typeArguments, argumentList); |
| 4372 } else if (expression is PrefixedIdentifier) { | 4417 } else if (expression is PrefixedIdentifier) { |
| 4373 PrefixedIdentifier identifier = expression as PrefixedIdentifier; | 4418 PrefixedIdentifier identifier = expression as PrefixedIdentifier; |
| 4374 expression = new MethodInvocation( | 4419 expression = new MethodInvocation( |
| 4375 identifier.prefix, | 4420 identifier.prefix, |
| 4376 identifier.period, | 4421 identifier.period, |
| 4377 identifier.identifier, | 4422 identifier.identifier, |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4566 } | 4611 } |
| 4567 } else { | 4612 } else { |
| 4568 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, | 4613 _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken, |
| 4569 [_currentToken.lexeme]); | 4614 [_currentToken.lexeme]); |
| 4570 functionName = _createSyntheticIdentifier(); | 4615 functionName = _createSyntheticIdentifier(); |
| 4571 } | 4616 } |
| 4572 assert((expression == null && functionName != null) || | 4617 assert((expression == null && functionName != null) || |
| 4573 (expression != null && functionName == null)); | 4618 (expression != null && functionName == null)); |
| 4574 if (_isLikelyParameterList()) { | 4619 if (_isLikelyParameterList()) { |
| 4575 while (_isLikelyParameterList()) { | 4620 while (_isLikelyParameterList()) { |
| 4576 TypeArgumentList typeArguments = null; | 4621 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
| 4577 if (_matches(TokenType.LT)) { | |
| 4578 typeArguments = parseTypeArgumentList(); | |
| 4579 } | |
| 4580 if (functionName != null) { | 4622 if (functionName != null) { |
| 4581 expression = new MethodInvocation(expression, period, functionName, | 4623 expression = new MethodInvocation(expression, period, functionName, |
| 4582 typeArguments, parseArgumentList()); | 4624 typeArguments, parseArgumentList()); |
| 4583 period = null; | 4625 period = null; |
| 4584 functionName = null; | 4626 functionName = null; |
| 4585 } else if (expression == null) { | 4627 } else if (expression == null) { |
| 4586 // It should not be possible to get here. | 4628 // It should not be possible to get here. |
| 4587 expression = new MethodInvocation(expression, period, | 4629 expression = new MethodInvocation(expression, period, |
| 4588 _createSyntheticIdentifier(), typeArguments, parseArgumentList()); | 4630 _createSyntheticIdentifier(), typeArguments, parseArgumentList()); |
| 4589 } else { | 4631 } else { |
| 4590 expression = new FunctionExpressionInvocation( | 4632 expression = new FunctionExpressionInvocation( |
| 4591 expression, typeArguments, parseArgumentList()); | 4633 expression, typeArguments, parseArgumentList()); |
| 4592 } | 4634 } |
| 4593 } | 4635 } |
| 4594 } else if (functionName != null) { | 4636 } else if (functionName != null) { |
| 4595 expression = new PropertyAccess(expression, period, functionName); | 4637 expression = new PropertyAccess(expression, period, functionName); |
| 4596 period = null; | 4638 period = null; |
| 4597 } | 4639 } |
| 4598 assert(expression != null); | 4640 assert(expression != null); |
| 4599 bool progress = true; | 4641 bool progress = true; |
| 4600 while (progress) { | 4642 while (progress) { |
| 4601 progress = false; | 4643 progress = false; |
| 4602 Expression selector = _parseAssignableSelector(expression, true); | 4644 Expression selector = _parseAssignableSelector(expression, true); |
| 4603 if (!identical(selector, expression)) { | 4645 if (!identical(selector, expression)) { |
| 4604 expression = selector; | 4646 expression = selector; |
| 4605 progress = true; | 4647 progress = true; |
| 4606 while (_isLikelyParameterList()) { | 4648 while (_isLikelyParameterList()) { |
| 4607 TypeArgumentList typeArguments = null; | 4649 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
| 4608 if (_matches(TokenType.LT)) { | |
| 4609 typeArguments = parseTypeArgumentList(); | |
| 4610 } | |
| 4611 if (expression is PropertyAccess) { | 4650 if (expression is PropertyAccess) { |
| 4612 PropertyAccess propertyAccess = expression as PropertyAccess; | 4651 PropertyAccess propertyAccess = expression as PropertyAccess; |
| 4613 expression = new MethodInvocation( | 4652 expression = new MethodInvocation( |
| 4614 propertyAccess.target, | 4653 propertyAccess.target, |
| 4615 propertyAccess.operator, | 4654 propertyAccess.operator, |
| 4616 propertyAccess.propertyName, | 4655 propertyAccess.propertyName, |
| 4617 typeArguments, | 4656 typeArguments, |
| 4618 parseArgumentList()); | 4657 parseArgumentList()); |
| 4619 } else { | 4658 } else { |
| 4620 expression = new FunctionExpressionInvocation( | 4659 expression = new FunctionExpressionInvocation( |
| (...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5684 * | 'var' | 5723 * | 'var' |
| 5685 * | type | 5724 * | type |
| 5686 */ | 5725 */ |
| 5687 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { | 5726 FinalConstVarOrType _parseFinalConstVarOrType(bool optional) { |
| 5688 Token keyword = null; | 5727 Token keyword = null; |
| 5689 TypeName type = null; | 5728 TypeName type = null; |
| 5690 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) { | 5729 if (_matchesKeyword(Keyword.FINAL) || _matchesKeyword(Keyword.CONST)) { |
| 5691 keyword = getAndAdvance(); | 5730 keyword = getAndAdvance(); |
| 5692 if (_isTypedIdentifier(_currentToken)) { | 5731 if (_isTypedIdentifier(_currentToken)) { |
| 5693 type = parseTypeName(); | 5732 type = parseTypeName(); |
| 5733 } else { |
| 5734 // Support `final/*=T*/ x;` |
| 5735 type = _parseOptionalTypeNameComment(); |
| 5694 } | 5736 } |
| 5695 } else if (_matchesKeyword(Keyword.VAR)) { | 5737 } else if (_matchesKeyword(Keyword.VAR)) { |
| 5696 keyword = getAndAdvance(); | 5738 keyword = getAndAdvance(); |
| 5739 // Support `var/*=T*/ x;` |
| 5740 type = _parseOptionalTypeNameComment(); |
| 5741 if (type != null) { |
| 5742 // Clear the keyword to prevent an error. |
| 5743 keyword = null; |
| 5744 } |
| 5745 } else if (_isTypedIdentifier(_currentToken)) { |
| 5746 type = parseReturnType(); |
| 5747 } else if (!optional) { |
| 5748 _reportErrorForCurrentToken( |
| 5749 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); |
| 5697 } else { | 5750 } else { |
| 5698 if (_isTypedIdentifier(_currentToken)) { | 5751 // Support parameters such as `(/*=K*/ key, /*=V*/ value)` |
| 5699 type = parseReturnType(); | 5752 // This is not supported if the type is required. |
| 5700 } else if (!optional) { | 5753 type = _parseOptionalTypeNameComment(); |
| 5701 _reportErrorForCurrentToken( | |
| 5702 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE); | |
| 5703 } | |
| 5704 } | 5754 } |
| 5705 return new FinalConstVarOrType(keyword, type); | 5755 return new FinalConstVarOrType(keyword, type); |
| 5706 } | 5756 } |
| 5707 | 5757 |
| 5708 /** | 5758 /** |
| 5709 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be | 5759 * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be |
| 5710 * `true`. The [kind] is the kind of parameter being expected based on the | 5760 * `true`. The [kind] is the kind of parameter being expected based on the |
| 5711 * presence or absence of group delimiters. Return the formal parameter that | 5761 * presence or absence of group delimiters. Return the formal parameter that |
| 5712 * was parsed. | 5762 * was parsed. |
| 5713 * | 5763 * |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6018 bool isGetter = false; | 6068 bool isGetter = false; |
| 6019 if (_matchesKeyword(Keyword.GET) && | 6069 if (_matchesKeyword(Keyword.GET) && |
| 6020 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 6070 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 6021 keyword = getAndAdvance(); | 6071 keyword = getAndAdvance(); |
| 6022 isGetter = true; | 6072 isGetter = true; |
| 6023 } else if (_matchesKeyword(Keyword.SET) && | 6073 } else if (_matchesKeyword(Keyword.SET) && |
| 6024 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { | 6074 !_tokenMatches(_peek(), TokenType.OPEN_PAREN)) { |
| 6025 keyword = getAndAdvance(); | 6075 keyword = getAndAdvance(); |
| 6026 } | 6076 } |
| 6027 SimpleIdentifier name = parseSimpleIdentifier(); | 6077 SimpleIdentifier name = parseSimpleIdentifier(); |
| 6028 TypeParameterList typeParameters = null; | 6078 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 6029 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 6030 typeParameters = parseTypeParameterList(); | |
| 6031 } | |
| 6032 FormalParameterList parameters = null; | 6079 FormalParameterList parameters = null; |
| 6033 if (!isGetter) { | 6080 if (!isGetter) { |
| 6034 if (_matches(TokenType.OPEN_PAREN)) { | 6081 if (_matches(TokenType.OPEN_PAREN)) { |
| 6035 parameters = parseFormalParameterList(); | 6082 parameters = parseFormalParameterList(); |
| 6036 _validateFormalParameterList(parameters); | 6083 _validateFormalParameterList(parameters); |
| 6037 } else { | 6084 } else { |
| 6038 _reportErrorForCurrentToken( | 6085 _reportErrorForCurrentToken( |
| 6039 ParserErrorCode.MISSING_FUNCTION_PARAMETERS); | 6086 ParserErrorCode.MISSING_FUNCTION_PARAMETERS); |
| 6040 parameters = new FormalParameterList( | 6087 parameters = new FormalParameterList( |
| 6041 _createSyntheticToken(TokenType.OPEN_PAREN), | 6088 _createSyntheticToken(TokenType.OPEN_PAREN), |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6175 commentAndMetadata.metadata, | 6222 commentAndMetadata.metadata, |
| 6176 keyword, | 6223 keyword, |
| 6177 returnType, | 6224 returnType, |
| 6178 name, | 6225 name, |
| 6179 typeParameters, | 6226 typeParameters, |
| 6180 parameters, | 6227 parameters, |
| 6181 semicolon); | 6228 semicolon); |
| 6182 } | 6229 } |
| 6183 | 6230 |
| 6184 /** | 6231 /** |
| 6232 * Parses generic type parameters from a comment. |
| 6233 * |
| 6234 * Normally this is handled by [_parseGenericMethodTypeParameters], but if the |
| 6235 * code already handles the normal generic type parameters, the comment |
| 6236 * matcher can be called directly. For example, we may have already tried |
| 6237 * matching `<` (less than sign) in a method declaration, and be currently |
| 6238 * on the `(` (open paren) because we didn't find it. In that case, this |
| 6239 * function will parse the preceding comment such as `/*<T, R>*/`. |
| 6240 */ |
| 6241 TypeParameterList _parseGenericCommentTypeParameters() { |
| 6242 if (_injectGenericCommentTypeList()) { |
| 6243 return parseTypeParameterList(); |
| 6244 } |
| 6245 return null; |
| 6246 } |
| 6247 |
| 6248 /** |
| 6249 * Parse the generic method or function's type parameters. |
| 6250 * |
| 6251 * For backwards compatibility this can optionally use comments. |
| 6252 * See [parseGenericMethodComments]. |
| 6253 */ |
| 6254 TypeParameterList _parseGenericMethodTypeParameters() { |
| 6255 if (parseGenericMethods && _matches(TokenType.LT) || |
| 6256 _injectGenericCommentTypeList()) { |
| 6257 return parseTypeParameterList(); |
| 6258 } |
| 6259 } |
| 6260 |
| 6261 /** |
| 6185 * Parse a getter. The [commentAndMetadata] is the documentation comment and | 6262 * Parse a getter. The [commentAndMetadata] is the documentation comment and |
| 6186 * metadata to be associated with the declaration. The externalKeyword] is the | 6263 * metadata to be associated with the declaration. The externalKeyword] is the |
| 6187 * 'external' token. The staticKeyword] is the static keyword, or `null` if | 6264 * 'external' token. The staticKeyword] is the static keyword, or `null` if |
| 6188 * the getter is not static. The [returnType] the return type that has already | 6265 * the getter is not static. The [returnType] the return type that has already |
| 6189 * been parsed, or `null` if there was no return type. Return the getter that | 6266 * been parsed, or `null` if there was no return type. Return the getter that |
| 6190 * was parsed. | 6267 * was parsed. |
| 6191 * | 6268 * |
| 6192 * getter ::= | 6269 * getter ::= |
| 6193 * getterSignature functionBody? | 6270 * getterSignature functionBody? |
| 6194 * | 6271 * |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6466 /** | 6543 /** |
| 6467 * Parse a list or map literal. The [modifier] is the 'const' modifier | 6544 * Parse a list or map literal. The [modifier] is the 'const' modifier |
| 6468 * appearing before the literal, or `null` if there is no modifier. Return the | 6545 * appearing before the literal, or `null` if there is no modifier. Return the |
| 6469 * list or map literal that was parsed. | 6546 * list or map literal that was parsed. |
| 6470 * | 6547 * |
| 6471 * listOrMapLiteral ::= | 6548 * listOrMapLiteral ::= |
| 6472 * listLiteral | 6549 * listLiteral |
| 6473 * | mapLiteral | 6550 * | mapLiteral |
| 6474 */ | 6551 */ |
| 6475 TypedLiteral _parseListOrMapLiteral(Token modifier) { | 6552 TypedLiteral _parseListOrMapLiteral(Token modifier) { |
| 6476 TypeArgumentList typeArguments = null; | 6553 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
| 6477 if (_matches(TokenType.LT)) { | |
| 6478 typeArguments = parseTypeArgumentList(); | |
| 6479 } | |
| 6480 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { | 6554 if (_matches(TokenType.OPEN_CURLY_BRACKET)) { |
| 6481 return _parseMapLiteral(modifier, typeArguments); | 6555 return _parseMapLiteral(modifier, typeArguments); |
| 6482 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || | 6556 } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) || |
| 6483 _matches(TokenType.INDEX)) { | 6557 _matches(TokenType.INDEX)) { |
| 6484 return _parseListLiteral(modifier, typeArguments); | 6558 return _parseListLiteral(modifier, typeArguments); |
| 6485 } | 6559 } |
| 6486 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL); | 6560 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL); |
| 6487 return new ListLiteral( | 6561 return new ListLiteral( |
| 6488 modifier, | 6562 modifier, |
| 6489 typeArguments, | 6563 typeArguments, |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6603 * functionDeclaration ::= | 6677 * functionDeclaration ::= |
| 6604 * 'external'? 'static'? functionSignature functionBody | 6678 * 'external'? 'static'? functionSignature functionBody |
| 6605 * | 'external'? functionSignature ';' | 6679 * | 'external'? functionSignature ';' |
| 6606 */ | 6680 */ |
| 6607 MethodDeclaration _parseMethodDeclarationAfterReturnType( | 6681 MethodDeclaration _parseMethodDeclarationAfterReturnType( |
| 6608 CommentAndMetadata commentAndMetadata, | 6682 CommentAndMetadata commentAndMetadata, |
| 6609 Token externalKeyword, | 6683 Token externalKeyword, |
| 6610 Token staticKeyword, | 6684 Token staticKeyword, |
| 6611 TypeName returnType) { | 6685 TypeName returnType) { |
| 6612 SimpleIdentifier methodName = parseSimpleIdentifier(); | 6686 SimpleIdentifier methodName = parseSimpleIdentifier(); |
| 6613 TypeParameterList typeParameters = null; | 6687 TypeParameterList typeParameters = _parseGenericMethodTypeParameters(); |
| 6614 if (parseGenericMethods && _matches(TokenType.LT)) { | |
| 6615 typeParameters = parseTypeParameterList(); | |
| 6616 } | |
| 6617 FormalParameterList parameters; | 6688 FormalParameterList parameters; |
| 6618 if (!_matches(TokenType.OPEN_PAREN) && | 6689 if (!_matches(TokenType.OPEN_PAREN) && |
| 6619 (_matches(TokenType.OPEN_CURLY_BRACKET) || | 6690 (_matches(TokenType.OPEN_CURLY_BRACKET) || |
| 6620 _matches(TokenType.FUNCTION))) { | 6691 _matches(TokenType.FUNCTION))) { |
| 6621 _reportErrorForToken( | 6692 _reportErrorForToken( |
| 6622 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous); | 6693 ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous); |
| 6623 parameters = new FormalParameterList( | 6694 parameters = new FormalParameterList( |
| 6624 _createSyntheticToken(TokenType.OPEN_PAREN), | 6695 _createSyntheticToken(TokenType.OPEN_PAREN), |
| 6625 null, | 6696 null, |
| 6626 null, | 6697 null, |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7003 null, | 7074 null, |
| 7004 parameters, | 7075 parameters, |
| 7005 body); | 7076 body); |
| 7006 } | 7077 } |
| 7007 | 7078 |
| 7008 /** | 7079 /** |
| 7009 * Parse a return type if one is given, otherwise return `null` without | 7080 * Parse a return type if one is given, otherwise return `null` without |
| 7010 * advancing. Return the return type that was parsed. | 7081 * advancing. Return the return type that was parsed. |
| 7011 */ | 7082 */ |
| 7012 TypeName _parseOptionalReturnType() { | 7083 TypeName _parseOptionalReturnType() { |
| 7013 if (_matchesKeyword(Keyword.VOID)) { | 7084 TypeName typeComment = _parseOptionalTypeNameComment(); |
| 7085 if (typeComment != null) { |
| 7086 return typeComment; |
| 7087 } else if (_matchesKeyword(Keyword.VOID)) { |
| 7014 return parseReturnType(); | 7088 return parseReturnType(); |
| 7015 } else if (_matchesIdentifier() && | 7089 } else if (_matchesIdentifier() && |
| 7016 !_matchesKeyword(Keyword.GET) && | 7090 !_matchesKeyword(Keyword.GET) && |
| 7017 !_matchesKeyword(Keyword.SET) && | 7091 !_matchesKeyword(Keyword.SET) && |
| 7018 !_matchesKeyword(Keyword.OPERATOR) && | 7092 !_matchesKeyword(Keyword.OPERATOR) && |
| 7019 (_tokenMatchesIdentifier(_peek()) || | 7093 (_tokenMatchesIdentifier(_peek()) || |
| 7020 _tokenMatches(_peek(), TokenType.LT))) { | 7094 _tokenMatches(_peek(), TokenType.LT))) { |
| 7021 return parseReturnType(); | 7095 return parseReturnType(); |
| 7022 } else if (_matchesIdentifier() && | 7096 } else if (_matchesIdentifier() && |
| 7023 _tokenMatches(_peek(), TokenType.PERIOD) && | 7097 _tokenMatches(_peek(), TokenType.PERIOD) && |
| 7024 _tokenMatchesIdentifier(_peekAt(2)) && | 7098 _tokenMatchesIdentifier(_peekAt(2)) && |
| 7025 (_tokenMatchesIdentifier(_peekAt(3)) || | 7099 (_tokenMatchesIdentifier(_peekAt(3)) || |
| 7026 _tokenMatches(_peekAt(3), TokenType.LT))) { | 7100 _tokenMatches(_peekAt(3), TokenType.LT))) { |
| 7027 return parseReturnType(); | 7101 return parseReturnType(); |
| 7028 } | 7102 } |
| 7029 return null; | 7103 return null; |
| 7030 } | 7104 } |
| 7031 | 7105 |
| 7032 /** | 7106 /** |
| 7107 * Parse a [TypeArgumentList] if present, otherwise return null. |
| 7108 * This also supports the comment form, if enabled: `/*<T>*/` |
| 7109 */ |
| 7110 TypeArgumentList _parseOptionalTypeArguments() { |
| 7111 if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) { |
| 7112 return parseTypeArgumentList(); |
| 7113 } |
| 7114 return null; |
| 7115 } |
| 7116 |
| 7117 TypeName _parseOptionalTypeNameComment() { |
| 7118 if (_injectGenericCommentTypeAssign()) { |
| 7119 return _parseTypeName(); |
| 7120 } |
| 7121 return null; |
| 7122 } |
| 7123 |
| 7124 /** |
| 7033 * Parse a part or part-of directive. The [commentAndMetadata] is the metadata | 7125 * Parse a part or part-of directive. The [commentAndMetadata] is the metadata |
| 7034 * to be associated with the directive. Return the part or part-of directive | 7126 * to be associated with the directive. Return the part or part-of directive |
| 7035 * that was parsed. | 7127 * that was parsed. |
| 7036 * | 7128 * |
| 7037 * partDirective ::= | 7129 * partDirective ::= |
| 7038 * metadata 'part' stringLiteral ';' | 7130 * metadata 'part' stringLiteral ';' |
| 7039 * | 7131 * |
| 7040 * partOfDirective ::= | 7132 * partOfDirective ::= |
| 7041 * metadata 'part' 'of' identifier ';' | 7133 * metadata 'part' 'of' identifier ';' |
| 7042 */ | 7134 */ |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7074 */ | 7166 */ |
| 7075 Expression _parsePostfixExpression() { | 7167 Expression _parsePostfixExpression() { |
| 7076 Expression operand = _parseAssignableExpression(true); | 7168 Expression operand = _parseAssignableExpression(true); |
| 7077 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || | 7169 if (_matches(TokenType.OPEN_SQUARE_BRACKET) || |
| 7078 _matches(TokenType.PERIOD) || | 7170 _matches(TokenType.PERIOD) || |
| 7079 _matches(TokenType.QUESTION_PERIOD) || | 7171 _matches(TokenType.QUESTION_PERIOD) || |
| 7080 _matches(TokenType.OPEN_PAREN) || | 7172 _matches(TokenType.OPEN_PAREN) || |
| 7081 (parseGenericMethods && _matches(TokenType.LT))) { | 7173 (parseGenericMethods && _matches(TokenType.LT))) { |
| 7082 do { | 7174 do { |
| 7083 if (_isLikelyParameterList()) { | 7175 if (_isLikelyParameterList()) { |
| 7084 TypeArgumentList typeArguments = null; | 7176 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
| 7085 if (_matches(TokenType.LT)) { | |
| 7086 typeArguments = parseTypeArgumentList(); | |
| 7087 } | |
| 7088 ArgumentList argumentList = parseArgumentList(); | 7177 ArgumentList argumentList = parseArgumentList(); |
| 7089 if (operand is PropertyAccess) { | 7178 if (operand is PropertyAccess) { |
| 7090 PropertyAccess access = operand as PropertyAccess; | 7179 PropertyAccess access = operand as PropertyAccess; |
| 7091 operand = new MethodInvocation(access.target, access.operator, | 7180 operand = new MethodInvocation(access.target, access.operator, |
| 7092 access.propertyName, typeArguments, argumentList); | 7181 access.propertyName, typeArguments, argumentList); |
| 7093 } else { | 7182 } else { |
| 7094 operand = new FunctionExpressionInvocation( | 7183 operand = new FunctionExpressionInvocation( |
| 7095 operand, typeArguments, argumentList); | 7184 operand, typeArguments, argumentList); |
| 7096 } | 7185 } |
| 7097 } else { | 7186 } else { |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7734 TypeAlias typeAlias = | 7823 TypeAlias typeAlias = |
| 7735 _parseClassTypeAlias(commentAndMetadata, null, keyword); | 7824 _parseClassTypeAlias(commentAndMetadata, null, keyword); |
| 7736 _reportErrorForToken( | 7825 _reportErrorForToken( |
| 7737 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); | 7826 ParserErrorCode.DEPRECATED_CLASS_TYPE_ALIAS, keyword); |
| 7738 return typeAlias; | 7827 return typeAlias; |
| 7739 } | 7828 } |
| 7740 } | 7829 } |
| 7741 return _parseFunctionTypeAlias(commentAndMetadata, keyword); | 7830 return _parseFunctionTypeAlias(commentAndMetadata, keyword); |
| 7742 } | 7831 } |
| 7743 | 7832 |
| 7833 TypeName _parseTypeName() { |
| 7834 Identifier typeName; |
| 7835 if (_matchesKeyword(Keyword.VAR)) { |
| 7836 _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME); |
| 7837 typeName = new SimpleIdentifier(getAndAdvance()); |
| 7838 } else if (_matchesIdentifier()) { |
| 7839 typeName = parsePrefixedIdentifier(); |
| 7840 } else { |
| 7841 typeName = _createSyntheticIdentifier(); |
| 7842 _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME); |
| 7843 } |
| 7844 TypeArgumentList typeArguments = _parseOptionalTypeArguments(); |
| 7845 return new TypeName(typeName, typeArguments); |
| 7846 } |
| 7847 |
| 7744 /** | 7848 /** |
| 7745 * Parse a unary expression. Return the unary expression that was parsed. | 7849 * Parse a unary expression. Return the unary expression that was parsed. |
| 7746 * | 7850 * |
| 7747 * unaryExpression ::= | 7851 * unaryExpression ::= |
| 7748 * prefixOperator unaryExpression | 7852 * prefixOperator unaryExpression |
| 7749 * | awaitExpression | 7853 * | awaitExpression |
| 7750 * | postfixExpression | 7854 * | postfixExpression |
| 7751 * | unaryOperator 'super' | 7855 * | unaryOperator 'super' |
| 7752 * | '-' 'super' | 7856 * | '-' 'super' |
| 7753 * | incrementOperator assignableExpression | 7857 * | incrementOperator assignableExpression |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8077 void _reportErrorForToken(ErrorCode errorCode, Token token, | 8181 void _reportErrorForToken(ErrorCode errorCode, Token token, |
| 8078 [List<Object> arguments]) { | 8182 [List<Object> arguments]) { |
| 8079 if (token.type == TokenType.EOF) { | 8183 if (token.type == TokenType.EOF) { |
| 8080 token = token.previous; | 8184 token = token.previous; |
| 8081 } | 8185 } |
| 8082 _reportError(new AnalysisError(_source, token.offset, | 8186 _reportError(new AnalysisError(_source, token.offset, |
| 8083 math.max(token.length, 1), errorCode, arguments)); | 8187 math.max(token.length, 1), errorCode, arguments)); |
| 8084 } | 8188 } |
| 8085 | 8189 |
| 8086 /** | 8190 /** |
| 8191 * Scans the generic method comment, and returns the tokens, otherwise |
| 8192 * returns null. |
| 8193 */ |
| 8194 Token _scanGenericMethodComment(String code, int offset) { |
| 8195 BooleanErrorListener listener = new BooleanErrorListener(); |
| 8196 Scanner scanner = |
| 8197 new Scanner(null, new SubSequenceReader(code, offset), listener); |
| 8198 scanner.setSourceStart(1, 1); |
| 8199 Token firstToken = scanner.tokenize(); |
| 8200 if (listener.errorReported) { |
| 8201 return null; |
| 8202 } |
| 8203 return firstToken; |
| 8204 } |
| 8205 |
| 8206 /** |
| 8087 * Skips a block with all containing blocks. | 8207 * Skips a block with all containing blocks. |
| 8088 */ | 8208 */ |
| 8089 void _skipBlock() { | 8209 void _skipBlock() { |
| 8090 Token endToken = (_currentToken as BeginToken).endToken; | 8210 Token endToken = (_currentToken as BeginToken).endToken; |
| 8091 if (endToken == null) { | 8211 if (endToken == null) { |
| 8092 endToken = _currentToken.next; | 8212 endToken = _currentToken.next; |
| 8093 while (!identical(endToken, _currentToken)) { | 8213 while (!identical(endToken, _currentToken)) { |
| 8094 _currentToken = endToken; | 8214 _currentToken = endToken; |
| 8095 endToken = _currentToken.next; | 8215 endToken = _currentToken.next; |
| 8096 } | 8216 } |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8413 * This method must be kept in sync with [parseTypeArgumentList]. | 8533 * This method must be kept in sync with [parseTypeArgumentList]. |
| 8414 * | 8534 * |
| 8415 * typeArguments ::= | 8535 * typeArguments ::= |
| 8416 * '<' typeList '>' | 8536 * '<' typeList '>' |
| 8417 * | 8537 * |
| 8418 * typeList ::= | 8538 * typeList ::= |
| 8419 * type (',' type)* | 8539 * type (',' type)* |
| 8420 */ | 8540 */ |
| 8421 Token _skipTypeArgumentList(Token startToken) { | 8541 Token _skipTypeArgumentList(Token startToken) { |
| 8422 Token token = startToken; | 8542 Token token = startToken; |
| 8423 if (!_tokenMatches(token, TokenType.LT)) { | 8543 if (!_tokenMatches(token, TokenType.LT) && |
| 8544 !_injectGenericCommentTypeList()) { |
| 8424 return null; | 8545 return null; |
| 8425 } | 8546 } |
| 8426 token = _skipTypeName(token.next); | 8547 token = _skipTypeName(token.next); |
| 8427 if (token == null) { | 8548 if (token == null) { |
| 8428 // If the start token '<' is followed by '>' | 8549 // If the start token '<' is followed by '>' |
| 8429 // then assume this should be type argument list but is missing a type | 8550 // then assume this should be type argument list but is missing a type |
| 8430 token = startToken.next; | 8551 token = startToken.next; |
| 8431 if (_tokenMatches(token, TokenType.GT)) { | 8552 if (_tokenMatches(token, TokenType.GT)) { |
| 8432 return token.next; | 8553 return token.next; |
| 8433 } | 8554 } |
| (...skipping 2619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11053 } | 11174 } |
| 11054 | 11175 |
| 11055 /** | 11176 /** |
| 11056 * Copy resolution data from the [fromNode] to the [toNode]. | 11177 * Copy resolution data from the [fromNode] to the [toNode]. |
| 11057 */ | 11178 */ |
| 11058 static void copyResolutionData(AstNode fromNode, AstNode toNode) { | 11179 static void copyResolutionData(AstNode fromNode, AstNode toNode) { |
| 11059 ResolutionCopier copier = new ResolutionCopier(); | 11180 ResolutionCopier copier = new ResolutionCopier(); |
| 11060 copier._isEqualNodes(fromNode, toNode); | 11181 copier._isEqualNodes(fromNode, toNode); |
| 11061 } | 11182 } |
| 11062 } | 11183 } |
| OLD | NEW |