📄 parser.cc.svn-base
字号:
// empty statements, e.g. 'l1: l2: l3: break l2;' if (!label.is_null() && ContainsLabel(labels, label)) { return factory()->EmptyStatement(); } BreakableStatement* target = NULL; if (!is_pre_parsing_) { target = LookupBreakTarget(label, CHECK_OK); if (target == NULL) { // Illegal break statement. To be consistent with KJS we delay // reporting of the syntax error until runtime. Handle<String> error_type = Factory::illegal_break_symbol(); if (!label.is_null()) error_type = Factory::unknown_label_symbol(); Expression* throw_error = NewThrowSyntaxError(error_type, label); return NEW(ExpressionStatement(throw_error)); } } ExpectSemicolon(CHECK_OK); return NEW(BreakStatement(target));}Statement* Parser::ParseReturnStatement(bool* ok) { // ReturnStatement :: // 'return' Expression? ';' // Consume the return token. It is necessary to do the before // reporting any errors on it, because of the way errors are // reported (underlining). Expect(Token::RETURN, CHECK_OK); // An ECMAScript program is considered syntactically incorrect if it // contains a return statement that is not within the body of a // function. See ECMA-262, section 12.9, page 67. // // To be consistent with KJS we report the syntax error at runtime. if (!is_pre_parsing_ && !top_scope_->is_function_scope()) { Handle<String> type = Factory::illegal_return_symbol(); Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null()); return NEW(ExpressionStatement(throw_error)); } Token::Value tok = peek(); if (scanner_.has_line_terminator_before_next() || tok == Token::SEMICOLON || tok == Token::RBRACE || tok == Token::EOS) { ExpectSemicolon(CHECK_OK); return NEW(ReturnStatement(GetLiteralUndefined())); } Expression* expr = ParseExpression(true, CHECK_OK); ExpectSemicolon(CHECK_OK); return NEW(ReturnStatement(expr));}Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) { // Parse the statement and collect escaping labels. ZoneList<Label*>* label_list = NEW(ZoneList<Label*>(0)); LabelCollector collector(label_list); Statement* stat; { Target target(this, &collector); with_nesting_level_++; top_scope_->RecordWithStatement(); stat = ParseStatement(labels, CHECK_OK); with_nesting_level_--; } // Create resulting block with two statements. // 1: Evaluate the with expression. // 2: The try-finally block evaluating the body. Block* result = NEW(Block(NULL, 2, false)); if (result) { result->AddStatement(NEW(WithEnterStatement(obj))); // Create body block. Block* body = NEW(Block(NULL, 1, false)); body->AddStatement(stat); // Create exit block. Block* exit = NEW(Block(NULL, 1, false)); exit->AddStatement(NEW(WithExitStatement())); // Return a try-finally statement. TryFinally* wrapper = NEW(TryFinally(body, NULL, exit)); wrapper->set_escaping_labels(collector.labels()); result->AddStatement(wrapper); return result; } else { return NULL; }}Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { // WithStatement :: // 'with' '(' Expression ')' Statement // We do not allow the use of 'with' statements in the internal JS // code. If 'with' statements were allowed, the simplified setup of // the runtime context chain would allow access to properties in the // global object from within a 'with' statement. ASSERT(!Bootstrapper::IsActive()); Expect(Token::WITH, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); Expression* expr = ParseExpression(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); return WithHelper(expr, labels, CHECK_OK);}CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { // CaseClause :: // 'case' Expression ':' Statement* // 'default' ':' Statement* Expression* label = NULL; // NULL expression indicates default case if (peek() == Token::CASE) { Expect(Token::CASE, CHECK_OK); label = ParseExpression(true, CHECK_OK); } else { Expect(Token::DEFAULT, CHECK_OK); if (*default_seen_ptr) { ReportMessage("multiple_defaults_in_switch", Vector<const char*>::empty()); *ok = false; return NULL; } *default_seen_ptr = true; } Expect(Token::COLON, CHECK_OK); ZoneListWrapper<Statement> statements = factory()->NewList<Statement>(5); while (peek() != Token::CASE && peek() != Token::DEFAULT && peek() != Token::RBRACE) { Statement* stat = ParseStatement(NULL, CHECK_OK); statements.Add(stat); } return NEW(CaseClause(label, statements.elements()));}SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels, bool* ok) { // SwitchStatement :: // 'switch' '(' Expression ')' '{' CaseClause* '}' SwitchStatement* statement = NEW(SwitchStatement(labels)); Target target(this, statement); Expect(Token::SWITCH, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); Expression* tag = ParseExpression(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); bool default_seen = false; ZoneListWrapper<CaseClause> cases = factory()->NewList<CaseClause>(4); Expect(Token::LBRACE, CHECK_OK); while (peek() != Token::RBRACE) { CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK); cases.Add(clause); } Expect(Token::RBRACE, CHECK_OK); if (statement) statement->Initialize(tag, cases.elements()); return statement;}Statement* Parser::ParseThrowStatement(bool* ok) { // ThrowStatement :: // 'throw' Expression ';' Expect(Token::THROW, CHECK_OK); int pos = scanner().location().beg_pos; if (scanner_.has_line_terminator_before_next()) { ReportMessage("newline_after_throw", Vector<const char*>::empty()); *ok = false; return NULL; } Expression* exception = ParseExpression(true, CHECK_OK); ExpectSemicolon(CHECK_OK); return NEW(ExpressionStatement(new Throw(exception, pos)));}Expression* Parser::MakeCatchContext(Handle<String> id, VariableProxy* value) { ZoneListWrapper<ObjectLiteral::Property> properties = factory()->NewList<ObjectLiteral::Property>(1); Literal* key = NEW(Literal(id)); ObjectLiteral::Property* property = NEW(ObjectLiteral::Property(key, value)); properties.Add(property); // This must be called always, even during pre-parsing! // (Computation of literal index must happen before pre-parse bailout.) int literal_index = temp_scope_->NextMaterializedLiteralIndex(); if (is_pre_parsing_) { return NULL; } // Construct the expression for calling Runtime::CreateObjectLiteral // with the literal array as argument. Handle<FixedArray> constant_properties = Factory::empty_fixed_array(); ZoneList<Expression*>* arguments = new ZoneList<Expression*>(1); arguments->Add(new Literal(constant_properties)); return new ObjectLiteral(constant_properties, properties.elements(), literal_index);}TryStatement* Parser::ParseTryStatement(bool* ok) { // TryStatement :: // 'try' Block Catch // 'try' Block Finally // 'try' Block Catch Finally // // Catch :: // 'catch' '(' Identifier ')' Block // // Finally :: // 'finally' Block Expect(Token::TRY, CHECK_OK); ZoneList<Label*>* label_list = NEW(ZoneList<Label*>(0)); LabelCollector collector(label_list); Block* try_block; { Target target(this, &collector); try_block = ParseBlock(NULL, CHECK_OK); } Block* catch_block = NULL; VariableProxy* catch_var = NULL; Block* finally_block = NULL; Token::Value tok = peek(); if (tok != Token::CATCH && tok != Token::FINALLY) { ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); *ok = false; return NULL; } // If we can break out from the catch block and there is a finally block, // then we will need to collect labels from the catch block. Since we don't // know yet if there will be a finally block, we always collect the labels. ZoneList<Label*>* catch_label_list = NEW(ZoneList<Label*>(0)); LabelCollector catch_collector(catch_label_list); bool has_catch = false; if (tok == Token::CATCH) { has_catch = true; Consume(Token::CATCH); Expect(Token::LPAREN, CHECK_OK); Handle<String> name = ParseIdentifier(CHECK_OK); Expect(Token::RPAREN, CHECK_OK); if (peek() == Token::LBRACE) { // Allocate a temporary for holding the finally state while // executing the finally block. catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); Expression* obj = MakeCatchContext(name, catch_var); { Target target(this, &catch_collector); catch_block = WithHelper(obj, NULL, CHECK_OK); } } else { Expect(Token::LBRACE, CHECK_OK); } tok = peek(); } VariableProxy* finally_var = NULL; if (tok == Token::FINALLY || !has_catch) { Consume(Token::FINALLY); // Declare a variable for holding the finally state while // executing the finally block. finally_var = top_scope_->NewTemporary(Factory::finally_state_symbol()); finally_block = ParseBlock(NULL, CHECK_OK); } // Simplify the AST nodes by converting: // 'try { } catch { } finally { }' // to: // 'try { try { } catch { } } finally { }' if (!is_pre_parsing_ && catch_block != NULL && finally_block != NULL) { TryCatch* statement = NEW(TryCatch(try_block, catch_var, catch_block)); statement->set_escaping_labels(collector.labels()); try_block = NEW(Block(NULL, 1, false)); try_block->AddStatement(statement); catch_block = NULL; } TryStatement* result = NULL; if (!is_pre_parsing_) { if (catch_block != NULL) { ASSERT(finally_block == NULL); result = NEW(TryCatch(try_block, catch_var, catch_block)); result->set_escaping_labels(collector.labels()); } else { ASSERT(finally_block != NULL); result = NEW(TryFinally(try_block, finally_var, finally_block)); // Add the labels of the try block and the catch block. for (int i = 0; i < collector.labels()->length(); i++) { catch_collector.labels()->Add(collector.labels()->at(i)); } result->set_escaping_labels(catch_collector.labels()); } } return result;}LoopStatement* Parser::ParseDoStatement(ZoneStringList* labels, bool* ok) { // DoStatement :: // 'do' Statement 'while' '(' Expression ')' ';' LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::DO_LOOP)); Target target(this, loop); Expect(Token::DO, CHECK_OK); Statement* body = ParseStatement(NULL, CHECK_OK); Expect(Token::WHILE, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); Expression* cond = ParseExpression(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); // Allow do-statements to be terminated with and without // semi-colons. This allows code such as 'do;while(0)return' to // parse, which would not be the case if we had used the // ExpectSemicolon() functionality here. if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); if (loop) loop->Initialize(NULL, cond, NULL, body); return loop;}LoopStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { // WhileStatement :: // 'while' '(' Expression ')' Statement LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::WHILE_LOOP)); Target target(this, loop); Expect(Token::WHILE, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); Expression* cond = ParseExpression(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); Statement* body = ParseStatement(NULL, CHECK_OK); if (loop) loop->Initialize(NULL, cond, NULL, body); return loop;}Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { // ForStatement :: // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement Statement* init = NULL; Expect(Token::FOR, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); if (peek() != Token::SEMICOLON) { if (peek() == Token::VAR || peek() == Token::CONST) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -