⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
    LexicalScope lexical_scope(this, scope);    TemporaryScope temp_scope(this);    ZoneListWrapper<Statement> body(16);    bool ok = true;    ParseSourceElements(&body, Token::EOS, &ok);    if (ok) {      result = NEW(FunctionLiteral(no_name, top_scope_,                                   body.elements(),                                   temp_scope.materialized_literal_count(),                                   temp_scope.contains_array_literal(),                                   temp_scope.expected_property_count(),                                   0, 0, source->length(), false));    } 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;}FunctionLiteral* Parser::ParseLazy(Handle<String> source,                                   Handle<String> name,                                   int start_position,                                   bool is_expression) {  ZoneScope zone_scope(DONT_DELETE_ON_EXIT);  StatsRateScope timer(&Counters::parse_lazy);  Counters::total_parse_size.Increment(source->length());  SafeStringInputBuffer buffer(source.location());  // Initialize parser state.  source->TryFlatten();  scanner_.Init(source, &buffer, start_position);  ASSERT(target_stack_ == NULL);  mode_ = PARSE_EAGERLY;  // Place holder for the result.  FunctionLiteral* result = NULL;  {    // Parse the function literal.    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);    FunctionLiteralType type = is_expression ? EXPRESSION : DECLARATION;    bool ok = true;    result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok);    // Make sure the results agree.    ASSERT(ok == (result != NULL));    // The only errors should be stack overflows.    ASSERT(ok || scanner_.stack_overflow());  }  // Make sure the target stack is empty.  ASSERT(target_stack_ == NULL);  // If there was a stack overflow we have to get rid of AST and it is  // not safe to do before scope has been deleted.  if (result == NULL) {    Top::StackOverflow();    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);}void AstBuildingParser::ReportMessageAt(Scanner::Location source_location,                                        const char* type,                                        Vector<const char*> args) {  MessageLocation location(script_,                           source_location.beg_pos, source_location.end_pos);  Handle<JSArray> array = Factory::NewJSArray(args.length());  for (int i = 0; i < args.length(); i++) {    SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));  }  Handle<Object> result = Factory::NewSyntaxError(type, array);  Top::Throw(*result, &location);}void PreParser::ReportMessageAt(Scanner::Location source_location,                                const char* type,                                Vector<const char*> args) {  recorder()->LogMessage(source_location, type, args);}void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,                                  int end_token,                                  bool* ok) {  // SourceElements ::  //   (Statement)* <end_token>  // Allocate a target stack to use for this set of source  // elements. This way, all scripts and functions get their own  // target stack thus avoiding illegal breaks and continues across  // functions.  TargetScope scope(this);  ASSERT(processor != NULL);  while (peek() != end_token) {    Statement* stat = ParseStatement(NULL, CHECK_OK);    if (stat && !stat->IsEmpty()) processor->Add(stat);  }  return 0;}Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {  // Statement ::  //   Block  //   VariableStatement  //   EmptyStatement  //   ExpressionStatement  //   IfStatement  //   IterationStatement  //   ContinueStatement  //   BreakStatement  //   ReturnStatement  //   WithStatement  //   LabelledStatement  //   SwitchStatement  //   ThrowStatement  //   TryStatement  //   DebuggerStatement  // Note: Since labels can only be used by 'break' and 'continue'  // statements, which themselves are only valid within blocks,  // iterations or 'switch' statements (i.e., BreakableStatements),  // labels can be simply ignored in all other cases; except for  // trivial labelled break statements 'label: break label' which is  // parsed into an empty statement.  // Keep the source position of the statement  int statement_pos = scanner().peek_location().beg_pos;  Statement* stmt = NULL;  switch (peek()) {    case Token::LBRACE:      return ParseBlock(labels, ok);    case Token::CONST:  // fall through    case Token::VAR:      stmt = ParseVariableStatement(ok);      break;    case Token::SEMICOLON:      Next();      return factory()->EmptyStatement();    case Token::IF:      stmt = ParseIfStatement(labels, ok);      break;    case Token::DO:      stmt = ParseDoStatement(labels, ok);      break;    case Token::WHILE:      stmt = ParseWhileStatement(labels, ok);      break;    case Token::FOR:      stmt = ParseForStatement(labels, ok);      break;    case Token::CONTINUE:      stmt = ParseContinueStatement(ok);      break;    case Token::BREAK:      stmt = ParseBreakStatement(labels, ok);      break;    case Token::RETURN:      stmt = ParseReturnStatement(ok);      break;    case Token::WITH:      stmt = ParseWithStatement(labels, ok);      break;    case Token::SWITCH:      stmt = ParseSwitchStatement(labels, ok);      break;    case Token::THROW:      stmt = ParseThrowStatement(ok);      break;    case Token::TRY: {      // NOTE: It is somewhat complicated to have labels on      // try-statements. When breaking out of a try-finally statement,      // one must take great care not to treat it as a      // 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);      TryStatement* statement = ParseTryStatement(CHECK_OK);      if (result) result->AddStatement(statement);      return result;    }    case Token::FUNCTION:      return ParseFunctionDeclaration(ok);    case Token::NATIVE:      return ParseNativeDeclaration(ok);    case Token::DEBUGGER:      stmt = ParseDebuggerStatement(ok);      break;    default:      stmt = ParseExpressionOrLabelledStatement(labels, ok);  }  // Store the source position of the statement  if (stmt != NULL) stmt->set_statement_pos(statement_pos);  return stmt;}VariableProxy* AstBuildingParser::Declare(Handle<String> name,                                          Variable::Mode mode,                                          FunctionLiteral* fun,                                          bool resolve,                                          bool* ok) {  Variable* var = NULL;  // If we are inside a function, a declaration of a variable  // is a truly local variable, and the scope of the variable  // is always the function scope.  // If a function scope exists, then we can statically declare this  // variable and also set its mode. In any case, a Declaration node  // will be added to the scope so that the declaration can be added  // to the corresponding activation frame at runtime if necessary.  // For instance declarations inside an eval scope need to be added  // to the calling function context.  if (top_scope_->is_function_scope()) {    // Declare the variable in the function scope.    var = top_scope_->Lookup(name);    if (var == NULL) {      // Declare the name.      var = top_scope_->Declare(name, mode);    } else {      // The name was declared before; check for conflicting      // re-declarations. If the previous declaration was a const or the      // current declaration is a const then we have a conflict. There is      // similar code in runtime.cc in the Declare functions.      if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {        // We only have vars and consts in declarations.        ASSERT(var->mode() == Variable::VAR ||               var->mode() == Variable::CONST);        const char* type = (var->mode() == Variable::VAR) ? "var" : "const";        Handle<String> type_string =            Factory::NewStringFromUtf8(CStrVector(type), TENURED);        Expression* expression =            NewThrowTypeError(Factory::redeclaration_symbol(),                              type_string, name);        top_scope_->SetIllegalRedeclaration(expression);      }    }  }  // We add a declaration node for every declaration. The compiler  // will only generate code if necessary. In particular, declarations  // for inner local variables that do not represent functions won't  // result in any generated code.  //  // Note that we always add an unresolved proxy even if it's not  // used, simply because we don't know in this method (w/o extra  // parameters) if the proxy is needed or not. The proxy will be  // bound during variable resolution time unless it was pre-bound  // below.  //  // WARNING: This will lead to multiple declaration nodes for the  // same variable if it is declared several times. This is not a  // semantic issue as long as we keep the source order, but it may be  // a performance issue since it may lead to repeated  // Runtime::DeclareContextSlot() calls.  VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());  top_scope_->AddDeclaration(NEW(Declaration(proxy, mode, fun)));  // For global const variables we bind the proxy to a variable.  if (mode == Variable::CONST && top_scope_->is_global_scope()) {    ASSERT(resolve);  // should be set by all callers    var = NEW(Variable(top_scope_, name, Variable::CONST, true, false));  }  // If requested and we have a local variable, bind the proxy to the variable  // at parse-time. This is used for functions (and consts) declared inside  // statements: the corresponding function (or const) variable must be in the  // function scope and not a statement-local scope, e.g. as provided with a  // 'with' statement:  //  //   with (obj) {  //     function f() {}  //   }  //  // which is translated into:  //  //   with (obj) {  //     // in this case this is not: 'var f; f = function () {};'  //     var f = function () {};  //   }  //  // Note that if 'f' is accessed from inside the 'with' statement, it  // will be allocated in the context (because we must be able to look  // it up dynamically) but it will also be accessed statically, i.e.,  // with a context slot index and a context chain length for this  // initialization code. Thus, inside the 'with' statement, we need  // both access to the static and the dynamic context chain; the  // runtime needs to provide both.  if (resolve && var != NULL) proxy->BindTo(var);  return proxy;}// Language extension which is only enabled for source files loaded// through the API's extension mechanism.  A native function// declaration is resolved by looking up the function through a// callback provided by the extension.Statement* Parser::ParseNativeDeclaration(bool* ok) {  if (extension_ == NULL) {    ReportUnexpectedToken(Token::NATIVE);    *ok = false;    return NULL;  }  Expect(Token::NATIVE, CHECK_OK);  Expect(Token::FUNCTION, CHECK_OK);  Handle<String> name = ParseIdentifier(CHECK_OK);  Expect(Token::LPAREN, CHECK_OK);  bool done = (peek() == Token::RPAREN);  while (!done) {    ParseIdentifier(CHECK_OK);    done = (peek() == Token::RPAREN);    if (!done) Expect(Token::COMMA, CHECK_OK);  }  Expect(Token::RPAREN, CHECK_OK);  Expect(Token::SEMICOLON, CHECK_OK);  if (is_pre_parsing_) return NULL;  // Make sure that the function containing the native declaration  // isn't lazily compiled. The extension structures are only  // accessible while parsing the first time not when reparsing  // because of lazy compilation.  top_scope_->ForceEagerCompilation();  // Compute the function template for the native function.  v8::Handle<v8::FunctionTemplate> fun_template =      extension_->GetNativeFunction(v8::Utils::ToLocal(name));  ASSERT(!fun_template.IsEmpty());  // Instantiate the function and create a boilerplate function from it.  Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());  const int literals = fun->NumberOfLiterals();  Handle<Code> code = Handle<Code>(fun->shared()->code());  Handle<JSFunction> boilerplate =      Factory::NewFunctionBoilerplate(name, literals, false, code);  // Copy the function data to the boilerplate. Used by

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -