编译原理 词法分析

词法分析负责将字符流转为符号流(单词流)

注意:空格已经被删掉,因为没有具体的意义,在文末追加eof。

词法分析的实现方案: 1. 手工编码 GCC LLVM 2. 词法分析器的生成器 自动生成 

手工构造:

代码实现:

通过状态转移图进行识别,如果识别到了其他字符,如>a,识别到了a,那么需要回滚,即*处。

自动生成的方式:

输入声明式的规范,经过工具如c(lex flex),可以自动产生一个词法分析器。

1)如何获得声明式的规范? 正则表达式

 如何使用正则表达式表示程序语言设计中的词法?

语法糖 syntax sugar 

语法糖简化了编写。

声明式的规范即是re 正则表达式

2)如何实现该工具?

3)词法分析器

有限状态自动机

状态转移函数(q0,a)->q1,即当在q0状态遇到a时,转移到q1状态

从q0经过a,可以走到q0,q1即下一状态是一个状态集合(NFA 非确定)。

如果在所有状态上对于单一字符,下一个状态是确定的,则是DFA(确定的)。

NFA对于一个字符是否能走到可接受状态并不确定,因此可能需要回溯。

注意,NFA存在空串,即表示从一个状态转移到另一个状态可以通过空串转移,即直接跳转。

DFA的实现:有向图 1. 边上的信息 (字符)2.节点信息(如输入节点,输出节点)

如何从RE转换到NFA?

1. Thompson 算法 RE-> NFA

 

 

如下图所示即为该表达式对应的正则表达式

NFA->DFA

即将一个节点经过一个字符后能够达到的状态集合归纳为一个集合

需要注意的是,接受状态n9包括在了多个集合中,q1,q2都是接受状态。

1. 先对任何一个子集求转换过程,求结果

2.对结果求delta

基于深度优先去做

基于宽度优先去做

NFA转换为DFA

D[q,c]<- t 即为将子集之间字符读取,状态转换关系进行记录

worklist就是每次得到的状态的集合,实际上类似于深度优先节点中的父节点连接其子节点

q1,q2,q3中都有n9,除q0外都是接受状态。

子集构造算法:

1. esp_closure 给定一个集合,确定集合中起始节点经过eps转换能够达到的状态;

2. Q DFA里面所有的有限状态自动机

3. worklist 队列

4. 进入worklist的循环

    对于每一个字符,asic码c, 

     delta(q,c) 经过字符c可以到达的状态,改状态经过e-close,得到t

    则将q经过可以到达t的关系记录到D中(DFA)

最终所有的NFA中的状态都被考虑过了。

DFA的最小化:

Hopcropft对DFA进行最小化

q2,q3都包括接受状态,可以合并,q1和q4也可以合并

n非接受状态,a接受状态

对于所有的char b c A的集合都不会被分割,因此将q1,q2,q3合并为集合A

实际上是将经过输入状态的字符后,仍然跳转到相同状态的状态合并为一个集合

DFA的代码表示:

DFA是一个有向图,图,就可以用表来表示。

转移表 有n*m,n为状态集合个数,m为字符个数

nextToken 每次返回一个识别的字符

在while循环中,如果是接受状态,则清空,通过table【state】【c】进行查表

当读取到结束字符后面的字符时,将栈弹出,rollback 回退,回退回去

stack用于实现最长匹配 

栈底每次都是接受状态,每次接收到接受状态后,清空栈,将接受状态作为栈底。

当接受失败后,回滚,直到回滚到接收到状态弹出栈,即最后一个匹配的,最长匹配。

跳转表每个状态对应一长段代码

当使用代码失陷后,跳转表比转移表局部性更好,转移表可能代码量很大(状态很多),而跳转表每次只执行一段。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值