Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index ff6bd2728c929e865e90d137cf9040177b8b5e9f..183fb91e84d85ea6ee3e059bc4258461193d9a9d 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -114,6 +114,8 @@ class ParserBase : public Traits { |
} |
protected: |
+ friend class Traits::Type::Checkpoint; |
+ |
enum AllowEvalOrArgumentsAsIdentifier { |
kAllowEvalOrArguments, |
kDontAllowEvalOrArguments |
@@ -124,6 +126,8 @@ class ParserBase : public Traits { |
PARSE_EAGERLY |
}; |
+ class ParserCheckpoint; |
+ |
// --------------------------------------------------------------------------- |
// FunctionState and BlockState together implement the parser's scope stack. |
// The parser's current scope is in scope_. BlockState and FunctionState |
@@ -219,6 +223,39 @@ class ParserBase : public Traits { |
typename Traits::Type::Factory factory_; |
friend class ParserTraits; |
+ friend class ParserCheckpoint; |
+ }; |
+ |
+ // Annoyingly, arrow functions first parse as comma expressions, then when we |
+ // see the => we have to go back and reinterpret the arguments as being formal |
+ // parameters. To do so we need to reset some of the parser state back to |
+ // what it was before the arguments were first seen. |
+ class ParserCheckpoint : public Traits::Type::Checkpoint { |
+ public: |
+ ParserCheckpoint() : Traits::Type::Checkpoint() {} |
+ |
+ void Save(ParserBase* parser) { |
+ Traits::Type::Checkpoint::Save(parser); |
+ function_state_ = parser->function_state_; |
+ next_materialized_literal_index_ = |
+ function_state_->next_materialized_literal_index_; |
+ next_handler_index_ = function_state_->next_handler_index_; |
+ expected_property_count_ = function_state_->expected_property_count_; |
+ } |
+ |
+ void Restore() { |
+ Traits::Type::Checkpoint::Restore(); |
+ function_state_->next_materialized_literal_index_ = |
+ next_materialized_literal_index_; |
+ function_state_->next_handler_index_ = next_handler_index_; |
+ function_state_->expected_property_count_ = expected_property_count_; |
+ } |
+ |
+ private: |
+ FunctionState* function_state_; |
+ int next_materialized_literal_index_; |
+ int next_handler_index_; |
+ int expected_property_count_; |
}; |
class ParsingModeScope BASE_EMBEDDED { |
@@ -1021,6 +1058,15 @@ class PreParserFactory { |
}; |
+class PreParserCheckpoint BASE_EMBEDDED { |
+ public: |
+ PreParserCheckpoint() {} |
+ template <typename Parser> |
+ void Save(Parser* parser) {} |
+ void Restore() {} |
+}; |
+ |
+ |
class PreParser; |
class PreParserTraits { |
@@ -1033,6 +1079,7 @@ class PreParserTraits { |
// Used by FunctionState and BlockState. |
typedef PreParserScope Scope; |
typedef PreParserScope ScopePtr; |
+ typedef PreParserCheckpoint Checkpoint; |
// PreParser doesn't need to store generator variables. |
typedef void GeneratorVariable; |
@@ -2001,10 +2048,13 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
} |
if (fni_ != NULL) fni_->Enter(); |
+ ParserCheckpoint checkpoint; |
+ checkpoint.Save(this); |
rossberg
2014/08/05 13:51:31
Why the separate Save method instead of just
Pa
|
ExpressionT expression = |
this->ParseConditionalExpression(accept_IN, CHECK_OK); |
if (allow_arrow_functions() && peek() == Token::ARROW) { |
+ checkpoint.Restore(); |
expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos, |
expression, CHECK_OK); |
return expression; |