PHP语法分析器:RE2C BISON 总结

news/2024/7/3 14:36:48 标签: php, c, token, zend, scripting, yacc
cle class="baidu_pl">
cle_content" class="article_content clearfix">
content_views" class="htmledit_views">
cal-align: baseline; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); "> 声明:本文为 斯人原创࿰c;全部为作者一一分析得之࿰c;有不对的地方望赐教。
欢迎转载࿰c;转载请注明出处 。
本文地址: http://imsiren.com/archives/647

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">在这之前࿰c;我曾经尝试过一个项目࿰c;就是将我们的PHP代码自动生成so扩展࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">编译到PHP中࿰c;我叫它 class="tags" href="/tags/PHP.html" title=php>phptoc

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">但是由于各种原因࿰c;暂停了此项目。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">写这篇文章一是因为这方面资料太少࿰c;二是把自己的收获总结下来࿰c;以便以后参考࿰c;如果能明白PHP语法分析

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">那对PHP源码的研究会更上一层楼地 ^.^…

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">我尽可能写的通俗易懂些。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">这个项目思路源于facebook的开源项目 HipHop .

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">其实我对这个项目的性能提高50%-60%持怀疑态度࿰c;从根本来讲࿰c;如果PHP用到APC缓存࿰c;它的性能是否低

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">于HipHop࿰c;我还没有做测试࿰c;不敢断言。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">PHPtoc,我只是想把C程序员解放出来࿰c;希望能达到࿰c;让PHPer用PHP代码就可以写出接近于PHP扩展性能的一个扩展࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">它的流程如下࿰c;读取PHP文件࿰c;解析PHP代码࿰c;对其进行语法分析器࿰c;生成对应的ZendAPI࿰c;编译成扩展。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">class="aligncenter size-full wp-image-654" title="class="tags" href="/tags/PHP.html" title=php>phptoc" src="http://imsiren.com/wp-content/uploads/2012/10/class="tags" href="/tags/PHP.html" title=php>phptoc.jpg" alt="" width="511" height="95" style="margin: 10px auto; padding: 4px; border: 1px solid rgb(221, 221, 221); vertical-align: baseline; display: block; max-width: 610px; height: auto; background-color: rgb(255, 255, 255); clear: both; " />

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">cal-align: baseline; ">进入正题

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">这里最难的就是语法分析器了࿰c;大家应该都知道࿰c;PHP也有自己的语法分析器࿰c;现在版本用到的是re2c 和 Bison。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">所以࿰c;我自然也用到了这个组合。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">如果要用PHP的语法分析器就不太现实了࿰c;因为需要修改zend_language_parser.y和 zend_language_scanner.l 并重新编译࿰c;这难度大不说࿰c;还可能影响PHP自身。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">所以决定重新写一套自己的语法分析规则࿰c;这个功能就等于是重写了PHP的语法分析器࿰c;当然会舍弃一些不常用的。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">re2c && yacc/bison࿰c;通过引用自己的对应文件࿰c;然后将他们统一编译成一个*.c文件࿰c;最后再gcc编译就会生

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">成我们自己的程序。所以说࿰c;他们从根本来讲不是语法分析程序࿰c;他们只是将我们的规则生成一个独立的c

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">件࿰c;这个c文件才是真正的我们需要的语法分析程序࿰c;我更愿意叫它 语法生成器。如下图:

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">class="aligncenter size-full wp-image-656" title="way" src="http://imsiren.com/wp-content/uploads/2012/10/way1.jpg" alt="" width="312" height="348" style="margin: 10px auto; padding: 4px; border: 1px solid rgb(221, 221, 221); vertical-align: baseline; display: block; max-width: 610px; height: auto; background-color: rgb(255, 255, 255); clear: both; " />

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">注:图中a.c是 扫描器生成的最终代码。。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">re2c扫描器࿰c;假如我们写的扫描规则文件叫scanner.l࿰c;它会将我们写的PHP文件内容࿰c;进行扫描࿰c;然后根据

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">我们写的规则࿰c;生成不同的token传递给parse。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">我们写的(f)lex语法规则࿰c;比如我们叫他Parse.y

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">会通过 yacc/bison编译成一个parse.tab.h,parse.tab.c的文件࿰c;parse根据不同的token进行不同的操作

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">比如我们PHP代码是 “echo 1″;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">扫描其中有一个规则:

