编译原理期末复习

改写文法,消除左递归

通俗地讲,若在一个文法中,一个非终结符A经过多次推导得到了$A\alpha$,则称这个文法是左递归的。左递归会使分析陷入到无限循环之中:
image.png

消除直接左递归

如果A→A α,则称文法G是直接左递归的。
引入一个新的字符$P`$,将左递归变成右递归。
image.png
Capture_20240626_154302.jpg

消除间接左递归

简介左递归的表现
image.png
手动执行下面的伪代码,消除间接左递归
image.png
例子:
Capture_20240626_154600.jpg

根据产生式构造每个非终结符的FIRST集合和FOLLOW集合

求解FIRST集合

步骤:
Capture_20240626_155046.jpg
例子:
Capture_20240626_155316.jpg

求解FOLLOW集

步骤:
Capture_20240626_155527.jpg
例子:
image.png

利用FIRST集合和FOLLOW集合构造LL(1)分析表M[A,a]

自顶向下的分析步骤(推导),和下面的自下而上的分析(规约)都要考察。
非递归的预测分析表
何为预测分析表?
image.png
填写步骤:

  1. 先针对FIRST集,若$\alpha \in FIRST(A)$,则找到此推导的第一个产生式,将其写在$M[A,\alpha]$的格子上;
  2. 再针对FOLLOW集,若$\xi \in FIRST(A)$,则将产生式$A \rightarrow \xi$写在$M[A,\alpha]$上,其中$\alpha \in FOLLOW(A)$;

例子,手推一遍
image.png

根据分析表构造分析步骤(表格)

步骤,认真看可以理解
image.png
例子,手推一遍
Capture_20240626_160626.jpg

判断文法是否具有二义性

找到一个句子,画两个不同的语法分析树推导,可证明文法具有二义性。
image.png

NFA的确定化,NFA转换为DFA

NFA和DFA的概念

用五元组定义的有穷自动机DFA,记为$D_1={k,\Sigma,M,S,F }$。

  1. $k$表示状态的集合;
  2. $\Sigma$表示终结符的集合,即可接受的输入字符;
  3. $M$表示转换函数,产生式$A \rightarrow \alpha$对应的转化函数为$M(S,a)=A$;
  4. $S$表示文法的开始符号(也叫识别符号);
  5. $F$表示终结符集合。

一个DFA的例子
image.png
不确定的有穷自动机NFA:图中至少有一条弧上有两个字符,即一个字符a经过同一个字符b的产生后,得到两个不同的结果c和d;
一个NFA的例子:
image.png
NFA和DFA的区别:
image.png

新概念:$\xi-闭包$

  1. 状态$q$的$\xi-闭包$记作$\xi-closure(q)$;
  2. 状态$q$的$\xi-闭包$为从$q$出发,只经过空弧($\xi$)到达的状态集合;
    1. $q \in \xi-closure(q)$;
    2. 从$q$出发,经过任意条空弧到达的所有状态$q`\in \xi-closure(q)$;
  3. 状态集合$I$的$\xi-闭包$:由$I$中所有状态的$\xi-闭包$的并集组成,记作:$\xi-closure(I)={ q | q\in\xi-closure(q) 且q \in I}$;
  4. 状态集合$I$的$a$转换$I_a$:$I_a=\xi-closure(J)$,其中J为从I中任意状态出发,经过一条a(可以经过任意条空弧),到达的所有状态的集合;

Capture_20240626_151804.jpg

子集法将NFA转换为DFA

  1. 由正规式得到NFA,一般题目直接给定,以下面的NFA为例子说明NFA转换为DFA的过程:

image.png

  1. 由于NFA中初始状态和终止状态均不唯一(虽然本例子中是唯一的),引入新的初始状态X和新的终止状态Y,加入到原NFA中:

image.png

  1. 通过引入新的状态,简化弧上的标记(将多个变成一个)。即对每条有多个字符的弧,做如下变换:

