没有合适的资源?快使用搜索试试~ 我知道了~
首页使用yacc和lex编写文本分析器
资源详情
资源评论
资源推荐
使用 yacc 和 lex 编写文本分析器
Martin Brown (mc@mcslp.com), 自由撰稿人, Consultant
简介: 本文将研究使用 lex/ex 和 yacc/bison 工具构建分析器所需的步骤。
首先构建一个简单的计算器,然后深入地研究如何采用相同的原则进行文本分
析。分析文本,即理解和提取文本中的关键部分,是许多应用程序中一个重要
的部分。在 UNIX® 中,许多操作系统组成部分都依赖于文本分析,从用来与
系统进行交互的 shell,到诸如 awk or Perl 等各种常用的工具和命令,再到
用来构建软件和应用程序的 C 编译器。您可以在 UNIX 应用程序(以及其他的
应用程序)中使用分析器来构建简单的配置分析器,甚至构建最终的目标:您
自己的编程语言。
发布日期: 2006 年 9 月 14 日
级别: 中级
使用 lex 进行词法分析
编写文本分析器的第一步是要能够识别所读取的内容。有许多不同的方法可以
完成这项任务,但是最简单的方法是使用 lex,它是将输入信息转换为一系列
标记的工具。
什么是词法分析?
当使用编程语言编写程序或在命令行中输入命令时,您是否想过究竟执行了什
么操作将您输入的内容转换为一组指令呢?
这个处理过程非常简单,却又相当复杂。它很复杂,这是因为对于可能输入的
信息,表面上看起来似乎存在无限种可能的组合和序列。例如,要使用 Perl 语
言遍历一个哈希表,您可以使用如清单 1 所示的序列。
清单 1. 在 Perl 中遍历一个哈希表
foreach $key (keys %hash)
{
...
}
其中的每一项都是有意义的,虽然方式有所不同,这正是该处理过程的简单明
了之处。清单 1 中所示的表达式存在一个对应的结构,也就是说,与人类语言
一样,编程语言中也存在着特定的规则。因此,如果将输入分解为您所看到的
和该信息结构的组合,那么对该内容的分析过程则相当简单。
要理解提供给文本分析应用程序的信息,通常有两个阶段。第一个阶段是识别输入的或提
供给应用程序的内容是什么。您必须能够从输入源中识别关键字、短语或字符序列,以便
能够确定对其进行何种处理。第二个处理阶段是理解该信息的结构,即语法,以便对输入
进行验证和操作。有关语法的一个很好的示例是,大多数编程语言中圆括号的使用。很明
显,下面的表达式是错误的:
{ function)( {
其中,大括号不匹配,而圆括号的出现顺序错误。为了让分析器理解和识别表
达式,那么分析器必须知道正确的序列,以及匹配该序列后应该进行何种操作。
词法分析首先进行识别输入数据的处理,并且可以使用 lex 工具来完成该处理
过程。
回页首
lex 工具
lex 工具(或 GNU 工具 ex)使用一个配置文件来生成相应的 C 源代码,然后,可以用它
来创建独立的应用程序,或者在您自己的应用程序中使用它。配置文件定义了需要在待分
析的文件中查找的字符序列,以及当发现该序列之后应该进行什么操作。该文件的格式十
分简单,即指定输入序列和相应的结果,用空格(或制表符)隔开。例如:
sequence do-something
清单 2 显示了一个非常简单的定义,它可以接受单词并根据提供的单词打印出
一个字符串。
清单 2. 简单的 lex 定义
%{
#include <stdio.h>
%}
%%
begin printf("Started\n");
hello printf("Hello yourself!\n");
thanks printf("Your welcome\n");
end printf("Stopped\n");
%%
代码中的第一块由 %{...%} 定义,表示将其中的文本插入到生成的 C 源代码
中。在本示例中,因为后面使用了 printf() 函数,所以必须确保包含了
stdio.h Header。
代码中的第二块由 %% 序列标识,其中包含了要识别的字符串输入和相应结果
的定义。在上述的这些情况下,对于一个简单的单词,将打印出合适的响应。
回页首
生成 C 源代码
要生成能够真正分析输入文本的 C 源代码,可以对清单 1 所示的文件运行 lex(或
ex)。 Lex/ex 文件点号后缀为 'l',所以上面的文件可能名为 exampleA.l。要生成相应的
C 源代码:
$ ex exampleA.l
不管您使用哪种工具,其输出都将为 lex.yy.c。缺乏勇气的人往往不敢仔细研
究这个文件,分析器内部的处理过程的确非常复杂,并且建立在基于表格的复
杂分析系统的基础上,该系统可以根据原始 lex 定义中的定义对输入文本进行
匹配。因为存在这样的关联,所以该代码相当占用内存,特别是对于那些很大
且很复杂的文件。
与 lex 相比,ex 的优点在于它提供了大量附加的选项以改进性能(针对内存
或速度)、调试选项和对扫描器行为更好的控制(例如,可以忽略某些情况)。
在生成 C 源代码时,通过使用 -l 命令行选项,您可以生成与原始的 lex 工具
生成的源代码非常接近的 C 源代码。
既然已经有了 C 源代码,那么您可以将其编译为相应的应用程序以测试该处理过程:
$ gcc -o exampleA lex.yy.c -l
ex 库(使用 -l 进行包含,而 lex 则使用 -ll)包含执行分析代码的简单的
main() 函数。当运行生成的应用程序时,它将等待输入。清单 3 显示了该应
用程序的输入(和输出)。
清单 3. 简单 lex 应用程序的输入/输出
$ exampleA
begin
Started
hello
Hello yourself!
end
Stopped
thanks
Your welcome
hello thanks
Hello yourself!
Your welcome
hello Robert
Hello yourself!
Robert
对于单行输入 ('begin'),该应用程序根据您所提供的命令进行响应,在本示例
中,将打印出单词 'Started'。对于包含多个识别单词的行,该应用程序分别运
行多个命令,并以空格隔开。对于无法识别的标记(包括空白字符),仅对其
进行回显。
这个示例介绍了该系统的基本操作,但是您仅仅使用了标准的单词。要使用其
他的组合,如字符和元素,有各种不同的解决方案可供使用。
回页首
识别元素
可识别的元素可以不是前面介绍的固定字符串,标识符支持正则表达式和特殊
(例如标点符号)字符,如清单 4 所示。
清单 4. 正则表达式和特殊字符
%{
#include <stdio.h>
%}
%%
[a-z] printf("Lowercase word\n");
[A-Z] printf("Uppercase word\n");
[a-ZA-Z] printf("Word\n");
[0-9] printf("Integer\n");
[0-9.] printf("Float\n");
";" printf("Semicolon\n");
"(" printf("Open parentheses\n");
")" printf("Close parentheses\n");
%%
清单 4 中的示例应该是一目了然的,并且对于需要进行分析的任何正则表达式
或特殊字符都可以使用相同的原则。
回页首
真正的标记化
前面的示例所构建的 C 源代码实质上是独立的。尽管使用这种方法没有什么问
题,但是对于分析包含多个单词、短语或序列的给定指令中的文本或其他条目
的情况,这种方法并不是很有价值。
使用这种方式分析序列需要一个语法分析器,而它将定义标记序列。但是语法
分析器必须知道要分析的是什么标记。在 lex 定义中,当识别标记时所进行的
操作是回显字符串,如果要返回一个识别标记,那么需要对该操作进行更改。
例如,您可以如清单 5 所示对原始示例进行重写。
清单 5. 返回标记
剩余22页未读,继续阅读
youqi1st
- 粉丝: 3
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
- SPC统计方法基础知识.pptx
- MW全能培训汽轮机调节保安系统PPT教学课件.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0