没有合适的资源?快使用搜索试试~ 我知道了~
Lex(Lexical Analyzar 词法分析生成器),Yacc(Yet Another Compiler Compiler编译器代码生成器)是Unix下十分重要的词法分析,语法分析的工具。经常用于语言分析,公式编译等广泛领域
资源推荐
资源详情
资源评论
Lex 和 Yacc 应用方法
2007-07-22 23:02:39|分类:默认分类|字号订阅
Lex 和 Yacc 应用方法(一).初识 Lex
草木瓜 20070301
Lex(Lexical Analyzar词法分析生成器),Yacc(Yet Another Compiler Compiler 编译
器代码生成器)是 Unix 下十分重要的词法分析,语法分析的工具。经常用于语言分析,公
式编译等广泛领域。遗憾的是网上中文资料介绍不是过于简单,就是跳跃太大,入门参考
意义并不大。本文通过循序渐进的例子,从 0 开始了解掌握 Lex 和 Yacc 的用法。
<本系列文章的地址:http://blog.csdn.net/liwei_cmg/category/207528.aspx>
一.Lex(Lexical Analyzar)初步示例
先看简单的例子(注:本文所有实例皆在 RetHat Linux 下完成):
一个简单的 Lex 文件exfirst.l内容:
%{
#include "stdio.h"
%}
%%
[] ;
[0-9]+ printf("Int : %s",yytext);
[0-9]*\.[0-9]+ printf("Float : %s",yytext);
[a-zA-Z][a-zA-Z0-9]* printf("Var : %s",yytext);
[\+\-\*\/\%] printf("Op : %s",yytext);
. printf("Unknown : %c",yytext[0]);
%%
在命令行下执行命令 flex 解析,会自动生成 lex.yy.c 文件:
[root@localhost liweitest]flex exfirst.l
进行编译生成 parser 可执行程序:
[root@localhost liweitest]cc -o parser lex.yy.c -ll
[注意:如果不加-ll 链结选项,cc 编译时会出现以下错误,后面会进一步说明。]
/usr/lib/gcc-lib/i386-redhat-linux/3.2.2/../../../crt1.o(.text+0x18): In function `_start':
../sysdeps/i386/elf/start.S:77: undefined reference to `main'
/tmp/cciACkbX.o(.text+0x37b): In function `yylex':
: undefined reference to `yywrap'
/tmp/cciACkbX.o(.text+0xabd): In function `input':
: undefined reference to `yywrap'
collect2: ld returned 1 exit status
创建待解析的文件file.txt:
title
i=1+3.9;
a3=909/6
bcd=4%9-333
通过已生成的可执行程序,进行文件解析。
[root@localhost liweitest]# ./parser < file.txt
Var : title
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
到此 Lex 用法会有个直观的了解:
1.定义 Lex 描述文件
2.通过 lex,flex 工具解析成 lex.yy.c 文件
3.使用 cc 编译 lex.yy.c 生成可执行程序
再来看一个比较完整的 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
这里就没有加-ll 选项,但是可以编译通过。下面开始着重整理下 Lex 描述文件.l。
二.Lex(Lexical Analyzar)描述文件的结构介绍
Lex 工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词
识别程序,由该程序识别出输入文本中的各个单词。 一般可以分为<定义部分><规则部分
><用户子程序部分>。其中规则部分是必须的,定义和用户子程序部分是任选的。
(1)定义部分
定义部分起始于%{符号,终止于%}符号,其间可以是包括 include 语句、声明语句在
内的 C 语句。这部分跟普通 C 程序开头没什么区别。
%{
#include "stdio.h"
int linenum;
%}
(2)规则部分
规则部分起始于"%%"符号,终止于"%%"符号,其间则是词法规则。词法规则由模式
和动作两部分组成。模式部分可以由任意的正则表达式组成,动作部分是由 C 语言语句组
成,这些语句用来对所匹配的模式进行相应处理。需要注意的是,lex 将识别出来的单词存
放在 yytext[]字符数据中,因此该数组的内容就代表了所识别出来的单词的内容。
类似 yytext 这些预定义的变量函数会随着后面内容展开一一介绍。动作部分如果有多
行执行语句,也可以用{}括起来。
%%
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]);
%%
A.规则部分的正则表达式
规则部分是 Lex 描述文件中最为复杂的一部分,下面列出一些模式部分的正则表达式
字
符含义:
A-Z, 0-9, a-z构成模式部分的字符和数字。
-指定范围。例如:a-z指从a到z之间的所有字符。
\转义元字符。用来覆盖字符在此表达式中定义的特殊意义,只取字符的本身。
[]表示一个字符集合。匹配括号内的任意字符。如果第一个字符是^那么它表示
否定模式。例如: [abC]匹配a, b,和 C 的任何一个。
^表示否定。
*匹配 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。
B.规则部分的优先级
规则部分具有优先级的概念,先举个简单的例子:
%{
#include "stdio.h"
%}
%%
[\n] ;
A {printf("ONE\n");};
AA {printf("TWO\n");};
AAAA {printf("THREE\n");};
%%
此时,如果输入内容:
[root@localhost liweitest]# cat file1.txt
AAAAAAA
剩余36页未读,继续阅读
资源评论
轻舟78
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 5G建设和AI技术推动下,中证5G通信ETF的投资价值探讨
- Python项目之淘宝模拟登录.zip
- 课程设计项目:python+QT实现的小型编译器.zip
- (源码)基于AVR ATmega644的智能卡AES解密系统.zip
- (源码)基于C++插件框架的计算与打印系统.zip
- (源码)基于Spring Boot和Vue的苍穹外卖管理系统.zip
- (源码)基于wxWidgets库的QMiniIDE游戏开发环境管理系统.zip
- 通过C++实现原型模式(Prototype Pattern).rar
- 学习记录111111111111111111111111
- 通过java实现原型模式(Prototype Pattern).rar
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功