re2c使用小结(3)

本文总结了在处理复杂正则表达式如URL格式时,re2c工具的局限性。作者提出了采用两遍搜索的方法,第一次匹配正则,第二次进行字符串分解,并涉及到在实现中使用goto语句。

之前两篇学习文章,虽然可以满足一些要求,但是对于十分复杂的正则表达式还是无能为力。

比如现实当中某,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




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值