2022年词法分析小结_第1页
2022年词法分析小结_第2页
2022年词法分析小结_第3页
2022年词法分析小结_第4页
2022年词法分析小结_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、高品质文档2022年词法分析小结 词法分析是编译器工作的第一阶段,它的工作就是从输入(源代码)中取得token,以作为parser(语法分析)的输入,一般在词法分析阶段都会把一些无用的空白字符(white space,即空格、tab和换行)以及解释剔除,以降低下一步分析的简单度,词法分析器一般会供应一个gettoken()这样的方法,parser可以在做语法分析时调用词法分析器的这个方法来得到下一个token,所以词法分析器并不是一次性遍历全部源代码,而是实行这种on-demand的方式:只在parser需要时才工作,并且每次只取一个token。 token和lexeme 首先,token不等

2、于lexeme。token和lexeme的关系就类似于面对对象语言中“类”和“实例”(或“对象”)之间的关系,这个用中文不知该如何解释才好,比如语言中的变量a和b,它们都属于同一种token:identifier,而a的lexeme是”a”,b则是”b”,而每个关键字都是一种token。token可以附带有一个值属性,例如变量a,当调用词法分析器的gettoken()时,会返回一个identifier类型的token,这个token带有一个属性“a”,属性可以是多样的,例如表示数字的token可以带有一个表示数字值的属性,它是整型的。 如下代码: int age = 23; int count

3、 = 50; 可以依次提取出8个token:int(值为”int”),id(值为”age”),assign(值为”=”),number(值为整型数值23),int(值为”int”),id(值为”count”),assign(值为”=”),number(值为50) 正则表达式 正则表达式可以用来描述字符串模式,例如我们可以用digit+来表示number的token,其中digit表示单个数字(这里说正则表达式并不完全和实现的正则引擎所识别的正则表达式等价,这里只是为了描述问题而已)。 然而像c语言的的多行解释,用正则表达式来描述就比较麻烦,此时更倾向于直接用有穷自动机(finite autom

4、aton)来描述,因为用它来描述特别直观且很简单。 有穷自动机(finite automata) 有穷自动机也称为有限状态机,状态在输入字符的作用下发生迁移,因此,它可以用来识别token,也因此,我们只要画得出fa,之后再用代码实现这个fa,那词法分析器也就差不多弄好了。 有穷自动机分确定性(dfa)和非确定性(nfa)两种,假如对于同一个输入,只会有一个确定的状态迁移路线,也就是只有一个确定的“下一状态”,那就是dfa,否则就是nfa。 因为dfa对于同一个输入只有一个确定的下一状态,所以词法分析器当然优先采纳它,那nfa拿来干嘛用呢?nfa用来做描述用时更便利,我们可以特别快速地画出一个

5、识别token的nfa图,但要想直接画出个dfa那要动不少脑筋。 依据正则表达式构建nfa 如上所述,nfa更简单画出,那我们就先讨论nfa,在定义token时,我们可以用正则表达式来描述它,因为正则表达式干这行很合适,例如一个digit+就可以描述数字,多便利。因此,我们需要依据正则表达式画出与之等价的nfa。而这个算法特别简洁,就是tompsons construction,这个书上写得很清晰了。 将nfa转化成dfa(nfa的确定化) 对于计算机来说,面对同一个输入,假如有多个下一状态,那计算机就不清晰要转到哪个状态,所以我们期望能从正则表达式得到dfa,而不是nfa,因为这样将来编程实

6、现时比较自然(同一输入有确定的一个下一状态),而幸运的是,每个nfa都可以转化成dfa。为什么nfa可以转化成dfa?因为fa(finite automata)中的状态都是我们自己画的,只要fa能正确的识别token,那就ok了,也就是,假如nfa和dfa都可以达到一样的效果:识别token,那其它的我们就不管了。 而nfa确定化的本质,就是将原来多个状态改用一个状态来表示,新状态其实是一个状态集,比如nfa中状态s1在输入a下可以到达s2和s3,那么,在dfa中,就把s2和s3合起来认为是一个状态。还有一个问题是nfa中的空转换(?输入),假如s1在?输入下可以到达s2,就表示s1可以无条件

