编译原理学习笔记---龙书第三版(精简习题版)

目录概要1.词法分析1.1正则表达式转NFA1.2 NFA转DFA1.3 DFA最小化2.语法分析2.1 自顶向下分析2.2自底向上分析LR(0)SLR(对LR(0)改进)LR(1)LALR3.语法制导翻译概述(区分SDD和SDT)语法制导定义(SDD)专有名词解释:SDD的应用语法制导的翻译方案(SDT)例题4.中间...
摘要由CSDN通过智能技术生成

目录

概要

1.词法分析

1.1正则表达式转NFA

1.2 NFA转DFA

1.3 DFA最小化

2.语法分析

2.1 自顶向下分析

2.2自底向上分析

LR(0)

SLR(对LR(0)改进)

LR(1)

LALR

3.语法制导翻译

概述(区分SDD和SDT)

语法制导定义(SDD)

专有名词解释:

SDD的应用

语法制导的翻译方案(SDT)

例题

4.中间代码(中间表示形式)

后缀式(逆波兰式)

DAG(有向无环图)

三地址码

5.优化方案

6.基本块和流图

7.基本块的DAG表示&DAG到基本块的重组

8.数据流分析&寄存器分配


推荐视频:https://www.bilibili.com/video/av17404276/?p=87 中科大华保健老师

概要

编译器(compiler)和解释器(interpreter)

编译器将源程序翻译成一个等价的、用另一种语言(目标语言)编写的程序。

解释器并不通过翻译的方式生成目标程序,其特点是逐个语句地执行源程序。

对比:由编译器产生的机器语言目标程序通常比一个解释器快很多,而解释器的错误诊断效果通常比编译器更好,因为它逐个语句地执行源程序。

1.词法分析

1.1正则表达式转NFA

Thomson算法过程,注意连接时并不是加上一条无用的ε边,先将这个字符的Thomson的形式独立地画出来,然后用另一堆的最后一个状态(暂时的终结状态)替换掉start指向的那个状态。记得加初始状态箭头。

记住基础的形式

              

 

 

1.2 NFA转DFA

子集构造算法/工作表算法
q0 <- eps_clouse(n0)
Q  <- {q0}
worklist <- q0
while(worklist!=[ ])
{
	remove q from worklist
	foreach(character c)   //256 for ASCII
	{
	  t <- eps_clouse(delta(q,c))         //q集合中能接收该字符的状态,对其进行状态转换后再求
eps闭包所得到的集合,q包含多个状态时,t是这多个状态接受该字符的后的eps闭包的并集 
	  D[q,c] <- t
	  if(t\not\in Q)
	  add t to Q and worklist
	}
}

注意接受一个字符得到的新的状态是指原来的A状态集合所有的move(q,a)得到的状态的并集!

例题:

Dtran转换表(状态转换表)(初始的NFA状态集合是第1个状态求闭包)

NFA STATE

DFA STATE

a

b

{1,2,3,5,7,8}

A

B

C

{2,3,4,5,7,8,9}

B

B

D

{2,3,5,6,7,8}

C

B

C

{2,3,5,6,7,8,10}

D

B

E(终结)

{2,3,5,6,7,8,11}

E

B

C

画出的DFA

1.3 DFA最小化

Hopcroft最小化算法:合并状态,基于等价类
split(S)
  foreach(character c)
    if(c can split S)
      split S into T1,...Tk

hopcroft()
{
	split all nodes into N,A  //非接受/接受状态
	while(set is still changes)
	  split(S) 
}

先将终结/非终结状态划分成A和N集合,再看哪个终结符能划分集合(集合中的状态接受该终结符能跳转到不同的集合则划分)

step1:N A {q0,q1,q2,q4}  {q3,q5}

step2:e字符将N split ->  {q0,q1}  {q2,q4}  {q3,q5}

step3:e字符将{q0,q1} split -> {q0}  {q1}  {q2,q4}  {q3,q5}

 

2.语法分析

2.1 自顶向下分析

消除左递归 & 提取左公因子

          

LL(1)分析

整理流程:NULLABLE集(能推出ε的非终结符的集合)->FIRST(N)集(从非终结符N推导的句子开头的所有可能的终结符的集合)->FOLLOW(N)集(紧跟在非终结符N后面的终结符号的集合)->FIRST_S(p)集(每个产生式推导的句子开头的所有可能的终结符的集合)

注意:该方法与龙书上的不同

PS:ε在计算FIRST_S时视为属于NULLABLE的非终结符(如果一个产生式右部只有ε,那么使用其FOLLOW集),且计算FIRST集时不视为终结符

如何使用LL(1)分析表?

栈中为非终结符,匹配前看符号(要检验的句子)的字符从而决定将哪一条产生式的右部压入栈,然后匹配成功(一般情况下)又弹出该字符。

step1:NULLABLE集:对所有的产生式循环,NULLABLE集合初始化为空集,记录右边第一个字符可能为ε的非终结符,如果右边为1个ε或ε开头,则该非终结符加入NULLABLE;如果右边只有非终结符且它们全部属于NULLABLE,则该非终结符加入NULLABLE。(这个直接写基本上能看出来)

step2:带NULLABLE的FIRST集构造

如果产生式右边是终结符a则FIRST(N)=a,如果是非终结符就并上其FIRST集,再看其是否属于NULLABLE,属于则继续往下,否则结束。

step3:FOLLOW集

为什么temp一开始要等于FOLLOW(N)?关于这一点,比如产生式X->Y

表示X能推出Y,那么temp一开始就等于FOLLOW(X),然后FOLLOW(Y)就∪=temp了,可以这么理解,X能推出Y那么跟着X的非终结符不就也可能跟着Y,所以才这么初始化。

step4:产生式的FIRST集(FIRST_S)

理解:FOLLOW集的用途,如果该产生式右部的非终结符全部属于NULLABLE集合(即都有可能为ε),那么就必须知道这个非终结符后面可能跟着哪些终结符,否则无法正确得出什么时候使用该产生式。这就是FOLLOW集合所做的事。

注意下面的ε!计算FIRST_S时视为属于NULLABLE的非终结符(如果一个产生式右部只有ε,那么使用其FOLLOW集),且计算FIRST集时不视为终结符。

 

2.2自底向上分析

LR(0)

从左至右读入程序(L),最右推导(R),零个前看符号(0)(这个0有特殊含义)

点记号:为了方便标记语法分析器已经读入了多少输入,我们可以引入一个点记号

  • 24
    点赞
  • 120
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值