词法分析器完工!

根据确定有限自动状态转换机(汗,真拗口,英文叫Determinate Finite Automan,以下简称状态机)实现的词法分析器,目前还不支持从正则表达式直接生成状态机,要人肉生成(呵呵,就是手动)。

整个程序用标准c语言写成,平台可移植。共分为四个模块:缓冲区,状态机,符号表,词法器。

缓冲区:设置缓冲区的目的不言而喻了,是要用来减少文件访问次数,加快程序速度的。当然如果我们的内存有无限大,那就一次把文件加载到内存里就行了,但是现实是我们的内存总是有限大小的,所以我们的缓冲区不能过大。这就会带来一些问题:比如我们在查找一个单词的过程中已经到了缓冲区的末尾,如果此时只是简单的再从文件里读取源文件进来装载到缓冲区里,原来的缓冲区内容就会被覆盖掉,那么当前查找的单词的前半部分也就被丢弃了。我采用的方法是龙书上介绍的缓冲对(Buff Pair)。即装载缓冲区以缓冲器要一半大小为单位,当读到缓冲区前半段末尾的时候装载后半段,当读到后半段末尾的时候装载前半段,并且指针调到缓冲区开始。这样便构成了一个循环使用的缓冲区,当然这要要求每个单词的长度不超过半个缓冲区长度,这一点是很容易办到的,因为缓冲区再小(哪怕是手机),也可以1k以上吧?那每个单词也可以有512个字符了,足矣。

状态机:状态机是词法分析的中枢神经,整个词法分析过程由状态机驱动着。分析一个单词即是一个状态转换过程。状态始终是从初态(状态0)开始,根据一个个条件(即一个个读入的字符),在一个个状态之间跳转,最终达到终结态(找到单词)。当然其中还有一些细节,比如某些终结态也许是另一个终结态的中间态。比如<和<=,当读到字符'<'时,虽然到达了小于号的终态(找到一个小于符),但是还不能断定,因为如果后面跟着一个字符'='那就应该算找到一个小于等于号,但是也有不跟'='的,也就是说是真正的小于号,那么就应该回退字符指针,返回小于号。等等。。再个关于状态机的访问速度问题,由于普通线性表实现的状态机每次查找下一个状态时都要遍历,这样效率很低,而且这个操作每读入一个字符就要执行一遍,再编译过程中使用非常频繁,所以这个操作的效率就至关重要了。龙书上有个比较好的算法,就是为状态机(其实就是一个数组)建立一张索引表(另一个数组),以每个状态号为下标,数组内容就是此状态在状态机中的基地址。这样就可以很名显得提高访问速度。当然也可以用哈希表,但任何哈希表实现都会浪费空间,而且建立一张哈希表的工作量比建索引表大。当然了,如果用第三方函数库(或类库)那就是另外一回事了。

符号表:我们知道一个程序里同一个关键字,变量名等等单词往往出现多次,如果每一次出现都为其创建一个存储区是不科学的,因为那样浪费的空间是巨大的。所有我们可以引入一个符号表的概念。每次找到一个新单词都可以先查找一下符号表,如果此单词已存在,则直接返回次单词的位置或索引号,否则便插入该单词。由于符号表经常要执行插入和查找操作,所以为了提高访问速度,可以采用哈希表来实现。

词法器:此模块是词法分析器的最上层,他通过一个函数NextToken为整个词法分析器的上层——语法分析器提供服务。其实现即每次从初态开始,不断地通过缓冲区模块提供的方法读入单个字符,然后交给状态机得到下一个状态,再继续取字符,继续状态转换,直到找到一个单词,于是调用符号表的Insert方法,至于是插入新的还是引用旧的就是符号表模块的事了,词法器只得到一个结果,即:此单词在符号表中的位置。

现在临近期末了,各种考试逼近,考研的压力也袭来。写程序的冲动只能压一压了。如果有时间的话最多把以前写的自底向上简单优先语法分析器(那时没有做词法分析,假设每个单词都是由一个字符组成)和这个词法分析器连起来。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值