先好好学学DFA吧~~
该用C写还是用java呢?语言应该是无所谓吧!
然后在网上找了些资料,先留着~~给自己打点气,争取这个星期完工~~然后发帖~
整个程序用标准c语言写成,平台可移植。共分为四个模块:缓冲区,状态机,符号表,词法器。
缓冲区:设置缓冲区的目的不言而喻了,是要用来减少文件访问次数,加快程序速度的。当然如果我们的内存有无限大,那就一次把文件加载到内存里就行了,但是现实是我们的内存总是有限大小的,所以我们的缓冲区不能过大。这就会带来一些问题:比如我们在查找一个单词的过程中已经到了缓冲区的末尾,如果此时只是简单的再从文件里读取源文件进来装载到缓冲区里,原来的缓冲区内容就会被覆盖掉,那么当前查找的单词的前半部分也就被丢弃了。我采用的方法是龙书上介绍的缓冲对(Buff Pair)。即装载缓冲区以缓冲器要一半大小为单位,当读到缓冲区前半段末尾的时候装载后半段,当读到后半段末尾的时候装载前半段,并且指针调到缓冲区开始。这样便构成了一个循环使用的缓冲区,当然这要要求每个单词的长度不超过半个缓冲区长度,这一点是很容易办到的,因为缓冲区再小(哪怕是手机),也可以1k以上吧?那每个单词也可以有512个字符了,足矣。
状态机:状态机是词法分析的中枢神经,整个词法分析过程由状态机驱动着。分析一个单词即是一个状态转换过程。状态始终是从初态(状态0)开始,根据一个个条件(即一个个读入的字符),在一个个状态之间跳转,最终达到终结态(找到单词)。当然其中还有一些细节,比如某些终结态也许是另一个终结态的中间态。比如<和<=,当读到字符'<'时,虽然到达了小于号的终态(找到一个小于符),但是还不能断定,因为如果后面跟着一个字符'='那就应该算找到一个小于等于号,但是也有不跟'='的,也就是说是真正的小于号,那么就应该回退字符指针,返回小于号。等等。。再个关于状态机的访问速度问题,由于普通线性表实现的状态机每次查找下一个状态时都要遍历,这样效率很低,而且这个操作每读入一个字符就要执行一遍,再编译过程中使用非常频繁,所以这个操作的效率就至关重要了。龙书上有个比较好的算法,就是为状态机(其实就是一个数组)建立一张索引表(另一个数组),以每个状态号为下标,数组内容就是此状态在状态机中的基地址。这样就可以很名显得提高访问速度。当然也可以用哈希表,但任何哈希表实现都会浪费空间,而且建立一张哈希表的工作量比建索引表大。当然了,如果用第三方函数库(或类库)那就是另外一回事了。
符号表:我们知道一个程序里同一个关键字,变量名等等单词往往出现多次,如果每一次出现都为其创建一个存储区是不科学的,因为那样浪费的空间是巨大的。所有我们可以引入一个符号表的概念。每次找到一个新单词都可以先查找一下符号表,如果此单词已存在,则直接返回次单词的位置或索引号,否则便插入该单词。由于符号表经常要执行插入和查找操作,所以为了提高访问速度,可以采用哈希表来实现。
词法器:此模块是词法分析器的最上层,他通过一个函数NextToken为整个词法分析器的上层——语法分析器提供服务。其实现即每次从初态开始,不断地通过缓冲区模块提供的方法读入单个字符,然后交给状态机得到下一个状态,再继续取字符,继续状态转换,直到找到一个单词,于是调用符号表的Insert方法,至于是插入新的还是引用旧的就是符号表模块的事了,词法器只得到一个结果,即:此单词在符号表中的位置。http://blog.csdn.net/Cocoa17/archive/2005/05/21/377584.aspx