本文共 2806 字,大约阅读时间需要 9 分钟。
1.正则表达式下面列出一些模式部分的正则表达式字符含义:A-Z, 0-9, a-z 构成模式部分的字符和数字。- 指定范围。例如:a-z 指从 a 到 z 之间的所有字符。/ 转义元字符。用来覆盖字符在此表达式中定义的特殊意义,只取字符的本身。[] 表示一个字符集合。匹配括号内的任意字符。如果第一个字符是^那么它表示否定模式。例如: [abC] 匹配 a, b, 和C的任何一个,[^a-zA-Z]匹配表示所有不是字母的单个字符。^ 表示否定。* 匹配0个或者多个上述模式。+ 匹配1个或者多个上述模式。? 匹配0个或1个上述模式。$ 作为模式的最后一个字符时匹配一行的结尾。{ } 表示一个模式可能出现的次数。 例如: A{1,3} 表示 A 可能出现1次或3次。[a-z]{5} 表示长度为5的,由a-z组成的字符。此外,还可以表示预定义的变量。. 匹配任意字符,除了 /n。( ) 将一系列常规表达式分组。如:{Letter}({Letter}|{Digit})* | 表达式间的逻辑或。"一些符号" 字符的字面含义。元字符具有。如:"*" 相当于 [/*]。/ 向前匹配。如果在匹配的模式中的"/"后跟有后续表达式,只匹配模版中"/"前面的部分。如:模式为 ABC/D 输入 ABCD,时ABC会匹配ABC/D,而D会匹配相应的模式。输入ABCE的话, ABCE就不会去匹配ABC/D。
2.规则优先级
简单的说就两条:
a.如果 有两条规则都满足,且两个规则匹配的字符长度不同,则选取较长的匹配;
b.如果有两个规则都满足,且他们匹配的字符串长度相同,则选取靠前的那条规则匹配。
比如:
有以下3条规则:
a action1()
aaa action2()
aaa action3()
如果有字符aaa,则上面3条规则都是满足的,但是第一条规则能匹配的字符比后面两条规则短,所以选择后面两条规则;而对于后面两条规则,它们匹配的字符串长度相同,所以选取靠前的第二条规则。
3.一些内置变量
yytext char * 当前匹配的字符串yyleng int 当前匹配的字符串长度yyin FILE * lex当前的解析文件,默认为标准输出yyout FILE * lex解析后的输出文件,默认为标准输入yylineno int 当前的行数信息int yylval 当前匹配的串的属性信息内部预定义宏:ECHO #define ECHO fwrite(yytext, yyleng, 1, yyout) 也是未匹配字符的 默认动作 内部预定义的函数:int yylex(void) 调用Lex进行词法分析int yywrap(void) 在文件(或输入)的末尾调用。如果函数的返回值是1,就停止解 析。 因此它可以用来解析多个文件。代码可以写在第三段,这 样可以解析多个文件。 方法是使用 yyin 文件指针指向不同的 文件,直到所有的文件都被解析。最后,yywrap() 可以返回1 来表示解析的结束。 4.书写格式
%{ 位置1 %} 位置2 %%
位置3
%%
位置4
注:上面的位置1-位置4的内容如下:
位置1:变量声明、预处理指令(与位置4的用户程序有关);(注:我自己的经验:使用flex和VS2008,位置4中的程序要用到的变量都必须在此处声明,无论是只在局部变量使用还是全局变量使用)
位置2:正则表达式定义(可用于简化位置3的规则);
位置3:匹配规则(一行一条,不需要分号分割)及相应的动作;
位置4:用户程序;可以被位置3调用,用于生成最后的处理程序(这里需要注意的是,当编译时不带-ll选项时,是必须加入main()函数和yywrap())。
例:
%{ #include <stdio.h>int int_count;%}%option noyywrapD [0-9]E [Ee][+-]?{D}+SPACE [ /t/n]INT {D}+%%{INT} { printf("INT =%s/n",yytext); } {SPACE}%%main()
{ yylex();}上面给出了识别整型整数的例子(各个整数用tab或者空格分割)。
注意:%option noyywrap这个是一个选项参数,可以不要,但是就必须自己提供wrap()函数。
再用一个例子(摘自):
待解析的文件 file.txt:titlei=1+3.9;a3=909/6bcd=4%9-333
再来看一个比较完整的Lex描述文件 exsec.l :%{ #include "stdio.h"int linenum;%}%%title showtitle();[/n] linenum++;[0-9]+ printf("Int : %s/n",yytext);[0-9]*/.[0-9]+ printf("Float : %s/n",yytext);[a-zA-Z][a-zA-Z0-9]* printf("Var : %s/n",yytext);[/+/-/*///%] printf("Op : %s/n",yytext);. printf("Unknown : %c/n",yytext[0]);%%showtitle(){ printf("----- Lex Example -----/n");}int main(){ linenum=0; yylex(); /* 进行分析 */ printf("/nLine Count: %d/n",linenum); return 0;}int yywrap(){ return 1;}进行解析编译:[root@localhost liweitest]flex exsec.l[root@localhost liweitest]cc -o parser lex.yy.c[root@localhost liweitest]./parser < file.txt----- Lex Example -----Var : iUnknown : =Int : 1Op : +Float : 3.9Unknown : ;Var : a3Unknown : =Int : 909Op : /Int : 6Var : bcdUnknown : =Int : 4Op : %Int : 9Op : -Int : 333Line Count: 4
参考http://blog.csdn.net/liwei_cmg/archive/2007/03/15/1530492.aspx, 这篇博客确实写得不错。