image.png
将原先的NFA转换成:
image.png

  1. 构造计算状态集的转换表。NFA中具有2个终结符,所以转换表为3列。
    1. 首先,令转换表第一行第一列为开始符号的$\xi-闭包$,求出这一列的$I_a和I_b$;
    2. 检查得到的$I_a和I_b$是否在第一列中出现,若未出现,则补上;
    3. 计算下一行的$I_a和I_b$;
    4. 重复上述过程,直到所有2,3列的子集全部出现在第一列为止。

例子中的转换表为:
Capture_20240626_152845.jpg

  1. 像上面的黄色笔迹那样给每个状态集标上号,将得到的转换表转换为转换矩阵,并依据转换矩阵得到DFA。

转换矩阵
Capture_20240626_153033.jpg
DFA
image.png

语法制导的翻译

image.png
可以不看那些复杂的概念,先从下至上实现输入字符串的规约过程,每用到一条产生式就执行其语义属性(代码)。

类型转换(书写代码)

根据拓广文法的产生式求规范项目集和LR分析表

LR分析法

LR分析法是自下而上的分析方法,跟之前的不一样。

短语,直接短语和句柄

image.png
最右推导称为规范推导,规范推导的逆过程称为规范规约。
由规范推导得到的句型称为规范句型。

LR文法

image.png

LR(0)分析

对于每一条产生式,可以在其中间的任意位置加上·,加上·的产生式称为项目。
image.png
项目的分类:

  1. 移进项目:圆点后面是终结符的项目;
  2. 待约项目:圆点后面是非终结符的项目;
  3. 规约项目:圆点在产生式最右端的项目;
  4. 接受项目:形似与Z->S·,其中s是文法的识别符号(开始符号),接受项目是规约项目的一种。

LR(0)项目集规范族的构造

  1. 先拓广文法,引入新的开始符号,将原先的开始符号作为新产生式的右部;
  2. 从以新的开始符号为左部的产生式开始,生成项目;
  3. 对于待约项目(圆点后面是非终结符),把圆点后端的终结符的产生式的第一个项目也加入到当前项目集;
  4. 重复上面的过程,直到各项目集中的项目不再增加,且每个产生式的每个项目都在项目集中。

对于文法:
image.png
构造识别其活前缀的DFA:
Capture_20240626_142037.jpg
构成识别一个文法活前缀的DFA的项目集(状态)的全体称为文法的LR(0)项目集规范族。
因此,上图中框框内的$I_1-I_{11}$就是这个文法的项目集规范族。

分析表(ACTION子表和GOTO子表)

  1. 将项目集$I_k$的下标k作为分析器的状态,即分析表的行标;
  2. 规定s表示移进(shift),r表示规约(reduce);
  3. ACTION[k,a]表示当当前项目集$I_k$遇到终结符a的时候需要采取的动作;GOTO[k,a]表示当前项目集$I_k$遇到非终结符A的时候需要进入哪个项目集,用行标数字表示;
  4. ACTION子表的动作分为三类:①sk,其中k为数字,表示用$I_k$个项目集移进;②rk,k表示数字,表示用第k条产生式规约;③acc表示接受;

步骤:
image.png
例子:
image.png

一般来讲,拓广文法中新增加的那条产生式编号为0。

根据产生式写出文法的规范规约过程

属于算符优先分析的内容,和上面的分析预测不一样。

  1. 算符优先分析是从下至上的规约过程,是由输入串得到文法的开始符号的过程;
  2. 分析预测是至上而下的推导过程,是由文法的开始符号得到输入串的过程;
  3. 上述两种不同的顺序在各自的算法中需要体现在表格里面。

步骤(仅供参考):

  1. 先按照规范推导(最右推导)的过程得到语法推导树;
  2. 再开始画表格,开始时符号栈中什么都没有(若是分析预测,符号栈中最开始会有一个开始符号),首先将输入串的第一个字符移进;
  3. 查看语法推导树,若当前的字符是当前推导树的句柄,则进行规约,否则进行移进;
  4. 重复上述过程,直到接受。

例题
image.png
答案:
Capture_20240627_085849.jpg

posted @ 2024-06-27 19:27  emo~~~~  阅读(18)  评论(0编辑  收藏  举报