Unify several checking methods between parser and pre-parser.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/27206002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17207 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 75a02eb2
...@@ -3025,7 +3025,7 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) { ...@@ -3025,7 +3025,7 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
} }
static int Precedence(Token::Value tok, bool accept_IN) { int ParserBase::Precedence(Token::Value tok, bool accept_IN) {
if (tok == Token::IN && !accept_IN) if (tok == Token::IN && !accept_IN)
return 0; // 0 precedence will terminate binary expression parsing return 0; // 0 precedence will terminate binary expression parsing
...@@ -3845,11 +3845,6 @@ void Parser::BuildObjectLiteralConstantProperties( ...@@ -3845,11 +3845,6 @@ void Parser::BuildObjectLiteralConstantProperties(
} }
// Force instantiation of template instances class.
template void ObjectLiteralChecker<Parser>::CheckProperty(
Token::Value property, PropertyKind type, bool* ok);
Expression* Parser::ParseObjectLiteral(bool* ok) { Expression* Parser::ParseObjectLiteral(bool* ok) {
// ObjectLiteral :: // ObjectLiteral ::
// '{' ( // '{' (
...@@ -3863,8 +3858,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { ...@@ -3863,8 +3858,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
int number_of_boilerplate_properties = 0; int number_of_boilerplate_properties = 0;
bool has_function = false; bool has_function = false;
ObjectLiteralChecker<Parser> checker(this, &scanner_, ObjectLiteralChecker checker(this, top_scope_->language_mode());
top_scope_->language_mode());
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);
...@@ -4618,9 +4612,9 @@ bool ParserBase::peek_any_identifier() { ...@@ -4618,9 +4612,9 @@ bool ParserBase::peek_any_identifier() {
} }
bool Parser::CheckContextualKeyword(Vector<const char> keyword) { bool ParserBase::CheckContextualKeyword(Vector<const char> keyword) {
if (peek() == Token::IDENTIFIER && if (peek() == Token::IDENTIFIER &&
scanner().is_next_contextual_keyword(keyword)) { scanner()->is_next_contextual_keyword(keyword)) {
Consume(Token::IDENTIFIER); Consume(Token::IDENTIFIER);
return true; return true;
} }
...@@ -4645,12 +4639,12 @@ void ParserBase::ExpectSemicolon(bool* ok) { ...@@ -4645,12 +4639,12 @@ void ParserBase::ExpectSemicolon(bool* ok) {
} }
void Parser::ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { void ParserBase::ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
Expect(Token::IDENTIFIER, ok); Expect(Token::IDENTIFIER, ok);
if (!*ok) return; if (!*ok) return;
if (!scanner().is_literal_contextual_keyword(keyword)) { if (!scanner()->is_literal_contextual_keyword(keyword)) {
ReportUnexpectedToken(scanner()->current_token());
*ok = false; *ok = false;
ReportUnexpectedToken(scanner().current_token());
} }
} }
...@@ -4745,14 +4739,11 @@ void Parser::CheckStrictModeLValue(Expression* expression, ...@@ -4745,14 +4739,11 @@ void Parser::CheckStrictModeLValue(Expression* expression,
// Checks whether an octal literal was last seen between beg_pos and end_pos. // Checks whether an octal literal was last seen between beg_pos and end_pos.
// If so, reports an error. Only called for strict mode. // If so, reports an error. Only called for strict mode.
void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { void ParserBase::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Scanner::Location octal = scanner().octal_position(); Scanner::Location octal = scanner()->octal_position();
if (octal.IsValid() && if (octal.IsValid() && beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
beg_pos <= octal.beg_pos && ReportMessageAt(octal, "strict_octal_literal");
octal.end_pos <= end_pos) { scanner()->clear_octal_position();
ReportMessageAt(octal, "strict_octal_literal",
Vector<const char*>::empty());
scanner().clear_octal_position();
*ok = false; *ok = false;
} }
} }
......
...@@ -439,13 +439,6 @@ class Parser : public ParserBase { ...@@ -439,13 +439,6 @@ class Parser : public ParserBase {
static bool Parse(CompilationInfo* info) { return Parser(info).Parse(); } static bool Parse(CompilationInfo* info) { return Parser(info).Parse(); }
bool Parse(); bool Parse();
void ReportMessageAt(Scanner::Location loc,
const char* message,
Vector<const char*> args = Vector<const char*>::empty());
void ReportMessageAt(Scanner::Location loc,
const char* message,
Vector<Handle<String> > args);
private: private:
static const int kMaxNumFunctionLocals = 131071; // 2^17-1 static const int kMaxNumFunctionLocals = 131071; // 2^17-1
...@@ -562,6 +555,15 @@ class Parser : public ParserBase { ...@@ -562,6 +555,15 @@ class Parser : public ParserBase {
void ReportInvalidPreparseData(Handle<String> name, bool* ok); void ReportInvalidPreparseData(Handle<String> name, bool* ok);
void ReportMessage(const char* message, Vector<const char*> args); void ReportMessage(const char* message, Vector<const char*> args);
void ReportMessage(const char* message, Vector<Handle<String> > args); void ReportMessage(const char* message, Vector<Handle<String> > args);
void ReportMessageAt(Scanner::Location location, const char* type) {
ReportMessageAt(location, type, Vector<const char*>::empty());
}
void ReportMessageAt(Scanner::Location loc,
const char* message,
Vector<const char*> args);
void ReportMessageAt(Scanner::Location loc,
const char* message,
Vector<Handle<String> > args);
void set_pre_parse_data(ScriptDataImpl *data) { void set_pre_parse_data(ScriptDataImpl *data) {
pre_parse_data_ = data; pre_parse_data_ = data;
...@@ -570,8 +572,6 @@ class Parser : public ParserBase { ...@@ -570,8 +572,6 @@ class Parser : public ParserBase {
bool inside_with() const { return top_scope_->inside_with(); } bool inside_with() const { return top_scope_->inside_with(); }
Scanner& scanner() { return scanner_; } Scanner& scanner() { return scanner_; }
int position() { return scanner_.location().beg_pos; }
int peek_position() { return scanner_.peek_location().beg_pos; }
Mode mode() const { return mode_; } Mode mode() const { return mode_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; } ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
bool is_extended_mode() { bool is_extended_mode() {
...@@ -694,9 +694,6 @@ class Parser : public ParserBase { ...@@ -694,9 +694,6 @@ class Parser : public ParserBase {
bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode); bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
bool CheckContextualKeyword(Vector<const char> keyword);
void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
Handle<String> LiteralString(PretenureFlag tenured) { Handle<String> LiteralString(PretenureFlag tenured) {
if (scanner().is_literal_ascii()) { if (scanner().is_literal_ascii()) {
return isolate_->factory()->NewStringFromAscii( return isolate_->factory()->NewStringFromAscii(
...@@ -741,9 +738,6 @@ class Parser : public ParserBase { ...@@ -741,9 +738,6 @@ class Parser : public ParserBase {
const char* error, const char* error,
bool* ok); bool* ok);
// Strict mode octal literal validation.
void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
// For harmony block scoping mode: Check if the scope has conflicting var/let // For harmony block scoping mode: Check if the scope has conflicting var/let
// declarations from different scopes. It covers for example // declarations from different scopes. It covers for example
// //
...@@ -826,7 +820,6 @@ class Parser : public ParserBase { ...@@ -826,7 +820,6 @@ class Parser : public ParserBase {
CompilationInfo* info_; CompilationInfo* info_;
friend class BlockState; friend class BlockState;
friend class FunctionState; friend class FunctionState;
friend class ObjectLiteralChecker<Parser>;
}; };
......
...@@ -65,7 +65,7 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( ...@@ -65,7 +65,7 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
function_scope.set_is_generator(is_generator); function_scope.set_is_generator(is_generator);
ASSERT_EQ(i::Token::LBRACE, scanner()->current_token()); ASSERT_EQ(i::Token::LBRACE, scanner()->current_token());
bool ok = true; bool ok = true;
int start_position = scanner()->peek_location().beg_pos; int start_position = peek_position();
ParseLazyFunctionLiteralBody(&ok); ParseLazyFunctionLiteralBody(&ok);
if (stack_overflow()) return kPreParseStackOverflow; if (stack_overflow()) return kPreParseStackOverflow;
if (!ok) { if (!ok) {
...@@ -129,18 +129,6 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) { ...@@ -129,18 +129,6 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) {
} }
// Checks whether octal literal last seen is between beg_pos and end_pos.
// If so, reports an error.
void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
i::Scanner::Location octal = scanner()->octal_position();
if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
ReportMessageAt(octal, "strict_octal_literal", NULL);
scanner()->clear_octal_position();
*ok = false;
}
}
#define CHECK_OK ok); \ #define CHECK_OK ok); \
if (!*ok) return kUnknownSourceElements; \ if (!*ok) return kUnknownSourceElements; \
((void)0 ((void)0
...@@ -659,10 +647,9 @@ PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { ...@@ -659,10 +647,9 @@ PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
bool PreParser::CheckInOrOf(bool accept_OF) { bool PreParser::CheckInOrOf(bool accept_OF) {
if (peek() == i::Token::IN || if (Check(Token::IN) ||
(allow_for_of() && accept_OF && peek() == i::Token::IDENTIFIER && (allow_for_of() && accept_OF &&
scanner()->is_next_contextual_keyword(v8::internal::CStrVector("of")))) { CheckContextualKeyword(CStrVector("of")))) {
Next();
return true; return true;
} }
return false; return false;
...@@ -901,14 +888,6 @@ PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN, ...@@ -901,14 +888,6 @@ PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
} }
int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
if (tok == i::Token::IN && !accept_IN)
return 0; // 0 precedence will terminate binary expression parsing
return i::Token::Precedence(tok);
}
// Precedence >= 4 // Precedence >= 4
PreParser::Expression PreParser::ParseBinaryExpression(int prec, PreParser::Expression PreParser::ParseBinaryExpression(int prec,
bool accept_IN, bool accept_IN,
...@@ -1238,7 +1217,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -1238,7 +1217,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
// )*[','] '}' // )*[','] '}'
i::ObjectLiteralChecker<PreParser> checker(this, scanner(), language_mode()); ObjectLiteralChecker checker(this, language_mode());
Expect(i::Token::LBRACE, CHECK_OK); Expect(i::Token::LBRACE, CHECK_OK);
while (peek() != i::Token::RBRACE) { while (peek() != i::Token::RBRACE) {
...@@ -1265,8 +1244,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -1265,8 +1244,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
if (!is_keyword) { if (!is_keyword) {
LogSymbol(); LogSymbol();
} }
i::PropertyKind type = is_getter ? i::kGetterProperty PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
: i::kSetterProperty;
checker.CheckProperty(name, type, CHECK_OK); checker.CheckProperty(name, type, CHECK_OK);
ParseFunctionLiteral(false, CHECK_OK); ParseFunctionLiteral(false, CHECK_OK);
if (peek() != i::Token::RBRACE) { if (peek() != i::Token::RBRACE) {
...@@ -1274,22 +1252,22 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -1274,22 +1252,22 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
} }
continue; // restart the while continue; // restart the while
} }
checker.CheckProperty(next, i::kValueProperty, CHECK_OK); checker.CheckProperty(next, kValueProperty, CHECK_OK);
break; break;
} }
case i::Token::STRING: case i::Token::STRING:
Consume(next); Consume(next);
checker.CheckProperty(next, i::kValueProperty, CHECK_OK); checker.CheckProperty(next, kValueProperty, CHECK_OK);
GetStringSymbol(); GetStringSymbol();
break; break;
case i::Token::NUMBER: case i::Token::NUMBER:
Consume(next); Consume(next);
checker.CheckProperty(next, i::kValueProperty, CHECK_OK); checker.CheckProperty(next, kValueProperty, CHECK_OK);
break; break;
default: default:
if (i::Token::IsKeyword(next)) { if (i::Token::IsKeyword(next)) {
Consume(next); Consume(next);
checker.CheckProperty(next, i::kValueProperty, CHECK_OK); checker.CheckProperty(next, kValueProperty, CHECK_OK);
} else { } else {
// Unexpected token. // Unexpected token.
*ok = false; *ok = false;
...@@ -1368,7 +1346,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator, ...@@ -1368,7 +1346,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
// FormalParameterList :: // FormalParameterList ::
// '(' (Identifier)*[','] ')' // '(' (Identifier)*[','] ')'
Expect(i::Token::LPAREN, CHECK_OK); Expect(i::Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos; int start_position = position();
bool done = (peek() == i::Token::RPAREN); bool done = (peek() == i::Token::RPAREN);
i::DuplicateFinder duplicate_finder(scanner()->unicode_cache()); i::DuplicateFinder duplicate_finder(scanner()->unicode_cache());
while (!done) { while (!done) {
...@@ -1428,7 +1406,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator, ...@@ -1428,7 +1406,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
int body_start = scanner()->location().beg_pos; int body_start = position();
log_->PauseRecording(); log_->PauseRecording();
ParseSourceElements(i::Token::RBRACE, ok); ParseSourceElements(i::Token::RBRACE, ok);
log_->ResumeRecording(); log_->ResumeRecording();
...@@ -1462,7 +1440,7 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { ...@@ -1462,7 +1440,7 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
void PreParser::LogSymbol() { void PreParser::LogSymbol() {
int identifier_pos = scanner()->location().beg_pos; int identifier_pos = position();
if (scanner()->is_literal_ascii()) { if (scanner()->is_literal_ascii()) {
log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string()); log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string());
} else { } else {
...@@ -1602,7 +1580,7 @@ void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, ...@@ -1602,7 +1580,7 @@ void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
i::Token::Value next = Next(); i::Token::Value next = Next();
if (i::Token::IsKeyword(next)) { if (i::Token::IsKeyword(next)) {
int pos = scanner()->location().beg_pos; int pos = position();
const char* keyword = i::Token::String(next); const char* keyword = i::Token::String(next);
log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
i::StrLength(keyword))); i::StrLength(keyword)));
...@@ -1637,4 +1615,36 @@ PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get, ...@@ -1637,4 +1615,36 @@ PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
} }
void PreParser::ObjectLiteralChecker::CheckProperty(Token::Value property,
PropertyKind type,
bool* ok) {
int old;
if (property == Token::NUMBER) {
old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
} else if (scanner()->is_literal_ascii()) {
old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
} else {
old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
}
PropertyKind old_type = static_cast<PropertyKind>(old);
if (HasConflict(old_type, type)) {
if (IsDataDataConflict(old_type, type)) {
// Both are data properties.
if (language_mode_ == CLASSIC_MODE) return;
parser()->ReportMessageAt(scanner()->location(),
"strict_duplicate_property");
} else if (IsDataAccessorConflict(old_type, type)) {
// Both a data and an accessor property with the same name.
parser()->ReportMessageAt(scanner()->location(),
"accessor_data_property");
} else {
ASSERT(IsAccessorAccessorConflict(old_type, type));
// Both accessors of the same type.
parser()->ReportMessageAt(scanner()->location(),
"accessor_get_set");
}
*ok = false;
}
}
} } // v8::internal } } // v8::internal
...@@ -35,96 +35,6 @@ ...@@ -35,96 +35,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// Used to detect duplicates in object literals. Each of the values
// kGetterProperty, kSetterProperty and kValueProperty represents
// a type of object literal property. When parsing a property, its
// type value is stored in the DuplicateFinder for the property name.
// Values are chosen so that having intersection bits means the there is
// an incompatibility.
// I.e., you can add a getter to a property that already has a setter, since
// kGetterProperty and kSetterProperty doesn't intersect, but not if it
// already has a getter or a value. Adding the getter to an existing
// setter will store the value (kGetterProperty | kSetterProperty), which
// is incompatible with adding any further properties.
enum PropertyKind {
kNone = 0,
// Bit patterns representing different object literal property types.
kGetterProperty = 1,
kSetterProperty = 2,
kValueProperty = 7,
// Helper constants.
kValueFlag = 4
};
// Validation per 11.1.5 Object Initialiser
template<typename P>
class ObjectLiteralChecker {
public:
ObjectLiteralChecker(P* parser, Scanner* scanner, LanguageMode mode)
: parser_(parser),
scanner_(scanner),
finder_(scanner->unicode_cache()),
language_mode_(mode) { }
void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
private:
// Checks the type of conflict based on values coming from PropertyType.
bool HasConflict(PropertyKind type1, PropertyKind type2) {
return (type1 & type2) != 0;
}
bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
return ((type1 & type2) & kValueFlag) != 0;
}
bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
return ((type1 ^ type2) & kValueFlag) != 0;
}
bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
return ((type1 | type2) & kValueFlag) == 0;
}
P* parser_;
Scanner* scanner_;
DuplicateFinder finder_;
LanguageMode language_mode_;
};
template<typename P>
void ObjectLiteralChecker<P>::CheckProperty(Token::Value property,
PropertyKind type,
bool* ok) {
int old;
if (property == Token::NUMBER) {
old = finder_.AddNumber(scanner_->literal_ascii_string(), type);
} else if (scanner_->is_literal_ascii()) {
old = finder_.AddAsciiSymbol(scanner_->literal_ascii_string(), type);
} else {
old = finder_.AddUtf16Symbol(scanner_->literal_utf16_string(), type);
}
PropertyKind old_type = static_cast<PropertyKind>(old);
if (HasConflict(old_type, type)) {
if (IsDataDataConflict(old_type, type)) {
// Both are data properties.
if (language_mode_ == CLASSIC_MODE) return;
parser_->ReportMessageAt(scanner_->location(),
"strict_duplicate_property");
} else if (IsDataAccessorConflict(old_type, type)) {
// Both a data and an accessor property with the same name.
parser_->ReportMessageAt(scanner_->location(),
"accessor_data_property");
} else {
ASSERT(IsAccessorAccessorConflict(old_type, type));
// Both accessors of the same type.
parser_->ReportMessageAt(scanner_->location(),
"accessor_get_set");
}
*ok = false;
}
}
// Common base class shared between parser and pre-parser. // Common base class shared between parser and pre-parser.
class ParserBase { class ParserBase {
public: public:
...@@ -167,6 +77,8 @@ class ParserBase { ...@@ -167,6 +77,8 @@ class ParserBase {
protected: protected:
Scanner* scanner() const { return scanner_; } Scanner* scanner() const { return scanner_; }
int position() { return scanner_->location().beg_pos; }
int peek_position() { return scanner_->peek_location().beg_pos; }
bool stack_overflow() const { return stack_overflow_; } bool stack_overflow() const { return stack_overflow_; }
void set_stack_overflow() { stack_overflow_ = true; } void set_stack_overflow() { stack_overflow_ = true; }
...@@ -215,9 +127,72 @@ class ParserBase { ...@@ -215,9 +127,72 @@ class ParserBase {
bool peek_any_identifier(); bool peek_any_identifier();
void ExpectSemicolon(bool* ok); void ExpectSemicolon(bool* ok);
bool CheckContextualKeyword(Vector<const char> keyword);
void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
// Strict mode octal literal validation.
void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
// Determine precedence of given token.
static int Precedence(Token::Value token, bool accept_IN);
// Report syntax errors. // Report syntax errors.
virtual void ReportUnexpectedToken(Token::Value token) = 0; virtual void ReportUnexpectedToken(Token::Value token) = 0;
virtual void ReportMessageAt(Scanner::Location loc, const char* type) = 0;
// Used to detect duplicates in object literals. Each of the values
// kGetterProperty, kSetterProperty and kValueProperty represents
// a type of object literal property. When parsing a property, its
// type value is stored in the DuplicateFinder for the property name.
// Values are chosen so that having intersection bits means the there is
// an incompatibility.
// I.e., you can add a getter to a property that already has a setter, since
// kGetterProperty and kSetterProperty doesn't intersect, but not if it
// already has a getter or a value. Adding the getter to an existing
// setter will store the value (kGetterProperty | kSetterProperty), which
// is incompatible with adding any further properties.
enum PropertyKind {
kNone = 0,
// Bit patterns representing different object literal property types.
kGetterProperty = 1,
kSetterProperty = 2,
kValueProperty = 7,
// Helper constants.
kValueFlag = 4
};
// Validation per ECMA 262 - 11.1.5 "Object Initialiser".
class ObjectLiteralChecker {
public:
ObjectLiteralChecker(ParserBase* parser, LanguageMode mode)
: parser_(parser),
finder_(scanner()->unicode_cache()),
language_mode_(mode) { }
void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
private:
ParserBase* parser() const { return parser_; }
Scanner* scanner() const { return parser_->scanner(); }
// Checks the type of conflict based on values coming from PropertyType.
bool HasConflict(PropertyKind type1, PropertyKind type2) {
return (type1 & type2) != 0;
}
bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) {
return ((type1 & type2) & kValueFlag) != 0;
}
bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) {
return ((type1 ^ type2) & kValueFlag) != 0;
}
bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) {
return ((type1 | type2) & kValueFlag) == 0;
}
ParserBase* parser_;
DuplicateFinder finder_;
LanguageMode language_mode_;
};
private: private:
Scanner* scanner_; Scanner* scanner_;
...@@ -254,14 +229,13 @@ class PreParser : public ParserBase { ...@@ -254,14 +229,13 @@ class PreParser : public ParserBase {
kPreParseSuccess kPreParseSuccess
}; };
PreParser(Scanner* scanner,
PreParser(i::Scanner* scanner, ParserRecorder* log,
i::ParserRecorder* log,
uintptr_t stack_limit) uintptr_t stack_limit)
: ParserBase(scanner, stack_limit), : ParserBase(scanner, stack_limit),
log_(log), log_(log),
scope_(NULL), scope_(NULL),
strict_mode_violation_location_(i::Scanner::Location::invalid()), strict_mode_violation_location_(Scanner::Location::invalid()),
strict_mode_violation_type_(NULL), strict_mode_violation_type_(NULL),
parenthesized_function_(false) { } parenthesized_function_(false) { }
...@@ -275,7 +249,7 @@ class PreParser : public ParserBase { ...@@ -275,7 +249,7 @@ class PreParser : public ParserBase {
Scope top_scope(&scope_, kTopLevelScope); Scope top_scope(&scope_, kTopLevelScope);
bool ok = true; bool ok = true;
int start_position = scanner()->peek_location().beg_pos; int start_position = scanner()->peek_location().beg_pos;
ParseSourceElements(i::Token::EOS, &ok); ParseSourceElements(Token::EOS, &ok);
if (stack_overflow()) return kPreParseStackOverflow; if (stack_overflow()) return kPreParseStackOverflow;
if (!ok) { if (!ok) {
ReportUnexpectedToken(scanner()->current_token()); ReportUnexpectedToken(scanner()->current_token());
...@@ -293,9 +267,9 @@ class PreParser : public ParserBase { ...@@ -293,9 +267,9 @@ class PreParser : public ParserBase {
// keyword and parameters, and have consumed the initial '{'. // keyword and parameters, and have consumed the initial '{'.
// At return, unless an error occurred, the scanner is positioned before the // At return, unless an error occurred, the scanner is positioned before the
// the final '}'. // the final '}'.
PreParseResult PreParseLazyFunction(i::LanguageMode mode, PreParseResult PreParseLazyFunction(LanguageMode mode,
bool is_generator, bool is_generator,
i::ParserRecorder* log); ParserRecorder* log);
private: private:
// These types form an algebra over syntactic categories that is just // These types form an algebra over syntactic categories that is just
...@@ -556,7 +530,7 @@ class PreParser : public ParserBase { ...@@ -556,7 +530,7 @@ class PreParser : public ParserBase {
expected_properties_(0), expected_properties_(0),
with_nesting_count_(0), with_nesting_count_(0),
language_mode_( language_mode_(
(prev_ != NULL) ? prev_->language_mode() : i::CLASSIC_MODE), (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
is_generator_(false) { is_generator_(false) {
*variable = this; *variable = this;
} }
...@@ -570,12 +544,12 @@ class PreParser : public ParserBase { ...@@ -570,12 +544,12 @@ class PreParser : public ParserBase {
bool is_generator() { return is_generator_; } bool is_generator() { return is_generator_; }
void set_is_generator(bool is_generator) { is_generator_ = is_generator; } void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
bool is_classic_mode() { bool is_classic_mode() {
return language_mode_ == i::CLASSIC_MODE; return language_mode_ == CLASSIC_MODE;
} }
i::LanguageMode language_mode() { LanguageMode language_mode() {
return language_mode_; return language_mode_;
} }
void set_language_mode(i::LanguageMode language_mode) { void set_language_mode(LanguageMode language_mode) {
language_mode_ = language_mode; language_mode_ = language_mode;
} }
...@@ -599,15 +573,18 @@ class PreParser : public ParserBase { ...@@ -599,15 +573,18 @@ class PreParser : public ParserBase {
int materialized_literal_count_; int materialized_literal_count_;
int expected_properties_; int expected_properties_;
int with_nesting_count_; int with_nesting_count_;
i::LanguageMode language_mode_; LanguageMode language_mode_;
bool is_generator_; bool is_generator_;
}; };
// Report syntax error // Report syntax error
void ReportUnexpectedToken(i::Token::Value token); void ReportUnexpectedToken(Token::Value token);
void ReportMessageAt(i::Scanner::Location location, void ReportMessageAt(Scanner::Location location, const char* type) {
ReportMessageAt(location, type, NULL);
}
void ReportMessageAt(Scanner::Location location,
const char* type, const char* type,
const char* name_opt = NULL) { const char* name_opt) {
log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt); log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
} }
void ReportMessageAt(int start_pos, void ReportMessageAt(int start_pos,
...@@ -617,8 +594,6 @@ class PreParser : public ParserBase { ...@@ -617,8 +594,6 @@ class PreParser : public ParserBase {
log_->LogMessage(start_pos, end_pos, type, name_opt); log_->LogMessage(start_pos, end_pos, type, name_opt);
} }
void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
// All ParseXXX functions take as the last argument an *ok parameter // All ParseXXX functions take as the last argument an *ok parameter
// which is set to false if parsing failed; it is unchanged otherwise. // which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check // By making the 'exception handling' explicit, we are forced to check
...@@ -682,42 +657,38 @@ class PreParser : public ParserBase { ...@@ -682,42 +657,38 @@ class PreParser : public ParserBase {
// Log the currently parsed string literal. // Log the currently parsed string literal.
Expression GetStringSymbol(); Expression GetStringSymbol();
void set_language_mode(i::LanguageMode language_mode) { void set_language_mode(LanguageMode language_mode) {
scope_->set_language_mode(language_mode); scope_->set_language_mode(language_mode);
} }
bool is_classic_mode() { bool is_classic_mode() {
return scope_->language_mode() == i::CLASSIC_MODE; return scope_->language_mode() == CLASSIC_MODE;
} }
bool is_extended_mode() { bool is_extended_mode() {
return scope_->language_mode() == i::EXTENDED_MODE; return scope_->language_mode() == EXTENDED_MODE;
} }
i::LanguageMode language_mode() { return scope_->language_mode(); } LanguageMode language_mode() { return scope_->language_mode(); }
bool CheckInOrOf(bool accept_OF); bool CheckInOrOf(bool accept_OF);
static int Precedence(i::Token::Value tok, bool accept_IN); void SetStrictModeViolation(Scanner::Location,
void SetStrictModeViolation(i::Scanner::Location,
const char* type, const char* type,
bool* ok); bool* ok);
void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);
void StrictModeIdentifierViolation(i::Scanner::Location, void StrictModeIdentifierViolation(Scanner::Location,
const char* eval_args_type, const char* eval_args_type,
Identifier identifier, Identifier identifier,
bool* ok); bool* ok);
i::ParserRecorder* log_; ParserRecorder* log_;
Scope* scope_; Scope* scope_;
i::Scanner::Location strict_mode_violation_location_; Scanner::Location strict_mode_violation_location_;
const char* strict_mode_violation_type_; const char* strict_mode_violation_type_;
bool parenthesized_function_; bool parenthesized_function_;
friend class i::ObjectLiteralChecker<PreParser>;
}; };
} } // v8::internal } } // v8::internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment