Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index cc69b8d2efc355623af062c07f24c200cddf901d..aad7a615a514bd3427d18d8f1504b2acfdf514c4 100644 |
--- a/src/parser.cc |
+++ b/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; |
@@ -1683,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; |
@@ -1807,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); |
@@ -2023,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); |
@@ -2418,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); |
@@ -2501,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); |
@@ -2558,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); |
} |
@@ -2594,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 { |
@@ -2653,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); |
@@ -2686,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); |
@@ -2716,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); |
@@ -2750,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); |
@@ -2769,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); |
@@ -3859,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 :: |
@@ -5217,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(); |
@@ -5275,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(); |
@@ -5290,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(); |
@@ -5312,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(); |