<code class="language-cpp">"echo" {

return T_ECHO;
 }
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">扫描器函数scan会拿到”echo 1″字符串࿰c;它对这一段代码进行循环࿰c;如果发现有echo字符串࿰c;那么它就作为关键字返回token:T_ECHO,

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">parse.y和scanner.l会分别生成两个c文件࿰c;scanner.c和parse.tab.cc;用gcc编译到一起࿰c;就成了。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">下面会具体的说一说

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">re2c,关于它的英文文档在 http://re2c.org/manual.html࿰c;感兴趣的可以去看看࿰c;我也翻译了一个中文版本࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">还么有结束࿰c;稍后我会放上来。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">re2c提供了一些宏接口࿰c;方面我们使用࿰c;我简单做了翻译࿰c;英语水平不好࿰c;可能有误࿰c;需要原文的可以去上面那个地址查看。

<code class="language-cpp">接口代码:
不像其他的扫描器程序࿰c;re2c 不会生成完整的扫描器:用户必须提供一些接口代码。用户必须定义下面的宏或者是其他相应的配置。
YYCONDTYPE
	用-c 模式你可以使用-to参数用来生成一个文件:使用包含枚举类型的作为条件。每个值都会在规则集合里面作为条件来使用。
YYCTYPE
	用来维持一个输入符号。通常是 char 或者unsigned char。
YYCTXMARKER
	*YYCTYPE类型的表达式࿰c;生成的代码回溯信息的上下文会保存在 YYCTXMARKER。如果扫描器规则需要使用上下文中的一个或多个正则表达式则用户需要定义这个宏。
YYCURSOR
	*YYCTYPE类型的表达式指针指向当前输入的符号࿰c;生成的代码作为符号相匹配࿰c;在开始的地方࿰c;YYCURSOR假定指向当前token的第一个字符。结束时࿰c;YYCURSOR将会指向下一个token的第一个字符。
YYDEBUG(state,current)
	这个只有指定-d标示符的时候才会需要。调用用户定义的函数时可以非常容易的调试生成的代码。
	这个函数应该有以下签名:void YYDEBUG(int state,char current)。第一个参数接受 state ࿰c;默认值为-1第二个参数接受输入的当前位置。
YYFILL(n)
	当缓冲器需要填充的时候࿰c;生成的代码将会调用YYFILL(n):至少提供n个字符。YYFILL(n)将会根据需要调整YYCURSOR,YYLIMIT,YYMARKER 和 YYCTXMARKER。注意在典型的程序语言当中࿰c;n等于最长的关键词的长度加一。用户可以在/*!max:re2c*/一次定义YYMAXFILL来指定最长长度。如果使用了-1࿰c;YYMAXFILL将会在/*!re2c*/之后调用一次阻塞。
YYGETCONDITION()
	如果使用了-c模式࿰c;这个定义将会在扫描器代码之前获取条件集。这个值࿰c;必须初始化为枚举YYCONDTYPE的类型。
YYGETSTATE()
	如果-f模式指定了࿰c;用户就需要定义这个宏。如果这样࿰c;扫描器在开始时为了获取保存的状态࿰c;生成的代码将会调用YYGETSTATE()࿰c;YYGETSTATE()必须返回一个带符号的整数࿰c;这个值如果是-1࿰c;告诉扫描器这是第一次执行࿰c;否则这个值等于以前YYSETSTATE(s) 保存的状态。否则࿰c;扫描器将会恢复操作之后立即调用YYFILL(n)。
YYLIMIT
	表达式的类型 *YYCTYPE 标记缓冲器的结尾(YYLIMIT(-1)是缓冲区的最后一个字符)。生成的代码将会不断的比较YYCORSUR 和 YYLIMIT 以决定 什么时候填充缓冲区。
