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

Unified Diff: src/parsing/preparser.h

Issue 1504833002: Split ParserBase into separate file (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/parsing/preparser.h
diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h
index 7a699670bbdf3b87d01cb465a02ded7cbfdda698..6b39bd987900b5f926792a7c82b78fb70a4f0dcc 100644
--- a/src/parsing/preparser.h
+++ b/src/parsing/preparser.h
@@ -11,6 +11,7 @@
#include "src/messages.h"
#include "src/parsing/expression-classifier.h"
#include "src/parsing/func-name-inferrer.h"
+#include "src/parsing/parser-base.h"
#include "src/parsing/scanner.h"
#include "src/parsing/token.h"
@@ -18,914 +19,6 @@ namespace v8 {
namespace internal {
-enum FunctionNameValidity {
- kFunctionNameIsStrictReserved,
- kSkipFunctionNameCheck,
- kFunctionNameValidityUnknown
-};
-
-
-struct FormalParametersBase {
- explicit FormalParametersBase(Scope* scope) : scope(scope) {}
- Scope* scope;
- bool has_rest = false;
- bool is_simple = true;
- int materialized_literals_count = 0;
- mutable int rest_array_literal_index = -1;
-};
-
-
-// Common base class shared between parser and pre-parser. Traits encapsulate
-// the differences between Parser and PreParser:
-
-// - Return types: For example, Parser functions return Expression* and
-// PreParser functions return PreParserExpression.
-
-// - Creating parse tree nodes: Parser generates an AST during the recursive
-// descent. PreParser doesn't create a tree. Instead, it passes around minimal
-// data objects (PreParserExpression, PreParserIdentifier etc.) which contain
-// just enough data for the upper layer functions. PreParserFactory is
-// responsible for creating these dummy objects. It provides a similar kind of
-// interface as AstNodeFactory, so ParserBase doesn't need to care which one is
-// used.
-
-// - Miscellaneous other tasks interleaved with the recursive descent. For
-// example, Parser keeps track of which function literals should be marked as
-// pretenured, and PreParser doesn't care.
-
-// The traits are expected to contain the following typedefs:
-// struct Traits {
-// // In particular...
-// struct Type {
-// // Used by FunctionState and BlockState.
-// typedef Scope;
-// typedef GeneratorVariable;
-// // Return types for traversing functions.
-// typedef Identifier;
-// typedef Expression;
-// typedef FunctionLiteral;
-// typedef ClassLiteral;
-// typedef ObjectLiteralProperty;
-// typedef Literal;
-// typedef ExpressionList;
-// typedef PropertyList;
-// typedef FormalParameter;
-// typedef FormalParameters;
-// // For constructing objects returned by the traversing functions.
-// typedef Factory;
-// };
-// // ...
-// };
-
-template <typename Traits>
-class ParserBase : public Traits {
- public:
- // Shorten type names defined by Traits.
- typedef typename Traits::Type::Expression ExpressionT;
- typedef typename Traits::Type::Identifier IdentifierT;
- typedef typename Traits::Type::FormalParameter FormalParameterT;
- typedef typename Traits::Type::FormalParameters FormalParametersT;
- typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
- typedef typename Traits::Type::Literal LiteralT;
- typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
- typedef typename Traits::Type::StatementList StatementListT;
-
- ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
- v8::Extension* extension, AstValueFactory* ast_value_factory,
- ParserRecorder* log, typename Traits::Type::Parser this_object)
- : Traits(this_object),
- parenthesized_function_(false),
- scope_(NULL),
- function_state_(NULL),
- extension_(extension),
- fni_(NULL),
- ast_value_factory_(ast_value_factory),
- log_(log),
- mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
- stack_limit_(stack_limit),
- zone_(zone),
- scanner_(scanner),
- stack_overflow_(false),
- allow_lazy_(false),
- allow_natives_(false),
- allow_harmony_sloppy_(false),
- allow_harmony_sloppy_function_(false),
- allow_harmony_sloppy_let_(false),
- allow_harmony_rest_parameters_(false),
- allow_harmony_default_parameters_(false),
- allow_harmony_destructuring_bind_(false),
- allow_harmony_destructuring_assignment_(false),
- allow_strong_mode_(false),
- allow_legacy_const_(true),
- allow_harmony_do_expressions_(false) {}
-
-#define ALLOW_ACCESSORS(name) \
- bool allow_##name() const { return allow_##name##_; } \
- void set_allow_##name(bool allow) { allow_##name##_ = allow; }
-
- ALLOW_ACCESSORS(lazy);
- ALLOW_ACCESSORS(natives);
- ALLOW_ACCESSORS(harmony_sloppy);
- ALLOW_ACCESSORS(harmony_sloppy_function);
- ALLOW_ACCESSORS(harmony_sloppy_let);
- ALLOW_ACCESSORS(harmony_rest_parameters);
- ALLOW_ACCESSORS(harmony_default_parameters);
- ALLOW_ACCESSORS(harmony_destructuring_bind);
- ALLOW_ACCESSORS(harmony_destructuring_assignment);
- ALLOW_ACCESSORS(strong_mode);
- ALLOW_ACCESSORS(legacy_const);
- ALLOW_ACCESSORS(harmony_do_expressions);
-#undef ALLOW_ACCESSORS
-
- uintptr_t stack_limit() const { return stack_limit_; }
-
- protected:
- enum AllowRestrictedIdentifiers {
- kAllowRestrictedIdentifiers,
- kDontAllowRestrictedIdentifiers
- };
-
- enum Mode {
- PARSE_LAZILY,
- PARSE_EAGERLY
- };
-
- enum VariableDeclarationContext {
- kStatementListItem,
- kStatement,
- kForStatement
- };
-
- class Checkpoint;
- class ObjectLiteralCheckerBase;
-
- // ---------------------------------------------------------------------------
- // FunctionState and BlockState together implement the parser's scope stack.
- // The parser's current scope is in scope_. BlockState and FunctionState
- // constructors push on the scope stack and the destructors pop. They are also
- // used to hold the parser's per-function and per-block state.
- class BlockState BASE_EMBEDDED {
- public:
- BlockState(Scope** scope_stack, Scope* scope)
- : scope_stack_(scope_stack), outer_scope_(*scope_stack) {
- *scope_stack_ = scope;
- }
- ~BlockState() { *scope_stack_ = outer_scope_; }
-
- private:
- Scope** scope_stack_;
- Scope* outer_scope_;
- };
-
- struct DestructuringAssignment {
- public:
- DestructuringAssignment(ExpressionT expression, Scope* scope)
- : assignment(expression), scope(scope) {}
-
- ExpressionT assignment;
- Scope* scope;
- };
-
- class FunctionState BASE_EMBEDDED {
- public:
- FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
- Scope* scope, FunctionKind kind,
- typename Traits::Type::Factory* factory);
- ~FunctionState();
-
- int NextMaterializedLiteralIndex() {
- return next_materialized_literal_index_++;
- }
- int materialized_literal_count() {
- return next_materialized_literal_index_;
- }
-
- void SkipMaterializedLiterals(int count) {
- next_materialized_literal_index_ += count;
- }
-
- void AddProperty() { expected_property_count_++; }
- int expected_property_count() { return expected_property_count_; }
-
- Scanner::Location this_location() const { return this_location_; }
- Scanner::Location super_location() const { return super_location_; }
- Scanner::Location return_location() const { return return_location_; }
- void set_this_location(Scanner::Location location) {
- this_location_ = location;
- }
- void set_super_location(Scanner::Location location) {
- super_location_ = location;
- }
- void set_return_location(Scanner::Location location) {
- return_location_ = location;
- }
-
- bool is_generator() const { return IsGeneratorFunction(kind_); }
-
- FunctionKind kind() const { return kind_; }
- FunctionState* outer() const { return outer_function_state_; }
-
- void set_generator_object_variable(
- typename Traits::Type::GeneratorVariable* variable) {
- DCHECK(variable != NULL);
- DCHECK(is_generator());
- generator_object_variable_ = variable;
- }
- typename Traits::Type::GeneratorVariable* generator_object_variable()
- const {
- return generator_object_variable_;
- }
-
- typename Traits::Type::Factory* factory() { return factory_; }
-
- const List<DestructuringAssignment>& destructuring_assignments_to_rewrite()
- const {
- return destructuring_assignments_to_rewrite_;
- }
-
- void AddDestructuringAssignment(DestructuringAssignment pair) {
- destructuring_assignments_to_rewrite_.Add(pair);
- }
-
- private:
- // Used to assign an index to each literal that needs materialization in
- // the function. Includes regexp literals, and boilerplate for object and
- // array literals.
- int next_materialized_literal_index_;
-
- // Properties count estimation.
- int expected_property_count_;
-
- // Location of most recent use of 'this' (invalid if none).
- Scanner::Location this_location_;
-
- // Location of most recent 'return' statement (invalid if none).
- Scanner::Location return_location_;
-
- // Location of call to the "super" constructor (invalid if none).
- Scanner::Location super_location_;
-
- FunctionKind kind_;
- // For generators, this variable may hold the generator object. It variable
- // is used by yield expressions and return statements. It is not necessary
- // for generator functions to have this variable set.
- Variable* generator_object_variable_;
-
- FunctionState** function_state_stack_;
- FunctionState* outer_function_state_;
- Scope** scope_stack_;
- Scope* outer_scope_;
-
- List<DestructuringAssignment> destructuring_assignments_to_rewrite_;
-
- void RewriteDestructuringAssignments();
-
- typename Traits::Type::Factory* factory_;
-
- friend class ParserTraits;
- friend class Checkpoint;
- };
-
- // 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 Checkpoint BASE_EMBEDDED {
- public:
- explicit Checkpoint(ParserBase* parser) {
- function_state_ = parser->function_state_;
- next_materialized_literal_index_ =
- function_state_->next_materialized_literal_index_;
- expected_property_count_ = function_state_->expected_property_count_;
- }
-
- void Restore(int* materialized_literal_index_delta) {
- *materialized_literal_index_delta =
- function_state_->next_materialized_literal_index_ -
- next_materialized_literal_index_;
- function_state_->next_materialized_literal_index_ =
- next_materialized_literal_index_;
- function_state_->expected_property_count_ = expected_property_count_;
- }
-
- private:
- FunctionState* function_state_;
- int next_materialized_literal_index_;
- int expected_property_count_;
- };
-
- class ParsingModeScope BASE_EMBEDDED {
- public:
- ParsingModeScope(ParserBase* parser, Mode mode)
- : parser_(parser),
- old_mode_(parser->mode()) {
- parser_->mode_ = mode;
- }
- ~ParsingModeScope() {
- parser_->mode_ = old_mode_;
- }
-
- private:
- ParserBase* parser_;
- Mode old_mode_;
- };
-
- Scope* NewScope(Scope* parent, ScopeType scope_type) {
- // Must always pass the function kind for FUNCTION_SCOPE.
- DCHECK(scope_type != FUNCTION_SCOPE);
- return NewScope(parent, scope_type, kNormalFunction);
- }
-
- Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) {
- DCHECK(ast_value_factory());
- DCHECK(scope_type != MODULE_SCOPE || FLAG_harmony_modules);
- Scope* result = new (zone())
- Scope(zone(), parent, scope_type, ast_value_factory(), kind);
- result->Initialize();
- return result;
- }
-
- Scanner* scanner() const { return scanner_; }
- AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
- int position() { return scanner_->location().beg_pos; }
- int peek_position() { return scanner_->peek_location().beg_pos; }
- bool stack_overflow() const { return stack_overflow_; }
- void set_stack_overflow() { stack_overflow_ = true; }
- Mode mode() const { return mode_; }
- Zone* zone() const { return zone_; }
-
- INLINE(Token::Value peek()) {
- if (stack_overflow_) return Token::ILLEGAL;
- return scanner()->peek();
- }
-
- INLINE(Token::Value PeekAhead()) {
- if (stack_overflow_) return Token::ILLEGAL;
- return scanner()->PeekAhead();
- }
-
- INLINE(Token::Value Next()) {
- if (stack_overflow_) return Token::ILLEGAL;
- {
- if (GetCurrentStackPosition() < stack_limit_) {
- // Any further calls to Next or peek will return the illegal token.
- // The current call must return the next token, which might already
- // have been peek'ed.
- stack_overflow_ = true;
- }
- }
- return scanner()->Next();
- }
-
- void Consume(Token::Value token) {
- Token::Value next = Next();
- USE(next);
- USE(token);
- DCHECK(next == token);
- }
-
- bool Check(Token::Value token) {
- Token::Value next = peek();
- if (next == token) {
- Consume(next);
- return true;
- }
- return false;
- }
-
- void Expect(Token::Value token, bool* ok) {
- Token::Value next = Next();
- if (next != token) {
- ReportUnexpectedToken(next);
- *ok = false;
- }
- }
-
- void ExpectSemicolon(bool* ok) {
- // Check for automatic semicolon insertion according to
- // the rules given in ECMA-262, section 7.9, page 21.
- Token::Value tok = peek();
- if (tok == Token::SEMICOLON) {
- Next();
- return;
- }
- if (scanner()->HasAnyLineTerminatorBeforeNext() ||
- tok == Token::RBRACE ||
- tok == Token::EOS) {
- return;
- }
- Expect(Token::SEMICOLON, ok);
- }
-
- bool peek_any_identifier() {
- Token::Value next = peek();
- return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD ||
- next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
- next == Token::STATIC || next == Token::YIELD;
- }
-
- bool CheckContextualKeyword(Vector<const char> keyword) {
- if (PeekContextualKeyword(keyword)) {
- Consume(Token::IDENTIFIER);
- return true;
- }
- return false;
- }
-
- bool PeekContextualKeyword(Vector<const char> keyword) {
- return peek() == Token::IDENTIFIER &&
- scanner()->is_next_contextual_keyword(keyword);
- }
-
- void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
- Expect(Token::IDENTIFIER, ok);
- if (!*ok) return;
- if (!scanner()->is_literal_contextual_keyword(keyword)) {
- ReportUnexpectedToken(scanner()->current_token());
- *ok = false;
- }
- }
-
- bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) {
- if (Check(Token::IN)) {
- if (is_strong(language_mode())) {
- ReportMessageAt(scanner()->location(), MessageTemplate::kStrongForIn);
- *ok = false;
- } else {
- *visit_mode = ForEachStatement::ENUMERATE;
- }
- return true;
- } else if (CheckContextualKeyword(CStrVector("of"))) {
- *visit_mode = ForEachStatement::ITERATE;
- return true;
- }
- return false;
- }
-
- // Checks whether an octal literal was last seen between beg_pos and end_pos.
- // If so, reports an error. Only called for strict mode and template strings.
- void CheckOctalLiteral(int beg_pos, int end_pos,
- MessageTemplate::Template message, bool* ok) {
- Scanner::Location octal = scanner()->octal_position();
- if (octal.IsValid() && beg_pos <= octal.beg_pos &&
- octal.end_pos <= end_pos) {
- ReportMessageAt(octal, message);
- scanner()->clear_octal_position();
- *ok = false;
- }
- }
-
- inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) {
- CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral,
- ok);
- }
-
- inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) {
- CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral,
- ok);
- }
-
- void CheckDestructuringElement(ExpressionT element,
- ExpressionClassifier* classifier, int beg_pos,
- int end_pos);
-
- // Checking the name of a function literal. This has to be done after parsing
- // the function, since the function can declare itself strict.
- void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name,
- FunctionNameValidity function_name_validity,
- const Scanner::Location& function_name_loc, bool* ok) {
- if (function_name_validity == kSkipFunctionNameCheck) return;
- // The function name needs to be checked in strict mode.
- if (is_sloppy(language_mode)) return;
-
- if (this->IsEvalOrArguments(function_name)) {
- Traits::ReportMessageAt(function_name_loc,
- MessageTemplate::kStrictEvalArguments);
- *ok = false;
- return;
- }
- if (function_name_validity == kFunctionNameIsStrictReserved) {
- Traits::ReportMessageAt(function_name_loc,
- MessageTemplate::kUnexpectedStrictReserved);
- *ok = false;
- return;
- }
- if (is_strong(language_mode) && this->IsUndefined(function_name)) {
- Traits::ReportMessageAt(function_name_loc,
- MessageTemplate::kStrongUndefined);
- *ok = false;
- return;
- }
- }
-
- // Determine precedence of given token.
- static int Precedence(Token::Value token, bool accept_IN) {
- if (token == Token::IN && !accept_IN)
- return 0; // 0 precedence will terminate binary expression parsing
- return Token::Precedence(token);
- }
-
- typename Traits::Type::Factory* factory() {
- return function_state_->factory();
- }
-
- LanguageMode language_mode() { return scope_->language_mode(); }
- bool is_generator() const { return function_state_->is_generator(); }
-
- bool allow_const() {
- return is_strict(language_mode()) || allow_harmony_sloppy() ||
- allow_legacy_const();
- }
-
- bool allow_let() {
- return is_strict(language_mode()) || allow_harmony_sloppy_let();
- }
-
- // Report syntax errors.
- void ReportMessage(MessageTemplate::Template message, const char* arg = NULL,
- ParseErrorType error_type = kSyntaxError) {
- Scanner::Location source_location = scanner()->location();
- Traits::ReportMessageAt(source_location, message, arg, error_type);
- }
-
- void ReportMessageAt(Scanner::Location location,
- MessageTemplate::Template message,
- ParseErrorType error_type = kSyntaxError) {
- Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0),
- error_type);
- }
-
- void GetUnexpectedTokenMessage(
- Token::Value token, MessageTemplate::Template* message, const char** arg,
- MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken);
-
- void ReportUnexpectedToken(Token::Value token);
- void ReportUnexpectedTokenAt(
- Scanner::Location location, Token::Value token,
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken);
-
-
- void ReportClassifierError(const ExpressionClassifier::Error& error) {
- Traits::ReportMessageAt(error.location, error.message, error.arg,
- error.type);
- }
-
- void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) {
- if (!classifier->is_valid_expression() ||
- classifier->has_cover_initialized_name()) {
- const Scanner::Location& a = classifier->expression_error().location;
- const Scanner::Location& b =
- classifier->cover_initialized_name_error().location;
- if (a.beg_pos < 0 || (b.beg_pos >= 0 && a.beg_pos > b.beg_pos)) {
- ReportClassifierError(classifier->cover_initialized_name_error());
- } else {
- ReportClassifierError(classifier->expression_error());
- }
- *ok = false;
- }
- }
-
- void ValidateFormalParameterInitializer(
- const ExpressionClassifier* classifier, bool* ok) {
- if (!classifier->is_valid_formal_parameter_initializer()) {
- ReportClassifierError(classifier->formal_parameter_initializer_error());
- *ok = false;
- }
- }
-
- void ValidateBindingPattern(const ExpressionClassifier* classifier,
- bool* ok) {
- if (!classifier->is_valid_binding_pattern()) {
- ReportClassifierError(classifier->binding_pattern_error());
- *ok = false;
- }
- }
-
- void ValidateAssignmentPattern(const ExpressionClassifier* classifier,
- bool* ok) {
- if (!classifier->is_valid_assignment_pattern()) {
- ReportClassifierError(classifier->assignment_pattern_error());
- *ok = false;
- }
- }
-
- void ValidateFormalParameters(const ExpressionClassifier* classifier,
- LanguageMode language_mode,
- bool allow_duplicates, bool* ok) {
- if (!allow_duplicates &&
- !classifier->is_valid_formal_parameter_list_without_duplicates()) {
- ReportClassifierError(classifier->duplicate_formal_parameter_error());
- *ok = false;
- } else if (is_strict(language_mode) &&
- !classifier->is_valid_strict_mode_formal_parameters()) {
- ReportClassifierError(classifier->strict_mode_formal_parameter_error());
- *ok = false;
- } else if (is_strong(language_mode) &&
- !classifier->is_valid_strong_mode_formal_parameters()) {
- ReportClassifierError(classifier->strong_mode_formal_parameter_error());
- *ok = false;
- }
- }
-
- void ValidateArrowFormalParameters(const ExpressionClassifier* classifier,
- ExpressionT expr,
- bool parenthesized_formals, bool* ok) {
- if (classifier->is_valid_binding_pattern()) {
- // A simple arrow formal parameter: IDENTIFIER => BODY.
- if (!this->IsIdentifier(expr)) {
- Traits::ReportMessageAt(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(scanner()->current_token()));
- *ok = false;
- }
- } else if (!classifier->is_valid_arrow_formal_parameters()) {
- // If after parsing the expr, we see an error but the expression is
- // neither a valid binding pattern nor a valid parenthesized formal
- // parameter list, show the "arrow formal parameters" error if the formals
- // started with a parenthesis, and the binding pattern error otherwise.
- const ExpressionClassifier::Error& error =
- parenthesized_formals ? classifier->arrow_formal_parameters_error()
- : classifier->binding_pattern_error();
- ReportClassifierError(error);
- *ok = false;
- }
- }
-
- void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) {
- if (!classifier->is_valid_let_pattern()) {
- ReportClassifierError(classifier->let_pattern_error());
- *ok = false;
- }
- }
-
- void ExpressionUnexpectedToken(ExpressionClassifier* classifier) {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordExpressionError(scanner()->peek_location(), message, arg);
- }
-
- void BindingPatternUnexpectedToken(ExpressionClassifier* classifier) {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordBindingPatternError(scanner()->peek_location(), message,
- arg);
- }
-
- void ArrowFormalParametersUnexpectedToken(ExpressionClassifier* classifier) {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordArrowFormalParametersError(scanner()->peek_location(),
- message, arg);
- }
-
- void FormalParameterInitializerUnexpectedToken(
- ExpressionClassifier* classifier) {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- GetUnexpectedTokenMessage(peek(), &message, &arg);
- classifier->RecordFormalParameterInitializerError(
- scanner()->peek_location(), message, arg);
- }
-
- // Recursive descent functions:
-
- // Parses an identifier that is valid for the current scope, in particular it
- // fails on strict mode future reserved keywords in a strict scope. If
- // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
- // "arguments" as identifier even in strict mode (this is needed in cases like
- // "var foo = eval;").
- IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok);
- IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
- bool* ok);
- // Parses an identifier or a strict mode future reserved word, and indicate
- // whether it is strict mode future reserved. Allows passing in is_generator
- // for the case of parsing the identifier in a function expression, where the
- // relevant "is_generator" bit is of the function being parsed, not the
- // containing
- // function.
- IdentifierT ParseIdentifierOrStrictReservedWord(bool is_generator,
- bool* is_strict_reserved,
- bool* ok);
- IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
- bool* ok) {
- return ParseIdentifierOrStrictReservedWord(this->is_generator(),
- is_strict_reserved, ok);
- }
-
- IdentifierT ParseIdentifierName(bool* ok);
- // Parses an identifier and determines whether or not it is 'get' or 'set'.
- IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set,
- bool* ok);
-
-
- ExpressionT ParseRegExpLiteral(bool seen_equal,
- ExpressionClassifier* classifier, bool* ok);
-
- ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier,
- bool* ok);
- ExpressionT ParseExpression(bool accept_IN, bool* ok);
- ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier,
- bool* ok);
- ExpressionT ParseExpression(bool accept_IN, int flags,
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set,
- bool* is_static, bool* is_computed_name,
- bool* is_identifier, bool* is_escaped_keyword,
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok);
- ObjectLiteralPropertyT ParsePropertyDefinition(
- ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
- bool is_static, bool* is_computed_name, bool* has_seen_constructor,
- ExpressionClassifier* classifier, bool* ok);
- typename Traits::Type::ExpressionList ParseArguments(
- Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
- bool* ok);
-
- enum AssignmentExpressionFlags {
- kIsLeftHandSide = 0,
- kIsRightHandSide = 1 << 0,
- kIsPatternElement = 1 << 1,
- kIsPossibleArrowFormals = 1 << 2
- };
-
- ExpressionT ParseAssignmentExpression(bool accept_IN, int flags,
- ExpressionClassifier* classifier,
- bool* ok);
- ExpressionT ParseAssignmentExpression(bool accept_IN,
- ExpressionClassifier* classifier,
- bool* ok) {
- return ParseAssignmentExpression(accept_IN, kIsLeftHandSide, classifier,
- ok);
- }
- ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseConditionalExpression(bool accept_IN,
- ExpressionClassifier* classifier,
- bool* ok);
- ExpressionT ParseBinaryExpression(int prec, bool accept_IN,
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParsePostfixExpression(ExpressionClassifier* classifier,
- bool* ok);
- ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier,
- bool* ok);
- ExpressionT ParseMemberWithNewPrefixesExpression(
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseMemberExpressionContinuation(
- ExpressionT expression, ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
- const FormalParametersT& parameters,
- const ExpressionClassifier& classifier,
- bool* ok);
- ExpressionT ParseTemplateLiteral(ExpressionT tag, int start,
- ExpressionClassifier* classifier, bool* ok);
- void AddTemplateExpression(ExpressionT);
- ExpressionT ParseSuperExpression(bool is_new,
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseNewTargetExpression(bool* ok);
- ExpressionT ParseStrongInitializationExpression(
- ExpressionClassifier* classifier, bool* ok);
- ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier,
- bool* ok);
-
- void ParseFormalParameter(FormalParametersT* parameters,
- ExpressionClassifier* classifier, bool* ok);
- void ParseFormalParameterList(FormalParametersT* parameters,
- ExpressionClassifier* classifier, bool* ok);
- void CheckArityRestrictions(
- int param_count, FunctionLiteral::ArityRestriction arity_restriction,
- bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok);
-
- bool IsNextLetKeyword();
-
- // Checks if the expression is a valid reference expression (e.g., on the
- // left-hand side of assignments). Although ruled out by ECMA as early errors,
- // we allow calls for web compatibility and rewrite them to a runtime throw.
- ExpressionT CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, bool* ok);
- ExpressionT ClassifyAndRewriteReferenceExpression(
- ExpressionClassifier* classifier, ExpressionT expression, int beg_pos,
- int end_pos, MessageTemplate::Template message,
- ParseErrorType type = kSyntaxError);
- ExpressionT CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, ParseErrorType type, bool* ok);
-
- bool IsValidReferenceExpression(ExpressionT expression);
-
- bool IsAssignableIdentifier(ExpressionT expression) {
- if (!Traits::IsIdentifier(expression)) return false;
- if (is_strict(language_mode()) &&
- Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) {
- return false;
- }
- if (is_strong(language_mode()) &&
- Traits::IsUndefined(Traits::AsIdentifier(expression))) {
- return false;
- }
- return true;
- }
-
- // Used to validate property names in object literals and class literals
- enum PropertyKind {
- kAccessorProperty,
- kValueProperty,
- kMethodProperty
- };
-
- class ObjectLiteralCheckerBase {
- public:
- explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
-
- virtual void CheckProperty(Token::Value property, PropertyKind type,
- bool is_static, bool is_generator, bool* ok) = 0;
-
- virtual ~ObjectLiteralCheckerBase() {}
-
- protected:
- ParserBase* parser() const { return parser_; }
- Scanner* scanner() const { return parser_->scanner(); }
-
- private:
- ParserBase* parser_;
- };
-
- // Validation per ES6 object literals.
- class ObjectLiteralChecker : public ObjectLiteralCheckerBase {
- public:
- explicit ObjectLiteralChecker(ParserBase* parser)
- : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
-
- void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
- bool is_generator, bool* ok) override;
-
- private:
- bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
-
- bool has_seen_proto_;
- };
-
- // Validation per ES6 class literals.
- class ClassLiteralChecker : public ObjectLiteralCheckerBase {
- public:
- explicit ClassLiteralChecker(ParserBase* parser)
- : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
-
- void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
- bool is_generator, bool* ok) override;
-
- private:
- bool IsConstructor() {
- return this->scanner()->LiteralMatches("constructor", 11);
- }
- bool IsPrototype() {
- return this->scanner()->LiteralMatches("prototype", 9);
- }
-
- bool has_seen_constructor_;
- };
-
- // If true, the next (and immediately following) function literal is
- // preceded by a parenthesis.
- // Heuristically that means that the function will be called immediately,
- // so never lazily compile it.
- bool parenthesized_function_;
-
- Scope* scope_; // Scope stack.
- FunctionState* function_state_; // Function state stack.
- v8::Extension* extension_;
- FuncNameInferrer* fni_;
- AstValueFactory* ast_value_factory_; // Not owned.
- ParserRecorder* log_;
- Mode mode_;
- uintptr_t stack_limit_;
-
- private:
- Zone* zone_;
-
- Scanner* scanner_;
- bool stack_overflow_;
-
- bool allow_lazy_;
- bool allow_natives_;
- bool allow_harmony_sloppy_;
- bool allow_harmony_sloppy_function_;
- bool allow_harmony_sloppy_let_;
- bool allow_harmony_rest_parameters_;
- bool allow_harmony_default_parameters_;
- bool allow_harmony_destructuring_bind_;
- bool allow_harmony_destructuring_assignment_;
- bool allow_strong_mode_;
- bool allow_legacy_const_;
- bool allow_harmony_do_expressions_;
-};
-
-
class PreParserIdentifier {
public:
PreParserIdentifier() : type_(kUnknownIdentifier) {}
@@ -2056,2436 +1149,6 @@ PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
kind, function_type, ok);
}
-
-template <class Traits>
-ParserBase<Traits>::FunctionState::FunctionState(
- FunctionState** function_state_stack, Scope** scope_stack, Scope* scope,
- FunctionKind kind, typename Traits::Type::Factory* factory)
- : next_materialized_literal_index_(0),
- expected_property_count_(0),
- this_location_(Scanner::Location::invalid()),
- return_location_(Scanner::Location::invalid()),
- super_location_(Scanner::Location::invalid()),
- kind_(kind),
- generator_object_variable_(NULL),
- function_state_stack_(function_state_stack),
- outer_function_state_(*function_state_stack),
- scope_stack_(scope_stack),
- outer_scope_(*scope_stack),
- factory_(factory) {
- *scope_stack_ = scope;
- *function_state_stack = this;
-}
-
-
-template <class Traits>
-ParserBase<Traits>::FunctionState::~FunctionState() {
- *scope_stack_ = outer_scope_;
- *function_state_stack_ = outer_function_state_;
-}
-
-
-template <class Traits>
-void ParserBase<Traits>::GetUnexpectedTokenMessage(
- Token::Value token, MessageTemplate::Template* message, const char** arg,
- MessageTemplate::Template default_) {
- // Four of the tokens are treated specially
- switch (token) {
- case Token::EOS:
- *message = MessageTemplate::kUnexpectedEOS;
- *arg = nullptr;
- break;
- case Token::SMI:
- case Token::NUMBER:
- *message = MessageTemplate::kUnexpectedTokenNumber;
- *arg = nullptr;
- break;
- case Token::STRING:
- *message = MessageTemplate::kUnexpectedTokenString;
- *arg = nullptr;
- break;
- case Token::IDENTIFIER:
- *message = MessageTemplate::kUnexpectedTokenIdentifier;
- *arg = nullptr;
- break;
- case Token::FUTURE_RESERVED_WORD:
- *message = MessageTemplate::kUnexpectedReserved;
- *arg = nullptr;
- break;
- case Token::LET:
- case Token::STATIC:
- case Token::YIELD:
- case Token::FUTURE_STRICT_RESERVED_WORD:
- *message = is_strict(language_mode())
- ? MessageTemplate::kUnexpectedStrictReserved
- : MessageTemplate::kUnexpectedTokenIdentifier;
- *arg = nullptr;
- break;
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL:
- *message = MessageTemplate::kUnexpectedTemplateString;
- *arg = nullptr;
- break;
- case Token::ESCAPED_STRICT_RESERVED_WORD:
- case Token::ESCAPED_KEYWORD:
- *message = MessageTemplate::kInvalidEscapedReservedWord;
- *arg = nullptr;
- break;
- default:
- const char* name = Token::String(token);
- DCHECK(name != NULL);
- *arg = name;
- break;
- }
-}
-
-
-template <class Traits>
-void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
- return ReportUnexpectedTokenAt(scanner_->location(), token);
-}
-
-
-template <class Traits>
-void ParserBase<Traits>::ReportUnexpectedTokenAt(
- Scanner::Location source_location, Token::Value token,
- MessageTemplate::Template message) {
- const char* arg;
- GetUnexpectedTokenMessage(token, &message, &arg);
- Traits::ReportMessageAt(source_location, message, arg);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
- AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) {
- ExpressionClassifier classifier;
- auto result = ParseAndClassifyIdentifier(&classifier, ok);
- if (!*ok) return Traits::EmptyIdentifier();
-
- if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
- ValidateAssignmentPattern(&classifier, ok);
- if (!*ok) return Traits::EmptyIdentifier();
- ValidateBindingPattern(&classifier, ok);
- if (!*ok) return Traits::EmptyIdentifier();
- } else {
- ValidateExpression(&classifier, ok);
- if (!*ok) return Traits::EmptyIdentifier();
- }
-
- return result;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::IdentifierT
-ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
- bool* ok) {
- Token::Value next = Next();
- if (next == Token::IDENTIFIER) {
- IdentifierT name = this->GetSymbol(scanner());
- // When this function is used to read a formal parameter, we don't always
- // know whether the function is going to be strict or sloppy. Indeed for
- // arrow functions we don't always know that the identifier we are reading
- // is actually a formal parameter. Therefore besides the errors that we
- // must detect because we know we're in strict mode, we also record any
- // error that we might make in the future once we know the language mode.
- if (this->IsEval(name)) {
- classifier->RecordStrictModeFormalParameterError(
- scanner()->location(), MessageTemplate::kStrictEvalArguments);
- if (is_strict(language_mode())) {
- classifier->RecordBindingPatternError(
- scanner()->location(), MessageTemplate::kStrictEvalArguments);
- }
- }
- if (this->IsArguments(name)) {
- scope_->RecordArgumentsUsage();
- classifier->RecordStrictModeFormalParameterError(
- scanner()->location(), MessageTemplate::kStrictEvalArguments);
- if (is_strict(language_mode())) {
- classifier->RecordBindingPatternError(
- scanner()->location(), MessageTemplate::kStrictEvalArguments);
- }
- if (is_strong(language_mode())) {
- classifier->RecordExpressionError(scanner()->location(),
- MessageTemplate::kStrongArguments);
- }
- }
- if (this->IsUndefined(name)) {
- classifier->RecordStrongModeFormalParameterError(
- scanner()->location(), MessageTemplate::kStrongUndefined);
- if (is_strong(language_mode())) {
- // TODO(dslomov): allow 'undefined' in nested patterns.
- classifier->RecordBindingPatternError(
- scanner()->location(), MessageTemplate::kStrongUndefined);
- classifier->RecordAssignmentPatternError(
- scanner()->location(), MessageTemplate::kStrongUndefined);
- }
- }
-
- if (classifier->duplicate_finder() != nullptr &&
- scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
- classifier->RecordDuplicateFormalParameterError(scanner()->location());
- }
- return name;
- } else if (is_sloppy(language_mode()) &&
- (next == Token::FUTURE_STRICT_RESERVED_WORD ||
- next == Token::ESCAPED_STRICT_RESERVED_WORD ||
- next == Token::LET || next == Token::STATIC ||
- (next == Token::YIELD && !is_generator()))) {
- classifier->RecordStrictModeFormalParameterError(
- scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
- if (next == Token::ESCAPED_STRICT_RESERVED_WORD &&
- is_strict(language_mode())) {
- ReportUnexpectedToken(next);
- *ok = false;
- return Traits::EmptyIdentifier();
- }
- if (next == Token::LET) {
- classifier->RecordLetPatternError(scanner()->location(),
- MessageTemplate::kLetInLexicalBinding);
- }
- return this->GetSymbol(scanner());
- } else {
- this->ReportUnexpectedToken(next);
- *ok = false;
- return Traits::EmptyIdentifier();
- }
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::IdentifierT
-ParserBase<Traits>::ParseIdentifierOrStrictReservedWord(
- bool is_generator, bool* is_strict_reserved, bool* ok) {
- Token::Value next = Next();
- if (next == Token::IDENTIFIER) {
- *is_strict_reserved = false;
- } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
- next == Token::STATIC || (next == Token::YIELD && !is_generator)) {
- *is_strict_reserved = true;
- } else {
- ReportUnexpectedToken(next);
- *ok = false;
- return Traits::EmptyIdentifier();
- }
-
- IdentifierT name = this->GetSymbol(scanner());
- if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
- return name;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::IdentifierT
-ParserBase<Traits>::ParseIdentifierName(bool* ok) {
- Token::Value next = Next();
- if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
- next != Token::LET && next != Token::STATIC && next != Token::YIELD &&
- next != Token::FUTURE_STRICT_RESERVED_WORD &&
- next != Token::ESCAPED_KEYWORD &&
- next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
- this->ReportUnexpectedToken(next);
- *ok = false;
- return Traits::EmptyIdentifier();
- }
-
- IdentifierT name = this->GetSymbol(scanner());
- if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
- return name;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::IdentifierT
-ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
- bool* is_set,
- bool* ok) {
- IdentifierT result = ParseIdentifierName(ok);
- if (!*ok) return Traits::EmptyIdentifier();
- scanner()->IsGetOrSet(is_get, is_set);
- return result;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
- bool seen_equal, ExpressionClassifier* classifier, bool* ok) {
- int pos = peek_position();
- if (!scanner()->ScanRegExpPattern(seen_equal)) {
- Next();
- ReportMessage(MessageTemplate::kUnterminatedRegExp);
- *ok = false;
- return Traits::EmptyExpression();
- }
-
- int literal_index = function_state_->NextMaterializedLiteralIndex();
-
- IdentifierT js_pattern = this->GetNextSymbol(scanner());
- Maybe<RegExp::Flags> flags = scanner()->ScanRegExpFlags();
- if (flags.IsNothing()) {
- Next();
- ReportMessage(MessageTemplate::kMalformedRegExpFlags);
- *ok = false;
- return Traits::EmptyExpression();
- }
- int js_flags = flags.FromJust();
- Next();
- return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index,
- is_strong(language_mode()), pos);
-}
-
-
-#define CHECK_OK ok); \
- if (!*ok) return this->EmptyExpression(); \
- ((void)0
-#define DUMMY ) // to make indentation work
-#undef DUMMY
-
-// Used in functions where the return type is not ExpressionT.
-#define CHECK_OK_CUSTOM(x) ok); \
- if (!*ok) return this->x(); \
- ((void)0
-#define DUMMY ) // to make indentation work
-#undef DUMMY
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
- bool* ok) {
- // PrimaryExpression ::
- // 'this'
- // 'null'
- // 'true'
- // 'false'
- // Identifier
- // Number
- // String
- // ArrayLiteral
- // ObjectLiteral
- // RegExpLiteral
- // ClassLiteral
- // '(' Expression ')'
- // TemplateLiteral
- // do Block
-
- int beg_pos = peek_position();
- switch (peek()) {
- case Token::THIS: {
- BindingPatternUnexpectedToken(classifier);
- Consume(Token::THIS);
- if (FLAG_strong_this && is_strong(language_mode())) {
- // Constructors' usages of 'this' in strong mode are parsed separately.
- // TODO(rossberg): this does not work with arrow functions yet.
- if (IsClassConstructor(function_state_->kind())) {
- ReportMessage(MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return this->EmptyExpression();
- }
- }
- return this->ThisExpression(scope_, factory(), beg_pos);
- }
-
- case Token::NULL_LITERAL:
- case Token::TRUE_LITERAL:
- case Token::FALSE_LITERAL:
- BindingPatternUnexpectedToken(classifier);
- return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
- case Token::SMI:
- case Token::NUMBER:
- classifier->RecordBindingPatternError(
- scanner()->peek_location(), MessageTemplate::kUnexpectedTokenNumber);
- return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
-
- case Token::IDENTIFIER:
- case Token::LET:
- case Token::STATIC:
- case Token::YIELD:
- case Token::ESCAPED_STRICT_RESERVED_WORD:
- case Token::FUTURE_STRICT_RESERVED_WORD: {
- // Using eval or arguments in this context is OK even in strict mode.
- IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK);
- return this->ExpressionFromIdentifier(
- name, beg_pos, scanner()->location().end_pos, scope_, factory());
- }
-
- case Token::STRING: {
- classifier->RecordBindingPatternError(
- scanner()->peek_location(), MessageTemplate::kUnexpectedTokenString);
- Consume(Token::STRING);
- return this->ExpressionFromString(beg_pos, scanner(), factory());
- }
-
- case Token::ASSIGN_DIV:
- classifier->RecordBindingPatternError(
- scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp);
- return this->ParseRegExpLiteral(true, classifier, ok);
-
- case Token::DIV:
- classifier->RecordBindingPatternError(
- scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp);
- return this->ParseRegExpLiteral(false, classifier, ok);
-
- case Token::LBRACK:
- if (!allow_harmony_destructuring_bind()) {
- BindingPatternUnexpectedToken(classifier);
- }
- return this->ParseArrayLiteral(classifier, ok);
-
- case Token::LBRACE:
- if (!allow_harmony_destructuring_bind()) {
- BindingPatternUnexpectedToken(classifier);
- }
- return this->ParseObjectLiteral(classifier, ok);
-
- case Token::LPAREN: {
- // Arrow function formal parameters are either a single identifier or a
- // list of BindingPattern productions enclosed in parentheses.
- // Parentheses are not valid on the LHS of a BindingPattern, so we use the
- // is_valid_binding_pattern() check to detect multiple levels of
- // parenthesization.
- if (!classifier->is_valid_binding_pattern()) {
- ArrowFormalParametersUnexpectedToken(classifier);
- }
- BindingPatternUnexpectedToken(classifier);
- Consume(Token::LPAREN);
- if (Check(Token::RPAREN)) {
- // ()=>x. The continuation that looks for the => is in
- // ParseAssignmentExpression.
- classifier->RecordExpressionError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::RPAREN));
- classifier->RecordBindingPatternError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::RPAREN));
- return factory()->NewEmptyParentheses(beg_pos);
- } else if (allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) {
- // (...x)=>x. The continuation that looks for the => is in
- // ParseAssignmentExpression.
- int ellipsis_pos = position();
- classifier->RecordExpressionError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::ELLIPSIS));
- classifier->RecordNonSimpleParameter();
- Scanner::Location expr_loc = scanner()->peek_location();
- Token::Value tok = peek();
- ExpressionT expr =
- this->ParseAssignmentExpression(true, classifier, CHECK_OK);
- // Patterns are not allowed as rest parameters. There is no way we can
- // succeed so go ahead and use the convenient ReportUnexpectedToken
- // interface.
- if (!Traits::IsIdentifier(expr)) {
- ReportUnexpectedTokenAt(expr_loc, tok);
- *ok = false;
- return this->EmptyExpression();
- }
- if (peek() == Token::COMMA) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kParamAfterRest);
- *ok = false;
- return this->EmptyExpression();
- }
- Expect(Token::RPAREN, CHECK_OK);
- return factory()->NewSpread(expr, ellipsis_pos);
- }
- // Heuristically try to detect immediately called functions before
- // seeing the call parentheses.
- parenthesized_function_ = (peek() == Token::FUNCTION);
- ExpressionT expr = this->ParseExpression(true, kIsPossibleArrowFormals,
- classifier, CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
- if (peek() != Token::ARROW) {
- ValidateExpression(classifier, CHECK_OK);
- }
- return expr;
- }
-
- case Token::CLASS: {
- BindingPatternUnexpectedToken(classifier);
- Consume(Token::CLASS);
- if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
- ReportMessage(MessageTemplate::kSloppyLexical);
- *ok = false;
- return this->EmptyExpression();
- }
- int class_token_position = position();
- IdentifierT name = this->EmptyIdentifier();
- bool is_strict_reserved_name = false;
- Scanner::Location class_name_location = Scanner::Location::invalid();
- if (peek_any_identifier()) {
- name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
- CHECK_OK);
- class_name_location = scanner()->location();
- }
- return this->ParseClassLiteral(name, class_name_location,
- is_strict_reserved_name,
- class_token_position, ok);
- }
-
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL:
- classifier->RecordBindingPatternError(
- scanner()->peek_location(),
- MessageTemplate::kUnexpectedTemplateString);
- return this->ParseTemplateLiteral(Traits::NoTemplateTag(), beg_pos,
- classifier, ok);
-
- case Token::MOD:
- if (allow_natives() || extension_ != NULL) {
- BindingPatternUnexpectedToken(classifier);
- return this->ParseV8Intrinsic(ok);
- }
- break;
-
- case Token::DO:
- if (allow_harmony_do_expressions()) {
- BindingPatternUnexpectedToken(classifier);
- return Traits::ParseDoExpression(ok);
- }
- break;
-
- default:
- break;
- }
-
- ReportUnexpectedToken(Next());
- *ok = false;
- return this->EmptyExpression();
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
- bool accept_IN, bool* ok) {
- ExpressionClassifier classifier;
- ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK);
- ValidateExpression(&classifier, CHECK_OK);
- return result;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
- bool accept_IN, ExpressionClassifier* classifier, bool* ok) {
- return ParseExpression(accept_IN, kIsLeftHandSide, classifier, ok);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
- bool accept_IN, int flags, ExpressionClassifier* classifier, bool* ok) {
- // Expression ::
- // AssignmentExpression
- // Expression ',' AssignmentExpression
-
- ExpressionClassifier binding_classifier;
- ExpressionT result = this->ParseAssignmentExpression(
- accept_IN, flags, &binding_classifier, CHECK_OK);
- classifier->Accumulate(binding_classifier,
- ExpressionClassifier::AllProductions);
- bool is_simple_parameter_list = this->IsIdentifier(result);
- bool seen_rest = false;
- while (peek() == Token::COMMA) {
- if (seen_rest) {
- // At this point the production can't possibly be valid, but we don't know
- // which error to signal.
- classifier->RecordArrowFormalParametersError(
- scanner()->peek_location(), MessageTemplate::kParamAfterRest);
- }
- Consume(Token::COMMA);
- bool is_rest = false;
- if (allow_harmony_rest_parameters() && peek() == Token::ELLIPSIS) {
- // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
- // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
- // valid expression or binding pattern.
- ExpressionUnexpectedToken(classifier);
- BindingPatternUnexpectedToken(classifier);
- Consume(Token::ELLIPSIS);
- seen_rest = is_rest = true;
- }
- int pos = position();
- ExpressionT right = this->ParseAssignmentExpression(
- accept_IN, flags, &binding_classifier, CHECK_OK);
- if (is_rest) right = factory()->NewSpread(right, pos);
- is_simple_parameter_list =
- is_simple_parameter_list && this->IsIdentifier(right);
- classifier->Accumulate(binding_classifier,
- ExpressionClassifier::AllProductions);
- result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
- }
- if (!is_simple_parameter_list || seen_rest) {
- classifier->RecordNonSimpleParameter();
- }
-
- return result;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
- ExpressionClassifier* classifier, bool* ok) {
- // ArrayLiteral ::
- // '[' Expression? (',' Expression?)* ']'
-
- int pos = peek_position();
- typename Traits::Type::ExpressionList values =
- this->NewExpressionList(4, zone_);
- int first_spread_index = -1;
- Expect(Token::LBRACK, CHECK_OK);
- while (peek() != Token::RBRACK) {
- ExpressionT elem = this->EmptyExpression();
- if (peek() == Token::COMMA) {
- if (is_strong(language_mode())) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kStrongEllision);
- *ok = false;
- return this->EmptyExpression();
- }
- elem = this->GetLiteralTheHole(peek_position(), factory());
- } else if (peek() == Token::ELLIPSIS) {
- int start_pos = peek_position();
- Consume(Token::ELLIPSIS);
- ExpressionT argument =
- this->ParseAssignmentExpression(true, classifier, CHECK_OK);
- elem = factory()->NewSpread(argument, start_pos);
-
- if (first_spread_index < 0) {
- first_spread_index = values->length();
- }
-
- CheckDestructuringElement(argument, classifier, start_pos,
- scanner()->location().end_pos);
-
- if (peek() == Token::COMMA) {
- classifier->RecordPatternError(
- Scanner::Location(start_pos, scanner()->location().end_pos),
- MessageTemplate::kElementAfterRest);
- }
- } else {
- elem = this->ParseAssignmentExpression(true, kIsPatternElement,
- classifier, CHECK_OK);
- if (!this->IsValidReferenceExpression(elem) &&
- !classifier->is_valid_assignment_pattern()) {
- classifier->RecordPatternError(
- Scanner::Location(pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidDestructuringTarget);
- }
- }
- values->Add(elem, zone_);
- if (peek() != Token::RBRACK) {
- Expect(Token::COMMA, CHECK_OK);
- }
- }
- Expect(Token::RBRACK, CHECK_OK);
-
- // Update the scope information before the pre-parsing bailout.
- int literal_index = function_state_->NextMaterializedLiteralIndex();
-
- return factory()->NewArrayLiteral(values, first_spread_index, literal_index,
- is_strong(language_mode()), pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
- IdentifierT* name, bool* is_get, bool* is_set, bool* is_static,
- bool* is_computed_name, bool* is_identifier, bool* is_escaped_keyword,
- ExpressionClassifier* classifier, bool* ok) {
- Token::Value token = peek();
- int pos = peek_position();
-
- // For non computed property names we normalize the name a bit:
- //
- // "12" -> 12
- // 12.3 -> "12.3"
- // 12.30 -> "12.3"
- // identifier -> "identifier"
- //
- // This is important because we use the property name as a key in a hash
- // table when we compute constant properties.
- switch (token) {
- case Token::STRING:
- Consume(Token::STRING);
- *name = this->GetSymbol(scanner());
- break;
-
- case Token::SMI:
- Consume(Token::SMI);
- *name = this->GetNumberAsSymbol(scanner());
- break;
-
- case Token::NUMBER:
- Consume(Token::NUMBER);
- *name = this->GetNumberAsSymbol(scanner());
- break;
-
- case Token::LBRACK: {
- *is_computed_name = true;
- Consume(Token::LBRACK);
- ExpressionClassifier computed_name_classifier;
- ExpressionT expression =
- ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK);
- classifier->Accumulate(computed_name_classifier,
- ExpressionClassifier::ExpressionProductions);
- Expect(Token::RBRACK, CHECK_OK);
- return expression;
- }
-
- case Token::ESCAPED_KEYWORD:
- *is_escaped_keyword = true;
- *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK);
- break;
-
- case Token::STATIC:
- *is_static = true;
-
- // Fall through.
- default:
- *is_identifier = true;
- *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK);
- break;
- }
-
- uint32_t index;
- return this->IsArrayIndex(*name, &index)
- ? factory()->NewNumberLiteral(index, pos)
- : factory()->NewStringLiteral(*name, pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ObjectLiteralPropertyT
-ParserBase<Traits>::ParsePropertyDefinition(
- ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
- bool is_static, bool* is_computed_name, bool* has_seen_constructor,
- ExpressionClassifier* classifier, bool* ok) {
- DCHECK(!in_class || is_static || has_seen_constructor != nullptr);
- ExpressionT value = this->EmptyExpression();
- IdentifierT name = this->EmptyIdentifier();
- bool is_get = false;
- bool is_set = false;
- bool name_is_static = false;
- bool is_generator = Check(Token::MUL);
-
- Token::Value name_token = peek();
- int next_beg_pos = scanner()->peek_location().beg_pos;
- int next_end_pos = scanner()->peek_location().end_pos;
- bool is_identifier = false;
- bool is_escaped_keyword = false;
- ExpressionT name_expression = ParsePropertyName(
- &name, &is_get, &is_set, &name_is_static, is_computed_name,
- &is_identifier, &is_escaped_keyword, classifier,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-
- if (fni_ != nullptr && !*is_computed_name) {
- this->PushLiteralName(fni_, name);
- }
-
- bool escaped_static =
- is_escaped_keyword &&
- scanner()->is_literal_contextual_keyword(CStrVector("static"));
-
- if (!in_class && !is_generator) {
- DCHECK(!is_static);
-
- if (peek() == Token::COLON) {
- // PropertyDefinition
- // PropertyName ':' AssignmentExpression
- if (!*is_computed_name) {
- checker->CheckProperty(name_token, kValueProperty, false, false,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- }
- Consume(Token::COLON);
- int pos = peek_position();
- value = this->ParseAssignmentExpression(
- true, kIsPatternElement, classifier,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-
- if (!this->IsValidReferenceExpression(value) &&
- !classifier->is_valid_assignment_pattern()) {
- classifier->RecordPatternError(
- Scanner::Location(pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidDestructuringTarget);
- }
-
- return factory()->NewObjectLiteralProperty(name_expression, value, false,
- *is_computed_name);
- }
-
- if ((is_identifier || is_escaped_keyword) &&
- (peek() == Token::COMMA || peek() == Token::RBRACE ||
- peek() == Token::ASSIGN)) {
- // PropertyDefinition
- // IdentifierReference
- // CoverInitializedName
- //
- // CoverInitializedName
- // IdentifierReference Initializer?
- if (!Token::IsIdentifier(name_token, language_mode(),
- this->is_generator())) {
- if (!escaped_static) {
- ReportUnexpectedTokenAt(scanner()->location(), name_token);
- *ok = false;
- return this->EmptyObjectLiteralProperty();
- }
- }
- if (classifier->duplicate_finder() != nullptr &&
- scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
- classifier->RecordDuplicateFormalParameterError(scanner()->location());
- }
- if (name_token == Token::LET) {
- classifier->RecordLetPatternError(
- scanner()->location(), MessageTemplate::kLetInLexicalBinding);
- }
-
- ExpressionT lhs = this->ExpressionFromIdentifier(
- name, next_beg_pos, next_end_pos, scope_, factory());
-
- if (peek() == Token::ASSIGN) {
- Consume(Token::ASSIGN);
- ExpressionClassifier rhs_classifier;
- ExpressionT rhs = this->ParseAssignmentExpression(
- true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- classifier->Accumulate(rhs_classifier,
- ExpressionClassifier::ExpressionProductions);
- value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
- RelocInfo::kNoPosition);
- classifier->RecordCoverInitializedNameError(
- Scanner::Location(next_beg_pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidCoverInitializedName);
- } else {
- value = lhs;
- }
-
- return factory()->NewObjectLiteralProperty(
- name_expression, value, ObjectLiteralProperty::COMPUTED, false,
- false);
- }
- }
-
- if (in_class && escaped_static && !is_static) {
- ReportUnexpectedTokenAt(scanner()->location(), name_token);
- *ok = false;
- return this->EmptyObjectLiteralProperty();
- }
-
- // Method definitions are never valid in patterns.
- classifier->RecordPatternError(
- Scanner::Location(next_beg_pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidDestructuringTarget);
-
- if (is_generator || peek() == Token::LPAREN) {
- // MethodDefinition
- // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
- // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
- if (!*is_computed_name) {
- checker->CheckProperty(name_token, kMethodProperty, is_static,
- is_generator,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- }
-
- FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod
- : FunctionKind::kConciseMethod;
-
- if (in_class && !is_static && this->IsConstructor(name)) {
- *has_seen_constructor = true;
- kind = has_extends ? FunctionKind::kSubclassConstructor
- : FunctionKind::kBaseConstructor;
- }
-
- if (!in_class) kind = WithObjectLiteralBit(kind);
-
- value = this->ParseFunctionLiteral(
- name, scanner()->location(), kSkipFunctionNameCheck, kind,
- RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
- FunctionLiteral::NORMAL_ARITY, language_mode(),
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-
- return factory()->NewObjectLiteralProperty(name_expression, value,
- ObjectLiteralProperty::COMPUTED,
- is_static, *is_computed_name);
- }
-
- if (in_class && name_is_static && !is_static) {
- // ClassElement (static)
- // 'static' MethodDefinition
- return ParsePropertyDefinition(checker, true, has_extends, true,
- is_computed_name, nullptr, classifier, ok);
- }
-
- if (is_get || is_set) {
- // MethodDefinition (Accessors)
- // get PropertyName '(' ')' '{' FunctionBody '}'
- // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}'
- name = this->EmptyIdentifier();
- bool dont_care = false;
- name_token = peek();
-
- name_expression = ParsePropertyName(
- &name, &dont_care, &dont_care, &dont_care, is_computed_name, &dont_care,
- &dont_care, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-
- if (!*is_computed_name) {
- checker->CheckProperty(name_token, kAccessorProperty, is_static,
- is_generator,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- }
-
- FunctionKind kind = FunctionKind::kAccessorFunction;
- if (!in_class) kind = WithObjectLiteralBit(kind);
- typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
- name, scanner()->location(), kSkipFunctionNameCheck, kind,
- RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
- is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
- language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
-
- // Make sure the name expression is a string since we need a Name for
- // Runtime_DefineAccessorPropertyUnchecked and since we can determine this
- // statically we can skip the extra runtime check.
- if (!*is_computed_name) {
- name_expression =
- factory()->NewStringLiteral(name, name_expression->position());
- }
-
- return factory()->NewObjectLiteralProperty(
- name_expression, value,
- is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER,
- is_static, *is_computed_name);
- }
-
- Token::Value next = Next();
- ReportUnexpectedToken(next);
- *ok = false;
- return this->EmptyObjectLiteralProperty();
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
- ExpressionClassifier* classifier, bool* ok) {
- // ObjectLiteral ::
- // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
-
- int pos = peek_position();
- typename Traits::Type::PropertyList properties =
- this->NewPropertyList(4, zone_);
- int number_of_boilerplate_properties = 0;
- bool has_function = false;
- bool has_computed_names = false;
- ObjectLiteralChecker checker(this);
-
- Expect(Token::LBRACE, CHECK_OK);
-
- while (peek() != Token::RBRACE) {
- if (fni_ != nullptr) fni_->Enter();
-
- const bool in_class = false;
- const bool is_static = false;
- const bool has_extends = false;
- bool is_computed_name = false;
- ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
- &checker, in_class, has_extends, is_static, &is_computed_name, NULL,
- classifier, CHECK_OK);
-
- if (is_computed_name) {
- has_computed_names = true;
- }
-
- // Mark top-level object literals that contain function literals and
- // pretenure the literal so it can be added as a constant function
- // property. (Parser only.)
- this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property,
- &has_function);
-
- // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
- if (!has_computed_names && this->IsBoilerplateProperty(property)) {
- number_of_boilerplate_properties++;
- }
- properties->Add(property, zone());
-
- if (peek() != Token::RBRACE) {
- // Need {} because of the CHECK_OK macro.
- Expect(Token::COMMA, CHECK_OK);
- }
-
- if (fni_ != nullptr) {
- fni_->Infer();
- fni_->Leave();
- }
- }
- Expect(Token::RBRACE, CHECK_OK);
-
- // Computation of literal_index must happen before pre parse bailout.
- int literal_index = function_state_->NextMaterializedLiteralIndex();
-
- return factory()->NewObjectLiteral(properties,
- literal_index,
- number_of_boilerplate_properties,
- has_function,
- is_strong(language_mode()),
- pos);
-}
-
-
-template <class Traits>
-typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
- Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier,
- bool* ok) {
- // Arguments ::
- // '(' (AssignmentExpression)*[','] ')'
-
- Scanner::Location spread_arg = Scanner::Location::invalid();
- typename Traits::Type::ExpressionList result =
- this->NewExpressionList(4, zone_);
- Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
- bool done = (peek() == Token::RPAREN);
- bool was_unspread = false;
- int unspread_sequences_count = 0;
- while (!done) {
- int start_pos = peek_position();
- bool is_spread = Check(Token::ELLIPSIS);
-
- ExpressionT argument = this->ParseAssignmentExpression(
- true, classifier, CHECK_OK_CUSTOM(NullExpressionList));
- if (is_spread) {
- if (!spread_arg.IsValid()) {
- spread_arg.beg_pos = start_pos;
- spread_arg.end_pos = peek_position();
- }
- argument = factory()->NewSpread(argument, start_pos);
- }
- result->Add(argument, zone_);
-
- // unspread_sequences_count is the number of sequences of parameters which
- // are not prefixed with a spread '...' operator.
- if (is_spread) {
- was_unspread = false;
- } else if (!was_unspread) {
- was_unspread = true;
- unspread_sequences_count++;
- }
-
- if (result->length() > Code::kMaxArguments) {
- ReportMessage(MessageTemplate::kTooManyArguments);
- *ok = false;
- return this->NullExpressionList();
- }
- done = (peek() != Token::COMMA);
- if (!done) {
- Next();
- }
- }
- Scanner::Location location = scanner_->location();
- if (Token::RPAREN != Next()) {
- ReportMessageAt(location, MessageTemplate::kUnterminatedArgList);
- *ok = false;
- return this->NullExpressionList();
- }
- *first_spread_arg_loc = spread_arg;
-
- if (spread_arg.IsValid()) {
- // Unspread parameter sequences are translated into array literals in the
- // parser. Ensure that the number of materialized literals matches between
- // the parser and preparser
- Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count);
- }
-
- return result;
-}
-
-// Precedence = 2
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, int flags,
- ExpressionClassifier* classifier,
- bool* ok) {
- // AssignmentExpression ::
- // ConditionalExpression
- // ArrowFunction
- // YieldExpression
- // LeftHandSideExpression AssignmentOperator AssignmentExpression
- bool is_rhs = flags & kIsRightHandSide;
- bool is_pattern_element = flags & kIsPatternElement;
- bool is_destructuring_assignment = false;
- bool is_arrow_formals = flags & kIsPossibleArrowFormals;
- int lhs_beg_pos = peek_position();
-
- if (peek() == Token::YIELD && is_generator()) {
- return this->ParseYieldExpression(classifier, ok);
- }
-
- if (fni_ != NULL) fni_->Enter();
- ParserBase<Traits>::Checkpoint checkpoint(this);
- ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder());
- bool parenthesized_formals = peek() == Token::LPAREN;
- if (!parenthesized_formals) {
- ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier);
- }
- ExpressionT expression = this->ParseConditionalExpression(
- accept_IN, &arrow_formals_classifier, CHECK_OK);
- if (peek() == Token::ARROW) {
- BindingPatternUnexpectedToken(classifier);
- ValidateArrowFormalParameters(&arrow_formals_classifier, expression,
- parenthesized_formals, CHECK_OK);
- Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos);
- Scope* scope =
- this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
- // Because the arrow's parameters were parsed in the outer scope, any
- // usage flags that might have been triggered there need to be copied
- // to the arrow scope.
- scope_->PropagateUsageFlagsToScope(scope);
- FormalParametersT parameters(scope);
- if (!arrow_formals_classifier.is_simple_parameter_list()) {
- scope->SetHasNonSimpleParameters();
- parameters.is_simple = false;
- }
-
- Scanner::Location duplicate_loc = Scanner::Location::invalid();
- this->ParseArrowFunctionFormalParameterList(&parameters, expression, loc,
- &duplicate_loc, CHECK_OK);
-
- checkpoint.Restore(&parameters.materialized_literals_count);
-
- scope->set_start_position(lhs_beg_pos);
- if (duplicate_loc.IsValid()) {
- arrow_formals_classifier.RecordDuplicateFormalParameterError(
- duplicate_loc);
- }
- expression = this->ParseArrowFunctionLiteral(
- accept_IN, parameters, arrow_formals_classifier, CHECK_OK);
- if (is_pattern_element) {
- classifier->RecordPatternError(
- Scanner::Location(lhs_beg_pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidDestructuringTarget);
- }
- return expression;
- }
-
- if (this->IsValidReferenceExpression(expression)) {
- arrow_formals_classifier.ForgiveAssignmentPatternError();
- }
-
- // "expression" was not itself an arrow function parameter list, but it might
- // form part of one. Propagate speculative formal parameter error locations.
- classifier->Accumulate(
- arrow_formals_classifier,
- ExpressionClassifier::StandardProductions |
- ExpressionClassifier::FormalParametersProductions |
- ExpressionClassifier::CoverInitializedNameProduction);
-
- bool maybe_pattern =
- expression->IsObjectLiteral() || expression->IsArrayLiteral();
- // bool binding_pattern =
- // allow_harmony_destructuring_bind() && maybe_pattern && !is_rhs;
-
- if (!Token::IsAssignmentOp(peek())) {
- if (fni_ != NULL) fni_->Leave();
- // Parsed conditional expression only (no assignment).
- if (is_pattern_element && !this->IsValidReferenceExpression(expression) &&
- !maybe_pattern) {
- classifier->RecordPatternError(
- Scanner::Location(lhs_beg_pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidDestructuringTarget);
- } else if (is_rhs && maybe_pattern) {
- ValidateExpression(classifier, CHECK_OK);
- }
-
- return expression;
- }
-
- if (!(allow_harmony_destructuring_bind() ||
- allow_harmony_default_parameters())) {
- BindingPatternUnexpectedToken(classifier);
- }
-
- if (allow_harmony_destructuring_assignment() && maybe_pattern &&
- peek() == Token::ASSIGN) {
- classifier->ForgiveCoverInitializedNameError();
- ValidateAssignmentPattern(classifier, CHECK_OK);
- is_destructuring_assignment = true;
- } else if (is_arrow_formals) {
- expression = this->ClassifyAndRewriteReferenceExpression(
- classifier, expression, lhs_beg_pos, scanner()->location().end_pos,
- MessageTemplate::kInvalidLhsInAssignment);
- } else {
- expression = this->CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, scanner()->location().end_pos,
- MessageTemplate::kInvalidLhsInAssignment, CHECK_OK);
- }
-
- expression = this->MarkExpressionAsAssigned(expression);
-
- Token::Value op = Next(); // Get assignment operator.
- if (op != Token::ASSIGN) {
- classifier->RecordBindingPatternError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(op));
- }
- int pos = position();
-
- ExpressionClassifier rhs_classifier;
-
- int rhs_flags = flags;
- rhs_flags &= ~(kIsPatternElement | kIsPossibleArrowFormals);
- rhs_flags |= kIsRightHandSide;
- ExpressionT right = this->ParseAssignmentExpression(
- accept_IN, rhs_flags, &rhs_classifier, CHECK_OK);
- classifier->Accumulate(
- rhs_classifier, ExpressionClassifier::ExpressionProductions |
- ExpressionClassifier::CoverInitializedNameProduction);
-
- // TODO(1231235): We try to estimate the set of properties set by
- // constructors. We define a new property whenever there is an
- // assignment to a property of 'this'. We should probably only add
- // properties if we haven't seen them before. Otherwise we'll
- // probably overestimate the number of properties.
- if (op == Token::ASSIGN && this->IsThisProperty(expression)) {
- function_state_->AddProperty();
- }
-
- this->CheckAssigningFunctionLiteralToProperty(expression, right);
-
- if (fni_ != NULL) {
- // Check if the right hand side is a call to avoid inferring a
- // name if we're dealing with "a = function(){...}();"-like
- // expression.
- if ((op == Token::INIT || op == Token::ASSIGN) &&
- (!right->IsCall() && !right->IsCallNew())) {
- fni_->Infer();
- } else {
- fni_->RemoveLastFunction();
- }
- fni_->Leave();
- }
-
- ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
-
- if (is_destructuring_assignment) {
- result = factory()->NewRewritableAssignmentExpression(result);
- Traits::QueueDestructuringAssignmentForRewriting(result);
- }
-
- return result;
-}
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier,
- bool* ok) {
- // YieldExpression ::
- // 'yield' ([no line terminator] '*'? AssignmentExpression)?
- int pos = peek_position();
- BindingPatternUnexpectedToken(classifier);
- FormalParameterInitializerUnexpectedToken(classifier);
- Expect(Token::YIELD, CHECK_OK);
- ExpressionT generator_object =
- factory()->NewVariableProxy(function_state_->generator_object_variable());
- ExpressionT expression = Traits::EmptyExpression();
- Yield::Kind kind = Yield::kSuspend;
- if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
- if (Check(Token::MUL)) kind = Yield::kDelegating;
- switch (peek()) {
- case Token::EOS:
- case Token::SEMICOLON:
- case Token::RBRACE:
- case Token::RBRACK:
- case Token::RPAREN:
- case Token::COLON:
- case Token::COMMA:
- // The above set of tokens is the complete set of tokens that can appear
- // after an AssignmentExpression, and none of them can start an
- // AssignmentExpression. This allows us to avoid looking for an RHS for
- // a Yield::kSuspend operation, given only one look-ahead token.
- if (kind == Yield::kSuspend)
- break;
- DCHECK_EQ(Yield::kDelegating, kind);
- // Delegating yields require an RHS; fall through.
- default:
- expression = ParseAssignmentExpression(false, classifier, CHECK_OK);
- break;
- }
- }
- if (kind == Yield::kDelegating) {
- // var iterator = subject[Symbol.iterator]();
- // Hackily disambiguate o from o.next and o [Symbol.iterator]().
- // TODO(verwaest): Come up with a better solution.
- expression = this->GetIterator(expression, factory(), pos + 1);
- }
- // Hackily disambiguate o from o.next and o [Symbol.iterator]().
- // TODO(verwaest): Come up with a better solution.
- typename Traits::Type::YieldExpression yield =
- factory()->NewYield(generator_object, expression, kind, pos);
- return yield;
-}
-
-
-// Precedence = 3
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseConditionalExpression(bool accept_IN,
- ExpressionClassifier* classifier,
- bool* ok) {
- // ConditionalExpression ::
- // LogicalOrExpression
- // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
-
- int pos = peek_position();
- // We start using the binary expression parser for prec >= 4 only!
- ExpressionT expression =
- this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK);
- if (peek() != Token::CONDITIONAL) return expression;
- ArrowFormalParametersUnexpectedToken(classifier);
- BindingPatternUnexpectedToken(classifier);
- Consume(Token::CONDITIONAL);
- // In parsing the first assignment expression in conditional
- // expressions we always accept the 'in' keyword; see ECMA-262,
- // section 11.12, page 58.
- ExpressionT left = ParseAssignmentExpression(true, classifier, CHECK_OK);
- Expect(Token::COLON, CHECK_OK);
- ExpressionT right =
- ParseAssignmentExpression(accept_IN, classifier, CHECK_OK);
- return factory()->NewConditional(expression, left, right, pos);
-}
-
-
-// Precedence >= 4
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN,
- ExpressionClassifier* classifier,
- bool* ok) {
- DCHECK(prec >= 4);
- ExpressionT x = this->ParseUnaryExpression(classifier, CHECK_OK);
- for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
- // prec1 >= 4
- while (Precedence(peek(), accept_IN) == prec1) {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- Token::Value op = Next();
- Scanner::Location op_location = scanner()->location();
- int pos = position();
- ExpressionT y =
- ParseBinaryExpression(prec1 + 1, accept_IN, classifier, CHECK_OK);
-
- if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
- factory())) {
- continue;
- }
-
- // For now we distinguish between comparisons and other binary
- // operations. (We could combine the two and get rid of this
- // code and AST node eventually.)
- if (Token::IsCompareOp(op)) {
- // We have a comparison.
- Token::Value cmp = op;
- switch (op) {
- case Token::NE: cmp = Token::EQ; break;
- case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
- default: break;
- }
- if (cmp == Token::EQ && is_strong(language_mode())) {
- ReportMessageAt(op_location, MessageTemplate::kStrongEqual);
- *ok = false;
- return this->EmptyExpression();
- }
- x = factory()->NewCompareOperation(cmp, x, y, pos);
- if (cmp != op) {
- // The comparison was negated - add a NOT.
- x = factory()->NewUnaryOperation(Token::NOT, x, pos);
- }
-
- } else {
- // We have a "normal" binary operation.
- x = factory()->NewBinaryOperation(op, x, y, pos);
- }
- }
- }
- return x;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
- bool* ok) {
- // UnaryExpression ::
- // PostfixExpression
- // 'delete' UnaryExpression
- // 'void' UnaryExpression
- // 'typeof' UnaryExpression
- // '++' UnaryExpression
- // '--' UnaryExpression
- // '+' UnaryExpression
- // '-' UnaryExpression
- // '~' UnaryExpression
- // '!' UnaryExpression
-
- Token::Value op = peek();
- if (Token::IsUnaryOp(op)) {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
-
- op = Next();
- int pos = position();
- ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK);
-
- if (op == Token::DELETE && is_strict(language_mode())) {
- if (is_strong(language_mode())) {
- ReportMessage(MessageTemplate::kStrongDelete);
- *ok = false;
- return this->EmptyExpression();
- } else if (this->IsIdentifier(expression)) {
- // "delete identifier" is a syntax error in strict mode.
- ReportMessage(MessageTemplate::kStrictDelete);
- *ok = false;
- return this->EmptyExpression();
- }
- }
-
- // Allow Traits do rewrite the expression.
- return this->BuildUnaryExpression(expression, op, pos, factory());
- } else if (Token::IsCountOp(op)) {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- op = Next();
- int beg_pos = peek_position();
- ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK);
- expression = this->CheckAndRewriteReferenceExpression(
- expression, beg_pos, scanner()->location().end_pos,
- MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK);
- this->MarkExpressionAsAssigned(expression);
-
- return factory()->NewCountOperation(op,
- true /* prefix */,
- expression,
- position());
-
- } else {
- return this->ParsePostfixExpression(classifier, ok);
- }
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier,
- bool* ok) {
- // PostfixExpression ::
- // LeftHandSideExpression ('++' | '--')?
-
- int lhs_beg_pos = peek_position();
- ExpressionT expression =
- this->ParseLeftHandSideExpression(classifier, CHECK_OK);
- if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
- Token::IsCountOp(peek())) {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
-
- expression = this->CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, scanner()->location().end_pos,
- MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK);
- expression = this->MarkExpressionAsAssigned(expression);
-
- Token::Value next = Next();
- expression =
- factory()->NewCountOperation(next,
- false /* postfix */,
- expression,
- position());
- }
- return expression;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseLeftHandSideExpression(
- ExpressionClassifier* classifier, bool* ok) {
- // LeftHandSideExpression ::
- // (NewExpression | MemberExpression) ...
-
- ExpressionT result =
- this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK);
-
- while (true) {
- switch (peek()) {
- case Token::LBRACK: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- Consume(Token::LBRACK);
- int pos = position();
- ExpressionT index = ParseExpression(true, classifier, CHECK_OK);
- result = factory()->NewProperty(result, index, pos);
- Expect(Token::RBRACK, CHECK_OK);
- break;
- }
-
- case Token::LPAREN: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
-
- if (is_strong(language_mode()) && this->IsIdentifier(result) &&
- this->IsEval(this->AsIdentifier(result))) {
- ReportMessage(MessageTemplate::kStrongDirectEval);
- *ok = false;
- return this->EmptyExpression();
- }
- int pos;
- if (scanner()->current_token() == Token::IDENTIFIER ||
- scanner()->current_token() == Token::SUPER) {
- // For call of an identifier we want to report position of
- // the identifier as position of the call in the stack trace.
- pos = position();
- } else {
- // For other kinds of calls we record position of the parenthesis as
- // position of the call. Note that this is extremely important for
- // expressions of the form function(){...}() for which call position
- // should not point to the closing brace otherwise it will intersect
- // with positions recorded for function literal and confuse debugger.
- pos = peek_position();
- // Also the trailing parenthesis are a hint that the function will
- // be called immediately. If we happen to have parsed a preceding
- // function literal eagerly, we can also compile it eagerly.
- if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
- result->AsFunctionLiteral()->set_should_eager_compile();
- }
- }
- Scanner::Location spread_pos;
- typename Traits::Type::ExpressionList args =
- ParseArguments(&spread_pos, classifier, CHECK_OK);
-
- // Keep track of eval() calls since they disable all local variable
- // optimizations.
- // The calls that need special treatment are the
- // direct eval calls. These calls are all of the form eval(...), with
- // no explicit receiver.
- // These calls are marked as potentially direct eval calls. Whether
- // they are actually direct calls to eval is determined at run time.
- this->CheckPossibleEvalCall(result, scope_);
-
- bool is_super_call = result->IsSuperCallReference();
- if (spread_pos.IsValid()) {
- args = Traits::PrepareSpreadArguments(args);
- result = Traits::SpreadCall(result, args, pos);
- } else {
- result = factory()->NewCall(result, args, pos);
- }
-
- // Explicit calls to the super constructor using super() perform an
- // implicit binding assignment to the 'this' variable.
- if (is_super_call) {
- ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
- result =
- factory()->NewAssignment(Token::INIT, this_expr, result, pos);
- }
-
- if (fni_ != NULL) fni_->RemoveLastFunction();
- break;
- }
-
- case Token::PERIOD: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- Consume(Token::PERIOD);
- int pos = position();
- IdentifierT name = ParseIdentifierName(CHECK_OK);
- result = factory()->NewProperty(
- result, factory()->NewStringLiteral(name, pos), pos);
- if (fni_ != NULL) this->PushLiteralName(fni_, name);
- break;
- }
-
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK);
- break;
- }
-
- default:
- return result;
- }
- }
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
- ExpressionClassifier* classifier, bool* ok) {
- // NewExpression ::
- // ('new')+ MemberExpression
- //
- // NewTarget ::
- // 'new' '.' 'target'
-
- // The grammar for new expressions is pretty warped. We can have several 'new'
- // keywords following each other, and then a MemberExpression. When we see '('
- // after the MemberExpression, it's associated with the rightmost unassociated
- // 'new' to create a NewExpression with arguments. However, a NewExpression
- // can also occur without arguments.
-
- // Examples of new expression:
- // new foo.bar().baz means (new (foo.bar)()).baz
- // new foo()() means (new foo())()
- // new new foo()() means (new (new foo())())
- // new new foo means new (new foo)
- // new new foo() means new (new foo())
- // new new foo().bar().baz means (new (new foo()).bar()).baz
-
- if (peek() == Token::NEW) {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- Consume(Token::NEW);
- int new_pos = position();
- ExpressionT result = this->EmptyExpression();
- if (peek() == Token::SUPER) {
- const bool is_new = true;
- result = ParseSuperExpression(is_new, classifier, CHECK_OK);
- } else if (peek() == Token::PERIOD) {
- return ParseNewTargetExpression(CHECK_OK);
- } else {
- result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK);
- }
- if (peek() == Token::LPAREN) {
- // NewExpression with arguments.
- Scanner::Location spread_pos;
- typename Traits::Type::ExpressionList args =
- this->ParseArguments(&spread_pos, classifier, CHECK_OK);
-
- if (spread_pos.IsValid()) {
- args = Traits::PrepareSpreadArguments(args);
- result = Traits::SpreadCallNew(result, args, new_pos);
- } else {
- result = factory()->NewCallNew(result, args, new_pos);
- }
- // The expression can still continue with . or [ after the arguments.
- result =
- this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK);
- return result;
- }
- // NewExpression without arguments.
- return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
- new_pos);
- }
- // No 'new' or 'super' keyword.
- return this->ParseMemberExpression(classifier, ok);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
- bool* ok) {
- // MemberExpression ::
- // (PrimaryExpression | FunctionLiteral | ClassLiteral)
- // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
-
- // The '[' Expression ']' and '.' Identifier parts are parsed by
- // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
- // caller.
-
- // Parse the initial primary or function expression.
- ExpressionT result = this->EmptyExpression();
- if (peek() == Token::FUNCTION) {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
-
- Consume(Token::FUNCTION);
- int function_token_position = position();
- bool is_generator = Check(Token::MUL);
- IdentifierT name = this->EmptyIdentifier();
- bool is_strict_reserved_name = false;
- Scanner::Location function_name_location = Scanner::Location::invalid();
- FunctionLiteral::FunctionType function_type =
- FunctionLiteral::ANONYMOUS_EXPRESSION;
- if (peek_any_identifier()) {
- name = ParseIdentifierOrStrictReservedWord(
- is_generator, &is_strict_reserved_name, CHECK_OK);
- function_name_location = scanner()->location();
- function_type = FunctionLiteral::NAMED_EXPRESSION;
- }
- result = this->ParseFunctionLiteral(
- name, function_name_location,
- is_strict_reserved_name ? kFunctionNameIsStrictReserved
- : kFunctionNameValidityUnknown,
- is_generator ? FunctionKind::kGeneratorFunction
- : FunctionKind::kNormalFunction,
- function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
- language_mode(), CHECK_OK);
- } else if (peek() == Token::SUPER) {
- const bool is_new = false;
- result = ParseSuperExpression(is_new, classifier, CHECK_OK);
- } else {
- result = ParsePrimaryExpression(classifier, CHECK_OK);
- }
-
- result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK);
- return result;
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseStrongInitializationExpression(
- ExpressionClassifier* classifier, bool* ok) {
- // InitializationExpression :: (strong mode)
- // 'this' '.' IdentifierName '=' AssignmentExpression
- // 'this' '[' Expression ']' '=' AssignmentExpression
-
- if (fni_ != NULL) fni_->Enter();
-
- Consume(Token::THIS);
- int pos = position();
- function_state_->set_this_location(scanner()->location());
- ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
-
- ExpressionT left = this->EmptyExpression();
- switch (peek()) {
- case Token::LBRACK: {
- Consume(Token::LBRACK);
- int pos = position();
- ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK);
- left = factory()->NewProperty(this_expr, index, pos);
- if (fni_ != NULL) {
- this->PushPropertyName(fni_, index);
- }
- Expect(Token::RBRACK, CHECK_OK);
- break;
- }
- case Token::PERIOD: {
- Consume(Token::PERIOD);
- int pos = position();
- IdentifierT name = ParseIdentifierName(CHECK_OK);
- left = factory()->NewProperty(
- this_expr, factory()->NewStringLiteral(name, pos), pos);
- if (fni_ != NULL) {
- this->PushLiteralName(fni_, name);
- }
- break;
- }
- default:
- ReportMessage(MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return this->EmptyExpression();
- }
-
- if (peek() != Token::ASSIGN) {
- ReportMessageAt(function_state_->this_location(),
- MessageTemplate::kStrongConstructorThis);
- *ok = false;
- return this->EmptyExpression();
- }
- Consume(Token::ASSIGN);
- left = this->MarkExpressionAsAssigned(left);
-
- ExpressionT right =
- this->ParseAssignmentExpression(true, classifier, CHECK_OK);
- this->CheckAssigningFunctionLiteralToProperty(left, right);
- function_state_->AddProperty();
- if (fni_ != NULL) {
- // Check if the right hand side is a call to avoid inferring a
- // name if we're dealing with "this.a = function(){...}();"-like
- // expression.
- if (!right->IsCall() && !right->IsCallNew()) {
- fni_->Infer();
- } else {
- fni_->RemoveLastFunction();
- }
- fni_->Leave();
- }
-
- if (function_state_->return_location().IsValid()) {
- ReportMessageAt(function_state_->return_location(),
- MessageTemplate::kStrongConstructorReturnMisplaced);
- *ok = false;
- return this->EmptyExpression();
- }
-
- return factory()->NewAssignment(Token::ASSIGN, left, right, pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseStrongSuperCallExpression(
- ExpressionClassifier* classifier, bool* ok) {
- // SuperCallExpression :: (strong mode)
- // 'super' '(' ExpressionList ')'
- BindingPatternUnexpectedToken(classifier);
-
- Consume(Token::SUPER);
- int pos = position();
- Scanner::Location super_loc = scanner()->location();
- ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
-
- if (peek() != Token::LPAREN) {
- ReportMessage(MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return this->EmptyExpression();
- }
-
- Scanner::Location spread_pos;
- typename Traits::Type::ExpressionList args =
- ParseArguments(&spread_pos, classifier, CHECK_OK);
-
- // TODO(rossberg): This doesn't work with arrow functions yet.
- if (!IsSubclassConstructor(function_state_->kind())) {
- ReportMessage(MessageTemplate::kUnexpectedSuper);
- *ok = false;
- return this->EmptyExpression();
- } else if (function_state_->super_location().IsValid()) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongSuperCallDuplicate);
- *ok = false;
- return this->EmptyExpression();
- } else if (function_state_->this_location().IsValid()) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongSuperCallMisplaced);
- *ok = false;
- return this->EmptyExpression();
- } else if (function_state_->return_location().IsValid()) {
- ReportMessageAt(function_state_->return_location(),
- MessageTemplate::kStrongConstructorReturnMisplaced);
- *ok = false;
- return this->EmptyExpression();
- }
-
- function_state_->set_super_location(super_loc);
- if (spread_pos.IsValid()) {
- args = Traits::PrepareSpreadArguments(args);
- expr = Traits::SpreadCall(expr, args, pos);
- } else {
- expr = factory()->NewCall(expr, args, pos);
- }
-
- // Explicit calls to the super constructor using super() perform an implicit
- // binding assignment to the 'this' variable.
- ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
- return factory()->NewAssignment(Token::INIT, this_expr, expr, pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseSuperExpression(bool is_new,
- ExpressionClassifier* classifier,
- bool* ok) {
- Expect(Token::SUPER, CHECK_OK);
- int pos = position();
-
- Scope* scope = scope_->ReceiverScope();
- FunctionKind kind = scope->function_kind();
- if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
- IsClassConstructor(kind)) {
- if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
- scope->RecordSuperPropertyUsage();
- return this->SuperPropertyReference(scope_, factory(), pos);
- }
- // new super() is never allowed.
- // super() is only allowed in derived constructor
- if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) {
- if (is_strong(language_mode())) {
- // Super calls in strong mode are parsed separately.
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kStrongConstructorSuper);
- *ok = false;
- return this->EmptyExpression();
- }
- // TODO(rossberg): This might not be the correct FunctionState for the
- // method here.
- function_state_->set_super_location(scanner()->location());
- return this->SuperCallReference(scope_, factory(), pos);
- }
- }
-
- ReportMessageAt(scanner()->location(), MessageTemplate::kUnexpectedSuper);
- *ok = false;
- return this->EmptyExpression();
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseNewTargetExpression(bool* ok) {
- int pos = position();
- Consume(Token::PERIOD);
- ExpectContextualKeyword(CStrVector("target"), CHECK_OK);
-
- if (!scope_->ReceiverScope()->is_function_scope()) {
- ReportMessageAt(scanner()->location(),
- MessageTemplate::kUnexpectedNewTarget);
- *ok = false;
- return this->EmptyExpression();
- }
-
- return this->NewTargetExpression(scope_, factory(), pos);
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseMemberExpressionContinuation(
- ExpressionT expression, ExpressionClassifier* classifier, bool* ok) {
- // Parses this part of MemberExpression:
- // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
- while (true) {
- switch (peek()) {
- case Token::LBRACK: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
-
- Consume(Token::LBRACK);
- int pos = position();
- ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK);
- expression = factory()->NewProperty(expression, index, pos);
- if (fni_ != NULL) {
- this->PushPropertyName(fni_, index);
- }
- Expect(Token::RBRACK, CHECK_OK);
- break;
- }
- case Token::PERIOD: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
-
- Consume(Token::PERIOD);
- int pos = position();
- IdentifierT name = ParseIdentifierName(CHECK_OK);
- expression = factory()->NewProperty(
- expression, factory()->NewStringLiteral(name, pos), pos);
- if (fni_ != NULL) {
- this->PushLiteralName(fni_, name);
- }
- break;
- }
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL: {
- BindingPatternUnexpectedToken(classifier);
- ArrowFormalParametersUnexpectedToken(classifier);
- int pos;
- if (scanner()->current_token() == Token::IDENTIFIER) {
- pos = position();
- } else {
- pos = peek_position();
- if (expression->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
- // If the tag function looks like an IIFE, set_parenthesized() to
- // force eager compilation.
- expression->AsFunctionLiteral()->set_should_eager_compile();
- }
- }
- expression =
- ParseTemplateLiteral(expression, pos, classifier, CHECK_OK);
- break;
- }
- default:
- return expression;
- }
- }
- DCHECK(false);
- return this->EmptyExpression();
-}
-
-
-template <class Traits>
-void ParserBase<Traits>::ParseFormalParameter(
- FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) {
- // FormalParameter[Yield,GeneratorParameter] :
- // BindingElement[?Yield, ?GeneratorParameter]
- bool is_rest = parameters->has_rest;
-
- Token::Value next = peek();
- ExpressionT pattern = ParsePrimaryExpression(classifier, ok);
- if (!*ok) return;
-
- ValidateBindingPattern(classifier, ok);
- if (!*ok) return;
-
- if (!Traits::IsIdentifier(pattern)) {
- if (is_rest || !allow_harmony_destructuring_bind()) {
- ReportUnexpectedToken(next);
- *ok = false;
- return;
- }
- parameters->is_simple = false;
- ValidateFormalParameterInitializer(classifier, ok);
- if (!*ok) return;
- classifier->RecordNonSimpleParameter();
- }
-
- if (is_rest) {
- parameters->rest_array_literal_index =
- function_state_->NextMaterializedLiteralIndex();
- ++parameters->materialized_literals_count;
- }
-
- ExpressionT initializer = Traits::EmptyExpression();
- if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) {
- ExpressionClassifier init_classifier;
- initializer = ParseAssignmentExpression(true, &init_classifier, ok);
- if (!*ok) return;
- ValidateExpression(&init_classifier, ok);
- ValidateFormalParameterInitializer(&init_classifier, ok);
- if (!*ok) return;
- parameters->is_simple = false;
- classifier->RecordNonSimpleParameter();
- }
-
- Traits::AddFormalParameter(parameters, pattern, initializer,
- scanner()->location().end_pos, is_rest);
-}
-
-
-template <class Traits>
-void ParserBase<Traits>::ParseFormalParameterList(
- FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) {
- // FormalParameters[Yield,GeneratorParameter] :
- // [empty]
- // FormalParameterList[?Yield, ?GeneratorParameter]
- //
- // FormalParameterList[Yield,GeneratorParameter] :
- // FunctionRestParameter[?Yield]
- // FormalsList[?Yield, ?GeneratorParameter]
- // FormalsList[?Yield, ?GeneratorParameter] , FunctionRestParameter[?Yield]
- //
- // FormalsList[Yield,GeneratorParameter] :
- // FormalParameter[?Yield, ?GeneratorParameter]
- // FormalsList[?Yield, ?GeneratorParameter] ,
- // FormalParameter[?Yield,?GeneratorParameter]
-
- DCHECK_EQ(0, parameters->Arity());
-
- if (peek() != Token::RPAREN) {
- do {
- if (parameters->Arity() > Code::kMaxArguments) {
- ReportMessage(MessageTemplate::kTooManyParameters);
- *ok = false;
- return;
- }
- parameters->has_rest =
- allow_harmony_rest_parameters() && Check(Token::ELLIPSIS);
- ParseFormalParameter(parameters, classifier, ok);
- if (!*ok) return;
- } while (!parameters->has_rest && Check(Token::COMMA));
-
- if (parameters->has_rest) {
- parameters->is_simple = false;
- classifier->RecordNonSimpleParameter();
- if (peek() == Token::COMMA) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kParamAfterRest);
- *ok = false;
- return;
- }
- }
- }
-
- for (int i = 0; i < parameters->Arity(); ++i) {
- auto parameter = parameters->at(i);
- Traits::DeclareFormalParameter(parameters->scope, parameter, classifier);
- }
-}
-
-
-template <class Traits>
-void ParserBase<Traits>::CheckArityRestrictions(
- int param_count, FunctionLiteral::ArityRestriction arity_restriction,
- bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) {
- switch (arity_restriction) {
- case FunctionLiteral::GETTER_ARITY:
- if (param_count != 0) {
- ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
- MessageTemplate::kBadGetterArity);
- *ok = false;
- }
- break;
- case FunctionLiteral::SETTER_ARITY:
- if (param_count != 1) {
- ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
- MessageTemplate::kBadSetterArity);
- *ok = false;
- }
- if (has_rest) {
- ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos),
- MessageTemplate::kBadSetterRestParameter);
- *ok = false;
- }
- break;
- default:
- break;
- }
-}
-
-
-template <class Traits>
-bool ParserBase<Traits>::IsNextLetKeyword() {
- DCHECK(peek() == Token::LET);
- if (!allow_let()) {
- return false;
- }
- Token::Value next_next = PeekAhead();
- switch (next_next) {
- case Token::LBRACE:
- case Token::LBRACK:
- case Token::IDENTIFIER:
- case Token::STATIC:
- case Token::LET: // Yes, you can do let let = ... in sloppy mode
- case Token::YIELD:
- return true;
- default:
- return false;
- }
-}
-
-
-template <class Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseArrowFunctionLiteral(
- bool accept_IN, const FormalParametersT& formal_parameters,
- const ExpressionClassifier& formals_classifier, bool* ok) {
- if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
- // ASI inserts `;` after arrow parameters if a line terminator is found.
- // `=> ...` is never a valid expression, so report as syntax error.
- // If next token is not `=>`, it's a syntax error anyways.
- ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW);
- *ok = false;
- return this->EmptyExpression();
- }
-
- typename Traits::Type::StatementList body;
- int num_parameters = formal_parameters.scope->num_parameters();
- int materialized_literal_count = -1;
- int expected_property_count = -1;
- Scanner::Location super_loc;
-
- {
- typename Traits::Type::Factory function_factory(ast_value_factory());
- FunctionState function_state(&function_state_, &scope_,
- formal_parameters.scope, kArrowFunction,
- &function_factory);
-
- function_state.SkipMaterializedLiterals(
- formal_parameters.materialized_literals_count);
-
- this->ReindexLiterals(formal_parameters);
-
- Expect(Token::ARROW, CHECK_OK);
-
- if (peek() == Token::LBRACE) {
- // Multiple statement body
- Consume(Token::LBRACE);
- bool is_lazily_parsed =
- (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation());
- if (is_lazily_parsed) {
- body = this->NewStatementList(0, zone());
- this->SkipLazyFunctionBody(&materialized_literal_count,
- &expected_property_count, CHECK_OK);
-
- if (formal_parameters.materialized_literals_count > 0) {
- materialized_literal_count +=
- formal_parameters.materialized_literals_count;
- }
- } else {
- body = this->ParseEagerFunctionBody(
- this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters,
- kArrowFunction, FunctionLiteral::ANONYMOUS_EXPRESSION, CHECK_OK);
- materialized_literal_count =
- function_state.materialized_literal_count();
- expected_property_count = function_state.expected_property_count();
- }
- } else {
- // Single-expression body
- int pos = position();
- parenthesized_function_ = false;
- ExpressionClassifier classifier;
- ExpressionT expression =
- ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK);
- ValidateExpression(&classifier, CHECK_OK);
- body = this->NewStatementList(1, zone());
- this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK);
- body->Add(factory()->NewReturnStatement(expression, pos), zone());
- materialized_literal_count = function_state.materialized_literal_count();
- expected_property_count = function_state.expected_property_count();
- }
- super_loc = function_state.super_location();
-
- formal_parameters.scope->set_end_position(scanner()->location().end_pos);
-
- // Arrow function formal parameters are parsed as StrictFormalParameterList,
- // which is not the same as "parameters of a strict function"; it only means
- // that duplicates are not allowed. Of course, the arrow function may
- // itself be strict as well.
- const bool allow_duplicate_parameters = false;
- this->ValidateFormalParameters(&formals_classifier, language_mode(),
- allow_duplicate_parameters, CHECK_OK);
-
- // Validate strict mode.
- if (is_strict(language_mode())) {
- CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
- scanner()->location().end_pos, CHECK_OK);
- }
- if (is_strict(language_mode()) || allow_harmony_sloppy()) {
- this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
- }
-
- Traits::RewriteDestructuringAssignments();
- }
-
- FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
- this->EmptyIdentifierString(), ast_value_factory(),
- formal_parameters.scope, body, materialized_literal_count,
- expected_property_count, num_parameters,
- FunctionLiteral::kNoDuplicateParameters,
- FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
- FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction,
- formal_parameters.scope->start_position());
-
- function_literal->set_function_token_position(
- formal_parameters.scope->start_position());
- if (super_loc.IsValid()) function_state_->set_super_location(super_loc);
-
- if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
-
- return function_literal;
-}
-
-
-template <typename Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start,
- ExpressionClassifier* classifier,
- bool* ok) {
- // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
- // text followed by a substitution expression), finalized by a single
- // TEMPLATE_TAIL.
- //
- // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
- // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
- // NoSubstitutionTemplate.
- //
- // When parsing a TemplateLiteral, we must have scanned either an initial
- // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
- CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
-
- // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
- // In this case we may simply consume the token and build a template with a
- // single TEMPLATE_SPAN and no expressions.
- if (peek() == Token::TEMPLATE_TAIL) {
- Consume(Token::TEMPLATE_TAIL);
- int pos = position();
- CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
- typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
- Traits::AddTemplateSpan(&ts, true);
- return Traits::CloseTemplateLiteral(&ts, start, tag);
- }
-
- Consume(Token::TEMPLATE_SPAN);
- int pos = position();
- typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos);
- Traits::AddTemplateSpan(&ts, false);
- Token::Value next;
-
- // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
- // and repeat if the following token is a TEMPLATE_SPAN as well (in this
- // case, representing a TemplateMiddle).
-
- do {
- CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
- next = peek();
- if (next == Token::EOS) {
- ReportMessageAt(Scanner::Location(start, peek_position()),
- MessageTemplate::kUnterminatedTemplate);
- *ok = false;
- return Traits::EmptyExpression();
- } else if (next == Token::ILLEGAL) {
- Traits::ReportMessageAt(
- Scanner::Location(position() + 1, peek_position()),
- MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError);
- *ok = false;
- return Traits::EmptyExpression();
- }
-
- int expr_pos = peek_position();
- ExpressionT expression = this->ParseExpression(true, classifier, CHECK_OK);
- Traits::AddTemplateExpression(&ts, expression);
-
- if (peek() != Token::RBRACE) {
- ReportMessageAt(Scanner::Location(expr_pos, peek_position()),
- MessageTemplate::kUnterminatedTemplateExpr);
- *ok = false;
- return Traits::EmptyExpression();
- }
-
- // If we didn't die parsing that expression, our next token should be a
- // TEMPLATE_SPAN or TEMPLATE_TAIL.
- next = scanner()->ScanTemplateContinuation();
- Next();
- pos = position();
-
- if (next == Token::EOS) {
- ReportMessageAt(Scanner::Location(start, pos),
- MessageTemplate::kUnterminatedTemplate);
- *ok = false;
- return Traits::EmptyExpression();
- } else if (next == Token::ILLEGAL) {
- Traits::ReportMessageAt(
- Scanner::Location(position() + 1, peek_position()),
- MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError);
- *ok = false;
- return Traits::EmptyExpression();
- }
-
- Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL);
- } while (next == Token::TEMPLATE_SPAN);
-
- DCHECK_EQ(next, Token::TEMPLATE_TAIL);
- CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK);
- // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
- return Traits::CloseTemplateLiteral(&ts, start, tag);
-}
-
-
-template <typename Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, bool* ok) {
- return this->CheckAndRewriteReferenceExpression(expression, beg_pos, end_pos,
- message, kReferenceError, ok);
-}
-
-
-template <typename Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, ParseErrorType type, bool* ok) {
- ExpressionClassifier classifier;
- ExpressionT result = ClassifyAndRewriteReferenceExpression(
- &classifier, expression, beg_pos, end_pos, message, type);
- ValidateExpression(&classifier, ok);
- if (!*ok) return this->EmptyExpression();
- return result;
-}
-
-
-template <typename Traits>
-typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ClassifyAndRewriteReferenceExpression(
- ExpressionClassifier* classifier, ExpressionT expression, int beg_pos,
- int end_pos, MessageTemplate::Template message, ParseErrorType type) {
- Scanner::Location location(beg_pos, end_pos);
- if (this->IsIdentifier(expression)) {
- if (is_strict(language_mode()) &&
- this->IsEvalOrArguments(this->AsIdentifier(expression))) {
- classifier->RecordExpressionError(
- location, MessageTemplate::kStrictEvalArguments, kSyntaxError);
- return expression;
- }
- if (is_strong(language_mode()) &&
- this->IsUndefined(this->AsIdentifier(expression))) {
- classifier->RecordExpressionError(
- location, MessageTemplate::kStrongUndefined, kSyntaxError);
- return expression;
- }
- }
- if (expression->IsValidReferenceExpression()) {
- return expression;
- } else if (expression->IsCall()) {
- // If it is a call, make it a runtime error for legacy web compatibility.
- // Rewrite `expr' to `expr[throw ReferenceError]'.
- int pos = location.beg_pos;
- ExpressionT error = this->NewThrowReferenceError(message, pos);
- return factory()->NewProperty(expression, error, pos);
- } else {
- classifier->RecordExpressionError(location, message, type);
- return expression;
- }
-}
-
-
-template <typename Traits>
-bool ParserBase<Traits>::IsValidReferenceExpression(ExpressionT expression) {
- return this->IsAssignableIdentifier(expression) || expression->IsProperty();
-}
-
-
-template <typename Traits>
-void ParserBase<Traits>::CheckDestructuringElement(
- ExpressionT expression, ExpressionClassifier* classifier, int begin,
- int end) {
- static const MessageTemplate::Template message =
- MessageTemplate::kInvalidDestructuringTarget;
- if (!this->IsAssignableIdentifier(expression)) {
- const Scanner::Location location(begin, end);
- classifier->RecordBindingPatternError(location, message);
- if (!expression->IsProperty() &&
- !(expression->IsObjectLiteral() || expression->IsArrayLiteral())) {
- classifier->RecordAssignmentPatternError(location, message);
- }
- }
-}
-
-
-#undef CHECK_OK
-#undef CHECK_OK_CUSTOM
-
-
-template <typename Traits>
-void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
- Token::Value property, PropertyKind type, bool is_static, bool is_generator,
- bool* ok) {
- DCHECK(!is_static);
- DCHECK(!is_generator || type == kMethodProperty);
-
- if (property == Token::SMI || property == Token::NUMBER) return;
-
- if (type == kValueProperty && IsProto()) {
- if (has_seen_proto_) {
- this->parser()->ReportMessage(MessageTemplate::kDuplicateProto);
- *ok = false;
- return;
- }
- has_seen_proto_ = true;
- return;
- }
-}
-
-
-template <typename Traits>
-void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
- Token::Value property, PropertyKind type, bool is_static, bool is_generator,
- bool* ok) {
- DCHECK(type == kMethodProperty || type == kAccessorProperty);
-
- if (property == Token::SMI || property == Token::NUMBER) return;
-
- if (is_static) {
- if (IsPrototype()) {
- this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
- *ok = false;
- return;
- }
- } else if (IsConstructor()) {
- if (is_generator || type == kAccessorProperty) {
- MessageTemplate::Template msg =
- is_generator ? MessageTemplate::kConstructorIsGenerator
- : MessageTemplate::kConstructorIsAccessor;
- this->parser()->ReportMessage(msg);
- *ok = false;
- return;
- }
- if (has_seen_constructor_) {
- this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor);
- *ok = false;
- return;
- }
- has_seen_constructor_ = true;
- return;
- }
-}
} // namespace internal
} // namespace v8
« no previous file with comments | « src/parsing/parser-base.h ('k') | src/parsing/preparser.cc » ('j') | src/parsing/preparser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698