// interface as AstNodeFactory, so ParserBase doesn't need to care which one is
// used.
-// - Miscellanous other tasks interleaved with the recursive descent. For
+// - 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.
typedef typename Traits::Type::Expression ExpressionT;
typedef typename Traits::Type::Identifier IdentifierT;
typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
+ typedef typename Traits::Type::Literal LiteralT;
+ typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
ParserBase(Scanner* scanner, uintptr_t stack_limit, v8::Extension* extension,
ParserRecorder* log, typename Traits::Type::Zone* zone,
ExpressionT ParseExpression(bool accept_IN, bool* ok);
ExpressionT ParseArrayLiteral(bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
+ ObjectLiteralPropertyT ParsePropertyDefinition(bool* ok);
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
}
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
- PreParserScope* scope, PreParserExpression value, bool* has_function) {}
+ PreParserScope* scope, PreParserExpression property, bool* has_function) {
+ }
static void CheckAssigningFunctionLiteralToProperty(
PreParserExpression left, PreParserExpression right) {}
static PreParserExpression EmptyLiteral() {
return PreParserExpression::Default();
}
+ static PreParserExpression EmptyObjectLiteralProperty() {
+ return PreParserExpression::Default();
+ }
static PreParserExpressionList NullExpressionList() {
return PreParserExpressionList();
}
template <class Traits>
+typename ParserBase<Traits>::ObjectLiteralPropertyT
+ParserBase<Traits>::ParsePropertyDefinition(bool* ok) {
+ LiteralT key = this->EmptyLiteral();
+ Token::Value next = peek();
+ int next_pos = peek_position();
+
+ switch (next) {
+ case Token::STRING: {
+ Consume(Token::STRING);
+ IdentifierT string = this->GetSymbol(scanner_);
+ if (fni_ != NULL) this->PushLiteralName(fni_, string);
+ uint32_t index;
+ if (this->IsArrayIndex(string, &index)) {
+ key = factory()->NewNumberLiteral(index, next_pos);
+ break;
+ }
+ key = factory()->NewStringLiteral(string, next_pos);
+ break;
+ }
+ case Token::NUMBER: {
+ Consume(Token::NUMBER);
+ key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
+ factory());
+ break;
+ }
+ default: {
+ bool is_getter = false;
+ bool is_setter = false;
+ IdentifierT id = ParseIdentifierNameOrGetOrSet(
+ &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ if (fni_ != NULL) this->PushLiteralName(fni_, id);
+
+ if ((is_getter || is_setter) && peek() != Token::COLON) {
+ // Special handling of getter and setter syntax:
+ // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
+ // We have already read the "get" or "set" keyword.
+ IdentifierT name = this->EmptyIdentifier();
+ switch (peek()) {
+ case Token::STRING:
+ Consume(Token::STRING);
+ name = this->GetSymbol(scanner_);
+ break;
+ case Token::NUMBER:
+ Consume(Token::NUMBER);
+ // TODO(arv): Fix issue with numeric keys. get 1.0() should be
+ // treated as if the key was '1'
+ // https://code.google.com/p/v8/issues/detail?id=3507
+ name = this->GetSymbol(scanner_);
+ break;
+ default:
+ name = ParseIdentifierName(
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ }
+ typename Traits::Type::FunctionLiteral value =
+ this->ParseFunctionLiteral(
+ name, scanner()->location(),
+ false, // reserved words are allowed here
+ false, // not a generator
+ RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
+ is_getter ? FunctionLiteral::GETTER_ARITY
+ : FunctionLiteral::SETTER_ARITY,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+ }
+ // Failed to parse as get/set property, so it's just a normal property
+ // (which might be called "get" or "set" or something else).
+ key = factory()->NewStringLiteral(id, next_pos);
+ }
+ }
+
+ Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ ExpressionT value = this->ParseAssignmentExpression(
+ true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+ return factory()->NewObjectLiteralProperty(key, value);
+}
+
+
+template <class Traits>
typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
bool* ok) {
// ObjectLiteral ::
- // '{' ((
- // ((IdentifierName | String | Number) ':' AssignmentExpression) |
- // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
- // ) ',')* '}'
- // (Except that the trailing comma is not required.)
+ // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
int pos = peek_position();
typename Traits::Type::PropertyList properties =
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
- typename Traits::Type::Literal key = this->EmptyLiteral();
- Token::Value next = peek();
- int next_pos = peek_position();
-
- switch (next) {
- case Token::FUTURE_RESERVED_WORD:
- case Token::FUTURE_STRICT_RESERVED_WORD:
- case Token::LET:
- case Token::YIELD:
- case Token::IDENTIFIER: {
- bool is_getter = false;
- bool is_setter = false;
- IdentifierT id =
- ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
- if (fni_ != NULL) this->PushLiteralName(fni_, id);
-
- if ((is_getter || is_setter) && peek() != Token::COLON) {
- // Special handling of getter and setter syntax:
- // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
- // We have already read the "get" or "set" keyword.
- Token::Value next = Next();
- if (next != i::Token::IDENTIFIER &&
- next != i::Token::FUTURE_RESERVED_WORD &&
- next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
- next != i::Token::LET &&
- next != i::Token::YIELD &&
- next != i::Token::NUMBER &&
- next != i::Token::STRING &&
- !Token::IsKeyword(next)) {
- ReportUnexpectedToken(next);
- *ok = false;
- return this->EmptyLiteral();
- }
- IdentifierT name = this->GetSymbol(scanner_);
- typename Traits::Type::FunctionLiteral value =
- this->ParseFunctionLiteral(
- name, scanner()->location(),
- false, // reserved words are allowed here
- false, // not a generator
- RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
- is_getter ? FunctionLiteral::GETTER_ARITY
- : FunctionLiteral::SETTER_ARITY,
- CHECK_OK);
- typename Traits::Type::ObjectLiteralProperty property =
- factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
- if (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_ != NULL) {
- fni_->Infer();
- fni_->Leave();
- }
- continue; // restart the while
- }
- // Failed to parse as get/set property, so it's just a normal property
- // (which might be called "get" or "set" or something else).
- key = factory()->NewStringLiteral(id, next_pos);
- break;
- }
- case Token::STRING: {
- Consume(Token::STRING);
- IdentifierT string = this->GetSymbol(scanner_);
- if (fni_ != NULL) this->PushLiteralName(fni_, string);
- uint32_t index;
- if (this->IsArrayIndex(string, &index)) {
- key = factory()->NewNumberLiteral(index, next_pos);
- break;
- }
- key = factory()->NewStringLiteral(string, next_pos);
- break;
- }
- case Token::NUMBER: {
- Consume(Token::NUMBER);
- key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
- factory());
- break;
- }
- default:
- if (Token::IsKeyword(next)) {
- Consume(next);
- IdentifierT string = this->GetSymbol(scanner_);
- key = factory()->NewStringLiteral(string, next_pos);
- } else {
- Token::Value next = Next();
- ReportUnexpectedToken(next);
- *ok = false;
- return this->EmptyLiteral();
- }
- }
-
- Expect(Token::COLON, CHECK_OK);
- ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK);
-
- typename Traits::Type::ObjectLiteralProperty property =
- factory()->NewObjectLiteralProperty(key, value);
+ ObjectLiteralPropertyT property = this->ParsePropertyDefinition(CHECK_OK);
// 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_, value,
+ this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property,
&has_function);
// Count CONSTANT or COMPUTED properties to maintain the enumeration order.