升C小调狂想曲

<递归的忧伤>
posts - 10, comments - 71, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

上一篇我已经将各个词法标记都设计好了,现在我们需要写出一个程序,他读入一个字符串,并输出一系列Token,其中每个Token就是一个词法标记,例如Keyword,Identifier,Number,Operator。

假设我们输入int a=100;这样一个字符串作为代码,那么我们将如何分析呢?

首先读入i,“i”符合Identifier的规则,但是继续读下去还有个n,一共是“in”,“in”也符合Identifier的规则,再读,变成“int”,“int”符合Type的规则,继续读入后面的空格,变成“int ”,这个可不符合任何规则了,因此我们不能承认这一步,只好取上一步的可接受的结果Type:“int”。这样我们就生成了第一个Token,他的类型是Type,值是“int”。以此类推,我们可以读完整个程序,并完成整个词法分析的过程。

但是每一次都去判断整个已读入的字符串是否匹配某个规则,效率非常低,我们需要一种线性读入字符串,并实时掌握目前字符串匹配状况的办法。确定性有穷自动机(DFA)就是这样一种状态机。

下面是我为CNScript画出的状态图:




例如刚才读的int a=100;
我们一开始是在编号为0的状态,现在输入i,因为i属于a-zA-Z的范围,所以通过最后一幅图我们看到,我们将迈向编号为44的状态。再输入n,因为n属于a-zA-Z0-9_的范围,所以我们继续走在编号44的状态,t也如此,但是输入空格时,我们发现44号状态没有接受空格字符的出口,也就是无法继续走下去了,而且44号状态是一个可接受状态,所以我们接受已经输入了的“int”。
在这里我们的44号状态,接受意义是一个name,可以是Identifier,也可以是Keyword,也可以是Type,当我们取得name:“int”时,我们再判断发现这是一个Type,所以我们得出Token:Type:“int”。然后状态回到0号,继续输入刚才的空格。以此类推。

所以我们只要按这个状态图去遍历字符串,我们就会不断的在各个状态中辗转反复,并不断的得出Tokens。这就是我们词法分析的基本原理。
下一篇我会写出这个DFA的代码和具体使用方案。

Feedback

# re: 你好,状态图 --- CNScript 成长日记(3)  回复  更多评论   

2008-08-08 09:53 by 长江三峡
学习了

# re: 你好,状态图 --- CNScript 成长日记(3)[未登录]  回复  更多评论   

2008-08-08 10:58 by cexer
这个 DFA 还不是最小状态的吧?

# re: 你好,状态图 --- CNScript 成长日记(3)  回复  更多评论   

2008-08-08 15:37 by 陈坤
对,这个还不是最小状态,例如20和22还可以合并。
但是剩下的任何合并工作都不会改善性能了,如果将20和22状态合并,那么也只是在判断当前状态时少了一个分支,这个影响非常小。目前这个状态图因为是为了手写词法分析器,所以要在性能最优的情况下,保持一种易读性。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理