7、地转移到s2,那s1和s2自然可以合并起来作为dfa中的一个状态,于是nfa转dfa的算法也就好理解了。但首先得先定义下空闭包(?-closure): ?-closure: 状态s的?-closure即s经过?转换可以到达的状态集,s的?-closure永久都会包含s自身。一个状态集的?-closure即该状态集中各状态的?-closure的集合。 nfa确定化算法(subset construction): 从开头状态开头,计算它的?-closure,得到状态集set1,然后考察set1在某个输入a的作用下会迁移到哪些状态,把这些状态集中到一起,再求这个集合的?-closure,得到set2

8、,这样我们就可以画两个圈,一个标上set1,另一个标上set2,然后画条从set1到set2的线把这两圆连起来,在线上标上a,这样dfa的一部分就画好了,然后我们再考察set1在其它输入下可以达到的状态集的?-closure,同样画圈连线,以此类推,最终的时候,把包含了原nfa中终结状态(final state或acceptin state)的dfa状态(在转换后的dfa中,每个状态都是包含了一个或多个原nfa中的状态)标记为终结状态。 最小化dfa状态数 由一个正则表达式,可以构建出一个等价的nfa,然后nfa又可以确定化成dfa,好像到此事情搞完了,但事实证明(有时也可以明显地发觉),最终

9、构成的这dfa好像有些简单,有些状态似乎很冗余,呃,是的,dfa是可以最小化的。 最小化dfa状态数算法的思想是,在开头时,假设是最完善的状况,整个dfa只有两个状态,一个终结状态,一个开头(莫非不能有只有一种状态的状况么?假如原dfa中存在非终结状态,当然就不能,非终结态怎么可以和终结态合并!),当然,这是假设,不是真的,所以这个算法,就是在这个完善的假设下,对假设进一步考察,假如发觉有些状态不能合并,那就分出来吧,这样重复考察,直到发觉没有状态会不能合并时,就做完了,此时不也正是最优解么。 嗯,就是这个,所以一开头,我们把全部非终结状态用一个袋子包起来,看成是一个状态,把全部终结状态也用另

10、一袋子包起来,也看成是一个状态,留意,别把原dfa中各状态间的连线给扯断了。然后,我们抽出其中一个袋子,考察其中的各个状态,我们预备好全部的可能输入,然后逐个拿出来测试,假如该袋子中的全部状态在某个输入a下达到的状态正好都在这个袋子中,那就说明,这个袋子中的这些状态“在目前看来”是可以合并的,也就是说,假如在全部的可能输入的作用下,袋子中的状态达到的新状态正好也都是这个袋子中的状态,那它们就可以合并。而假如,在某个输入a下,袋子中的一部分状态会转移到同一袋子中的其它状态,而有几个叛徒,假设是s1和s2,竟然在输入a下会迁移到其它袋子中的状态,那就说明s1和s2是不行以和其它转移到同一袋子中的状

11、态合并的,于是,我们就把s1和s2装成一个新袋子,从原袋子中分出来,当然,现在还是假设s1和s2可以合并,所以才把它们装一起,毕竟真的可不行以合并呆会还要再考察。考察完输入a,还要接着考察其它的可能输入。假如在考察完一个袋子后,发觉全部状态在a输入下都可以转移到本袋子中的状态,那么最终的dfa它们就被合并成一个状态,并且在a输入下,它有一个到自身的状态迁移。 实现词法分析器 对于一个token,比如用来表示数字的token:num,我们可以用正则表达式描述它,然后画出nfa,再将nfa转化成dfa,再最小化dfa的状态,但是我们的词法分析器是不是分析一个token,所以我们要把全部类型的tok

12、en的dfa合并成一个dfa,这样,这个dfa也就可以识别语言的全部token了,假如在某一连串的输入下,dfa达不到终结状态,那就说明源代码有错误了。 我用c#实现了一个用于compiler construction: principles and practice中tiny语言的词法分析器,tiny语言有关键字:if, then, else, end, repeat, until, read, write,有操作符+,-,*,/,=,(,),;,:=(全角逗号不算,是文章的分隔符)这10个,然后其余的token有number (一或多个数字)和identifier(一或多个字母),其dfa如下图: 上面这张图和编译原理及实践中的一样,其中的带中括号的输入说明这个输入是lookahead的,在匹配胜利后是要重新放回输入流中的,比如识别num时,假如发觉个非digit的,那就说明识别到了一个number,但是最终识别的那个非digit字符是要放回输入流的,因为它要留着下一次识别。 其中从start到done的那个other,指全部非white space,非,非letter,非

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论