YYSETCONDITION(c)
	这个宏用来在转换规则中设置条件࿰c;它只会在指定-c模式 和 使用转换规则时有用。
YYSETSTATE(s)
	用户只需要在指定-f模式时定义这个宏࿰c;如果是这样࿰c;生成的代码将会在YYFILL(n)之前调用YYSETSTATE(s)࿰c;YYSETSTATE的参数是一个有符号整型࿰c;被称为唯一的标示特定的YYFILL(n)实例。
YYMARKER
	类型为*YYCTYPE的表达式࿰c;生成的代码保存回溯信息到YYMARKER。一些简单的扫描器可能用不到。
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">扫描器࿰c;顾名思义࿰c;就是对文件扫描࿰c;找出关键代码来。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">扫描器文件结构:

<code class="language-cpp">/* #include 文件*/
/*宏定义*/
//扫描函数
int scan(char *p){
/*扫描器规则区*/
}
//执行scan扫描函数࿰c;返回token到yacc/bison中。
int yylex(){
        int token;
        char *p=YYCURSOR;//YYCURSOR是一个指针࿰c;指向我们的PHP文本内容
        while(token=scan(p)){//这里会移动指针p,一个一个判断是不是我们上面定义好的scanner...
                return token;
        }
}
int main(int argc,char**argv){
        BEGIN(INITIAL);//
        YYCURSOR=argv[1];//YYCURSOR是一个指针࿰c;指向我们的PHP文本内容,
        yyparse();
}
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">BEGIN 是定义的宏

<code class="language-cpp">#define YYCTYPE char   //输入符号的类型
#define STATE(name)     yyc##name
#define BEGIN(n)        YYSETCONDITION(STATE(n))
#define LANG_SCNG(v)    (sc_globals.v)
#define SCNG    LANG_SCNG
#define YYGETCONDITION()        SCNG(yy_state)
#define YYSETCONDITION(s)       SCNG(yy_state)=s
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">yyparse函数是在yacc 中定义的࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">里面有一个关键宏: YYLEX

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">#define YYLEX yylex()

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">它会执行scaner扫描器的yylex

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">可能会有点绕࿰c;重新缕一缕:

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">在scanner.l中࿰c;通过调用parse.y解析器函数yyparse࿰c;该函数调用scanner.l的yylex生成关键代码tokenc;yylex

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">将扫描器返回的

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">token返回给parse.y࿰c;parse根据不同的token执行不同的代码.

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">举例:

<code class="language-cpp">scanner.l
#include "scanner.h"
#include "parse.tab.h"
int scan(char *p){
/*!re2c
     <INITIAL>"<?class="tags" href="/tags/PHP.html" title=php>php"([ \t]|{NEWLINE})? {
                BEGIN(ST_IN_SCRIPTING);
                return T_OPEN_TAG;
        }
    "echo" {

                return T_ECHO;
        }
    [0-9]+ {
                return T_LNUMBER;
        }
*/
}
int yylex(){
          int c;

//       return T_STRING;
        int token;
        char *p=YYCURSOR;
        while(token=scan(p)){
                return token;
        }
}

int main (int argc,char ** argv){
        BEGIN(INITIAL);//初始化
        YYCURSOR=argv[1];//将用户输入的字符串放到YYCURSOR
        yyparse();//yyparse() -》yylex()-》yyparse()
        return 0;
}
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">这样一个简单的扫描器就做成了࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">那解析器呢?

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">解析器我用的是flex和bison。。。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">关于flex的文件结构:

<code class="language-cpp">%{
/*
  C代码段将逐字拷贝到lex编译后产生的C源文件中
  可以定义一些全局变量࿰c;数组࿰c;函数例程等...
*/
#include
#include "scanner.h"
extern int yylex();//它在scanner.l中定义的。。
void yyerror(char *);
# define YYPARSE_PARAM tsrm_ls
# define YYLEX_PARAM tsrm_ls
%}
{定义段࿰c;也就是token定义的地方}
//这就是关键  token程序是根据这是做switch的。
%token T_OPEN_TAG
%token T_ECHO
%token T_LNUMBER
%%
{规则段}
start:
         T_OPEN_TAG{printf("start\n"); }
        |start statement
