}
+int ParserTraits::NextMaterializedLiteralIndex() {
+ return parser_->current_function_state_->NextMaterializedLiteralIndex();
+}
+
+
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<const char*> args) {
return parser_->LookupSymbol(symbol_id);
}
+
+Handle<String> ParserTraits::NextLiteralString(PretenureFlag tenured) {
+ Scanner& scanner = parser_->scanner();
+ if (scanner.is_next_literal_ascii()) {
+ return parser_->isolate_->factory()->NewStringFromAscii(
+ scanner.next_literal_ascii_string(), tenured);
+ } else {
+ return parser_->isolate_->factory()->NewStringFromTwoByte(
+ scanner.next_literal_utf16_string(), tenured);
+ }
+}
+
+
+Expression* ParserTraits::NewRegExpLiteral(Handle<String> js_pattern,
+ Handle<String> js_flags,
+ int literal_index,
+ int pos) {
+ return parser_->factory()->NewRegExpLiteral(
+ js_pattern, js_flags, literal_index, pos);
+}
+
Parser::Parser(CompilationInfo* info)
: ParserBase<ParserTraits>(&scanner_,
info->isolate()->stack_guard()->real_climit(),
}
-Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
- int pos = peek_position();
- if (!scanner().ScanRegExpPattern(seen_equal)) {
- Next();
- ReportMessage("unterminated_regexp", Vector<const char*>::empty());
- *ok = false;
- return NULL;
- }
-
- int literal_index = current_function_state_->NextMaterializedLiteralIndex();
-
- Handle<String> js_pattern = NextLiteralString(TENURED);
- scanner().ScanRegExpFlags();
- Handle<String> js_flags = NextLiteralString(TENURED);
- Next();
-
- return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
-}
-
-
ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
typedef Parser* ParserType;
// Return types for traversing functions.
typedef Handle<String> IdentifierType;
+ typedef Expression* ExpressionType;
explicit ParserTraits(Parser* parser) : parser_(parser) {}
bool is_classic_mode() const;
bool is_generator() const;
bool IsEvalOrArguments(Handle<String> identifier) const;
+ int NextMaterializedLiteralIndex();
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<Handle<String> > args);
- // Identifiers:
+ // "null" return type creators.
static IdentifierType EmptyIdentifier() {
return Handle<String>();
}
+ static ExpressionType EmptyExpression() {
+ return NULL;
+ }
+ // Producing data during the recursive descent.
IdentifierType GetSymbol();
+ IdentifierType NextLiteralString(PretenureFlag tenured);
+ ExpressionType NewRegExpLiteral(IdentifierType js_pattern,
+ IdentifierType js_flags,
+ int literal_index,
+ int pos);
private:
Parser* parser_;
Expression* ParsePrimaryExpression(bool* ok);
Expression* ParseArrayLiteral(bool* ok);
Expression* ParseObjectLiteral(bool* ok);
- Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
// Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt,
}
}
- Handle<String> NextLiteralString(PretenureFlag tenured) {
- if (scanner().is_next_literal_ascii()) {
- return isolate_->factory()->NewStringFromAscii(
- scanner().next_literal_ascii_string(), tenured);
- } else {
- return isolate_->factory()->NewStringFromTwoByte(
- scanner().next_literal_utf16_string(), tenured);
- }
- }
-
// Get odd-ball literals.
Literal* GetLiteralUndefined(int position);
Literal* GetLiteralTheHole(int position);
}
+int PreParserTraits::NextMaterializedLiteralIndex() {
+ return pre_parser_->scope_->NextMaterializedLiteralIndex();
+}
+
+
void PreParserTraits::ReportMessageAt(Scanner::Location location,
const char* message,
Vector<const char*> args) {
}
-PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
- bool* ok) {
- if (!scanner()->ScanRegExpPattern(seen_equal)) {
- Next();
- ReportMessageAt(scanner()->location(), "unterminated_regexp");
- *ok = false;
- return Expression::Default();
- }
-
- scope_->NextMaterializedLiteralIndex();
-
- if (!scanner()->ScanRegExpFlags()) {
- Next();
- ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
- *ok = false;
- return Expression::Default();
- }
- Next();
- return Expression::Default();
-}
-
-
PreParser::Arguments PreParser::ParseArguments(bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
bool* is_set,
bool* ok);
+ typename Traits::ExpressionType ParseRegExpLiteral(bool seen_equal, bool* ok);
+
// 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
typedef PreParser* ParserType;
// Return types for traversing functions.
typedef PreParserIdentifier IdentifierType;
+ typedef PreParserExpression ExpressionType;
explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
static bool IsEvalOrArguments(IdentifierType identifier) {
return identifier.IsEvalOrArguments();
}
+ int NextMaterializedLiteralIndex();
// Reporting errors.
void ReportMessageAt(Scanner::Location location,
const char* type,
const char* name_opt);
- // Identifiers:
+ // "null" return type creators.
static IdentifierType EmptyIdentifier() {
return PreParserIdentifier::Default();
}
+ static ExpressionType EmptyExpression() {
+ return PreParserExpression::Default();
+ }
+ // Producing data during the recursive descent.
IdentifierType GetSymbol();
+ static IdentifierType NextLiteralString(PretenureFlag tenured) {
+ return PreParserIdentifier::Default();
+ }
+ ExpressionType NewRegExpLiteral(IdentifierType js_pattern,
+ IdentifierType js_flags,
+ int literal_index,
+ int pos) {
+ return PreParserExpression::Default();
+ }
private:
PreParser* pre_parser_;
*variable = this;
}
~Scope() { *variable_ = prev_; }
- void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
+ int NextMaterializedLiteralIndex() { return materialized_literal_count_++; }
void AddProperty() { expected_properties_++; }
ScopeType type() { return type_; }
int expected_properties() { return expected_properties_; }
Expression ParsePrimaryExpression(bool* ok);
Expression ParseArrayLiteral(bool* ok);
Expression ParseObjectLiteral(bool* ok);
- Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
Expression ParseV8Intrinsic(bool* ok);
Arguments ParseArguments(bool* ok);
}
+template <class Traits>
+typename Traits::ExpressionType
+ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
+ int pos = peek_position();
+ if (!scanner()->ScanRegExpPattern(seen_equal)) {
+ Next();
+ ReportMessage("unterminated_regexp", Vector<const char*>::empty());
+ *ok = false;
+ return Traits::EmptyExpression();
+ }
+
+ int literal_index = this->NextMaterializedLiteralIndex();
+
+ typename Traits::IdentifierType js_pattern = this->NextLiteralString(TENURED);
+ if (!scanner()->ScanRegExpFlags()) {
+ Next();
+ ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
+ *ok = false;
+ return Traits::EmptyExpression();
+ }
+ typename Traits::IdentifierType js_flags = this->NextLiteralString(TENURED);
+ Next();
+ return this->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
+}
+
+
template <typename Traits>
void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
Token::Value property,
RunParserSyncTest(context_data, statement_data, kSuccess);
}
+
+
+TEST(ErrorsRegexpLiteral) {
+ const char* context_data[][2] = {
+ {"var r = ", ""},
+ { NULL, NULL }
+ };
+
+ const char* statement_data[] = {
+ "/unterminated",
+ NULL
+ };
+
+ RunParserSyncTest(context_data, statement_data, kError);
+}
+
+
+TEST(NoErrorsRegexpLiteral) {
+ const char* context_data[][2] = {
+ {"var r = ", ""},
+ { NULL, NULL }
+ };
+
+ const char* statement_data[] = {
+ "/foo/",
+ "/foo/g",
+ "/foo/whatever", // This is an error but not detected by the parser.
+ NULL
+ };
+
+ RunParserSyncTest(context_data, statement_data, kSuccess);
+}