之前两篇学习文章,虽然可以满足一些要求,但是对于十分复杂的正则表达式还是无能为力。
比如现实当中某,URL的格式定义如下
dvb://<original_network_id>.<transport_stream_ id>.<service_id>[.<component_tag>{&<component_tag>}][;<event_id>]{/<path-element>}
如何正确解析这样的URL,用上面两种方法显然不行。
我这里想到一种方法,二遍搜素。第一遍匹配正则,第二遍再做分解字符串。
这里要用到goto语句。
#include <stdio.h>
#include <stdlib.h>
/*
* 定义符号
*/
enum{
T_EOL = -1,
T_DVB,
T_HEX,
T_ID,
T_CUT,
T_UNKNOWN,
};
/*!types:re2c */
/*
* 扫描
* dvb://<original_network_id>.<transport_stream_ id>.<service_id>[.<component_tag>{&<component_tag>}][;<event_id>]{/<path-element>}
*/
static enum ScanContition cond = 0;
int scan(char *buf, int *length){
#define YYCTYPE char
YYCTYPE * YYCURSOR = buf;
YYCTYPE * YYSTART = buf;
YYCTYPE * YYMARKER = NULL;
YYCTYPE * YYCTXMARKER = NULL;
unsigned int ret = 0;
if(YYCURSOR==NULL)
{
return T_EOL;
} else {
/* 二次搜索 */
start:
/*!re2c
re2c:yyfill:enable = 0;
re2c:condenumprefix = EState;
re2c:define:YYCONDTYPE = ScanContition;
re2c:define:YYSETCONDITION = "cond = #;";
re2c:define:YYSETCONDITION@cond = #;
re2c:define:YYGETCONDITION = cond;
re2c:define:YYGETCONDITION:naked = 1;
CHAR = [a-zA-Z];
DIGIT = [0-9];
HEX = ( DIGIT | [a-fA-F] )+;
ID = CHAR ( CHAR | DIGIT )*;
DOT = [.];
AND = [&];
SLASH = [/];
SEMICOLON = [;];
<> :=> START
<DVB> "dvb:" {
*length = YYCURSOR - YYSTART;
return T_DVB;
}
<DVB> HEX {
*length = YYCURSOR - YYSTART;
return T_HEX;
}
<DVB> ID {
*length = YYCURSOR - YYSTART;
return T_ID;
}
<DVB> DOT {
*length = YYCURSOR - YYSTART;
return T_CUT;
}
<DVB> AND {
*length = YYCURSOR - YYSTART;
return T_CUT;
}
<DVB> SLASH {
*length = YYCURSOR - YYSTART;
return T_CUT;
}
<DVB> SEMICOLON {
*length = YYCURSOR - YYSTART;
return T_CUT;
}
<START> "dvb:" SLASH SLASH HEX DOT HEX DOT HEX (DOT HEX( AND HEX)*)?(SEMICOLON ID)?(SLASH ID)* => DVB
{
YYCURSOR = YYSTART;
/*如果匹配上了,二次搜索*/
goto start;
}
<*> [^\x00] {
*length = YYCURSOR - YYSTART;
return T_UNKNOWN;
}
<*> [\x00] {
return T_EOL;
}
*/
}
}
static char buf[] = "dvd:/dvb://888.12.12a.df&a&23;123/adfs";
int yylex(){
int token = 0;
char *tmp = buf;
char *start;
int length;
token = scan(tmp, &length);
printf("token:%d,",token);
while(token!=T_EOL) {
printf("len:%u,str:%.*s\n",length,length,tmp);
tmp = tmp+length;
length = 0;
token = scan(tmp, &length);
printf("token:%d,",token);
}
return 0;
}
int main (int argc,char ** argv){
yylex();
return 0;
}
编译
re2c -isc dvb03.re >dvb03.out.c
运行结果
<pre name="code" class="cpp">token:4,len:1,str:d
token:4,len:1,str:v
token:4,len:1,str:d
token:4,len:1,str::
token:4,len:1,str:/
token:0,len:4,str:dvb:
token:3,len:1,str:/
token:3,len:1,str:/
token:1,len:3,str:888
token:3,len:1,str:.
token:1,len:2,str:12
token:3,len:1,str:.
token:1,len:3,str:12a
token:3,len:1,str:.
token:1,len:2,str:df
token:3,len:1,str:&
token:1,len:1,str:a
token:3,len:1,str:&
token:1,len:2,str:23
token:3,len:1,str:;
token:1,len:3,str:123
token:3,len:1,str:/
token:2,len:4,str:adfs
本文总结了在处理复杂正则表达式如URL格式时,re2c工具的局限性。作者提出了采用两遍搜索的方法,第一次匹配正则,第二次进行字符串分解,并涉及到在实现中使用goto语句。
30

被折叠的 条评论
为什么被折叠?