;
statement:
T_ECHO expr {printf("echo :%s\n",$3)}
;
expr:
        T_LNUMBER {$$=$1;}
%%
{用户代码段}
void yyerror(char *msg){
        printf("error:%s\n",msg);
}
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">在规则段中࿰c;start是开始的地方࿰c;如果 scan识别到PHP开始标签就会返回T_OPEN_TAG,然后执行括号的代码,输出start.

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">在scanner.l中,调用scan的是个while循环,所以它会检查到class="tags" href="/tags/PHP.html" title=php>php代码的末尾,

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">yyparse会根据scan返回的标记做switch࿰c;然后goto到相应的代码,比如 yyparse.y发现当前的token是T_OPEN_TAG,

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">它会通过宏 #line 映射到 parse.y所对应 21行࿰c;T_OPEN_TAG的位置࿰c;然后执行

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">画个图来说明一下࿰c;
class="aligncenter size-full wp-image-663" title="111" src="http://imsiren.com/wp-content/uploads/2012/10/111.jpg" alt="" width="399" height="847" style="margin: 10px auto; padding: 4px; border: 1px solid rgb(221, 221, 221); vertical-align: baseline; display: block; max-width: 610px; height: auto; background-color: rgb(255, 255, 255); clear: both; " />

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">那࿰c;TOKEN返回给yyparse之后做了什么呢?

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">为了能直观一些࿰c;我用gdb跟踪:

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">class="aligncenter size-full wp-image-664" title="22" src="http://imsiren.com/wp-content/uploads/2012/10/22.png" alt="" width="446" height="308" style="margin: 10px auto; padding: 4px; border: 1px solid rgb(221, 221, 221); vertical-align: baseline; display: block; max-width: 610px; height: auto; background-color: rgb(255, 255, 255); clear: both; " />

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">这个时候yychar是258,258是什么?

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">class="aligncenter size-full wp-image-665" title="20121018144231" src="http://imsiren.com/wp-content/uploads/2012/10/20121018144231.png" alt="" width="209" height="298" style="margin: 10px auto; padding: 4px; border: 1px solid rgb(221, 221, 221); vertical-align: baseline; display: block; max-width: 610px; height: auto; background-color: rgb(255, 255, 255); clear: both; " />

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">258是bison自动生成的枚举类型数据。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">继续

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">YYTRANSLATE宏接受yychar࿰c;然后返回所对应的值

<code class="language-cpp">#define YYTRANSLATE(YYX)                                                \
  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)

/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
static const yytype_uint8 yytranslate[] =
{
       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,    27,     2,
      22,    23,     2,     2,    28,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,    21,
       2,    26,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,    24,     2,    25,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
      15,    16,    17,    18,    19,    20
};
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">yyparse拿到这个值࿰c;不断地translate࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">c="http://imsiren.com/wp-content/uploads/2012/10/444444.png" alt="" title="444444" width="445" height="410" class="aligncenter size-full wp-image-666" style="margin: 10px auto; padding: 4px; border: 1px solid rgb(221, 221, 221); vertical-align: baseline; display: block; max-width: 610px; height: auto; background-color: rgb(255, 255, 255); clear: both; " />

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">bison会生成很多用来映射的数组࿰c;将最终的translate保存到yyn,

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">这样bison就能找到token所对应的代码

