diff options
Diffstat (limited to 'deps/v8/src/parser.cc')
-rw-r--r-- | deps/v8/src/parser.cc | 614 |
1 files changed, 184 insertions, 430 deletions
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 180d0d2456..aad7a615a5 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -87,112 +87,6 @@ class PositionStack { }; -template <typename T, int initial_size> -class BufferedZoneList { - public: - BufferedZoneList() : list_(NULL), last_(NULL) {} - - // Adds element at end of list. This element is buffered and can - // be read using last() or removed using RemoveLast until a new Add or until - // RemoveLast or GetList has been called. - void Add(T* value) { - if (last_ != NULL) { - if (list_ == NULL) { - list_ = new ZoneList<T*>(initial_size); - } - list_->Add(last_); - } - last_ = value; - } - - T* last() { - ASSERT(last_ != NULL); - return last_; - } - - T* RemoveLast() { - ASSERT(last_ != NULL); - T* result = last_; - if (list_ != NULL && list_->length() > 0) - last_ = list_->RemoveLast(); - else - last_ = NULL; - return result; - } - - T* Get(int i) { - ASSERT(0 <= i && i < length()); - if (list_ == NULL) { - ASSERT_EQ(0, i); - return last_; - } else { - if (i == list_->length()) { - ASSERT(last_ != NULL); - return last_; - } else { - return list_->at(i); - } - } - } - - void Clear() { - list_ = NULL; - last_ = NULL; - } - - int length() { - int length = (list_ == NULL) ? 0 : list_->length(); - return length + ((last_ == NULL) ? 0 : 1); - } - - ZoneList<T*>* GetList() { - if (list_ == NULL) { - list_ = new ZoneList<T*>(initial_size); - } - if (last_ != NULL) { - list_->Add(last_); - last_ = NULL; - } - return list_; - } - - private: - ZoneList<T*>* list_; - T* last_; -}; - - -// Accumulates RegExp atoms and assertions into lists of terms and alternatives. -class RegExpBuilder: public ZoneObject { - public: - RegExpBuilder(); - void AddCharacter(uc16 character); - // "Adds" an empty expression. Does nothing except consume a - // following quantifier - void AddEmpty(); - void AddAtom(RegExpTree* tree); - void AddAssertion(RegExpTree* tree); - void NewAlternative(); // '|' - void AddQuantifierToAtom(int min, int max, RegExpQuantifier::Type type); - RegExpTree* ToRegExp(); - private: - void FlushCharacters(); - void FlushText(); - void FlushTerms(); - bool pending_empty_; - ZoneList<uc16>* characters_; - BufferedZoneList<RegExpTree, 2> terms_; - BufferedZoneList<RegExpTree, 2> text_; - BufferedZoneList<RegExpTree, 2> alternatives_; -#ifdef DEBUG - enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_; -#define LAST(x) last_added_ = x; -#else -#define LAST(x) -#endif -}; - - RegExpBuilder::RegExpBuilder() : pending_empty_(false), characters_(NULL), @@ -352,124 +246,13 @@ void RegExpBuilder::AddQuantifierToAtom(int min, } -class RegExpParser { - public: - RegExpParser(FlatStringReader* in, - Handle<String>* error, - bool multiline_mode); - RegExpTree* ParsePattern(); - RegExpTree* ParseDisjunction(); - RegExpTree* ParseGroup(); - RegExpTree* ParseCharacterClass(); - - // Parses a {...,...} quantifier and stores the range in the given - // out parameters. - bool ParseIntervalQuantifier(int* min_out, int* max_out); - - // Parses and returns a single escaped character. The character - // must not be 'b' or 'B' since they are usually handle specially. - uc32 ParseClassCharacterEscape(); - - // Checks whether the following is a length-digit hexadecimal number, - // and sets the value if it is. - bool ParseHexEscape(int length, uc32* value); - - uc32 ParseControlLetterEscape(); - uc32 ParseOctalLiteral(); - - // Tries to parse the input as a back reference. If successful it - // stores the result in the output parameter and returns true. If - // it fails it will push back the characters read so the same characters - // can be reparsed. - bool ParseBackReferenceIndex(int* index_out); - - CharacterRange ParseClassAtom(uc16* char_class); - RegExpTree* ReportError(Vector<const char> message); - void Advance(); - void Advance(int dist); - void Reset(int pos); - - // Reports whether the pattern might be used as a literal search string. - // Only use if the result of the parse is a single atom node. - bool simple(); - bool contains_anchor() { return contains_anchor_; } - void set_contains_anchor() { contains_anchor_ = true; } - int captures_started() { return captures_ == NULL ? 0 : captures_->length(); } - int position() { return next_pos_ - 1; } - bool failed() { return failed_; } - - static const int kMaxCaptures = 1 << 16; - static const uc32 kEndMarker = (1 << 21); - - private: - enum SubexpressionType { - INITIAL, - CAPTURE, // All positive values represent captures. - POSITIVE_LOOKAHEAD, - NEGATIVE_LOOKAHEAD, - GROUPING - }; - - class RegExpParserState : public ZoneObject { - public: - RegExpParserState(RegExpParserState* previous_state, - SubexpressionType group_type, - int disjunction_capture_index) - : previous_state_(previous_state), - builder_(new RegExpBuilder()), - group_type_(group_type), - disjunction_capture_index_(disjunction_capture_index) {} - // Parser state of containing expression, if any. - RegExpParserState* previous_state() { return previous_state_; } - bool IsSubexpression() { return previous_state_ != NULL; } - // RegExpBuilder building this regexp's AST. - RegExpBuilder* builder() { return builder_; } - // Type of regexp being parsed (parenthesized group or entire regexp). - SubexpressionType group_type() { return group_type_; } - // Index in captures array of first capture in this sub-expression, if any. - // Also the capture index of this sub-expression itself, if group_type - // is CAPTURE. - int capture_index() { return disjunction_capture_index_; } - private: - // Linked list implementation of stack of states. - RegExpParserState* previous_state_; - // Builder for the stored disjunction. - RegExpBuilder* builder_; - // Stored disjunction type (capture, look-ahead or grouping), if any. - SubexpressionType group_type_; - // Stored disjunction's capture index (if any). - int disjunction_capture_index_; - }; - - uc32 current() { return current_; } - bool has_more() { return has_more_; } - bool has_next() { return next_pos_ < in()->length(); } - uc32 Next(); - FlatStringReader* in() { return in_; } - void ScanForCaptures(); - uc32 current_; - bool has_more_; - bool multiline_; - int next_pos_; - FlatStringReader* in_; - Handle<String>* error_; - bool simple_; - bool contains_anchor_; - ZoneList<RegExpCapture*>* captures_; - bool is_scanned_for_captures_; - // The capture count is only valid after we have scanned for captures. - int capture_count_; - bool failed_; -}; - - // A temporary scope stores information during parsing, just like // a plain scope. However, temporary scopes are not kept around // after parsing or referenced by syntax trees so they can be stack- // allocated and hence used by the pre-parser. class TemporaryScope BASE_EMBEDDED { public: - explicit TemporaryScope(Parser* parser); + explicit TemporaryScope(TemporaryScope** variable); ~TemporaryScope(); int NextMaterializedLiteralIndex() { @@ -518,27 +301,25 @@ class TemporaryScope BASE_EMBEDDED { int loop_count_; // Bookkeeping - Parser* parser_; + TemporaryScope** variable_; TemporaryScope* parent_; - - friend class Parser; }; -TemporaryScope::TemporaryScope(Parser* parser) +TemporaryScope::TemporaryScope(TemporaryScope** variable) : materialized_literal_count_(0), expected_property_count_(0), only_simple_this_property_assignments_(false), this_property_assignments_(Factory::empty_fixed_array()), loop_count_(0), - parser_(parser), - parent_(parser->temp_scope_) { - parser->temp_scope_ = this; + variable_(variable), + parent_(*variable) { + *variable = this; } TemporaryScope::~TemporaryScope() { - parser_->temp_scope_ = parent_; + *variable_ = parent_; } @@ -1141,20 +922,20 @@ VariableProxy* PreParser::Declare(Handle<String> name, Variable::Mode mode, class Target BASE_EMBEDDED { public: - Target(Parser* parser, AstNode* node) - : parser_(parser), node_(node), previous_(parser_->target_stack_) { - parser_->target_stack_ = this; + Target(Target** variable, AstNode* node) + : variable_(variable), node_(node), previous_(*variable) { + *variable = this; } ~Target() { - parser_->target_stack_ = previous_; + *variable_ = previous_; } Target* previous() { return previous_; } AstNode* node() { return node_; } private: - Parser* parser_; + Target** variable_; AstNode* node_; Target* previous_; }; @@ -1162,17 +943,17 @@ class Target BASE_EMBEDDED { class TargetScope BASE_EMBEDDED { public: - explicit TargetScope(Parser* parser) - : parser_(parser), previous_(parser->target_stack_) { - parser->target_stack_ = NULL; + explicit TargetScope(Target** variable) + : variable_(variable), previous_(*variable) { + *variable = NULL; } ~TargetScope() { - parser_->target_stack_ = previous_; + *variable_ = previous_; } private: - Parser* parser_; + Target** variable_; Target* previous_; }; @@ -1184,22 +965,26 @@ class TargetScope BASE_EMBEDDED { class LexicalScope BASE_EMBEDDED { public: - LexicalScope(Parser* parser, Scope* scope) - : parser_(parser), - prev_scope_(parser->top_scope_), - prev_level_(parser->with_nesting_level_) { - parser_->top_scope_ = scope; - parser_->with_nesting_level_ = 0; + LexicalScope(Scope** scope_variable, + int* with_nesting_level_variable, + Scope* scope) + : scope_variable_(scope_variable), + with_nesting_level_variable_(with_nesting_level_variable), + prev_scope_(*scope_variable), + prev_level_(*with_nesting_level_variable) { + *scope_variable = scope; + *with_nesting_level_variable = 0; } ~LexicalScope() { - parser_->top_scope_->Leave(); - parser_->top_scope_ = prev_scope_; - parser_->with_nesting_level_ = prev_level_; + (*scope_variable_)->Leave(); + *scope_variable_ = prev_scope_; + *with_nesting_level_variable_ = prev_level_; } private: - Parser* parser_; + Scope** scope_variable_; + int* with_nesting_level_variable_; Scope* prev_scope_; int prev_level_; }; @@ -1262,8 +1047,8 @@ bool Parser::PreParseProgram(Handle<String> source, mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY; if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY; DummyScope top_scope; - LexicalScope scope(this, &top_scope); - TemporaryScope temp_scope(this); + LexicalScope scope(&this->top_scope_, &this->with_nesting_level_, &top_scope); + TemporaryScope temp_scope(&this->temp_scope_); ZoneListWrapper<Statement> processor; bool ok = true; ParseSourceElements(&processor, Token::EOS, &ok); @@ -1297,8 +1082,9 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, FunctionLiteral* result = NULL; { Scope* scope = factory()->NewScope(top_scope_, type, inside_with()); - LexicalScope lexical_scope(this, scope); - TemporaryScope temp_scope(this); + LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, + scope); + TemporaryScope temp_scope(&this->temp_scope_); ZoneListWrapper<Statement> body(16); bool ok = true; ParseSourceElements(&body, Token::EOS, &ok); @@ -1356,8 +1142,9 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) { Handle<String> no_name = factory()->EmptySymbol(); Scope* scope = factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with()); - LexicalScope lexical_scope(this, scope); - TemporaryScope temp_scope(this); + LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, + scope); + TemporaryScope temp_scope(&this->temp_scope_); FunctionLiteralType type = info->is_expression() ? EXPRESSION : DECLARATION; @@ -1382,56 +1169,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); @@ -1733,7 +1470,7 @@ void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor, // elements. This way, all scripts and functions get their own // target stack thus avoiding illegal breaks and continues across // functions. - TargetScope scope(this); + TargetScope scope(&this->target_stack_); ASSERT(processor != NULL); InitializationBlockFinder block_finder; @@ -1857,7 +1594,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { // fall-through. It is much easier just to wrap the entire // try-statement in a statement block and put the labels there Block* result = NEW(Block(labels, 1, false)); - Target target(this, result); + Target target(&this->target_stack_, result); TryStatement* statement = ParseTryStatement(CHECK_OK); if (statement) { statement->set_statement_pos(statement_pos); @@ -2073,7 +1810,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { // // Construct block expecting 16 statements. Block* result = NEW(Block(labels, 16, false)); - Target target(this, result); + Target target(&this->target_stack_, result); Expect(Token::LBRACE, CHECK_OK); while (peek() != Token::RBRACE) { Statement* stat = ParseStatement(NULL, CHECK_OK); @@ -2468,7 +2205,7 @@ Block* Parser::WithHelper(Expression* obj, ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0)); TargetCollector collector(target_list); Statement* stat; - { Target target(this, &collector); + { Target target(&this->target_stack_, &collector); with_nesting_level_++; top_scope_->RecordWithStatement(); stat = ParseStatement(labels, CHECK_OK); @@ -2551,7 +2288,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels, // 'switch' '(' Expression ')' '{' CaseClause* '}' SwitchStatement* statement = NEW(SwitchStatement(labels)); - Target target(this, statement); + Target target(&this->target_stack_, statement); Expect(Token::SWITCH, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); @@ -2608,7 +2345,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { TargetCollector collector(target_list); Block* try_block; - { Target target(this, &collector); + { Target target(&this->target_stack_, &collector); try_block = ParseBlock(NULL, CHECK_OK); } @@ -2644,7 +2381,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); Literal* name_literal = NEW(Literal(name)); Expression* obj = NEW(CatchExtensionObject(name_literal, catch_var)); - { Target target(this, &catch_collector); + { Target target(&this->target_stack_, &catch_collector); catch_block = WithHelper(obj, NULL, true, CHECK_OK); } } else { @@ -2703,7 +2440,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, temp_scope_->AddLoop(); DoWhileStatement* loop = NEW(DoWhileStatement(labels)); - Target target(this, loop); + Target target(&this->target_stack_, loop); Expect(Token::DO, CHECK_OK); Statement* body = ParseStatement(NULL, CHECK_OK); @@ -2736,7 +2473,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { temp_scope_->AddLoop(); WhileStatement* loop = NEW(WhileStatement(labels)); - Target target(this, loop); + Target target(&this->target_stack_, loop); Expect(Token::WHILE, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); @@ -2766,7 +2503,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { ParseVariableDeclarations(false, &each, CHECK_OK); if (peek() == Token::IN && each != NULL) { ForInStatement* loop = NEW(ForInStatement(labels)); - Target target(this, loop); + Target target(&this->target_stack_, loop); Expect(Token::IN, CHECK_OK); Expression* enumerable = ParseExpression(true, CHECK_OK); @@ -2800,7 +2537,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { expression = NewThrowReferenceError(type); } ForInStatement* loop = NEW(ForInStatement(labels)); - Target target(this, loop); + Target target(&this->target_stack_, loop); Expect(Token::IN, CHECK_OK); Expression* enumerable = ParseExpression(true, CHECK_OK); @@ -2819,7 +2556,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { // Standard 'for' loop ForStatement* loop = NEW(ForStatement(labels)); - Target target(this, loop); + Target target(&this->target_stack_, loop); // Parsed initializer at this point. Expect(Token::SEMICOLON, CHECK_OK); @@ -3909,8 +3646,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, // Parse function body. { Scope* scope = factory()->NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); - LexicalScope lexical_scope(this, scope); - TemporaryScope temp_scope(this); + LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, + scope); + TemporaryScope temp_scope(&this->temp_scope_); top_scope_->SetScopeName(name); // FormalParameterList :: @@ -4281,145 +4019,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(); + // Allocate a fixed array with all the elements. + Handle<FixedArray> fast_elements = + Factory::NewFixedArray(elements.length()); - if (is_pre_parsing_) return NULL; - - // 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 @@ -5247,9 +5005,9 @@ bool ScriptDataImpl::HasError() { // Preparse, but only collect data that is immediately useful, // even if the preparser data is only used once. -ScriptDataImpl* Parser::PartialPreParse(Handle<String> source, - unibrow::CharacterStream* stream, - v8::Extension* extension) { +ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source, + unibrow::CharacterStream* stream, + v8::Extension* extension) { Handle<Script> no_script; bool allow_natives_syntax = FLAG_allow_natives_syntax || Bootstrapper::IsActive(); @@ -5305,9 +5063,9 @@ int ScriptDataImpl::ReadNumber(byte** source) { } -ScriptDataImpl* Parser::PreParse(Handle<String> source, - unibrow::CharacterStream* stream, - v8::Extension* extension) { +ScriptDataImpl* ParserApi::PreParse(Handle<String> source, + unibrow::CharacterStream* stream, + v8::Extension* extension) { Handle<Script> no_script; bool allow_natives_syntax = FLAG_allow_natives_syntax || Bootstrapper::IsActive(); @@ -5320,9 +5078,9 @@ ScriptDataImpl* Parser::PreParse(Handle<String> source, } -bool Parser::ParseRegExp(FlatStringReader* input, - bool multiline, - RegExpCompileData* result) { +bool RegExpParser::ParseRegExp(FlatStringReader* input, + bool multiline, + RegExpCompileData* result) { ASSERT(result != NULL); RegExpParser parser(input, &result->error, multiline); RegExpTree* tree = parser.ParsePattern(); @@ -5342,7 +5100,7 @@ bool Parser::ParseRegExp(FlatStringReader* input, } -bool Parser::Parse(CompilationInfo* info) { +bool ParserApi::Parse(CompilationInfo* info) { ASSERT(info->function() == NULL); FunctionLiteral* result = NULL; Handle<Script> script = info->script(); @@ -5368,11 +5126,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()); } } |