利用lex和yacc解决通讯录问题(1)
前言
一般的编译原理教材上关于使用lex和yacc构造词法分析的好例子并不多.很多教程都只是在讲解词法分析和语法分析的时候简单地提到了一下lex和yacc这两个工具,甚至有很多国内的大学教材对lex和yacc只字不提。其实lex和Yacc并非只是为了构造编译系统而开发的。本节通过一个提取通讯记录的信息的简单问题,来讲解一下lex和yacc的使用.
提取通讯录的信息
前几天收到朋友询问一下如何通过词法,语言分析,把一个通讯录中的人物姓名和电话号码的信息提取出来。我把问题改了一下,大致如下:
我有个记事本,里面的信息都是电话机生成的通讯记录信息。以文本格式保存在record.txt文件里面。里面的信息是以下面的方式组成的。
---------2004.1.10----------
姓名:jeclee
电话:05513606124
---------2004.1.11----------
姓名:wangan
电话:075528979205
…
现在我要建立一个数据库系统,需要把跟我同过电话的人的姓名和电话号码都输入进去。那么我需要考虑从这种电话机生成的记录格式文件中提取有用的信息。当然,解决的办法多不胜数,但是本节,我们将探讨使用lex和yacc两个工具,十分方便的构造语法分析器,来里面的信息。
寻找lex和yacc两个工具
或许你觉得动用编译原理来解决这种问题太麻烦了,但是当我们有了lex和yacc后,复杂的处理将被简化。Lex和yacc这两个东西本来是unix下的两个工具,一般大家使用windows操作系统就需要在网上去寻找。我使用的是cygwin中的flex.exe和bison.exe。bison.exe就是yacc.而cygwin就是一个在windows平台上模拟unix的工具。大家可以去下一个cygwin就可以用了。
词法分析器的输入文件
关于正则表达式的问题,我在本系列前面的文章中已经提到过,其详细的讲解请大家参考编译原理教材。
这里我先给出一些基本的词法的正则表达式,它们都是几乎在每个词法输入文件里面都会出现的。
digit [0-9]
number {digit}+
letter [a-zA-Z_]
identifier ({letter}|_)({number}|{letter}|_)*
newline [\n]|[\r][\n]
whitespace [ \t]+
在电话机中的记录文件中另外还有标记头”---------2004.1.10----------“我们没有考虑。标记头的正则表达式十分简单,就是”-“和数字和点的组合而已,那么可以很容易地写下它的正则表达式。
Begin [-]+({number}[.])+[-]+
这里的[-]表示的”-“符号,而number前面已经给出,为任意一个整数.而逗号”.”也是以[.]表示出来.那么({number}[.])+就表示记录头里面的日期信息,可是这里我们并不需要知道日期信息,所以就没有必要把它单独提取出来,而完全可以埋藏在一个简单的正则表达式里面。
好了,把这些正则表达式整理到一个名字为record.l的flex输入文件里面就可以了。
整个电话机记录都使用一种固定的文法形式,那么文法输入文件的编写就相对简单,完成词法分析后,我们的工作差不多就完成了一半了。
2003-1-13
作者:唐良 tangl_99
QQ:8664220
email:tangl_99@sohu.com
成都,四川大学,计算机学院