<code class="language-cpp">  switch (yyn)
    {
        case 2:

/* Line 1455 of yacc.c  */
#line 30 "parse.y"
    {printf("start\n"); ;}
    break;
code>

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">这样࿰c;不断循环࿰c;生成token逐条执行࿰c;然后解析成所对应的zend 函数等࿰c;生成对应的op保存在哈希表中࿰c;这些不是本文的重点࿰c;

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">就不细说了。

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">到这里࿰c;整体的流程就结束了。。剩下的就是细化的工作࿰c;如果有时间࿰c;我再继续class="tags" href="/tags/PHP.html" title=php>phptoc :)

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">我写的可能很乱࿰c;如果哪儿有不懂的话࿰c;就留言吧。。。 :)

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">下面是一些相关资料:

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">Yacc: http://dinosaur.compilertools.net/yacc/

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">Yacc译文:http://blog.chinaunix.net/space.class="tags" href="/tags/PHP.html" title=php>php?uid=20106293&do=blog&id=142118

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">Bison:http://dinosaur.compilertools.net/bison/bison_6.html#SEC56

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">Re2c:http://re2c.org/manual.html

cal-align: baseline; line-height: 18px; color: rgb(51, 51, 51); font-family: Tahoma, Arial, Helvetica, sans-serif; text-align: left; background-color: rgb(247, 247, 247); ">还有我翻译了一部分的re2c

cle>

http://www.niftyadmin.cn/n/1790427.html

相关文章

CF 331 E. Biologist

CF 331 E. Biologist 题目描述 题目大意&#xff1a;有\(n\)个点&#xff0c;初始时每个点为黑色或者白色&#xff0c;你可以花费\(v_i\)的代价将一个点反色。然后你有许多计划&#xff0c;每个计划要求一个点集中的所有点为同种颜色。满足了一个计划就可以得到\(w_i\)相应的价…

makefile中的gcc -o $@ $^是什么意思?

$表示目标&#xff0c;$^表示依赖列表。 比如&#xff1a; edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o $就是edit $^就是main.o kbd.o command.o display.o insert.o search.o files.o utils.o 转载于:https://www.cnblogs.com/codingmengmen…

PHP命令执行PHP脚本,结束之前,内存会回收吗?

在往下看之前,如果你不明白什么是GC (Garbage Collection) 的话,那一定要先去了解GC,不然你根本不知道我在说什么! Links: http://www.php.net/manual/en/features.gc.php http://blog.csdn.net/phpkernel/article/details/5734743再详细说下问题&#xff1a; unix下&#xff0…

java常用工具包

1、国外 org.apache.commons.lang3 http://commons.apache.org/proper/commons-lang/javadocs/api-3.8.1/index.html 2、国内 https://apidoc.gitee.com/loolly/hutool/转载于:https://www.cnblogs.com/fanrenren/p/10618090.html

css小知识点

移动端input输入框文字颜色问题 -webkit-text-fill-color: rgba(0, 0, 0, 0.7); -webkit-opacity: 0.7; 巧用css &#xff1a;before和&#xff1a;after &#xff1a;http://www.cnblogs.com/ys-ys/p/5092760.html转载于:https://www.cnblogs.com/xiaoyue-/p/10620393.html

PHP的json_encode分析

json的优点就不说了&#xff0c; 有个习惯&#xff0c;我在输出json的时候&#xff0c;喜欢用 sprintf 拼成json格式&#xff0c; 前两天被朋友说不标准&#xff0c;必须要用json_encode生成的才是标准的json格式&#xff0c;我当然很郁闷啦&#xff0c; 用了这么多年了&#x…

拐点

拐点&#xff0c;又称反曲点&#xff0c;在数学上指改变曲线向上或向下方向的点&#xff0c;直观地说拐点是使切线穿越曲线的点&#xff08;即曲线的凹凸分界点&#xff09;。若该曲线图形的函数在拐点有二阶导数&#xff0c;则二阶导数在拐点处异号&#xff08;由正变负或由负…

Elasticsearch笔记七之setting,mapping,分片查询方式

Elasticsearch笔记七之setting,mapping,分片查询方式setting通过setting可以更改es配置可以用来修改副本数和分片数。1&#xff1a;查看&#xff0c;通过curl或浏览器可以看到副本分片信息curl -XGET http://192.168.79.131:9200/shb01/_settings?prettyhttp://192.168.79.131…