php[022]re2c

re2c 测试运行示例

1
2
3
4
5
6
$ ./integer 1024
decimal
$ ./integer sda
error
$ ./integer 0b10
binary

re2c

Re2c 是一个免费的开源词典生成器,适用于 C 和C++。其主要目标是生成与仔细优化的手写代码的速度相匹配或超过速度的快速词典。Re2c 使用有限状态机的直接编码,而不是表驱动的方法,并优化生成的代码。re2c 的另一个显著功能是异常灵活的用户界面:re2c 将接口代码的定义留给用户,而不是假设一个固定的程序模板。这为用户提供了为特定环境和输入模型自定义 lexer 的自由。Re2c 支持使用 POSIX 或最左侧贪婪语义的快速和轻量级子匹配提取。Re2c被许多其他项目使用(如php),旨在完全向后兼容。另一方面,它是一个研究项目和一个游乐场,在正式语法和自动机领域开发新的算法

re2c运行来源参考php源码学习d10 词法分析

https://github.com/skvadrik/re2c

安装

1
2
3
4
5
6
$git clone https://github.com/skvadrik/re2c.git
$cd re2c
$./autogen.sh
$./configure
$ make
$ make install

re2ctest.l

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
enum num_t { ERR, BIN, OCT, DEC, HEX};
static num_t lex(const char *YYCURSOR)
{
const char *YYMARKER;
/*!re2c
re2c:define:YYCTYPE = char;
re2c:yyfill:enable = 0;
end = "\x00";
bin = '0b'[01]+;
oct = "0"[0-7]*;
dec = [1-9][0-9]*;
hex = '0x'[0-9a-fA-F]+;
* {return ERR;}
bin end {return BIN;}
oct end {return OCT;}
dec end {return DEC;}
hex end {return HEX;}
*/
}

int main(int argc ,char **argv)
{
for(int i = 1; i< argc; ++i) {
switch (lex(argv[i])) {
case ERR: printf("error\n"); break;
case BIN: printf("binary\n"); break;
case OCT: printf("octal\n"); break;
case DEC: printf("decimal\n"); break;
case HEX: printf("hexadecimal\n"); break;

}
}
}

re2c转换+g++编译

1
re2c re2ctest.l -o re2ctest.c && g++ re2ctest.c -o re2ctest 

re2ctest

1
2
3
4
5
6
$ ./integer 1024
decimal
$ ./integer sda
error
$ ./integer 0b10
binary

查看re2ctest.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* Generated by re2c 1.3 on Mon Jan 20 20:53:54 2020 */
#line 1 "integer.l"
#include <stdio.h>
enum num_t { ERR, BIN, OCT, DEC, HEX};
static num_t lex(const char *YYCURSOR)
{
const char *YYMARKER;

#line 10 "integer.c"
{
char yych;
yych = *YYCURSOR;
switch (yych) {
case '0': goto yy4;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': goto yy5;
default: goto yy2;
}
yy2:
++YYCURSOR;
yy3:
#line 14 "integer.l"
{return ERR;}
#line 32 "integer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
switch (yych) {
case 0x00: goto yy6;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': goto yy8;
case 'B':
case 'b': goto yy11;
case 'X':
case 'x': goto yy12;
default: goto yy3;
}
yy5:
yych = *(YYMARKER = ++YYCURSOR);
switch (yych) {
case 0x00: goto yy13;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': goto yy15;
default: goto yy3;
}
yy6:
++YYCURSOR;
#line 16 "integer.l"
{return OCT;}
#line 71 "integer.c"
yy8:
yych = *++YYCURSOR;
switch (yych) {
case 0x00: goto yy6;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': goto yy8;
default: goto yy10;
}
yy10:
YYCURSOR = YYMARKER;
goto yy3;
yy11:
yych = *++YYCURSOR;
if (yych <= 0x00) goto yy10;
goto yy18;
yy12:
yych = *++YYCURSOR;
if (yych <= 0x00) goto yy10;
goto yy20;
yy13:
++YYCURSOR;
#line 17 "integer.l"
{return DEC;}
#line 101 "integer.c"
yy15:
yych = *++YYCURSOR;
switch (yych) {
case 0x00: goto yy13;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': goto yy15;
default: goto yy10;
}
yy17:
yych = *++YYCURSOR;
yy18:
switch (yych) {
case 0x00: goto yy21;
case '0':
case '1': goto yy17;
default: goto yy10;
}
yy19:
yych = *++YYCURSOR;
yy20:
switch (yych) {
case 0x00: goto yy23;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f': goto yy19;
default: goto yy10;
}
yy21:
++YYCURSOR;
#line 15 "integer.l"
{return BIN;}
#line 160 "integer.c"
yy23:
++YYCURSOR;
#line 18 "integer.l"
{return HEX;}
#line 165 "integer.c"
}
#line 19 "integer.l"

}

int main(int argc ,char **argv)
{
for(int i = 1; i< argc; ++i) {
switch (lex(argv[i])) {
case ERR: printf("error\n"); break;
case BIN: printf("binary\n"); break;
case OCT: printf("octal\n"); break;
case DEC: printf("decimal\n"); break;
case HEX: printf("hexadecimal\n"); break;

}
}
}