Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 7690e92d520988de3fbae454f38049341ac6b20d..41db700253158aa0386482c106d7e3e094b1febb 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -1382,56 +1382,6 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) { |
} |
-FunctionLiteral* Parser::ParseJson(Handle<String> source) { |
- CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); |
- |
- HistogramTimerScope timer(&Counters::parse); |
- Counters::total_parse_size.Increment(source->length()); |
- |
- // Initialize parser state. |
- source->TryFlatten(TENURED); |
- scanner_.Initialize(source, JSON); |
- ASSERT(target_stack_ == NULL); |
- |
- FunctionLiteral* result = NULL; |
- Handle<String> no_name = factory()->EmptySymbol(); |
- |
- { |
- Scope* scope = factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, false); |
- LexicalScope lexical_scope(this, scope); |
- TemporaryScope temp_scope(this); |
- bool ok = true; |
- Expression* expression = ParseJson(&ok); |
- if (ok) { |
- ZoneListWrapper<Statement> statement = factory()->NewList<Statement>(1); |
- statement.Add(new ExpressionStatement(expression)); |
- result = NEW(FunctionLiteral( |
- no_name, |
- top_scope_, |
- statement.elements(), |
- temp_scope.materialized_literal_count(), |
- temp_scope.expected_property_count(), |
- temp_scope.only_simple_this_property_assignments(), |
- temp_scope.this_property_assignments(), |
- 0, |
- 0, |
- source->length(), |
- false, |
- temp_scope.ContainsLoops())); |
- } else if (scanner().stack_overflow()) { |
- Top::StackOverflow(); |
- } |
- } |
- |
- // Make sure the target stack is empty. |
- ASSERT(target_stack_ == NULL); |
- |
- // If there was a syntax error we have to get rid of the AST |
- // and it is not safe to do so before the scope has been deleted. |
- if (result == NULL) zone_scope.DeleteOnExit(); |
- return result; |
-} |
- |
void Parser::ReportMessage(const char* type, Vector<const char*> args) { |
Scanner::Location source_location = scanner_.location(); |
ReportMessageAt(source_location, type, args); |
@@ -4283,145 +4233,165 @@ Expression* Parser::NewThrowError(Handle<String> constructor, |
// ---------------------------------------------------------------------------- |
// JSON |
-Expression* Parser::ParseJson(bool* ok) { |
- Expression* result = ParseJsonValue(CHECK_OK); |
- Expect(Token::EOS, CHECK_OK); |
+Handle<Object> JsonParser::ParseJson(Handle<String> source) { |
+ source->TryFlatten(); |
+ scanner_.Initialize(source, JSON); |
+ Handle<Object> result = ParseJsonValue(); |
+ if (result.is_null() || scanner_.Next() != Token::EOS) { |
+ if (scanner_.stack_overflow()) { |
+ // Scanner failed. |
+ Top::StackOverflow(); |
+ } else { |
+ // Parse failed. Scanner's current token is the unexpected token. |
+ Token::Value token = scanner_.current_token(); |
+ |
+ const char* message; |
+ const char* name_opt = NULL; |
+ |
+ switch (token) { |
+ case Token::EOS: |
+ message = "unexpected_eos"; |
+ break; |
+ case Token::NUMBER: |
+ message = "unexpected_token_number"; |
+ break; |
+ case Token::STRING: |
+ message = "unexpected_token_string"; |
+ break; |
+ case Token::IDENTIFIER: |
+ message = "unexpected_token_identifier"; |
+ break; |
+ default: |
+ message = "unexpected_token"; |
+ name_opt = Token::String(token); |
+ ASSERT(name_opt != NULL); |
+ break; |
+ } |
+ |
+ Scanner::Location source_location = scanner_.location(); |
+ MessageLocation location(Factory::NewScript(source), |
+ source_location.beg_pos, |
+ source_location.end_pos); |
+ int argc = (name_opt == NULL) ? 0 : 1; |
+ Handle<JSArray> array = Factory::NewJSArray(argc); |
+ if (name_opt != NULL) { |
+ SetElement(array, |
+ 0, |
+ Factory::NewStringFromUtf8(CStrVector(name_opt))); |
+ } |
+ Handle<Object> result = Factory::NewSyntaxError(message, array); |
+ Top::Throw(*result, &location); |
+ return Handle<Object>::null(); |
+ } |
+ } |
return result; |
} |
+Handle<String> JsonParser::GetString() { |
+ int literal_length = scanner_.literal_length(); |
+ if (literal_length == 0) { |
+ return Factory::empty_string(); |
+ } |
+ const char* literal_string = scanner_.literal_string(); |
+ Vector<const char> literal(literal_string, literal_length); |
+ return Factory::NewStringFromUtf8(literal); |
+} |
+ |
+ |
// Parse any JSON value. |
-Expression* Parser::ParseJsonValue(bool* ok) { |
- Token::Value token = peek(); |
+Handle<Object> JsonParser::ParseJsonValue() { |
+ Token::Value token = scanner_.Next(); |
switch (token) { |
case Token::STRING: { |
- Consume(Token::STRING); |
- int literal_length = scanner_.literal_length(); |
- const char* literal_string = scanner_.literal_string(); |
- if (literal_length == 0) { |
- return NEW(Literal(Factory::empty_string())); |
- } |
- Vector<const char> literal(literal_string, literal_length); |
- return NEW(Literal(Factory::NewStringFromUtf8(literal, TENURED))); |
+ return GetString(); |
} |
case Token::NUMBER: { |
- Consume(Token::NUMBER); |
- ASSERT(scanner_.literal_length() > 0); |
double value = StringToDouble(scanner_.literal(), |
NO_FLAGS, // Hex, octal or trailing junk. |
OS::nan_value()); |
- return NewNumberLiteral(value); |
+ return Factory::NewNumber(value); |
} |
case Token::FALSE_LITERAL: |
- Consume(Token::FALSE_LITERAL); |
- return NEW(Literal(Factory::false_value())); |
+ return Factory::false_value(); |
case Token::TRUE_LITERAL: |
- Consume(Token::TRUE_LITERAL); |
- return NEW(Literal(Factory::true_value())); |
+ return Factory::true_value(); |
case Token::NULL_LITERAL: |
- Consume(Token::NULL_LITERAL); |
- return NEW(Literal(Factory::null_value())); |
- case Token::LBRACE: { |
- Expression* result = ParseJsonObject(CHECK_OK); |
- return result; |
- } |
- case Token::LBRACK: { |
- Expression* result = ParseJsonArray(CHECK_OK); |
- return result; |
- } |
+ return Factory::null_value(); |
+ case Token::LBRACE: |
+ return ParseJsonObject(); |
+ case Token::LBRACK: |
+ return ParseJsonArray(); |
default: |
- *ok = false; |
- ReportUnexpectedToken(token); |
- return NULL; |
+ return ReportUnexpectedToken(); |
} |
} |
// Parse a JSON object. Scanner must be right after '{' token. |
-Expression* Parser::ParseJsonObject(bool* ok) { |
- Consume(Token::LBRACE); |
- ZoneListWrapper<ObjectLiteral::Property> properties = |
- factory()->NewList<ObjectLiteral::Property>(4); |
- int boilerplate_properties = 0; |
- if (peek() != Token::RBRACE) { |
+Handle<Object> JsonParser::ParseJsonObject() { |
+ Handle<JSFunction> object_constructor( |
+ Top::global_context()->object_function()); |
+ Handle<JSObject> json_object = Factory::NewJSObject(object_constructor); |
+ if (scanner_.peek() == Token::RBRACE) { |
+ scanner_.Next(); |
+ } else { |
do { |
- Expect(Token::STRING, CHECK_OK); |
- Handle<String> key = GetSymbol(CHECK_OK); |
- Expect(Token::COLON, CHECK_OK); |
- Expression* value = ParseJsonValue(CHECK_OK); |
- Literal* key_literal; |
+ if (scanner_.Next() != Token::STRING) { |
+ return ReportUnexpectedToken(); |
+ } |
+ Handle<String> key = GetString(); |
+ if (scanner_.Next() != Token::COLON) { |
+ return ReportUnexpectedToken(); |
+ } |
+ Handle<Object> value = ParseJsonValue(); |
+ if (value.is_null()) return Handle<Object>::null(); |
uint32_t index; |
if (key->AsArrayIndex(&index)) { |
- key_literal = NewNumberLiteral(index); |
+ SetElement(json_object, index, value); |
} else { |
- key_literal = NEW(Literal(key)); |
- } |
- ObjectLiteral::Property* property = |
- NEW(ObjectLiteral::Property(key_literal, value)); |
- properties.Add(property); |
- |
- if (IsBoilerplateProperty(property)) { |
- boilerplate_properties++; |
+ SetProperty(json_object, key, value, NONE); |
} |
- } while (Check(Token::COMMA)); |
+ } while (scanner_.Next() == Token::COMMA); |
+ if (scanner_.current_token() != Token::RBRACE) { |
+ return ReportUnexpectedToken(); |
+ } |
} |
- Expect(Token::RBRACE, CHECK_OK); |
- |
- int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
- if (is_pre_parsing_) return NULL; |
- |
- Handle<FixedArray> constant_properties = |
- Factory::NewFixedArray(boilerplate_properties * 2, TENURED); |
- bool is_simple = true; |
- bool fast_elements = true; |
- int depth = 1; |
- BuildObjectLiteralConstantProperties(properties.elements(), |
- constant_properties, |
- &is_simple, |
- &fast_elements, |
- &depth); |
- return new ObjectLiteral(constant_properties, |
- properties.elements(), |
- literal_index, |
- is_simple, |
- fast_elements, |
- depth); |
+ return json_object; |
} |
// Parse a JSON array. Scanner must be right after '[' token. |
-Expression* Parser::ParseJsonArray(bool* ok) { |
- Consume(Token::LBRACK); |
+Handle<Object> JsonParser::ParseJsonArray() { |
+ ZoneScope zone_scope(DELETE_ON_EXIT); |
+ ZoneList<Handle<Object> > elements(4); |
- ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4); |
- if (peek() != Token::RBRACK) { |
+ Token::Value token = scanner_.peek(); |
+ if (token == Token::RBRACK) { |
+ scanner_.Next(); |
+ } else { |
do { |
- Expression* exp = ParseJsonValue(CHECK_OK); |
- values.Add(exp); |
- } while (Check(Token::COMMA)); |
+ Handle<Object> element = ParseJsonValue(); |
+ if (element.is_null()) return Handle<Object>::null(); |
+ elements.Add(element); |
+ token = scanner_.Next(); |
+ } while (token == Token::COMMA); |
+ if (token != Token::RBRACK) { |
+ return ReportUnexpectedToken(); |
+ } |
} |
- Expect(Token::RBRACK, CHECK_OK); |
- |
- // Update the scope information before the pre-parsing bailout. |
- int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
- if (is_pre_parsing_) return NULL; |
+ // Allocate a fixed array with all the elements. |
+ Handle<FixedArray> fast_elements = |
+ Factory::NewFixedArray(elements.length()); |
- // Allocate a fixed array with all the literals. |
- Handle<FixedArray> literals = |
- Factory::NewFixedArray(values.length(), TENURED); |
+ for (int i = 0, n = elements.length(); i < n; i++) { |
+ fast_elements->set(i, *elements[i]); |
+ } |
- bool is_simple; |
- int depth; |
- BuildArrayLiteralBoilerplateLiterals(values.elements(), |
- literals, |
- &is_simple, |
- &depth); |
- return NEW(ArrayLiteral(literals, values.elements(), |
- literal_index, is_simple, depth)); |
+ return Factory::NewJSArrayWithElements(fast_elements); |
} |
- |
// ---------------------------------------------------------------------------- |
// Regular expressions |
@@ -5370,11 +5340,7 @@ bool Parser::Parse(CompilationInfo* info) { |
ASSERT(Top::has_pending_exception()); |
} else { |
Handle<String> source = Handle<String>(String::cast(script->source())); |
- // JSON is always global. |
- ASSERT(!info->is_json() || info->is_global()); |
- result = info->is_json() |
- ? parser.ParseJson(source) |
- : parser.ParseProgram(source, info->is_global()); |
+ result = parser.ParseProgram(source, info->is_global()); |
} |
} |