博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lex入门
阅读量:2437 次
发布时间:2019-05-10

本文共 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 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()函数。

再用一个例子(摘自):

待解析的文件 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, 这篇博客确实写得不错。

你可能感兴趣的文章
postgresql 优化与维护
查看>>
mongodb replica sets 测试
查看>>
linux AS6.2 与 as5.4 的对比,性能提升明显
查看>>
FLASHCACHE 的是是非非
查看>>
length() between oracle and postgresql
查看>>
求无序数组总第n大的数
查看>>
99-lisp lisp 的99个问题 P1-10
查看>>
PG 函数的易变性(Function Volatility Categories)
查看>>
Lisp Quote 和Backquote分析
查看>>
PG psql 变彩色显示
查看>>
SICP 练习 1.3
查看>>
pg 数据库HA 启动脚本的两个假设
查看>>
PG9.2.3 发布
查看>>
sql_log_bin在GTID复制下的一个现象
查看>>
双主+haproxy手工切换的一个注意点
查看>>
利用binlog2sql实现闪回
查看>>
mongos分片集群下db数量过多导致服务不可用
查看>>
mysql唯一索引的一个小常识--Duplicate entry 'XXX' for key 'XXX'
查看>>
故障处理--mongos count不准
查看>>
大量短连接导致haproxy服务器端口耗尽
查看>>