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