re2c是一个扫描器制作工具,可以创建非常快速灵活的扫描器。它可以产生高效代码,基于C语言,可以支持C/C++代码。 与其它类似的扫描器不同,它偏重于为正则表达式产生高效代码(和他的名字一样)。因此,这比传统的词法分析器有更广泛的应用范围。 你可以在sourceforge.net获取源码。
PHP在最开始的词法解析器是使用的是flex,后来PHP的改为使用re2c。 在源码目录下的Zend/zend_language_scanner.l 文件是re2c的规则文件, 如果需要修改该规则文件需要安装re2c才能重新编译。
re2c调用方式:
re2c [-bdefFghisuvVw1] [-o output] [-c [-t header]] file
我们通过一个简单的例子来看下re2c。如下是一个简单的扫描器,它的作用是判断所给的字符串是数字/小写字母/大小字母。 当然,这里没有做一些输入错误判断等异常操作处理。示例如下:
<span style="color: rgb(189, 72, 179); font-style: italic;">#include <stdio.h></span><br /><br /><span style="color: rgb(18, 153, 218);">char</span> <span style="color: rgb(224, 136, 47);">*</span>scan<span style="color: rgb(255, 255, 255);">(</span><span style="color: rgb(18, 153, 218);">char</span> <span style="color: rgb(224, 136, 47);">*</span>p<span style="color: rgb(255, 255, 255);">)</span><span style="color: rgb(255, 255, 255);">{</span><br /><span style="color: rgb(189, 72, 179); font-style: italic;">#define YYCTYPE char</span><br /><span style="color: rgb(189, 72, 179); font-style: italic;">#define YYCURSOR p</span><br /><span style="color: rgb(189, 72, 179); font-style: italic;">#define YYLIMIT p</span><br /><span style="color: rgb(189, 72, 179); font-style: italic;">#define YYMARKER q</span><br /><span style="color: rgb(189, 72, 179); font-style: italic;">#define YYFILL(n)</span><br /> <span style="color: rgb(189, 72, 179); font-style: italic;">/*!re2c<br /> [0-9]+ {return "number";}<br /> [a-z]+ {return "lower";}<br /> [A-Z]+ {return "upper";}<br /> [^] {return "unkown";}<br /> */</span><br /><span style="color: rgb(255, 255, 255);">}</span><br /><br /><span style="color: rgb(18, 153, 218);">int</span> main<span style="color: rgb(255, 255, 255);">(</span><span style="color: rgb(18, 153, 218);">int</span> argc<span style="color: rgb(224, 136, 47);">,</span> <span style="color: rgb(18, 153, 218);">char</span><span style="color: rgb(224, 136, 47);">*</span> argv<span style="color: rgb(255, 255, 255);">[</span><span style="color: rgb(255, 255, 255);">]</span><span style="color: rgb(255, 255, 255);">)</span><br /><span style="color: rgb(255, 255, 255);">{</span><br /> <a style="color: rgb(18, 153, 218); text-decoration: none;" href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: rgb(226, 57, 45);">printf</span></a><span style="color: rgb(255, 255, 255);">(</span><span style="color: rgb(153, 255, 0);">"%s<span>\n</span>"</span><span style="color: rgb(224, 136, 47);">,</span> scan<span style="color: rgb(255, 255, 255);">(</span>argv<span style="color: rgb(255, 255, 255);">[</span><span style="color: rgb(18, 153, 218);">1</span><span style="color: rgb(255, 255, 255);">]</span><span style="color: rgb(255, 255, 255);">)</span><span style="color: rgb(255, 255, 255);">)</span><span style="color: rgb(224, 136, 47);">;</span><br /><br /> <span style="color: rgb(255, 132, 0);">return</span> <span style="color: rgb(18, 153, 218);">0</span><span style="color: rgb(224, 136, 47);">;</span><br /><span style="color: rgb(255, 255, 255);">}</span>
如果你是在ubuntu环境下,可以执行下面的命令生成可执行文件。
re2c -o a.c a.l<br />gcc a.c -o a<br />chmod +x a<br />./a 1000
此时程序会输出number。
我们解释一下我们用到的几个re2c约定的宏。
参照如上几个标识的说明,可以较清楚的理解生成的a.c文件,当然,re2c不会仅仅只有上面代码所显示的标记, 这只是一个简单示例,更多的标识说明和帮助信息请移步 re2c帮助文档:http://re2c.org/manual.html。
更多编译器相关算法: Compiler Algorithms