美文网首页
【二】词法分析 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

    re2c PHP做词法分析用的是re2c,之前使用的是lex,Mysql的词法分析也是用的re2c。re2c和le...

  • php运行生命周期--脚本执行阶段 php_execute

    第1步:词法分析将PHP代码转换为有意义的标识Token。该步骤的词法分析器使用Re2c实现的。 第2步:语法分析...

  • Javascript 语法解析

    执行过程 词法分析 -> 语法分析 -> 预编译 -> 解释执行 一. 词法分析 核心:词法分析是将字符流(cha...

  • 一个编译器最简前端的python实现

    一个编译器的前端通常包括词法分析器和语法分析器。在分析过程中,文本输入词法分析器,根据词法规则解析出词法单元。词法...

  • PL/0简单编译系统(二)

    词法分析 词法分析又称词法分析器或者扫描器,是编译程序的基本子程序之一。本项目采用手工方式设计并实现词法分析程序。...

  • 编译原理笔记

    源程序分析: 词法分析 :线性分析 被称为词法分析 或者扫描比如:position=init+rate * 60 ...

  • 编译原理基础知识汇总

    前端: 词法分析 -> 语法分析 -> 语义分析后端: 生成中间代码 -> 优化 -> 生产目标代码 词法分析:有...

  • 三. Flex进阶:需要了解的一些知识

    参考:词法分析器生成工具flex词法分析器总结--flex&bison词法分析生成器flex的选项 1. Flex...

  • 基于LLVM的编译原理简明教程 (2) - 词法与语法分析初步

    递归 - 词法分析与语法分析的分界 一般来说,决定词法分析和语法分析的界限是是否需要递归。词法分析是将输入的符号流...

  • 龙书 第三章

    词法单元:词法分析器扫描源程序并输出一个由词法单元组成的序列。这些词法单元通常会逐个传送给语法分析器。有些词法单元...

网友评论

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

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