美文网首页
【二】词法分析 re2c

【二】词法分析 re2c

作者: Michael_abc | 来源:发表于2019-10-09 11:42 被阅读0次

    re2c

    PHP做词法分析用的是re2c,之前使用的是lex,Mysql的词法分析也是用的re2c。re2c和lex等词法分析工具都会根据输入字符串流,输出以C语言实现的词法分析器源码,这里简单介绍一下re2c

    re2c说明

    re2c是一个扫描器制作工具,可以创建非常快速灵活的扫描器。 它可以产生高效代码,基于C语言,可以支持C/C++代码。与其它类似的扫描器不同, 它偏重于为正则表达式产生高效代码(和他的名字一样)。因此,这比传统的词法分析器有更广泛的应用范围。 你可以在sourceforge.net获取源码。

    PHP的词法分析规则

    在源码目录下的Zend/zend_language_scanner.l 文件是re2c的规则文件, 如果需要修改该规则文件需要安装re2c才能重新编译,生成新的规则文件。

    re2c调用方式

    re2c [-bdefFghisuvVw1] [-o output] [-c [-t header]] file
    

    re2c使用举例

    我们通过一个简单的例子来看下re2c。如下是一个简单的扫描器,它的作用是判断所给的字符串是数字/小写字母/大小字母。 当然,这里没有做一些输入错误判断等异常操作处理。示例如下:

    #include <stdio.h> 
    char *scan(char *p){
        #define YYCTYPE char
        #define YYCURSOR p
        #define YYLIMIT p
        #define YYMARKER q
        #define YYFILL(n)
        /*!re2c
          [0-9]+ {return "number";}
          [a-z]+ {return "lower";}
          [A-Z]+ {return "upper";}
          [^] {return "unkown";}
         */
    } 
    int main(int argc, char* argv[])
    {
        printf("%s\n", scan(argv[1]));
        return 0;
    }
    

    如果你是在ubuntu环境下,可以执行下面的命令生成可执行文件。

    re2c -o a.c a.l
    gcc a.c -o a
    chmod +x a
    ./a 1000
    

    此时程序会输出number。
    我们解释一下我们用到的几个re2c约定的宏。

    YYCTYPE 用于保存输入符号的类型,通常为char型和unsigned char型
    YYCURSOR 指向当前输入标记, -当开始时,它指向当前标记的第一个字符,当结束时,它指向下一个标记的第一个字符
    YYFILL(n) 当生成的代码需要重新加载缓存的标记时,则会调用YYFILL(n)。
    YYLIMIT 缓存的最后一个字符,生成的代码会反复比较YYCURSOR和YYLIMIT,以确定是否需要重新填充缓冲区。

    PHP的语法规则

    规则代码:

    language_scanner_globals,此变量为一结构体,记录当前re2c解析的状态,文件信息,解析过程信息等

    #define SCNG    LANG_SCNG
    #ifdef ZTS
    ZEND_API ts_rsrc_id language_scanner_globals_id;
    #else
    ZEND_API zend_php_scanner_globals language_scanner_globals;
    #endif
    

    量贯穿了PHP词法解析的全过程,并且一些re2c的实现也依赖于此, 比如前面说到的条件表达式的存储及获取,就需要此变量的协助,我们看这两个宏在PHP词法中的定义

    #define YYCTYPE   unsigned char
    #define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } }
    #define YYCURSOR  SCNG(yy_cursor)
    #define YYLIMIT   SCNG(yy_limit)
    #define YYMARKER  SCNG(yy_marker)
    
    #define YYGETCONDITION()  SCNG(yy_state)
    #define YYSETCONDITION(s) SCNG(yy_state) = s
    # define LANG_SCNG(v) (language_scanner_globals.v)
    

    PHP词法规则表达式

    /*!re2c
    re2c:yyfill:check = 0;
    LNUM    [0-9]+
    DNUM    ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
    EXPONENT_DNUM   (({LNUM}|{DNUM})[eE][+-]?{LNUM})
    HNUM    "0x"[0-9a-fA-F]+
    BNUM    "0b"[01]+
    LABEL   [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
    WHITESPACE [ \n\r\t]+
    TABS_AND_SPACES [ \t]*
    TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]
    ANY_CHAR [^]
    NEWLINE ("\r"|"\n"|"\r\n")
    
    /* compute yyleng before each rule */
    <!*> := yyleng = YYCURSOR - SCNG(yy_text);
    
    <ST_IN_SCRIPTING>"exit" {
        return T_EXIT;
    }
    
    <ST_IN_SCRIPTING>"die" {
        return T_EXIT;
    }
    
    <ST_IN_SCRIPTING>"function" {
        return T_FUNCTION;
    }
    ....
    

    Zend/zend_language_scanner.c文件就是PHP的词法解析器,Zend/zend_language_scanner.l文件则是PHP的词法解析规则

    相关文章

      网友评论

          本文标题:【二】词法分析 re2c

          本文链接:https://www.haomeiwen.com/subject/vbbwpctx.html