v8编译过程(parser.cc文件)
1.创建编译环境MakeAST()
解析器AstBuildingParser parser->扫描器Scanner scanner_
扫描器结构: (1)TokenDesc current_
(2)TokenDesc next_
(3)缓冲 source_
2.语法分析(包含词法分析),创建抽象语法树(AST)FunctionLiteral-----(语句,声明,)
MakeAST()->ParseProgram()->ParseSourceElements():
进入while循环,每次解析一个JS语句
While(peek()!=end_token)
{
Statement* stat = ParseStatement(NULL, CHECK_OK);//解析一个语句
if (stat == NULL || stat->IsEmpty()) continue;//函数声明语句不放入FunctionLiteral
……
processor->Add(stat);//放入最外层FunctionLiteral的ZoneList
}
ParseStatement():解析一个语句
(1)根据下一个Token判断语句类型,并进入相应的语句解析函数
switch (peek()) //取下一个Token
{
case Token::LBRACE:
return ParseBlock(labels, ok); //{}Block语句
case Token::CONST:
case Token::VAR:
stmt = ParseVariableStatement(ok); //变量声明语句
break;
case Token::SEMICOLON:
Next();
return factory()->EmptyStatement(); //空语句
case Token::IF:
stmt = ParseIfStatement(labels, ok); //If语句
break;
case Token::DO:
stmt = ParseDoWhileStatement(labels, ok); //Do循环语句
break;
case Token::WHILE:
stmt = ParseWhileStatement(labels, ok); //While循环语句
break;
case Token::FOR:
stmt = ParseForStatement(labels, ok); //For循环语句
break;
case Token::CONTINUE:
stmt = ParseContinueStatement(ok); //Continue语句
break;
case Token::BREAK:
stmt = ParseBreakStatement(labels, ok); //Break语句
break;
case Token::RETURN:
stmt = ParseReturnStatement(ok); //返回语句
break;
case Token::WITH:
stmt = ParseWithStatement(labels, ok); //With语句??
break;
case Token::SWITCH:
stmt = ParseSwitchStatement(labels, ok); //Switch语句
break;
case Token::THROW:
stmt = ParseThrowStatement(ok); //Throw语句
break;
case Token::TRY:
{……} //Try语句
case Token::FUNCTION:
return ParseFunctionDeclaration(ok); //函数声明语句
case Token::NATIVE:
return ParseNativeDeclaration(ok);
case Token::DEBUGGER:
stmt = ParseDebuggerStatement(ok); //Debugger语句
break;
default: stmt = ParseExpressionOrLabelledStatement(labels, ok);//其他语句(表达式/标号)
}
(2)解析语句
首先,调用扫描器Scanner(对JS源码进行词法分析):每次扫描Scan()得到当前Token和下一个Token,把Token描述信息分别放入TokenDesc current_和 TokenDesc next_中,把Token的值放入缓冲source_中.
其次,根据JS的语法语义进行相应(编译时)处理
最后,
-1-一般(非声明)语句:创建Statement对象,放入FunctionLiteral对象中ZoneList<Statement*>.
-2-变量声明语句:创建Declaration对象放入当前抽象语法树FunctionLiteral的Scope的decls_,
再由CallRuntime语句创建ExpressionStatement对象,放入body_ (JS语句 数组)
-3-函数声明语句:根据函数体创建新的抽象语法树FunctionLiteral,放入新创建的
Declaration对象,再放入当前抽象语法树FunctionLiteral的Scope的 decls_.
解析完所有语句后,得到抽象语法树FunctionLiteral。
附:
抽象语法树4种结点:Statement(语句),Expression(表达式),Declaration(声明)和TargetCollector
---------------------------------------------------------------------------------------------------------------------------------
抽象语法树FunctionLiteral结构
1.ZoneList<Statement*> body_ JS语句数组
2.Scope* scope_
(1)ZoneList<Declaration*> decls_ 变量、函数声明数组(Declaration对象数组)
(2)……….
3.……
---------------------------------------------------------------------------------------------------------------------------------
抽象语法树FunctionLiteral结点的继承层次
ZoneObject
| AstNode
| | Statement
| | | BreakableStatement
| | | | Block
| | | | IterationStatement
| | | | | DoWhileStatement
| | | | | WhileStatement
| | | | | ForStatement
| | | | | ForInstatement
| | | | SwitchStatement
| | | ExpressionStatement
| | | ContinueStatement
| | | BreakStatement
| | | ReturnStatement
| | | WithEnterStatement
| | | WithExitStatement
| | | IfStatement
| | | TryStatement
| | | | TryCatchStatement
| | | | TryFinallyStatement
| | | DebuggerStatement
| | | EmptyStatement
| | Expression (会被转化为ExpressionStatement)
| | | ValidLeftHandSideSentinel
| | | Literal
| | | MaterializedLiteral
| | | | ObjectLiteral
| | | | RegExpLiteral
| | | | ArrayLiteral
| | | CatchExtensionObject
| | | VariableProxy
| | | | VariableProxySentinel
| | | Slot
| | | Property
| | | Call
| | | CallNew
| | | CallRuntime
| | | UnaryOperation
| | | BinaryOperation
| | | CountOperation
| | | CompareOperation
| | | Conditional
| | | Assignment
| | | Throw
| | | FunctionLiteral
| | | ShareFunctionInfoLiteral
| | | ThisFunction
| | Declaration
| | TargetCollector
| CaseClause