lex入门

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 noyywrap

D [0-9]
E [Ee][+-]?{D}+
SPACE [ /t/n]
INT {D}+

%%

{INT} { printf("INT =%s/n",yytext); } 
{SPACE}

%%
main()

{
 yylex();
}
上面给出了识别整型整数的例子(各个整数用tab或者空格分割)。

注意:%option noyywrap这个是一个选项参数,可以不要,但是就必须自己提供wrap()函数。

再用一个例子(摘自http://blog.csdn.net/liwei_cmg/archive/2007/03/15/1530492.aspx):

待解析的文件 file.txt:

title
i=1+3.9;
a3=909/6
bcd=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 : i
Unknown : =
Int : 1
Op : +
Float : 3.9
Unknown : ;
Var : a3
Unknown : =
Int : 909
Op : /
Int : 6
Var : bcd
Unknown : =
Int : 4
Op : %
Int : 9
Op : -
Int : 333

Line Count: 4

 

参考http://blog.csdn.net/liwei_cmg/archive/2007/03/15/1530492.aspx, 这篇博客确实写得不错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值