Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 #include "vm/parser.h" | 5 #include "vm/parser.h" |
| 6 #include "vm/flags.h" | 6 #include "vm/flags.h" |
| 7 | 7 |
| 8 #ifndef DART_PRECOMPILED_RUNTIME | 8 #ifndef DART_PRECOMPILED_RUNTIME |
| 9 | 9 |
| 10 #include "lib/invocation_mirror.h" | 10 #include "lib/invocation_mirror.h" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 | 41 |
| 42 namespace dart { | 42 namespace dart { |
| 43 | 43 |
| 44 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\"."); | 44 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\"."); |
| 45 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); | 45 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
| 46 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef."); | 46 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef."); |
| 47 // TODO(floitsch): remove the conditional-directive flag, once we publicly | 47 // TODO(floitsch): remove the conditional-directive flag, once we publicly |
| 48 // committed to the current version. | 48 // committed to the current version. |
| 49 DEFINE_FLAG(bool, conditional_directives, true, | 49 DEFINE_FLAG(bool, conditional_directives, true, |
| 50 "Enable conditional directives"); | 50 "Enable conditional directives"); |
| 51 DEFINE_FLAG(bool, generic_method_syntax, false, "Enbable generic functions."); | |
|
siva
2016/08/19 23:08:13
s/Enbable/Enable/
hausner
2016/08/19 23:12:01
Done. I was clearly babbling.
| |
| 51 DEFINE_FLAG(bool, initializing_formal_access, false, | 52 DEFINE_FLAG(bool, initializing_formal_access, false, |
| 52 "Make initializing formal parameters visible in initializer list."); | 53 "Make initializing formal parameters visible in initializer list."); |
| 53 DEFINE_FLAG(bool, warn_super, false, | 54 DEFINE_FLAG(bool, warn_super, false, |
| 54 "Warning if super initializer not last in initializer list."); | 55 "Warning if super initializer not last in initializer list."); |
| 55 DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax."); | 56 DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax."); |
| 56 DEFINE_FLAG(bool, await_is_keyword, false, | 57 DEFINE_FLAG(bool, await_is_keyword, false, |
| 57 "await and yield are treated as proper keywords in synchronous code."); | 58 "await and yield are treated as proper keywords in synchronous code."); |
| 58 | 59 |
| 59 DECLARE_FLAG(bool, profile_vm); | 60 DECLARE_FLAG(bool, profile_vm); |
| 60 DECLARE_FLAG(bool, trace_service); | 61 DECLARE_FLAG(bool, trace_service); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 ~BoolScope() { | 119 ~BoolScope() { |
| 119 *_addr = _saved_value; | 120 *_addr = _saved_value; |
| 120 } | 121 } |
| 121 | 122 |
| 122 private: | 123 private: |
| 123 bool* _addr; | 124 bool* _addr; |
| 124 bool _saved_value; | 125 bool _saved_value; |
| 125 }; | 126 }; |
| 126 | 127 |
| 127 | 128 |
| 129 // Helper class to save and restore token position. | |
| 130 class Parser::TokenPosScope : public ValueObject { | |
| 131 public: | |
| 132 explicit TokenPosScope(Parser *p) : p_(p) { | |
| 133 saved_pos_ = p_->TokenPos(); | |
| 134 } | |
| 135 TokenPosScope(Parser *p, TokenPosition pos) : p_(p), saved_pos_(pos) { | |
| 136 } | |
| 137 ~TokenPosScope() { | |
| 138 p_->SetPosition(saved_pos_); | |
| 139 } | |
| 140 | |
| 141 private: | |
| 142 Parser* p_; | |
| 143 TokenPosition saved_pos_; | |
| 144 DISALLOW_COPY_AND_ASSIGN(TokenPosScope); | |
| 145 }; | |
| 146 | |
| 147 | |
| 128 class RecursionChecker : public ValueObject { | 148 class RecursionChecker : public ValueObject { |
| 129 public: | 149 public: |
| 130 explicit RecursionChecker(Parser* p) : parser_(p) { | 150 explicit RecursionChecker(Parser* p) : parser_(p) { |
| 131 parser_->recursion_counter_++; | 151 parser_->recursion_counter_++; |
| 132 // No need to check the stack unless the parser is in an unusually deep | 152 // No need to check the stack unless the parser is in an unusually deep |
| 133 // recurive state. Thus, we omit the more expensive stack checks in | 153 // recurive state. Thus, we omit the more expensive stack checks in |
| 134 // the common case. | 154 // the common case. |
| 135 const int kMaxUncheckedDepth = 100; // Somewhat arbitrary. | 155 const int kMaxUncheckedDepth = 100; // Somewhat arbitrary. |
| 136 if (parser_->recursion_counter_ > kMaxUncheckedDepth) { | 156 if (parser_->recursion_counter_ > kMaxUncheckedDepth) { |
| 137 parser_->CheckStack(); | 157 parser_->CheckStack(); |
| (...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2058 const intptr_t num_existing_parameters = | 2078 const intptr_t num_existing_parameters = |
| 2059 params->num_fixed_parameters + params->num_optional_parameters; | 2079 params->num_fixed_parameters + params->num_optional_parameters; |
| 2060 for (intptr_t i = 0; i < num_existing_parameters; i++) { | 2080 for (intptr_t i = 0; i < num_existing_parameters; i++) { |
| 2061 ParamDesc& existing_parameter = (*params->parameters)[i]; | 2081 ParamDesc& existing_parameter = (*params->parameters)[i]; |
| 2062 if (existing_parameter.name->Equals(*parameter.name)) { | 2082 if (existing_parameter.name->Equals(*parameter.name)) { |
| 2063 ReportError(parameter.name_pos, "duplicate formal parameter '%s'", | 2083 ReportError(parameter.name_pos, "duplicate formal parameter '%s'", |
| 2064 parameter.name->ToCString()); | 2084 parameter.name->ToCString()); |
| 2065 } | 2085 } |
| 2066 } | 2086 } |
| 2067 | 2087 |
| 2068 if (CurrentToken() == Token::kLPAREN) { | 2088 if (IsParameterPart()) { |
| 2069 // This parameter is probably a closure. If we saw the keyword 'var' | 2089 // This parameter is probably a closure. If we saw the keyword 'var' |
| 2070 // or 'final', a closure is not legal here and we ignore the | 2090 // or 'final', a closure is not legal here and we ignore the |
| 2071 // opening parens. | 2091 // opening parens. |
| 2072 // TODO(hausner): The language spec appears to allow var and final | 2092 // TODO(hausner): The language spec appears to allow var and final |
| 2073 // in signature types when used with initializing formals: | 2093 // in signature types when used with initializing formals: |
| 2074 // fieldFormalParameter: | 2094 // fieldFormalParameter: |
| 2075 // metadata finalConstVarOrType? this ‘.’ identifier formalParameterList? ; | 2095 // metadata finalConstVarOrType? this ‘.’ identifier formalParameterList? ; |
| 2076 if (!var_seen && !final_seen) { | 2096 if (!var_seen && !final_seen) { |
| 2077 // The parsed parameter type is actually the function result type. | 2097 // The parsed parameter type is actually the function result type. |
| 2078 const AbstractType& result_type = | 2098 const AbstractType& result_type = |
| 2079 AbstractType::Handle(Z, parameter.type->raw()); | 2099 AbstractType::Handle(Z, parameter.type->raw()); |
| 2080 | 2100 |
| 2081 // Finish parsing the function type parameter. | 2101 // Finish parsing the function type parameter. |
| 2102 if (CurrentToken() == Token::kLT) { | |
| 2103 // TODO(hausner): handle generic function types. | |
| 2104 if (!FLAG_generic_method_syntax) { | |
| 2105 ReportError("generic function types not supported"); | |
| 2106 } | |
| 2107 TokenPosition type_param_pos = TokenPos(); | |
| 2108 if (!TryParseTypeParameters()) { | |
| 2109 ReportError(type_param_pos, "error in type parameters"); | |
| 2110 } | |
| 2111 } | |
| 2112 | |
| 2113 ASSERT(CurrentToken() == Token::kLPAREN); | |
| 2082 ParamList func_params; | 2114 ParamList func_params; |
| 2083 | 2115 |
| 2084 // Add implicit closure object parameter. | 2116 // Add implicit closure object parameter. |
| 2085 func_params.AddFinalParameter( | 2117 func_params.AddFinalParameter( |
| 2086 TokenPos(), | 2118 TokenPos(), |
| 2087 &Symbols::ClosureParameter(), | 2119 &Symbols::ClosureParameter(), |
| 2088 &Object::dynamic_type()); | 2120 &Object::dynamic_type()); |
| 2089 | 2121 |
| 2090 const bool no_explicit_default_values = false; | 2122 const bool no_explicit_default_values = false; |
| 2091 ParseFormalParameterList(no_explicit_default_values, false, &func_params); | 2123 ParseFormalParameterList(no_explicit_default_values, false, &func_params); |
| (...skipping 1617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3709 | 3741 |
| 3710 // We have a name that is not shadowed, followed by a period or #. | 3742 // We have a name that is not shadowed, followed by a period or #. |
| 3711 // Consume the identifier, let the caller consume the . or #. | 3743 // Consume the identifier, let the caller consume the . or #. |
| 3712 ConsumeToken(); | 3744 ConsumeToken(); |
| 3713 return prefix.raw(); | 3745 return prefix.raw(); |
| 3714 } | 3746 } |
| 3715 | 3747 |
| 3716 | 3748 |
| 3717 void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) { | 3749 void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) { |
| 3718 TRACE_PARSER("ParseMethodOrConstructor"); | 3750 TRACE_PARSER("ParseMethodOrConstructor"); |
| 3719 ASSERT(CurrentToken() == Token::kLPAREN || method->IsGetter()); | 3751 // We are at the beginning of the formal parameters list. |
| 3752 ASSERT(CurrentToken() == Token::kLPAREN || | |
| 3753 CurrentToken() == Token::kLT || | |
| 3754 method->IsGetter()); | |
| 3720 ASSERT(method->type != NULL); | 3755 ASSERT(method->type != NULL); |
| 3721 ASSERT(current_member_ == method); | 3756 ASSERT(current_member_ == method); |
| 3722 | 3757 |
| 3723 if (method->has_var) { | 3758 if (method->has_var) { |
| 3724 ReportError(method->name_pos, "keyword var not allowed for methods"); | 3759 ReportError(method->name_pos, "keyword var not allowed for methods"); |
| 3725 } | 3760 } |
| 3726 if (method->has_final) { | 3761 if (method->has_final) { |
| 3727 ReportError(method->name_pos, "'final' not allowed for methods"); | 3762 ReportError(method->name_pos, "'final' not allowed for methods"); |
| 3728 } | 3763 } |
| 3729 if (method->has_abstract && method->has_static) { | 3764 if (method->has_abstract && method->has_static) { |
| 3730 ReportError(method->name_pos, | 3765 ReportError(method->name_pos, |
| 3731 "static method '%s' cannot be abstract", | 3766 "static method '%s' cannot be abstract", |
| 3732 method->name->ToCString()); | 3767 method->name->ToCString()); |
| 3733 } | 3768 } |
| 3734 if (method->has_const && !method->IsFactoryOrConstructor()) { | 3769 if (method->has_const && !method->IsFactoryOrConstructor()) { |
| 3735 ReportError(method->name_pos, "'const' not allowed for methods"); | 3770 ReportError(method->name_pos, "'const' not allowed for methods"); |
| 3736 } | 3771 } |
| 3737 if (method->has_abstract && method->IsFactoryOrConstructor()) { | 3772 if (method->has_abstract && method->IsFactoryOrConstructor()) { |
| 3738 ReportError(method->name_pos, "constructor cannot be abstract"); | 3773 ReportError(method->name_pos, "constructor cannot be abstract"); |
| 3739 } | 3774 } |
| 3740 if (method->has_const && method->IsConstructor()) { | 3775 if (method->has_const && method->IsConstructor()) { |
| 3741 current_class().set_is_const(); | 3776 current_class().set_is_const(); |
| 3742 } | 3777 } |
| 3743 | 3778 |
| 3779 if (CurrentToken() == Token::kLT) { | |
| 3780 // Parse type parameters, but ignore them. | |
| 3781 // TODO(hausner): handle type parameters. | |
| 3782 if (!FLAG_generic_method_syntax) { | |
| 3783 ReportError("generic type arguments not supported."); | |
|
regis
2016/08/24 14:14:02
Being picky, but instead of "generic type argument
| |
| 3784 } | |
| 3785 TokenPosition type_param_pos = TokenPos(); | |
| 3786 if (method->IsFactoryOrConstructor()) { | |
| 3787 ReportError(method->name_pos, "constructor cannot be generic"); | |
| 3788 } | |
| 3789 if (method->IsGetter() || method->IsSetter()) { | |
| 3790 ReportError(type_param_pos, "%s cannot be generic", | |
| 3791 method->IsGetter() ? "getter" : "setter"); | |
| 3792 } | |
| 3793 if (!TryParseTypeParameters()) { | |
| 3794 ReportError(type_param_pos, "error in type parameters"); | |
| 3795 } | |
| 3796 } | |
| 3797 | |
| 3744 // Parse the formal parameters. | 3798 // Parse the formal parameters. |
| 3745 const bool are_implicitly_final = method->has_const; | 3799 const bool are_implicitly_final = method->has_const; |
| 3746 const bool allow_explicit_default_values = true; | 3800 const bool allow_explicit_default_values = true; |
| 3747 const TokenPosition formal_param_pos = TokenPos(); | 3801 const TokenPosition formal_param_pos = TokenPos(); |
| 3748 method->params.Clear(); | 3802 method->params.Clear(); |
| 3749 // Static functions do not have a receiver. | 3803 // Static functions do not have a receiver. |
| 3750 // The first parameter of a factory is the TypeArguments vector of | 3804 // The first parameter of a factory is the TypeArguments vector of |
| 3751 // the type of the instance to be allocated. | 3805 // the type of the instance to be allocated. |
| 3752 if (!method->has_static || method->IsConstructor()) { | 3806 if (!method->has_static || method->IsConstructor()) { |
| 3753 method->params.AddReceiver(ReceiverType(current_class()), formal_param_pos); | 3807 method->params.AddReceiver(ReceiverType(current_class()), formal_param_pos); |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4334 } else if ((CurrentToken() == Token::kFACTORY) && | 4388 } else if ((CurrentToken() == Token::kFACTORY) && |
| 4335 (LookaheadToken(1) != Token::kLPAREN)) { | 4389 (LookaheadToken(1) != Token::kLPAREN)) { |
| 4336 ConsumeToken(); | 4390 ConsumeToken(); |
| 4337 if (member.has_static) { | 4391 if (member.has_static) { |
| 4338 ReportError("factory method cannot be explicitly marked static"); | 4392 ReportError("factory method cannot be explicitly marked static"); |
| 4339 } | 4393 } |
| 4340 member.has_factory = true; | 4394 member.has_factory = true; |
| 4341 member.has_static = true; | 4395 member.has_static = true; |
| 4342 // The result type depends on the name of the factory method. | 4396 // The result type depends on the name of the factory method. |
| 4343 } | 4397 } |
| 4398 | |
| 4344 // Optionally parse a type. | 4399 // Optionally parse a type. |
| 4345 if (CurrentToken() == Token::kVOID) { | 4400 if (CurrentToken() == Token::kVOID) { |
| 4346 if (member.has_var || member.has_factory) { | 4401 if (member.has_var || member.has_factory) { |
| 4347 ReportError("void not expected"); | 4402 ReportError("void not expected"); |
| 4348 } | 4403 } |
| 4349 ConsumeToken(); | 4404 ConsumeToken(); |
| 4350 ASSERT(member.type == NULL); | 4405 ASSERT(member.type == NULL); |
| 4351 member.type = &Object::void_type(); | 4406 member.type = &Object::void_type(); |
| 4352 } else if (CurrentToken() == Token::kIDENT) { | 4407 } else { |
| 4353 // This is either a type name or the name of a method/constructor/field. | 4408 bool found_type = false; |
| 4354 if ((member.type == NULL) && !member.has_factory) { | 4409 { |
| 4355 // We have not seen a member type yet, so we check if the next | 4410 // Lookahead to determine whether the next tokens are a return type. |
| 4356 // identifier could represent a type before parsing it. | 4411 TokenPosScope saved_pos(this); |
| 4357 Token::Kind follower = LookaheadToken(1); | 4412 if (TryParseReturnType()) { |
| 4358 // We have an identifier followed by a 'follower' token. | 4413 if (IsIdentifier() || |
| 4359 // We either parse a type or assume that no type is specified. | 4414 (CurrentToken() == Token::kGET) || |
| 4360 if ((follower == Token::kLT) || // Parameterized type. | 4415 (CurrentToken() == Token::kSET) || |
| 4361 (follower == Token::kGET) || // Getter following a type. | 4416 (CurrentToken() == Token::kOPERATOR)) { |
| 4362 (follower == Token::kSET) || // Setter following a type. | 4417 found_type = true; |
| 4363 (follower == Token::kOPERATOR) || // Operator following a type. | 4418 } |
| 4364 (Token::IsIdentifier(follower)) || // Member name following a type. | |
| 4365 ((follower == Token::kPERIOD) && // Qualified class name of type, | |
| 4366 (LookaheadToken(3) != Token::kLPAREN))) { // but not a named constr. | |
| 4367 ASSERT(is_top_level_); | |
| 4368 // The declared type of fields is never ignored, even in unchecked mode, | |
| 4369 // because getters and setters could be closurized at some time (not | |
| 4370 // supported yet). | |
| 4371 member.type = &AbstractType::ZoneHandle(Z, | |
| 4372 ParseType(ClassFinalizer::kResolveTypeParameters)); | |
| 4373 } | 4419 } |
| 4374 } | 4420 } |
| 4421 if (found_type) { | |
| 4422 member.type = &AbstractType::ZoneHandle(Z, | |
| 4423 ParseType(ClassFinalizer::kResolveTypeParameters)); | |
| 4424 } | |
| 4375 } | 4425 } |
| 4376 | 4426 |
| 4377 // Optionally parse a (possibly named) constructor name or factory. | 4427 // Optionally parse a (possibly named) constructor name or factory. |
| 4378 if (IsIdentifier() && | 4428 if (IsIdentifier() && |
| 4379 (CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) { | 4429 (CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) { |
| 4380 member.name_pos = TokenPos(); | 4430 member.name_pos = TokenPos(); |
| 4381 member.name = CurrentLiteral(); // Unqualified identifier. | 4431 member.name = CurrentLiteral(); // Unqualified identifier. |
| 4382 ConsumeToken(); | 4432 ConsumeToken(); |
| 4383 if (member.has_factory) { | 4433 if (member.has_factory) { |
| 4384 // The factory name may be qualified, but the first identifier must match | 4434 // The factory name may be qualified, but the first identifier must match |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 4415 if (CurrentToken() == Token::kPERIOD) { | 4465 if (CurrentToken() == Token::kPERIOD) { |
| 4416 // Named constructor. | 4466 // Named constructor. |
| 4417 ConsumeToken(); | 4467 ConsumeToken(); |
| 4418 member.dict_name = ExpectIdentifier("identifier expected"); | 4468 member.dict_name = ExpectIdentifier("identifier expected"); |
| 4419 to_concat.Add(*member.dict_name); | 4469 to_concat.Add(*member.dict_name); |
| 4420 } | 4470 } |
| 4421 *member.name = Symbols::FromConcatAll(T, to_concat); | 4471 *member.name = Symbols::FromConcatAll(T, to_concat); |
| 4422 CheckToken(Token::kLPAREN); | 4472 CheckToken(Token::kLPAREN); |
| 4423 } else if ((CurrentToken() == Token::kGET) && !member.has_var && | 4473 } else if ((CurrentToken() == Token::kGET) && !member.has_var && |
| 4424 (LookaheadToken(1) != Token::kLPAREN) && | 4474 (LookaheadToken(1) != Token::kLPAREN) && |
| 4475 (LookaheadToken(1) != Token::kLT) && | |
| 4425 (LookaheadToken(1) != Token::kASSIGN) && | 4476 (LookaheadToken(1) != Token::kASSIGN) && |
| 4426 (LookaheadToken(1) != Token::kCOMMA) && | 4477 (LookaheadToken(1) != Token::kCOMMA) && |
| 4427 (LookaheadToken(1) != Token::kSEMICOLON)) { | 4478 (LookaheadToken(1) != Token::kSEMICOLON)) { |
| 4428 ConsumeToken(); | 4479 ConsumeToken(); |
| 4429 member.kind = RawFunction::kGetterFunction; | 4480 member.kind = RawFunction::kGetterFunction; |
| 4430 member.name_pos = this->TokenPos(); | 4481 member.name_pos = this->TokenPos(); |
| 4431 member.name = ExpectIdentifier("identifier expected"); | 4482 member.name = ExpectIdentifier("identifier expected"); |
| 4432 // If the result type was not specified, it will be set to DynamicType. | 4483 // If the result type was not specified, it will be set to DynamicType. |
| 4433 } else if ((CurrentToken() == Token::kSET) && !member.has_var && | 4484 } else if ((CurrentToken() == Token::kSET) && !member.has_var && |
| 4434 (LookaheadToken(1) != Token::kLPAREN) && | 4485 (LookaheadToken(1) != Token::kLPAREN) && |
| 4486 (LookaheadToken(1) != Token::kLT) && | |
| 4435 (LookaheadToken(1) != Token::kASSIGN) && | 4487 (LookaheadToken(1) != Token::kASSIGN) && |
| 4436 (LookaheadToken(1) != Token::kCOMMA) && | 4488 (LookaheadToken(1) != Token::kCOMMA) && |
| 4437 (LookaheadToken(1) != Token::kSEMICOLON)) { | 4489 (LookaheadToken(1) != Token::kSEMICOLON)) { |
| 4438 ConsumeToken(); | 4490 ConsumeToken(); |
| 4439 member.kind = RawFunction::kSetterFunction; | 4491 member.kind = RawFunction::kSetterFunction; |
| 4440 member.name_pos = this->TokenPos(); | 4492 member.name_pos = this->TokenPos(); |
| 4441 member.name = ExpectIdentifier("identifier expected"); | 4493 member.name = ExpectIdentifier("identifier expected"); |
| 4442 CheckToken(Token::kLPAREN); | 4494 CheckToken(Token::kLPAREN); |
| 4443 // The grammar allows a return type, so member.type is not always NULL here. | 4495 // The grammar allows a return type, so member.type is not always NULL here. |
| 4444 // If no return type is specified, the return type of the setter is dynamic. | 4496 // If no return type is specified, the return type of the setter is dynamic. |
| 4445 if (member.type == NULL) { | 4497 if (member.type == NULL) { |
| 4446 member.type = &Object::dynamic_type(); | 4498 member.type = &Object::dynamic_type(); |
| 4447 } | 4499 } |
| 4448 } else if ((CurrentToken() == Token::kOPERATOR) && !member.has_var && | 4500 } else if ((CurrentToken() == Token::kOPERATOR) && !member.has_var && |
| 4449 (LookaheadToken(1) != Token::kLPAREN) && | 4501 (LookaheadToken(1) != Token::kLPAREN) && |
| 4450 (LookaheadToken(1) != Token::kASSIGN) && | 4502 (LookaheadToken(1) != Token::kASSIGN) && |
| 4451 (LookaheadToken(1) != Token::kCOMMA) && | 4503 (LookaheadToken(1) != Token::kCOMMA) && |
| 4452 (LookaheadToken(1) != Token::kSEMICOLON)) { | 4504 (LookaheadToken(1) != Token::kSEMICOLON)) { |
| 4505 // TODO(hausner): handle the case of a generic function named 'operator': | |
| 4506 // eg: T operator<T>(a, b) => ... | |
| 4453 ConsumeToken(); | 4507 ConsumeToken(); |
| 4454 if (!Token::CanBeOverloaded(CurrentToken())) { | 4508 if (!Token::CanBeOverloaded(CurrentToken())) { |
| 4455 ReportError("invalid operator overloading"); | 4509 ReportError("invalid operator overloading"); |
| 4456 } | 4510 } |
| 4457 if (member.has_static) { | 4511 if (member.has_static) { |
| 4458 ReportError("operator overloading functions cannot be static"); | 4512 ReportError("operator overloading functions cannot be static"); |
| 4459 } | 4513 } |
| 4460 member.operator_token = CurrentToken(); | 4514 member.operator_token = CurrentToken(); |
| 4461 member.has_operator = true; | 4515 member.has_operator = true; |
| 4462 member.kind = RawFunction::kRegularFunction; | 4516 member.kind = RawFunction::kRegularFunction; |
| 4463 member.name_pos = this->TokenPos(); | 4517 member.name_pos = this->TokenPos(); |
| 4464 member.name = &String::ZoneHandle(Z, | 4518 member.name = &String::ZoneHandle(Z, |
| 4465 Symbols::Token(member.operator_token).raw()); | 4519 Symbols::Token(member.operator_token).raw()); |
| 4466 ConsumeToken(); | 4520 ConsumeToken(); |
| 4467 } else if (IsIdentifier()) { | 4521 } else if (IsIdentifier()) { |
| 4468 member.name = CurrentLiteral(); | 4522 member.name = CurrentLiteral(); |
| 4469 member.name_pos = TokenPos(); | 4523 member.name_pos = TokenPos(); |
| 4470 ConsumeToken(); | 4524 ConsumeToken(); |
| 4471 } else { | 4525 } else { |
| 4472 ReportError("identifier expected"); | 4526 ReportError("identifier expected"); |
| 4473 } | 4527 } |
| 4474 | 4528 |
| 4475 ASSERT(member.name != NULL); | 4529 ASSERT(member.name != NULL); |
| 4476 if (CurrentToken() == Token::kLPAREN || member.IsGetter()) { | 4530 if (IsParameterPart() || member.IsGetter()) { |
| 4477 // Constructor or method. | 4531 // Constructor or method. |
| 4478 if (member.type == NULL) { | 4532 if (member.type == NULL) { |
| 4479 member.type = &Object::dynamic_type(); | 4533 member.type = &Object::dynamic_type(); |
| 4480 } | 4534 } |
| 4481 ASSERT(member.IsFactory() == member.has_factory); | 4535 ASSERT(member.IsFactory() == member.has_factory); |
| 4482 ParseMethodOrConstructor(members, &member); | 4536 ParseMethodOrConstructor(members, &member); |
| 4483 } else if (CurrentToken() == Token::kSEMICOLON || | 4537 } else if (CurrentToken() == Token::kSEMICOLON || |
| 4484 CurrentToken() == Token::kCOMMA || | 4538 CurrentToken() == Token::kCOMMA || |
| 4485 CurrentToken() == Token::kASSIGN) { | 4539 CurrentToken() == Token::kASSIGN) { |
| 4486 // Field definition. | 4540 // Field definition. |
| (...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5121 | 5175 |
| 5122 | 5176 |
| 5123 // Look ahead to detect if we are seeing ident [ TypeParameters ] "(". | 5177 // Look ahead to detect if we are seeing ident [ TypeParameters ] "(". |
| 5124 // We need this lookahead to distinguish between the optional return type | 5178 // We need this lookahead to distinguish between the optional return type |
| 5125 // and the alias name of a function type alias. | 5179 // and the alias name of a function type alias. |
| 5126 // Token position remains unchanged. | 5180 // Token position remains unchanged. |
| 5127 bool Parser::IsFunctionTypeAliasName() { | 5181 bool Parser::IsFunctionTypeAliasName() { |
| 5128 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { | 5182 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { |
| 5129 return true; | 5183 return true; |
| 5130 } | 5184 } |
| 5131 const TokenPosition saved_pos = TokenPos(); | 5185 const TokenPosScope saved_pos(this); |
| 5132 bool is_alias_name = false; | |
| 5133 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { | 5186 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { |
| 5134 ConsumeToken(); | 5187 ConsumeToken(); |
| 5135 if (TryParseTypeParameters() && (CurrentToken() == Token::kLPAREN)) { | 5188 if (TryParseTypeParameters() && (CurrentToken() == Token::kLPAREN)) { |
| 5136 is_alias_name = true; | 5189 return true; |
| 5137 } | 5190 } |
| 5138 } | 5191 } |
| 5139 SetPosition(saved_pos); | 5192 return false; |
| 5140 return is_alias_name; | |
| 5141 } | 5193 } |
| 5142 | 5194 |
| 5143 | 5195 |
| 5144 // Look ahead to detect if we are seeing ident [ TypeParameters ] "=". | 5196 // Look ahead to detect if we are seeing ident [ TypeParameters ] "=". |
| 5145 // Token position remains unchanged. | 5197 // Token position remains unchanged. |
| 5146 bool Parser::IsMixinAppAlias() { | 5198 bool Parser::IsMixinAppAlias() { |
| 5147 if (IsIdentifier() && (LookaheadToken(1) == Token::kASSIGN)) { | 5199 if (IsIdentifier() && (LookaheadToken(1) == Token::kASSIGN)) { |
| 5148 return true; | 5200 return true; |
| 5149 } | 5201 } |
| 5150 const TokenPosition saved_pos = TokenPos(); | 5202 const TokenPosScope saved_pos(this); |
| 5151 bool is_mixin_def = false; | |
| 5152 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { | 5203 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { |
| 5153 ConsumeToken(); | 5204 ConsumeToken(); |
| 5154 if (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) { | 5205 if (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) { |
| 5155 is_mixin_def = true; | 5206 return true; |
| 5156 } | 5207 } |
| 5157 } | 5208 } |
| 5158 SetPosition(saved_pos); | 5209 return false; |
| 5159 return is_mixin_def; | |
| 5160 } | 5210 } |
| 5161 | 5211 |
| 5162 | 5212 |
| 5163 void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, | 5213 void Parser::ParseTypedef(const GrowableObjectArray& pending_classes, |
| 5164 const Object& tl_owner, | 5214 const Object& tl_owner, |
| 5165 TokenPosition metadata_pos) { | 5215 TokenPosition metadata_pos) { |
| 5166 TRACE_PARSER("ParseTypedef"); | 5216 TRACE_PARSER("ParseTypedef"); |
| 5167 TokenPosition declaration_pos = | 5217 TokenPosition declaration_pos = |
| 5168 metadata_pos.IsReal() ? metadata_pos : TokenPos(); | 5218 metadata_pos.IsReal() ? metadata_pos : TokenPos(); |
| 5169 ExpectToken(Token::kTYPEDEF); | 5219 ExpectToken(Token::kTYPEDEF); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5256 ASSERT(!function_type_alias.is_finalized()); | 5306 ASSERT(!function_type_alias.is_finalized()); |
| 5257 pending_classes.Add(function_type_alias, Heap::kOld); | 5307 pending_classes.Add(function_type_alias, Heap::kOld); |
| 5258 if (FLAG_enable_mirrors && metadata_pos.IsReal()) { | 5308 if (FLAG_enable_mirrors && metadata_pos.IsReal()) { |
| 5259 library_.AddClassMetadata(function_type_alias, | 5309 library_.AddClassMetadata(function_type_alias, |
| 5260 tl_owner, | 5310 tl_owner, |
| 5261 metadata_pos); | 5311 metadata_pos); |
| 5262 } | 5312 } |
| 5263 } | 5313 } |
| 5264 | 5314 |
| 5265 | 5315 |
| 5266 // Consumes exactly one right angle bracket. If the current token is a single | 5316 // Consumes exactly one right angle bracket. If the current token is |
| 5267 // bracket token, it is consumed normally. However, if it is a double or triple | 5317 // a single bracket token, it is consumed normally. However, if it is |
| 5268 // bracket, it is replaced by a single or double bracket token without | 5318 // a double bracket, it is replaced by a single bracket token without |
| 5269 // incrementing the token index. | 5319 // incrementing the token index. |
| 5270 void Parser::ConsumeRightAngleBracket() { | 5320 void Parser::ConsumeRightAngleBracket() { |
| 5271 if (token_kind_ == Token::kGT) { | 5321 if (token_kind_ == Token::kGT) { |
| 5272 ConsumeToken(); | 5322 ConsumeToken(); |
| 5273 } else if (token_kind_ == Token::kSHR) { | 5323 } else if (token_kind_ == Token::kSHR) { |
| 5274 token_kind_ = Token::kGT; | 5324 token_kind_ = Token::kGT; |
| 5275 } else { | 5325 } else { |
| 5276 UNREACHABLE(); | 5326 UNREACHABLE(); |
| 5277 } | 5327 } |
| 5278 } | 5328 } |
| 5279 | 5329 |
| 5280 | 5330 |
| 5281 bool Parser::IsPatchAnnotation(TokenPosition pos) { | 5331 bool Parser::IsPatchAnnotation(TokenPosition pos) { |
| 5282 if (pos == TokenPosition::kNoSource) { | 5332 if (pos == TokenPosition::kNoSource) { |
| 5283 return false; | 5333 return false; |
| 5284 } | 5334 } |
| 5285 TokenPosition saved_pos = TokenPos(); | 5335 TokenPosScope saved_pos(this); |
| 5286 SetPosition(pos); | 5336 SetPosition(pos); |
| 5287 ExpectToken(Token::kAT); | 5337 ExpectToken(Token::kAT); |
| 5288 bool is_patch = IsSymbol(Symbols::Patch()); | 5338 return IsSymbol(Symbols::Patch()); |
| 5289 SetPosition(saved_pos); | |
| 5290 return is_patch; | |
| 5291 } | 5339 } |
| 5292 | 5340 |
| 5293 | 5341 |
| 5294 TokenPosition Parser::SkipMetadata() { | 5342 TokenPosition Parser::SkipMetadata() { |
| 5295 if (CurrentToken() != Token::kAT) { | 5343 if (CurrentToken() != Token::kAT) { |
| 5296 return TokenPosition::kNoSource; | 5344 return TokenPosition::kNoSource; |
| 5297 } | 5345 } |
| 5298 TokenPosition metadata_pos = TokenPos(); | 5346 TokenPosition metadata_pos = TokenPos(); |
| 5299 while (CurrentToken() == Token::kAT) { | 5347 while (CurrentToken() == Token::kAT) { |
| 5300 ConsumeToken(); | 5348 ConsumeToken(); |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5638 metadata_pos = TokenPosition::kNoSource; | 5686 metadata_pos = TokenPosition::kNoSource; |
| 5639 } else if (CurrentToken() == Token::kEXTERNAL) { | 5687 } else if (CurrentToken() == Token::kEXTERNAL) { |
| 5640 ConsumeToken(); | 5688 ConsumeToken(); |
| 5641 is_external = true; | 5689 is_external = true; |
| 5642 } | 5690 } |
| 5643 if (CurrentToken() == Token::kVOID) { | 5691 if (CurrentToken() == Token::kVOID) { |
| 5644 ConsumeToken(); | 5692 ConsumeToken(); |
| 5645 result_type = Type::VoidType(); | 5693 result_type = Type::VoidType(); |
| 5646 } else { | 5694 } else { |
| 5647 // Parse optional type. | 5695 // Parse optional type. |
| 5648 if ((CurrentToken() == Token::kIDENT) && | 5696 if (IsFunctionReturnType()) { |
| 5649 (LookaheadToken(1) != Token::kLPAREN)) { | |
| 5650 result_type = ParseType(ClassFinalizer::kResolveTypeParameters); | 5697 result_type = ParseType(ClassFinalizer::kResolveTypeParameters); |
| 5651 } | 5698 } |
| 5652 } | 5699 } |
| 5653 const TokenPosition name_pos = TokenPos(); | 5700 const TokenPosition name_pos = TokenPos(); |
| 5654 const String& func_name = *ExpectIdentifier("function name expected"); | 5701 const String& func_name = *ExpectIdentifier("function name expected"); |
| 5655 | 5702 |
| 5656 bool found = library_.LookupLocalObject(func_name) != Object::null(); | 5703 bool found = library_.LookupLocalObject(func_name) != Object::null(); |
| 5657 if (found && !is_patch) { | 5704 if (found && !is_patch) { |
| 5658 ReportError(name_pos, "'%s' is already defined", func_name.ToCString()); | 5705 ReportError(name_pos, "'%s' is already defined", func_name.ToCString()); |
| 5659 } else if (!found && is_patch) { | 5706 } else if (!found && is_patch) { |
| 5660 ReportError(name_pos, "missing '%s' cannot be patched", | 5707 ReportError(name_pos, "missing '%s' cannot be patched", |
| 5661 func_name.ToCString()); | 5708 func_name.ToCString()); |
| 5662 } | 5709 } |
| 5663 String& accessor_name = String::Handle(Z, Field::GetterName(func_name)); | 5710 String& accessor_name = String::Handle(Z, Field::GetterName(func_name)); |
| 5664 if (library_.LookupLocalObject(accessor_name) != Object::null()) { | 5711 if (library_.LookupLocalObject(accessor_name) != Object::null()) { |
| 5665 ReportError(name_pos, "'%s' is already defined as getter", | 5712 ReportError(name_pos, "'%s' is already defined as getter", |
| 5666 func_name.ToCString()); | 5713 func_name.ToCString()); |
| 5667 } | 5714 } |
| 5668 // A setter named x= may co-exist with a function named x, thus we do | 5715 // A setter named x= may co-exist with a function named x, thus we do |
| 5669 // not need to check setters. | 5716 // not need to check setters. |
| 5670 | 5717 |
| 5718 if (CurrentToken() == Token::kLT) { | |
| 5719 // Type parameters of generic function. | |
| 5720 // TODO(hausner): handle type parameters. | |
| 5721 if (!FLAG_generic_method_syntax) { | |
| 5722 ReportError("generic functions not supported"); | |
| 5723 } | |
| 5724 TokenPosition type_arg_pos = TokenPos(); | |
| 5725 if (!TryParseTypeParameters()) { | |
| 5726 ReportError(type_arg_pos, "error in type parameters"); | |
| 5727 } | |
| 5728 } | |
| 5729 | |
| 5671 CheckToken(Token::kLPAREN); | 5730 CheckToken(Token::kLPAREN); |
| 5672 const TokenPosition function_pos = TokenPos(); | 5731 const TokenPosition function_pos = TokenPos(); |
| 5673 ParamList params; | 5732 ParamList params; |
| 5674 const bool allow_explicit_default_values = true; | 5733 const bool allow_explicit_default_values = true; |
| 5675 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); | 5734 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
| 5676 | 5735 |
| 5677 const TokenPosition modifier_pos = TokenPos(); | 5736 const TokenPosition modifier_pos = TokenPos(); |
| 5678 RawFunction::AsyncModifier func_modifier = ParseFunctionModifier(); | 5737 RawFunction::AsyncModifier func_modifier = ParseFunctionModifier(); |
| 5679 | 5738 |
| 5680 TokenPosition function_end_pos = function_pos; | 5739 TokenPosition function_end_pos = function_pos; |
| (...skipping 2072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7753 TRACE_PARSER("ParseFunctionStatement"); | 7812 TRACE_PARSER("ParseFunctionStatement"); |
| 7754 AbstractType& result_type = AbstractType::Handle(Z); | 7813 AbstractType& result_type = AbstractType::Handle(Z); |
| 7755 const String* variable_name = NULL; | 7814 const String* variable_name = NULL; |
| 7756 const String* function_name = NULL; | 7815 const String* function_name = NULL; |
| 7757 | 7816 |
| 7758 result_type = Type::DynamicType(); | 7817 result_type = Type::DynamicType(); |
| 7759 | 7818 |
| 7760 const TokenPosition function_pos = TokenPos(); | 7819 const TokenPosition function_pos = TokenPos(); |
| 7761 TokenPosition metadata_pos = TokenPosition::kNoSource; | 7820 TokenPosition metadata_pos = TokenPosition::kNoSource; |
| 7762 if (is_literal) { | 7821 if (is_literal) { |
| 7763 ASSERT(CurrentToken() == Token::kLPAREN); | 7822 ASSERT(CurrentToken() == Token::kLPAREN || CurrentToken() == Token::kLT); |
| 7764 function_name = &Symbols::AnonymousClosure(); | 7823 function_name = &Symbols::AnonymousClosure(); |
| 7765 } else { | 7824 } else { |
| 7766 metadata_pos = SkipMetadata(); | 7825 metadata_pos = SkipMetadata(); |
| 7767 if (CurrentToken() == Token::kVOID) { | 7826 if (CurrentToken() == Token::kVOID) { |
| 7768 ConsumeToken(); | 7827 ConsumeToken(); |
| 7769 result_type = Type::VoidType(); | 7828 result_type = Type::VoidType(); |
| 7770 } else if ((CurrentToken() == Token::kIDENT) && | 7829 } else if (IsFunctionReturnType()) { |
| 7771 (LookaheadToken(1) != Token::kLPAREN)) { | |
| 7772 result_type = ParseType(ClassFinalizer::kCanonicalize); | 7830 result_type = ParseType(ClassFinalizer::kCanonicalize); |
| 7773 } | 7831 } |
| 7774 const TokenPosition name_pos = TokenPos(); | 7832 const TokenPosition name_pos = TokenPos(); |
| 7775 variable_name = ExpectIdentifier("function name expected"); | 7833 variable_name = ExpectIdentifier("function name expected"); |
| 7776 function_name = variable_name; | 7834 function_name = variable_name; |
| 7777 | 7835 |
| 7778 // Check that the function name has not been referenced | 7836 // Check that the function name has not been referenced |
| 7779 // before this declaration. | 7837 // before this declaration. |
| 7780 ASSERT(current_block_ != NULL); | 7838 ASSERT(current_block_ != NULL); |
| 7781 const TokenPosition previous_pos = | 7839 const TokenPosition previous_pos = |
| 7782 current_block_->scope->PreviousReferencePos(*function_name); | 7840 current_block_->scope->PreviousReferencePos(*function_name); |
| 7783 if (previous_pos.IsReal()) { | 7841 if (previous_pos.IsReal()) { |
| 7784 ASSERT(!script_.IsNull()); | 7842 ASSERT(!script_.IsNull()); |
| 7785 intptr_t line_number; | 7843 intptr_t line_number; |
| 7786 script_.GetTokenLocation(previous_pos, &line_number, NULL); | 7844 script_.GetTokenLocation(previous_pos, &line_number, NULL); |
| 7787 ReportError(name_pos, | 7845 ReportError(name_pos, |
| 7788 "identifier '%s' previously used in line %" Pd "", | 7846 "identifier '%s' previously used in line %" Pd "", |
| 7789 function_name->ToCString(), | 7847 function_name->ToCString(), |
| 7790 line_number); | 7848 line_number); |
| 7791 } | 7849 } |
| 7792 } | 7850 } |
| 7851 | |
| 7852 if (CurrentToken() == Token::kLT) { | |
| 7853 if (!FLAG_generic_method_syntax) { | |
| 7854 ReportError("generic functions not supported"); | |
| 7855 } | |
| 7856 TokenPosition type_arg_pos = TokenPos(); | |
| 7857 // TODO(hausner): handle type parameters of generic function. | |
| 7858 if (!TryParseTypeParameters()) { | |
| 7859 ReportError(type_arg_pos, "error in type parameters"); | |
| 7860 } | |
| 7861 } | |
| 7862 | |
| 7793 CheckToken(Token::kLPAREN); | 7863 CheckToken(Token::kLPAREN); |
| 7794 | 7864 |
| 7795 // Check whether we have parsed this closure function before, in a previous | 7865 // Check whether we have parsed this closure function before, in a previous |
| 7796 // compilation. If so, reuse the function object, else create a new one | 7866 // compilation. If so, reuse the function object, else create a new one |
| 7797 // and register it in the current class. | 7867 // and register it in the current class. |
| 7798 // Note that we cannot share the same closure function between the closurized | 7868 // Note that we cannot share the same closure function between the closurized |
| 7799 // and non-closurized versions of the same parent function. | 7869 // and non-closurized versions of the same parent function. |
| 7800 Function& function = Function::ZoneHandle(Z); | 7870 Function& function = Function::ZoneHandle(Z); |
| 7801 bool found_func = true; | 7871 bool found_func = true; |
| 7802 // TODO(hausner): There could be two different closures at the given | 7872 // TODO(hausner): There could be two different closures at the given |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7956 AstNode* initialization = new(Z) StoreLocalNode( | 8026 AstNode* initialization = new(Z) StoreLocalNode( |
| 7957 function_pos, function_variable, closure); | 8027 function_pos, function_variable, closure); |
| 7958 return initialization; | 8028 return initialization; |
| 7959 } | 8029 } |
| 7960 } | 8030 } |
| 7961 | 8031 |
| 7962 | 8032 |
| 7963 // Returns true if the current and next tokens can be parsed as type | 8033 // Returns true if the current and next tokens can be parsed as type |
| 7964 // parameters. Current token position is not saved and restored. | 8034 // parameters. Current token position is not saved and restored. |
| 7965 bool Parser::TryParseTypeParameters() { | 8035 bool Parser::TryParseTypeParameters() { |
| 7966 if (CurrentToken() == Token::kLT) { | 8036 ASSERT(CurrentToken() == Token::kLT); |
| 7967 // We are possibly looking at type parameters. Find closing ">". | 8037 int nesting_level = 0; |
| 7968 int nesting_level = 0; | 8038 do { |
| 7969 do { | 8039 Token::Kind ct = CurrentToken(); |
| 7970 if (CurrentToken() == Token::kLT) { | 8040 if (ct == Token::kLT) { |
| 7971 nesting_level++; | 8041 nesting_level++; |
| 7972 } else if (CurrentToken() == Token::kGT) { | 8042 } else if (ct == Token::kGT) { |
| 7973 nesting_level--; | 8043 nesting_level--; |
| 7974 } else if (CurrentToken() == Token::kSHR) { | 8044 } else if (ct == Token::kSHR) { |
| 7975 nesting_level -= 2; | 8045 nesting_level -= 2; |
| 7976 } else if (CurrentToken() == Token::kIDENT) { | 8046 } else if (ct == Token::kIDENT) { |
| 7977 // Check to see if it is a qualified identifier. | 8047 // Check to see if it is a qualified identifier. |
| 7978 if (LookaheadToken(1) == Token::kPERIOD) { | 8048 if (LookaheadToken(1) == Token::kPERIOD) { |
| 7979 // Consume the identifier, the period will be consumed below. | 8049 // Consume the identifier, the period will be consumed below. |
| 7980 ConsumeToken(); | 8050 ConsumeToken(); |
| 7981 } | |
| 7982 } else if (CurrentToken() != Token::kCOMMA && | |
| 7983 CurrentToken() != Token::kEXTENDS) { | |
| 7984 // We are looking at something other than type parameters. | |
| 7985 return false; | |
| 7986 } | 8051 } |
| 7987 ConsumeToken(); | 8052 } else if ((ct != Token::kCOMMA) && |
| 7988 } while (nesting_level > 0); | 8053 (ct != Token::kEXTENDS) && |
| 7989 if (nesting_level < 0) { | 8054 (!FLAG_generic_method_syntax || (ct != Token::kSUPER))) { |
| 8055 // We are looking at something other than type parameters. | |
| 7990 return false; | 8056 return false; |
| 7991 } | 8057 } |
| 8058 ConsumeToken(); | |
| 8059 } while (nesting_level > 0); | |
| 8060 if (nesting_level < 0) { | |
| 8061 return false; | |
| 7992 } | 8062 } |
| 7993 return true; | 8063 return true; |
| 7994 } | 8064 } |
| 7995 | 8065 |
| 7996 | 8066 |
| 8067 // Returns true if the next tokens can be parsed as type parameters. | |
| 8068 bool Parser::IsTypeParameters() { | |
| 8069 if (CurrentToken() == Token::kLT) { | |
| 8070 TokenPosScope param_pos(this); | |
| 8071 if (!TryParseTypeParameters()) { | |
| 8072 return false; | |
| 8073 } | |
| 8074 return true; | |
| 8075 } | |
| 8076 return false; | |
| 8077 } | |
| 8078 | |
| 8079 | |
| 8080 // Returns true if the next tokens are [ typeParameters ] '('. | |
| 8081 bool Parser::IsParameterPart() { | |
| 8082 if (CurrentToken() == Token::kLPAREN) { | |
| 8083 return true; | |
| 8084 } | |
| 8085 if (CurrentToken() == Token::kLT) { | |
| 8086 TokenPosScope type_arg_pos(this); | |
| 8087 if (!TryParseTypeParameters()) { | |
| 8088 return false; | |
| 8089 } | |
| 8090 return CurrentToken() == Token::kLPAREN; | |
| 8091 } | |
| 8092 return false; | |
| 8093 } | |
| 8094 | |
| 8095 | |
| 8096 // Returns true if the current and next tokens can be parsed as type | |
| 8097 // arguments. Current token position is not saved and restored. | |
| 8098 bool Parser::TryParseTypeArguments() { | |
| 8099 ASSERT(CurrentToken() == Token::kLT); | |
| 8100 int nesting_level = 0; | |
| 8101 do { | |
| 8102 Token::Kind ct = CurrentToken(); | |
| 8103 if (ct == Token::kLT) { | |
| 8104 nesting_level++; | |
| 8105 } else if (ct == Token::kGT) { | |
| 8106 nesting_level--; | |
| 8107 } else if (ct == Token::kSHR) { | |
| 8108 nesting_level -= 2; | |
| 8109 } else if (ct == Token::kIDENT) { | |
| 8110 // Check to see if it is a qualified identifier. | |
| 8111 if (LookaheadToken(1) == Token::kPERIOD) { | |
| 8112 // Consume the identifier, the period will be consumed below. | |
| 8113 ConsumeToken(); | |
| 8114 } | |
| 8115 } else if (ct != Token::kCOMMA) { | |
| 8116 return false; | |
| 8117 } | |
| 8118 ConsumeToken(); | |
| 8119 } while (nesting_level > 0); | |
| 8120 if (nesting_level < 0) { | |
| 8121 return false; | |
| 8122 } | |
| 8123 return true; | |
| 8124 } | |
| 8125 | |
| 8126 | |
| 8127 // Returns true if the next tokens are [ typeArguments ] '('. | |
| 8128 bool Parser::IsArgumentPart() { | |
| 8129 if (CurrentToken() == Token::kLPAREN) { | |
| 8130 return true; | |
| 8131 } | |
| 8132 if (CurrentToken() == Token::kLT) { | |
| 8133 TokenPosScope type_arg_pos(this); | |
| 8134 if (!TryParseTypeArguments()) { | |
| 8135 return false; | |
| 8136 } | |
| 8137 return CurrentToken() == Token::kLPAREN; | |
| 8138 } | |
| 8139 return false; | |
| 8140 } | |
| 8141 | |
| 8142 | |
| 7997 bool Parser::IsSimpleLiteral(const AbstractType& type, Instance* value) { | 8143 bool Parser::IsSimpleLiteral(const AbstractType& type, Instance* value) { |
| 7998 // Assigning null never causes a type error. | 8144 // Assigning null never causes a type error. |
| 7999 if (CurrentToken() == Token::kNULL) { | 8145 if (CurrentToken() == Token::kNULL) { |
| 8000 *value = Instance::null(); | 8146 *value = Instance::null(); |
| 8001 return true; | 8147 return true; |
| 8002 } | 8148 } |
| 8003 // If the type of the const field is guaranteed to be instantiated once | 8149 // If the type of the const field is guaranteed to be instantiated once |
| 8004 // resolved at class finalization time, and if the type of the literal is one | 8150 // resolved at class finalization time, and if the type of the literal is one |
| 8005 // of int, double, String, or bool, then preset the field with the value and | 8151 // of int, double, String, or bool, then preset the field with the value and |
| 8006 // perform the type check (in checked mode only) at finalization time. | 8152 // perform the type check (in checked mode only) at finalization time. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8150 (CurrentToken() == Token::kASSIGN)) { | 8296 (CurrentToken() == Token::kASSIGN)) { |
| 8151 is_var_decl = true; | 8297 is_var_decl = true; |
| 8152 } | 8298 } |
| 8153 } | 8299 } |
| 8154 } | 8300 } |
| 8155 SetPosition(saved_pos); | 8301 SetPosition(saved_pos); |
| 8156 return is_var_decl; | 8302 return is_var_decl; |
| 8157 } | 8303 } |
| 8158 | 8304 |
| 8159 | 8305 |
| 8306 // Look ahead to see if the following tokens are a return type followed | |
| 8307 // by an identifier. | |
| 8308 bool Parser::IsFunctionReturnType() { | |
| 8309 TokenPosScope decl_pos(this); | |
| 8310 if (TryParseReturnType()) { | |
| 8311 if (IsIdentifier()) { | |
| 8312 // Return type followed by function name. | |
| 8313 return true; | |
| 8314 } | |
| 8315 } | |
| 8316 return false; | |
| 8317 } | |
| 8318 | |
| 8319 | |
| 8160 // Look ahead to detect whether the next tokens should be parsed as | 8320 // Look ahead to detect whether the next tokens should be parsed as |
| 8161 // a function declaration. Token position remains unchanged. | 8321 // a function declaration. Token position remains unchanged. |
| 8162 bool Parser::IsFunctionDeclaration() { | 8322 bool Parser::IsFunctionDeclaration() { |
| 8163 const TokenPosition saved_pos = TokenPos(); | |
| 8164 bool is_external = false; | 8323 bool is_external = false; |
| 8324 TokenPosScope decl_pos(this); | |
| 8165 SkipMetadata(); | 8325 SkipMetadata(); |
| 8166 if (is_top_level_ && (CurrentToken() == Token::kEXTERNAL)) { | 8326 if ((is_top_level_) && (CurrentToken() == Token::kEXTERNAL)) { |
| 8167 // Skip over 'external' for top-level function declarations. | 8327 // Skip over 'external' for top-level function declarations. |
| 8168 is_external = true; | 8328 is_external = true; |
| 8169 ConsumeToken(); | 8329 ConsumeToken(); |
| 8170 } | 8330 } |
| 8171 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { | 8331 const TokenPosition type_or_name_pos = TokenPos(); |
| 8172 // Possibly a function without explicit return type. | 8332 if (TryParseReturnType()) { |
| 8173 ConsumeToken(); // Consume function identifier. | |
| 8174 } else if (TryParseReturnType()) { | |
| 8175 if (!IsIdentifier()) { | 8333 if (!IsIdentifier()) { |
| 8176 SetPosition(saved_pos); | 8334 SetPosition(type_or_name_pos); |
| 8177 return false; | |
| 8178 } | 8335 } |
| 8179 ConsumeToken(); // Consume function identifier. | |
| 8180 } else { | 8336 } else { |
| 8181 SetPosition(saved_pos); | 8337 SetPosition(type_or_name_pos); |
| 8338 } | |
| 8339 // Check for function name followed by optional type parameters. | |
| 8340 if (!IsIdentifier()) { | |
| 8182 return false; | 8341 return false; |
| 8183 } | 8342 } |
| 8343 ConsumeToken(); | |
| 8344 if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) { | |
| 8345 return false; | |
| 8346 } | |
| 8347 | |
| 8348 // Optional type, function name and optinal type parameters are parsed. | |
| 8349 if (CurrentToken() != Token::kLPAREN) { | |
| 8350 return false; | |
| 8351 } | |
| 8352 | |
| 8184 // Check parameter list and the following token. | 8353 // Check parameter list and the following token. |
| 8185 if (CurrentToken() == Token::kLPAREN) { | 8354 SkipToMatchingParenthesis(); |
| 8186 SkipToMatchingParenthesis(); | 8355 if ((CurrentToken() == Token::kLBRACE) || |
| 8187 if ((CurrentToken() == Token::kLBRACE) || | 8356 (CurrentToken() == Token::kARROW) || |
| 8188 (CurrentToken() == Token::kARROW) || | 8357 (is_top_level_ && IsSymbol(Symbols::Native())) || |
| 8189 (is_top_level_ && IsSymbol(Symbols::Native())) || | 8358 is_external || |
| 8190 is_external || | 8359 IsSymbol(Symbols::Async()) || |
| 8191 IsSymbol(Symbols::Async()) || | 8360 IsSymbol(Symbols::Sync())) { |
| 8192 IsSymbol(Symbols::Sync())) { | 8361 return true; |
| 8193 SetPosition(saved_pos); | |
| 8194 return true; | |
| 8195 } | |
| 8196 } | 8362 } |
| 8197 SetPosition(saved_pos); | |
| 8198 return false; | 8363 return false; |
| 8199 } | 8364 } |
| 8200 | 8365 |
| 8201 | 8366 |
| 8202 bool Parser::IsTopLevelAccessor() { | 8367 bool Parser::IsTopLevelAccessor() { |
| 8203 const TokenPosition saved_pos = TokenPos(); | 8368 const TokenPosScope saved_pos(this); |
| 8204 if (CurrentToken() == Token::kEXTERNAL) { | 8369 if (CurrentToken() == Token::kEXTERNAL) { |
| 8205 ConsumeToken(); | 8370 ConsumeToken(); |
| 8206 } | 8371 } |
| 8207 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { | 8372 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { |
| 8208 SetPosition(saved_pos); | |
| 8209 return true; | 8373 return true; |
| 8210 } | 8374 } |
| 8211 if (TryParseReturnType()) { | 8375 if (TryParseReturnType()) { |
| 8212 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { | 8376 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { |
| 8213 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. | 8377 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. |
| 8214 SetPosition(saved_pos); | |
| 8215 return true; | 8378 return true; |
| 8216 } | 8379 } |
| 8217 } | 8380 } |
| 8218 } | 8381 } |
| 8219 SetPosition(saved_pos); | |
| 8220 return false; | 8382 return false; |
| 8221 } | 8383 } |
| 8222 | 8384 |
| 8223 | 8385 |
| 8224 bool Parser::IsFunctionLiteral() { | 8386 bool Parser::IsFunctionLiteral() { |
| 8225 if (CurrentToken() != Token::kLPAREN || !allow_function_literals_) { | 8387 if (!allow_function_literals_) { |
| 8226 return false; | 8388 return false; |
| 8227 } | 8389 } |
| 8228 const TokenPosition saved_pos = TokenPos(); | 8390 if ((CurrentToken() == Token::kLPAREN) || (CurrentToken() == Token::kLT)) { |
| 8229 bool is_function_literal = false; | 8391 TokenPosScope saved_pos(this); |
| 8230 SkipToMatchingParenthesis(); | 8392 if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) { |
| 8231 ParseFunctionModifier(); | 8393 return false; |
| 8232 if ((CurrentToken() == Token::kLBRACE) || | 8394 } |
| 8233 (CurrentToken() == Token::kARROW)) { | 8395 if (CurrentToken() != Token::kLPAREN) { |
| 8234 is_function_literal = true; | 8396 return false; |
| 8397 } | |
| 8398 SkipToMatchingParenthesis(); | |
| 8399 ParseFunctionModifier(); | |
| 8400 if ((CurrentToken() == Token::kLBRACE) || | |
| 8401 (CurrentToken() == Token::kARROW)) { | |
| 8402 return true; | |
| 8403 } | |
| 8235 } | 8404 } |
| 8236 SetPosition(saved_pos); | 8405 return false; |
| 8237 return is_function_literal; | |
| 8238 } | 8406 } |
| 8239 | 8407 |
| 8240 | 8408 |
| 8241 // Current token position is the token after the opening ( of the for | 8409 // Current token position is the token after the opening ( of the for |
| 8242 // statement. Returns true if we recognize a for ( .. in expr) | 8410 // statement. Returns true if we recognize a for ( .. in expr) |
| 8243 // statement. | 8411 // statement. |
| 8244 bool Parser::IsForInStatement() { | 8412 bool Parser::IsForInStatement() { |
| 8245 const TokenPosition saved_pos = TokenPos(); | 8413 const TokenPosScope saved_pos(this); |
| 8246 bool result = false; | |
| 8247 // Allow const modifier as well when recognizing a for-in statement | 8414 // Allow const modifier as well when recognizing a for-in statement |
| 8248 // pattern. We will get an error later if the loop variable is | 8415 // pattern. We will get an error later if the loop variable is |
| 8249 // declared with const. | 8416 // declared with const. |
| 8250 if (CurrentToken() == Token::kVAR || | 8417 if (CurrentToken() == Token::kVAR || |
| 8251 CurrentToken() == Token::kFINAL || | 8418 CurrentToken() == Token::kFINAL || |
| 8252 CurrentToken() == Token::kCONST) { | 8419 CurrentToken() == Token::kCONST) { |
| 8253 ConsumeToken(); | 8420 ConsumeToken(); |
| 8254 } | 8421 } |
| 8255 if (IsIdentifier()) { | 8422 if (IsIdentifier()) { |
| 8256 if (LookaheadToken(1) == Token::kIN) { | 8423 if (LookaheadToken(1) == Token::kIN) { |
| 8257 result = true; | 8424 return true; |
| 8258 } else if (TryParseOptionalType()) { | 8425 } else if (TryParseOptionalType()) { |
| 8259 if (IsIdentifier()) { | 8426 if (IsIdentifier()) { |
| 8260 ConsumeToken(); | 8427 ConsumeToken(); |
| 8261 } | 8428 } |
| 8262 result = (CurrentToken() == Token::kIN); | 8429 return CurrentToken() == Token::kIN; |
| 8263 } | 8430 } |
| 8264 } | 8431 } |
| 8265 SetPosition(saved_pos); | 8432 return false; |
| 8266 return result; | |
| 8267 } | 8433 } |
| 8268 | 8434 |
| 8269 | 8435 |
| 8270 static bool ContainsAbruptCompletingStatement(SequenceNode* seq); | 8436 static bool ContainsAbruptCompletingStatement(SequenceNode* seq); |
| 8271 | 8437 |
| 8272 static bool IsAbruptCompleting(AstNode* statement) { | 8438 static bool IsAbruptCompleting(AstNode* statement) { |
| 8273 return statement->IsReturnNode() || | 8439 return statement->IsReturnNode() || |
| 8274 statement->IsJumpNode() || | 8440 statement->IsJumpNode() || |
| 8275 statement->IsThrowNode() || | 8441 statement->IsThrowNode() || |
| 8276 (statement->IsSequenceNode() && | 8442 (statement->IsSequenceNode() && |
| (...skipping 3379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11656 left = new(Z) TypeNode(primary->token_pos(), type_parameter); | 11822 left = new(Z) TypeNode(primary->token_pos(), type_parameter); |
| 11657 } else { | 11823 } else { |
| 11658 // Super field access handled in ParseSuperFieldAccess(), | 11824 // Super field access handled in ParseSuperFieldAccess(), |
| 11659 // super calls handled in ParseSuperCall(). | 11825 // super calls handled in ParseSuperCall(). |
| 11660 ASSERT(!primary_node->IsSuper()); | 11826 ASSERT(!primary_node->IsSuper()); |
| 11661 left = LoadFieldIfUnresolved(left); | 11827 left = LoadFieldIfUnresolved(left); |
| 11662 } | 11828 } |
| 11663 } | 11829 } |
| 11664 const TokenPosition ident_pos = TokenPos(); | 11830 const TokenPosition ident_pos = TokenPos(); |
| 11665 String* ident = ExpectIdentifier("identifier expected"); | 11831 String* ident = ExpectIdentifier("identifier expected"); |
| 11666 if (CurrentToken() == Token::kLPAREN) { | 11832 if (IsArgumentPart()) { |
| 11667 // Identifier followed by a opening paren: method call. | 11833 // Identifier followed by optional type arguments and opening paren: |
| 11834 // method call. | |
| 11835 if (CurrentToken() == Token::kLT) { | |
| 11836 // Type arguments. | |
| 11837 if (!FLAG_generic_method_syntax) { | |
| 11838 ReportError("generic type arguments not supported."); | |
|
regis
2016/08/24 14:14:02
I would drop "generic".
Or maybe "type arguments o
| |
| 11839 } | |
| 11840 // TODO(hausner): handle type arguments. | |
| 11841 ParseTypeArguments(ClassFinalizer::kIgnore); | |
| 11842 } | |
| 11668 if (left->IsPrimaryNode() && | 11843 if (left->IsPrimaryNode() && |
| 11669 left->AsPrimaryNode()->primary().IsClass()) { | 11844 left->AsPrimaryNode()->primary().IsClass()) { |
| 11670 // Static method call prefixed with class name. | 11845 // Static method call prefixed with class name. |
| 11671 const Class& cls = Class::Cast(left->AsPrimaryNode()->primary()); | 11846 const Class& cls = Class::Cast(left->AsPrimaryNode()->primary()); |
| 11672 selector = ParseStaticCall(cls, *ident, ident_pos); | 11847 selector = ParseStaticCall(cls, *ident, ident_pos); |
| 11673 } else { | 11848 } else { |
| 11674 selector = ParseInstanceCall(left, *ident, ident_pos, is_conditional); | 11849 selector = ParseInstanceCall(left, *ident, ident_pos, is_conditional); |
| 11675 } | 11850 } |
| 11676 } else { | 11851 } else { |
| 11677 // Field access. | 11852 // Field access. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11749 TypeParameter::Cast(primary_node->primary()), | 11924 TypeParameter::Cast(primary_node->primary()), |
| 11750 ClassFinalizer::kCanonicalize); | 11925 ClassFinalizer::kCanonicalize); |
| 11751 ASSERT(!type_parameter.IsMalformed()); | 11926 ASSERT(!type_parameter.IsMalformed()); |
| 11752 array = new(Z) TypeNode(primary_pos, type_parameter); | 11927 array = new(Z) TypeNode(primary_pos, type_parameter); |
| 11753 } else { | 11928 } else { |
| 11754 UNREACHABLE(); // Internal parser error. | 11929 UNREACHABLE(); // Internal parser error. |
| 11755 } | 11930 } |
| 11756 } | 11931 } |
| 11757 selector = new(Z) LoadIndexedNode( | 11932 selector = new(Z) LoadIndexedNode( |
| 11758 bracket_pos, array, index, Class::ZoneHandle(Z)); | 11933 bracket_pos, array, index, Class::ZoneHandle(Z)); |
| 11759 } else if (CurrentToken() == Token::kLPAREN) { | 11934 } else if (IsArgumentPart()) { |
| 11935 if (CurrentToken() == Token::kLT) { | |
| 11936 // Type arguments. | |
| 11937 if (!FLAG_generic_method_syntax) { | |
| 11938 ReportError("generic type arguments not supported."); | |
|
regis
2016/08/24 14:14:02
ditto
| |
| 11939 } | |
| 11940 // TODO(hausner): handle type arguments. | |
| 11941 ParseTypeArguments(ClassFinalizer::kIgnore); | |
| 11942 } | |
| 11760 if (left->IsPrimaryNode()) { | 11943 if (left->IsPrimaryNode()) { |
| 11761 PrimaryNode* primary_node = left->AsPrimaryNode(); | 11944 PrimaryNode* primary_node = left->AsPrimaryNode(); |
| 11762 const TokenPosition primary_pos = primary_node->token_pos(); | 11945 const TokenPosition primary_pos = primary_node->token_pos(); |
| 11763 if (primary_node->primary().IsFunction()) { | 11946 if (primary_node->primary().IsFunction()) { |
| 11764 const Function& func = Function::Cast(primary_node->primary()); | 11947 const Function& func = Function::Cast(primary_node->primary()); |
| 11765 const String& func_name = String::ZoneHandle(Z, func.name()); | 11948 const String& func_name = String::ZoneHandle(Z, func.name()); |
| 11766 if (func.is_static()) { | 11949 if (func.is_static()) { |
| 11767 // Parse static function call. | 11950 // Parse static function call. |
| 11768 Class& cls = Class::Handle(Z, func.Owner()); | 11951 Class& cls = Class::Handle(Z, func.Owner()); |
| 11769 selector = ParseStaticCall(cls, func_name, primary_pos); | 11952 selector = ParseStaticCall(cls, func_name, primary_pos); |
| (...skipping 2600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14370 ConsumeToken(); | 14553 ConsumeToken(); |
| 14371 } else { | 14554 } else { |
| 14372 break; | 14555 break; |
| 14373 } | 14556 } |
| 14374 } | 14557 } |
| 14375 ExpectToken(Token::kRBRACE); | 14558 ExpectToken(Token::kRBRACE); |
| 14376 } | 14559 } |
| 14377 | 14560 |
| 14378 | 14561 |
| 14379 void Parser::SkipActualParameters() { | 14562 void Parser::SkipActualParameters() { |
| 14563 if (CurrentToken() == Token::kLT) { | |
| 14564 SkipTypeArguments(); | |
| 14565 } | |
| 14380 ExpectToken(Token::kLPAREN); | 14566 ExpectToken(Token::kLPAREN); |
| 14381 while (CurrentToken() != Token::kRPAREN) { | 14567 while (CurrentToken() != Token::kRPAREN) { |
| 14382 if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) { | 14568 if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) { |
| 14383 // Named actual parameter. | 14569 // Named actual parameter. |
| 14384 ConsumeToken(); | 14570 ConsumeToken(); |
| 14385 ConsumeToken(); | 14571 ConsumeToken(); |
| 14386 } | 14572 } |
| 14387 SkipNestedExpr(); | 14573 SkipNestedExpr(); |
| 14388 if (CurrentToken() == Token::kCOMMA) { | 14574 if (CurrentToken() == Token::kCOMMA) { |
| 14389 ConsumeToken(); | 14575 ConsumeToken(); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14537 ExpectIdentifier("identifier or [ expected after .."); | 14723 ExpectIdentifier("identifier or [ expected after .."); |
| 14538 } | 14724 } |
| 14539 } else if ((current_token == Token::kPERIOD) || | 14725 } else if ((current_token == Token::kPERIOD) || |
| 14540 (current_token == Token::kQM_PERIOD)) { | 14726 (current_token == Token::kQM_PERIOD)) { |
| 14541 ConsumeToken(); | 14727 ConsumeToken(); |
| 14542 ExpectIdentifier("identifier expected"); | 14728 ExpectIdentifier("identifier expected"); |
| 14543 } else if (current_token == Token::kLBRACK) { | 14729 } else if (current_token == Token::kLBRACK) { |
| 14544 ConsumeToken(); | 14730 ConsumeToken(); |
| 14545 SkipNestedExpr(); | 14731 SkipNestedExpr(); |
| 14546 ExpectToken(Token::kRBRACK); | 14732 ExpectToken(Token::kRBRACK); |
| 14547 } else if (current_token == Token::kLPAREN) { | 14733 } else if (IsArgumentPart()) { |
| 14548 SkipActualParameters(); | 14734 SkipActualParameters(); |
| 14549 } else { | 14735 } else { |
| 14550 break; | 14736 break; |
| 14551 } | 14737 } |
| 14552 } | 14738 } |
| 14553 } | 14739 } |
| 14554 | 14740 |
| 14555 void Parser::SkipPostfixExpr() { | 14741 void Parser::SkipPostfixExpr() { |
| 14556 SkipPrimary(); | 14742 SkipPrimary(); |
| 14557 if (CurrentToken() == Token::kHASH) { | 14743 if (CurrentToken() == Token::kHASH) { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14741 const ArgumentListNode& function_args, | 14927 const ArgumentListNode& function_args, |
| 14742 const LocalVariable* temp_for_last_arg, | 14928 const LocalVariable* temp_for_last_arg, |
| 14743 bool is_super_invocation) { | 14929 bool is_super_invocation) { |
| 14744 UNREACHABLE(); | 14930 UNREACHABLE(); |
| 14745 return NULL; | 14931 return NULL; |
| 14746 } | 14932 } |
| 14747 | 14933 |
| 14748 } // namespace dart | 14934 } // namespace dart |
| 14749 | 14935 |
| 14750 #endif // DART_PRECOMPILED_RUNTIME | 14936 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |