Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31976
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 82
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-23 20:17
个人简介

目前从事性能优化工作,主要做的是hhvm,php方向的性能调优和web server的开发

文章分类
文章存档

2013年(1)

我的朋友

分类: 架构设计与优化

2013-06-23 20:44:01

 

2.  Hiphop 编译原理分析

接着上节没有分析完的内容继续分析

2.1.  hiphop 编译处理流程

 

编译流程以 echo “test”;简单分析

(1)加载web server基本信息,通过调用RuntimeOption::Load(empty)方法进行加载

(2)初始化加载扩展基本内容:prepareOptions(po, argc, argv);初始化编译配置;BuiltinSymbols::LoadSuperGlobals()加载php 如_get,_session等函数的返回值类型等;BuiltinSymbols::Load和ar->loadBuiltins()加载扩展类、扩展方法、扩展常量、扩展变量

(3)parser:通过调用Package的parser方法,执行lex和bison进行词法和语法分析,生成语法分析树

(4) analyzeProgram:语义分析阶段,进行划分作用域和控制流等

(5)(7)代码优化

(6)类型推导

(8)生成代码

 

2.2.  hiphop 词法分析

例:echo “test”;

进入词法和语法分析的入口是Package::parse方法

词法分析规则文件是在src/Utile/Parse/hphp.x中,是用flex进行词法分析的

echo “test”

匹配了2个token分别为:

T_ECHO 和T_CONSTANT_ENCAPSED_STRING

Hphp.x中的匹配规则如下:

echo词法分析为T_ECHO

"echo"                 { SETTOKEN; return T_ECHO;}

“test” 解析TOKEN为T_CONSTANT_ENCAPSED_STRING

ANY_CHAR (.|[\n])

 

