re2c中文手册在php的实现过程中,包括php语言本身的词法分析,一共有多达8处的地方使用了re2c,如果我们常用的时间函数、pdo扩展等。对re2c的了解更能促进我们进php内核实现的认知。
本手册是re2c官网的manual.html文件翻译稿,仅适用于对re2c的初步了解,更多的资料见re2c项目中lessons目录和doc目录。
namere2c – 将正则表达式转化成c/c++代码
synopsisre2c [-bddeffghisuvvw1] [-o output] [-c [-t header]] file
descriptionre2c是一个将正则表达式转化成基于c语言标识的预处理器。
re2c的输入包含c/c++代码,并且以/*!re2c… */注释的格式将扫描标识交错嵌入到这些代码中。在它的输出中,这些注释将会被生成的代码替换掉,当执行时,它将会查找到下一个token,并且执行用户提供的针对该token的特定代码。
如下示例:
char *scan(char *p) { /*!re2c re2c:define:yyctype = unsigned char; re2c:define:yycursor = p; re2c:yyfill:enable = 0; re2c:yych:conversion = 1; re2c:indent:top = 1; [0-9]+ {return p;} [^] {return (char*)0;} */ }
re2c将生成如下代码:
/* generated by re2c on sat apr 16 11:40:58 1994 */ char *scan(char *p) { { unsigned char yych; yych = (unsigned char)*p; if(yych = ':') goto yy4; ++p; yych = (unsigned char)*p; goto yy7; yy3: {return p;} yy4: ++p; yych = (unsigned char)*p; {return char*)0;} yy6: ++p; yych = (unsigned char)*p; yy7: if(yych ’快捷方式来自动生成代码,它不仅仅可以设置新的状态,还可以继续执行新的状态。一个快捷规则不应该在循环中使用,这些循环代码在循环开始和re2c块之间,除非用 re2c:cond:goto使之 ‘continue;’如果一段代码必须放在所有的规则之前,你可以使用 condition { c/c++ code } regular-expression => condition := c/c++ code regular-expression :=> condition regular-expression { c/c++ code } regular-expression := c/c++ code regular-expression => condition { c/c++ code } regular-expression => condition := c/c++ code regular-expression :=> condition { c/c++ code } := c/c++ code => condition { c/c++ code } => condition := c/c++ code :=> condition { c/c++ code } := c/c++ code { c/c++ code } := c/c++ code
命名定义格式如下:
name = regular-expression;
如果使用了-f 模式,可以使用如下命名定义方法:
name regular-expression< /pre>以re2c开始的命名定义配置如下所示:re2c:name = value;re2c:name = value;
summary of re2c regular-expressionsre2c正则表达式小结“foo” 字符串foo。可以使用ansi-c转义序列。[xyz] 字符集;此种情况匹配字符x,y或z[abj-oz] 包含区间的字符集,此种情况匹配a,b,j到o之间的任一字符,或z[^class] 字符集否定匹配,匹配没有在方括号中定义的字符。r\s 匹配非s的正则,r和s都必须是可以表示为字符集的正则表达式r* 零次或多次匹配,r是任一正则表达式r+ 一次或多次匹配(至少一次)r? 零次或一次匹配name 这里name就是在前面的定义段给出的名字(r) 匹配规则表达式r,圆括号可以提高其优先级。rs 匹配规则表达式r,其后紧跟着表达式s。这称为联接(concatenation)。r|s 或者匹配规则表达式r,或者匹配表达式s。r/s 匹配模式r,但是要求其后紧跟着模式s。s并不会参与文本的匹配。这种正则表达式的匹配称之为“尾部上下文”r{n} n次匹配r{n,} 至少n次匹配r{n,m} 至少n次,至多m次匹配;匹配除换行符外的任意字符def 当没有使用-f参数时,匹配的命名定义通过def定义。当-f参数指定时,def语名和双引号包含的效果一样,直接匹配def字符串。字符集和字符串可能包含有八进制或十六进制或如下的转义字符 (\n, \t, \v, \b, \r, \f, \a, \)。一个八进制字符由一个反斜杠和紧跟着它的三个八进制数字组成,一个十六进制字符由一个反斜杠,一个小写的x,以及两个十六进制数字组成,或由一个反斜杠,一个大写的x,以及四个十六进制数字组成。re2c进一步会支持更多的c/c++的unicode符号。这些unicode符号由一个反斜杠+u+四个十六进制数字或一个反斜杠+u+八个十六进制的数字组成。然后,仅当-u模式下才能处理这些uincode字符。在非unicode模式下,大于\x00ff的字符是无法直接匹配的,除非使用”万金油“类型的 (.|”\n”)和[^]正则表达式匹配所有的字符时,包含它们。
如上所示的正则表达式列表按优先级分组,从最上面的最高优先级到最下面的最低优先级。这些组合之间的优先级相同。
inplace configuration现场配置它可能在re2c块中配置并生成代码,如下所示为可用的配置项:
re2c:condprefix = yyc_ ;
允许指定条件标签的前缀。它将在生成的输出文件中的所有条件标签前添加指定的前缀。re2c:condenumprefix = yyc ;
允许指定条件值的前缀。它将在生成的输出文件中的所有条件枚举值前添加指定的前缀。re2c:cond:divider = “/* *********************************** */” ;
允许为条件块自定义分隔符。你可以使用’@@’输出条件的名字或使用re2c:cond:divider@cond = @@ ;
指定即将被 re2c:cond:divider中的条件名替换的占位符。re2c:cond:goto = “goto @@;” ;
允许使用 ‘:=>’ 规则自定义条件跳转语句。你可以使用’@@’输出条件的名字或使用re2c:cond:divider@cond自定义占位符,同时你也可以使用此语句继续下一个循环周期,这个循环周期包括循环开始到re2c块之间的任何代码。re2c:cond:goto@cond = @@ ;
指定即将在 re2c:cond:goto语句中被替换的条件标签占位符re2c:indent:top = 0 ;
指定最小的缩进,大于或等于0re2c:indent:string = “\t” ;
指定缩进用的字符串。除非你想使用外部工具,否则就需要只包含空白字符串。最简单的方法就是用单引号或双引号包含它们。如果你不需要任何缩进,直接使用””即可。re2c:yych:conversion = 0 ;
当此设置非零时,re2c会在读取yych时自动生成转换代码。此时的类型必须使用re2c:define:yyctype定义。re2c:yych:emit = 1 ;
设置为0可以禁止yych的生成。re2c:yybm:hex = 0 ;
如果设置为0,则生成一个十进制表格,否则将生成一个十六进制表格re2c:yyfill:enable = 1 ;
将此设置为0可以禁止yyfill(n)的生成。当使用它时请确认生成的扫描器在输入之后不再读取。允许此行为将给你的程序引入服务安全问题。re2c:yyfill:check = 1 ;
当yylimit + max(yyfill)一直可用时,把此设置为0可以禁止使用yycursor和yylimit的先决条件的输出。re2c:yyfill:parameter = 1 ;
允许禁止yyfill调用的参数传递。如果设置为0,将没有任何参数传递到yyfill。然而,define:yyfill@len允许指定一个字符串替换实际字符中的长度。如果设置为非0,除非设置re2c:define:yyfill:naked,否则yyfill将使用紧跟其后的大括号内的所要求的字符数。其它请参照:re2c:define:yyfill:naked和re2c:define:yyfill@len.re2c:startlabel = 0 ;如果设置为0的整数,即使没有扫描器本身,下一个扫描块的开始标签也会被生成。否则仅在需要的时候生成常规的yy0开始标签。如果设置为一个文本值,不管常规的开始标签生成是否,包含当前文本的标签都会被生成。在开始标签生成后,当前设置会被重置为0。re2c:labelprefix = yy ;
允许修改数字标签的前缀,默认为yy,任何有效的标签都是可以的。re2c:state:abort = 0 ;
当设置为非零,并且开启-f模式时,yygetstate 块会包含一个默认的情况,初始化时设置为-1re2c:state:nextlabel = 0 ;
当开启-f模式时,使用此设置可以控制是否在yygetstate块后面接yynext标签行。通常,你可以用startlabel配置强制指定开始标签或用默认的yy0作为开始标签,而不是用yynext。通常我们通过放置”/*!getstate:re2c */” 注释来分隔实际扫描器的yygetstate 代码,而不是专用的标签。re2c:cgoto:threshold = 9 ;
当启用-g模式时,这个值指定生成的跳转表的复杂度阈值,而不是使用嵌套的if语句和决策位字段。re2c:yych:conversion = 0 ;
当输入使用有符号字符时,并且开启-s和-b械时,re2c会自动将其转化为无符号类型。当设置为0时会禁用空字符串转化。设置为非零时,转化将在yyctype处进行。如果这个值通过现场配置,则使用该值。否则,将会变成(yyctype),并且不能再修改成配置。当设置为一个字符串时,必须用括号括起来。现在,假设你的输入为char*并且使用上述的设置,你可以设置yyctype为unsigned char,并且当前值设置为1或者”(unsigned char)”re2c:define:define:yycondtype = yycondtype ;枚举用于支持-c模式的条件re2c:define:yyctxmarker = yyctxmarker ;
允许覆盖定义的yyctxmarker ,从而避免将其设置为实际所需的代码。re2c:define:yyctype = yyctype ;
允许覆盖定义的yyctype ,从而避免将其设置为实际所需的代码。re2c:define:yycursor = yycursor ;
允许覆盖定义的yycursor ,从而避免将其设置为实际所需的代码。re2c:define:yydebug = yydebug ;
允许覆盖定义的yydebug ,从而避免将其设置为实际所需的代码。re2c:define:yyfill = yyfill ;
允许覆盖定义的yyfill ,从而避免将其设置为实际所需的代码。re2c:define:yyfill:naked = 0 ;
当设置为1时,括号、参数、分号都会被发出。re2c:define:yyfill@len = @@ ;
当使用 re2c:define:yyfill 时,并且re2c:yyfill:parameter 为0时,yyfill 中的任何文本将会被新的实际的长度值替换。re2c:define:yygetcondition = yygetcondition ;
允许覆盖定义的yygetconditionre2c:define:yygetcondition:naked = ;
当设置为1时,括号、参数、分号都会被发出。re2c:define:yygetstate = yygetstate ;
允许覆盖定义的yygetstate ,从而避免将其设置为实际所需的代码。re2c:define:yygetstate:naked = 0 ;
当设置为1时,括号、参数、分号都会被发出。re2c:define:yylimit = yylimit ;
允许覆盖定义的yylimit ,从而避免将其设置为实际所需的代码。re2c:define:yymarker = yymarker ;
允许覆盖定义yymarker,从而避免将其设置为实际所需的代码。re2c:define:yysetcondition = yysetcondition ;
允许覆盖定义的yysetconditionre2c:define:yysetcondition@cond = @@ ;
当使用 re2c:define:yysetcondition时,yysetcondition中的任何文本将会被新的实际的
条件值替换。re2c:define:yysetstate = yysetstate ;
允许覆盖定义的yysetstate,从而避免将其设置为实际所需的代码。re2c:define:yysetstate:naked = 0 ;
当设置为1时,括号、参数、分号都会被发出。re2c:define:yysetstate@state = @@ ;
当使用re2c:define:yysetstate时,yysetcondition中的任何文本将会被新的实际的状态值替换re2c:label:yyfilllabel = yyfilllabel ;
允许覆盖标签yyfilllabel,即可以自定义生成的yyfilllabel 变量名。re2c:label:yynext = yynext ;
允许覆盖标签yynext ,即可以自定义生成的yynext变量名。re2c:variable:yyaccept = yyaccept ;
允许覆盖变量yyaccept,即可以自定义生成的yyaccept变量名。re2c:variable:yybm = yybm ;
允许覆盖变量yybm,即可以自定义生成的yybm变量名。re2c:variable:yych = yych ;
允许覆盖变量yych,即可以自定义生成的yych变量名。re2c:variable:yyctable = yyctable ;
当指定-c参数和-g参数时,re2c会使用此变量为yygetcondition生成静态跳转表。re2c:variable:yystable = yystable ;
当指定-f参数和-g参数时,re2c会使用此变量为yygetstate生成静态跳转表。re2c:variable:yytarget = yytarget ;
允许覆盖变量yytarget,即可以自定义生成的yytarget变量名。understanding re2c 理解re2cre2c的子目录中包含各种例子教你一步一步的如何开启re2c的世界,所有的例子都是可编译运行的。
features特点re2c不提供默认的动作:生成的代码假定输入包含一系列token。通常,可以通过添加一条规则实现,例如上面示例中的异常字符
因为re2c不提供结束表达式,所以用户必须安排一个输入结束符并让一个规则匹配并捕获它。
如果来源是一个以空字符串结尾的字符串,则匹配一个空字符串就可以了。如果来源是一个文件,你可以在文件后添加一个换行(或其它不会出现的标记);通过识别这个字符,以检查这是否为一个标记点并执行相应的操作。同样,你也可以使用yyfill(n)判断是否没有足够的字符可用时结束扫描。
bugsdifference only works for character sets.
the re2c internal algorithms need documentation.
see alsoflex(1), lex(1).
more information on re2c can be found here:
http://re2c.org/
authors
peter bumbulis peter@csg.uwaterloo.ca
brian young bayoung@acm.org
dan nuffer nuffer@users.sourceforge.net
marcus boerger helly@users.sourceforge.net
hartmut kaiser hkaiser@users.sourceforge.net
emmanuel mogenet mgix@mgix.com added storable state
英文原地址:http://re2c.org/manual.html
译者:胖子(http://www.phppan.com/)
友情协助:吴帅(http://www.imsiren.com/)
校验:reeze(http://www.reeze.cn)
特别鸣谢:老婆大人的亲自指点和崽崽的听话。 原文地址:re2c中文手册, 感谢原作者分享。
