Lex快速入门

用Lex语言表达的正则表达式:

. 匹配任意字符,除了 \n (换行)

- 用来指定范围。例如:A-Z 指从 A 到 Z 之间的所有字符;
a-z 指从 a 到 z 之间的所有字符;
0-9 指从 0 到 9 之间的所有字符;

* 匹配 0个或者多个上述的模式。例如:AB* 表示:A,AB,ABB,ABB...

+ 匹配 1个或者多个上述的模式。例如:AB+ 表示:AB,ABB,ABB,ABBB...

? 匹配 0个或1个上述模式。例如:AB? 表示:A或AB

\ 用来转义元字符。同样用来覆盖字符在此表中定义的特殊意义,只取字符的本意。
常见转义字符:
\a 响铃(BEL)
\b 退格(BS) ,将当前位置移到前一列
\f 换页(FF),将当前位置移到下页开头
\n 换行(LF) ,将当前位置移到下一行开头
\r 回车(CR) ,将当前位置移到本行开头
\t 水平制表(HT) (跳到下一个TAB位置)
\\ 代表一个反斜线字符''\'
\' 代表一个单引号(撇号)字符
\" 代表一个双引号字符
\0 空字符(NULL)

/ 向前匹配。如果在匹配的模版中的“/”后跟有后续表达式,只匹配模版中“/”前面的部分。例如:如果输入 A01,那么在模版 A0/1 中的 A0 是匹配的。

^ 表示否定。例如:[^ab]表示除ab以外的所有字符
[^0-9a-zA-Z]表示除了数字和字母以外的所有字符

| 表达式间的逻辑或。例如:("A"|"B")表示字符A或字符B
(r|s) 表示正则表达式r或s所表达的所有内容

$ 作为模式的最后一个字符匹配一行的结尾。

() 将一系列常规表达式分组,并且小括号内的优先级高于括号外的优先级

[] 一个字符集合。匹配括号内的任意字符。如果第一个字符是 ^ 那么它表示否定。例如: [abC] 匹配 a, b, 和 C中的任何一个。

{} 指出一个模式可能出现的次数。例如: A{1,3} 表示 A 可能出现1次或3次(即:A或AAA);
A{2} 表示 A 重复两次(即:AA)
A{10,}表示 A 重复十次以上
若包含名称,则以该名称替换。例如:正则表达式r [a-z](即:r表示小写字母) , 那么{r}+就表示所有以小写字母构成的字符串


认识几种表达式:
joke[rs] 匹配 jokes 或 joker。这里的r和s是字母不是表达式,若r或s是表达式,则应改写为joke[{r}{s}]

A{1,2}shis+ 匹配 Ashi, Ashis, Ashiss,Ashisss...... AAshi,AAshis,AAshiss,Ashisss.....

digit [0-9] 表达式digit表示一个数字
number {digit}+ 表达式number表示所有自然数

digit [0-9]
letter [a-zA-Z]
identifier {letter}({letter}|{digit})* 表示有字母开头,并且又字母和数字组成的所有标识符

whitespace [" "\t\n\r]+ 表示空白部分(即包含有空格,Tab,换行,回车)

compareoperator ["<""="">"]"="? 表示比较运算符(包括:<,=,>,<=,==,>=)

[a-z]{1,8} 表示任何一个长度不超过8的字符串

("+"|"-")?[0-9]+ 表示有符号整数

("+"|"-")?[0-9]+("."[0-9])? 表示可带小数点的有符号数

("+"|"-")?[0-9]+("."[0-9])?(E("+"|"-")?[0-9]+)? 表示可带指数的有符号数

 

 


LEX源程序结构:(分为三部分,各部分用%%隔开)


(1)说明部分
说明部分用于定义识别规则中要用到的正则表达式名,包括:变量说明、标识符常量说明、正则定义、C语言的说明信息。

其中C语言的说明信息必须用分界符“%{”和“%}”括起来,该部分主要包括将来生成词法分析程序要使用的一些库文件和全局变量的声明,%{和%}中间的内容
会原封不动地复制到LEX生成的词法分析程序的最前部。

下面是说明部分的一段Lex代码:
%{
# include<stdio.h>
int wordCount = 0;
%}
chars [A-Za-z]
numbers ([0-9])+
delim [" "\n\t]
whitespace {delim}+
words {chars}+
%%

(2)识别规则
识别规则用正则表达式给出单词的定义,以及在识别出该正则表达式以后要执行的程序片段,形式如下:
P1 {动作1}
P2 {动作2}
.
.
.
P3 {动作3}
这里的Pi(i=1,2...n)表示正则表达式,
{动作i} 表示当识别出Pi表达式所表达的字符串时,词法分析应执行的动作的C语言程序语句(该语句一般是返回该字符串记号和字符串值)

例如:
{words} { wordCount++; }
{whitespace} { /* do nothing*/ }
{numbers} { numcount++; }

(3)辅助过程
辅助过程给出用户所需要的其他操作,它是识别规则的某些动作需要调用的过程。如果不是C语言的库函数,则要在此给出具体的定义。这些程序也可以
存入另外的程序文件中,单独编译,最后和词法分析程序连接装配到一起。

例如:
void main()
{
printf("开始分析\n");
yylex(); /* start the analysis*/
printf("分析结果\n");
printf(" No of words: %d\n number: %d\n", wordCount, numcount);
return 0;
}

int yywrap()
{
return 1;
}

 


Lex变量和函数:
Lex 有几个函数和变量提供了不同的信息,可以用来编译实现复杂函数的程序。下表中列出了一些变量和函数,以及它们的使用。


Lex 变量:
yyin FILE* 类型。 它指向 lexer 正在解析的当前文件。

yyout FILE* 类型。 它指向记录 lexer 输出的位置。 缺省情况下,yyin 和 yyout 都指向标准输入和输出。

yytext 匹配模式的文本存储在这一变量中(char*)。

yyleng 给出匹配模式的长度。

yylineno 提供当前的行数信息。(lexer不一定支持。)

Lex 函数
yylex() 这一函数开始分析。 它由 Lex 自动生成。

yywrap() 这一函数在文件(或输入)的末尾调用。如果函数的返回值是1,就停止解析。 因此它可以用来解析多个文件。代码可以写在第三段, 这就能够解析多个文件。 方法是使用 yyin 文件指针(见上表)指向不同的文件,直到所有的文件都被解析。最后,yywrap() 可以返回 1 来
表示解析的结束。

yyless(int n) 这一函数可以用来送回除了前?n? 个字符外的所有读出标记。

yymore() 这一函数告诉 Lexer 将下一个标记附加到当前标记后。

posted @ 2015-08-19 11:55  一天一夜  阅读(2704)  评论(0编辑  收藏  举报