DOUBLE_QUOTES_LITERAL_DOLLAR("$"+([^a-zA-Z_\x7f-\xff$\"\\{]|("\\"{ANY_CHAR})))

 

DOUBLE_QUOTES_CHARS("{"*([^$\"\\{]|("\\"{ANY_CHAR}))|{DOUBLE_QUOTES_LITERAL_DOLLAR})

 

(b?[\"]{DOUBLE_QUOTES_CHARS}*("{"*|"$"*)[\"]){

       int bprefix = (yytext[0] != '"') ? 1 : 0;

       std::string strval =

         _scanner->escape(yytext + bprefix + 1,

                           yyleng - bprefix -2, '"');

       _scanner->setToken(yytext, yyleng, strval.c_str(), strval.length());

       return T_CONSTANT_ENCAPSED_STRING;

}

 

Hiphop 定义的默认Token 结构是:

#define YYSTYPE HPHP::ScannerToken

调用流程:

(1)首先调用:hphp.y中的

static int yylex(YYSTYPE *token,HPHP::Location *loc, Parser *_p) {

 return _p->scan(token, loc);}调用扫描器;

(2)然后扫描器scan调用扫描器:Scanner::getNextToken ,获取token

(3)然后调用hphp.x中的:

int Scanner::scan() {

   return yylex(m_token, m_loc, m_yyscanner);

  }

(4)执行yylex对lex语法进行分析

 

TOKEN分词,目前echo “test”给拆分成了2个TOKEN

echo => T_ECHO

“test” =>T_CONSTANT_ENCAPSED_STRING

 

这里都是通过正则匹配进行词法分析的:

(1)      echo

"echo"                 { SETTOKEN; return T_ECHO;}

当遇到echo 时则返回T_ECHO,其他依次类推,更多的分析,我们将在原理分析二中进行分析语句(statement)和表达式(expression)

(2)      “test”

通过正则分析最终匹配T_CONSTANT_ENCAPSED_STRING,常量String的这个TOKEN

词法分析完成后,下一步就是进行语法分析了

2.3.  hiphop 语法分析

之前lex 已经划分出了2个token: T_ECHO 和T_CONSTANT_ENCAPSED_STRING

根据token 查找语法规则:

Hphp的语法分析是用bison分析的,在src/Utile/Parse/hphp.y文件中

T_ECHO expr_list { _p->onEcho($$, $2,0);}

匹配上这里后,然后expr_list 又是一个合成规则,继续递归往下找,直到找到最终匹配规则:

common_scalar:

   T_LNUMBER                         { _p->onScalar($$, T_LNUMBER, $1);}

  |T_DNUMBER                          { _p->onScalar($$, T_DNUMBER,  $1);}

  |T_CONSTANT_ENCAPSED_STRING         {_p->onScalar($$,

                                        T_CONSTANT_ENCAPSED_STRING,  $1);}

最终封装为一个语法树

 

具体规则内容:

start:

   top_statement_list                { _p->popLabelInfo();

                                        _p->saveParseTree($$);}

;

 

top_statement_list:

   top_statement_list

   top_statement                     { _p->addStatement($$,$1,$2);}

 |                                    {_p->onStatementListStart($$);}

;

top_statement:

   statement                         { _p->nns($1.num() == T_DECLARE);

                                         $$ =$1;}

 ............

;

 

statement:

……..

  |T_ECHO expr_list ';'               {_p->onEcho($$, $2, 0);}

/////////////////////////////////////

expr_list:

   expr_list ',' expr                { _p->onExprListElem($$, &$1, $3);}

  |expr                               {_p->onExprListElem($$, NULL, $1);};

/////////////////////////////////

expr:

...............

  |scalar                             { $$ =$1;}

.............;

/////////////////////////////////////////

scalar:

.........

  |common_scalar                      { $$ =$1;}

............

;

 

 

common_scalar:

    T_LNUMBER                          { _p->onScalar($$,T_LNUMBER,  $1);}

  |T_DNUMBER                          {_p->onScalar($$, T_DNUMBER,  $1);}

  |T_CONSTANT_ENCAPSED_STRING         {_p->onScalar($$,

                                         T_CONSTANT_ENCAPSED_STRING,  $1);}

…………..

 

 

具体流程如下:

语法分析从start开始,类似top_statement:{…..}是一个语句;

如我们的echo,他会逐个的语句中去找,最终在

statement:

……..

  |T_ECHO expr_list ';'               {_p->onEcho($$, $2, 0);}

这个语句中找到了T_ECHO,然后{这里面的是调用的实现代码}

移进是一个自顶向下的过程,规约是一个自底向上的过程;

Statement=> T_ECHO=> expr_list=> expr=>scalar=>common_scalar=> T_CONSTANT_ENCAPSED_STRING

这就一个echo “test” 的语法分析:

首先找到T_ECHO 然后向下找expr_list;

expr_list 又有子集expr;

expr,这个表达式呢又找到是一个scalar的;

scalar表达式子集中common_scalar又有匹配;

 最终在common_scalar中找到匹配的TOKEN (T_CONSTANT_ENCAPSED_STRING)

 

 

匹配的过程其实就是一个移进规约的过程:

Echo “test”

这里的.是游标

Echo .”test” 移进

EchoExpression “test”. 规约

EchoExpression ExpressionList 规约

EchoExpression. ScalarExpression移进

EchoExpression ExpressionList. 移进

EchoExpression ExpressionList规约

EchoExpression. ExpressionList移进

Statement 规约

Statement. 移进

top_statement 规约

top_statement. 移进

top_statement_list 规约

 

移进规约后生成一颗语法树;

 

 

Parser::onScalar 这个方法是获取T_CONSTANT_ENCAPSED_STRING这个token 后创建一个saclarExpression的实例

然后调用_p->onExprListElem($$, NULL, $1);是将saclarExpression封装到exprList中

然后调用onEcho 是将exprList封装到EchoStatment语句中,这样就生成了一个语法树

上面的$$类似于树的顶点,也就是每次处理后返回的封装节点,$1则是传入的token或者表达式等内容的信息,对其进行封装

 

生成的语法树:

 

 

 

 

 

hiphop Token 的数据结构:

          class Token : public ScannerToken 

ExpressionPtr exp;

 StatementPtr stmt;

Class ScannerToken

  int m_num; // internal token id

  std::string m_text;

  bool m_check;

我的 iteye博文地址:
http://saiyaren.iteye.com/blog/1888996

下一节:hiphop原理分析2

阅读(3501) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~