当前位置: 代码迷 >> 综合 >> 编译原理(三)语法分析:6.预测分析器
  详细解决方案

编译原理(三)语法分析:6.预测分析器

热度:0   发布时间:2024-01-12 16:05:04.0

文章目录

  • 一、构造预测分析表
    • 1.FIRST集合
      • (1)定义3.10
      • (2)算法3.5 文法符号X
      • (3)FISRT(文法符号序列)
      • (4)例:
    • 2.FOLLOW集合
      • (1)定义3.11
      • (2)算法3.6
      • (3)例子
    • 3.算法3.7 构造预测分析表
  • 二、预测


【编译原理博客列表】》》》》》》


一、构造预测分析表

①首先构造FIRST集合与FOLLOW集合;
②然后根据两个集合构造预测分析表。

1.FIRST集合

(1)定义3.10

文法符号序列α的FIRST集合为: F I R S T ( α ) = { a ∣ α = ? > a . . . , a ∈ T } FIRST(α)=\{a|α=*>a...,a∈T\} FIRST(α)={ aα=?>a...aT},若 α = ? > ε α=*>ε α=?>ε,则 ε ∈ F I R S T ( α ) ε∈FIRST(α) εFIRST(α)

解析:

  • FIRST()内是文法符号序列α(包括终结符、非终结符)
  • a a a表示终结符。
  • 通俗地讲,文法符号序列α的FIRST集合就是从α开始可以导出的文法符号序列中的开头终结符。(开头意思是FIRST集合只取第一个终结符)

(2)算法3.5 文法符号X

  • 输入:文法符号X
  • 输出:X的FIRST集合
  • 方法:
  1. 若X是终结符,则就是自身,FIRST(X)={X};
  2. 若X是非终结符且有X→ε,则加入ε到FIRST(X);
  3. 若X是非终结符且有 X → X 1 X 2 . . . X k X→X_1X_2...X_k XX1?X2?...Xk?,FIRST(X)= FIRST( X 1 X 2 . . . X k X_1X_2...X_k X1?X2?...Xk?),同FISRT(文法符号序列)的方法

(3)FISRT(文法符号序列)

X 0 = ε X_0=ε X0?=ε X k + 1 = ε X_{k+1}=ε Xk+1?=ε
F I R S T ( X 1 X 2 . . . X n ) FIRST(X_1X_2...X_n) FIRST(X1?X2?...Xn?)是所有 F I R S T ( X i ) ( i = 1 , 2 , . . , k ) ? { ε } \textcolor{blue}{FIRST(X_i)(i=1,2,..,k)-\{ε\}} FIRST(Xi?)(i=1,2,..,k)?{ ε}的并集,其中 X k X_k Xk?为第一个具有ε不属于 F I R S T ( X j ) FIRST(X_j) FIRST(Xj?)性质或k>n的文法符号,从 1 ? k ? 1 1\sim k-1 1?k?1每个 X X X都满足 ε ∈ F I R S T ( X i ) ε∈FIRST(X_i) εFIRST(Xi?)
若k>n,则将ε加入 F I R S T ( X 1 X 2 . . . X n ) FIRST(X_1X_2...X_n) FIRST(X1?X2?...Xn?),即所有 F I R S T ( X i ) ? { ε } {FIRST(X_i)-\{ε\}} FIRST(Xi?)?{ ε}的并集再加上ε。

在这里插入图片描述

(4)例:

文法G为S→Ap|BqA→a|cAB→dB|ε

FIRST(a) = {a}FIRST(ε) = {ε}
FIRST(B) = {d,ε}FIRST(A) = {a,c}FIRST(S) = {a,c,d,q}
FIRST(cA) = {c}FIRST(dB) = {d}
FIRST(Aq) = FIRST(A) = {a,c},第一个就是 X k X_k Xk?
FIRST(Bq) = FIRST(B) - {ε} U FIRST(q) = {d,q},第二个就是 X k X_k Xk?

更多例子:FIRST(a)集合

2.FOLLOW集合

(1)定义3.11

非终结符A的FOLLOW集合如下:
F O L L O W ( A ) = { a ∣ S = ? > . . . A a . . . , a ∈ T } FOLLOW(A) = \{a |S=*>...Aa...,a∈T\} FOLLOW(A)={ aS=?>...Aa...aT}

若A是某句型的最右符号,则 # ∈ F O L L O W ( A ) \#∈FOLLOW(A) #FOLLOW(A)

解析:
A的FOLLOW集合,就是从开始符号可以导出的所有含A的文法符号序列中紧跟A之后的终结符

(2)算法3.6

  • 输入:文法G
  • 输出:G中所有非终结符的FOLLOW集合
  • 方法:
  1. 加入#到FOLLOW(S),其中S是开始符号,#是输入结束标记
  2. 若有产生式A→αB,则FOLLOW(A)的全体加入到FOLLOW(B)
  3. 若有产生式A→αBβ
    ①先将 F I R S T ( β ) \color{blue}FIRST(β) FIRST(β) 除ε外的全体加入到FOLLOW(B)
    ②然后判断如果 ε ∈ F I R S T ( β ) \color{blue}ε∈FIRST(β) εFIRST(β) ,则将 F O L L O W ( A ) \color{blue}FOLLOW(A) FOLLOW(A)的全体加入到FOLLOW(B)
    【先first,再follow,都是FOLLOW(A)】

解析:
这个α可以是终结符,也可以是非终结符(S→AB,那么FOLLOW(B)=FOLLOW(S)),我们只关心后面的β。
规则1只对开始符号起作用

(3)例子

例3.22 计算非终结符的FIRST与FOLLOW。
L →E;L|ε(1)
E →TE'(2)
E'→+TE'|-TE'|ε(3)
T →FT'(4)
T'→*FT'|/FT'|mod FT'|ε(5)
F →(E)|id|num(6)

自下而上计算FIRST(倒着,倒数第一)
自上而下计算FOLLOW(顺着FOLLOW)

解:

FIRST(F)  =	{
    ( id num}
FIRST(T') =	{
    * / mod ε}
FIRST(T)  = FIRST(F) =	{
    ( id num}
FIRST(E') =	{
    + - ε}
FIRST(E)  = FIRST(T) = FIRST(F) = {
    ( id num}
FIRST(L)  = {
    ε}FIRST(E) = {
    ε ( id num} FOLLOW(L)  = {
    #}							// 规则1
FOLL0W(E)  = {
    ) ;}							// (1)(6)规则3①
FOLLOW(E') = FOLL0W(E) = {
    ) ;}				// (2)(3)规则2
FOLLOW(T)  = {
    + - ) ;}						// (2)(3)规则3①{+ -}和②{) ;}
FOLLOW(T') = FOLLOW(T) = {
    +  -  ; )}		// (4)(5)规则2
FOLLOW(F)  = {
    * / mod + - ) ;} 				// (4)(5)规则3①{* / mod}和②{+ - ) ;}

3.算法3.7 构造预测分析表

  • 输入:文法G
  • 输出:分析表M
  • 方法:
  1. 对文法的每个产生式A→α,执行2和3;
    (分析表的行首是每个产生式的左部非终结符,列首是每个终结符和#)
    注意列首中没有ε那一列,ε列要填产生式相关部分就是ε,会和FOLLOW集填入的ε冲突。所以ε就要看有没有填入FOLLOW列就知道】
  2. F I R S T ( α ) \color{blue}FIRST(α) FIRST(α)的每个终结符a,加入 产 生 式 右 部 相 关 部 分 \color{red}产生式右部相关部分 到M[A,a];
  3. ε ∈ F I R S T ( α ) \color{blue}ε∈FIRST(α) εFIRST(α),则对 F O L L O W ( A ) \color{blue}FOLLOW(A) FOLLOW(A)的每个终结符b(包括#),加入 ε \color{red}ε ε到M[A,b];
  4. M中其它没有定义的条目均是error。

例:
L →E;L|ε(1)
E →TE'(2)
E'→+TE'|-TE'|ε(3)
T →FT'(4)
T'→*FT'|/FT'|mod FT'|ε(5)
F →(E)|id|num(6)

FIRST(F/T/E)= {
    (  id  num}
FIRST(T')   = {
    *  /  mod ε}
FIRST(E')   = {
    +  - ε}
FIRST(L)    = {
    ε (  id  num}
FOLLOW(L)   = {
    #}
FOLL0W(E/E')= {
    ) ;}
FOLLOW(T/T')= {
    +  -  ; )}
FOLLOW(F) = {
    +  -  *  /  mod  ) ;}  

在这里插入图片描述
比如F行,FIRST(F) = {( id num},比如列(,对应产生式是F→(E),将产生式右部相关部分(E)填入列(
比如T'行,FIRST(T') = {* / mod ε},填入对应的产生式右部相关部分后,有ε填FOLLOW,FOLLOW(T')= {+ - ; )},将这几列中填入ε

二、预测

已知某文法 G 如下所示,其中,S、A、B 为非终结符且 S 为开始符号。
G:S→ABA→aA |bA|εB→cB |ε
根据前面的计算结果说明在基于预测分析器的语法分析过程中,当要展开的非终结符为A时,如何根据输入的下一个终结符选择具体的候选项。

FIRST(B) = {
    c, ε}
FIRST(A) = {
    a, b, ε} 
FIRST(S) = {
    a, b, c, ε} FOLLOW(S) = {
    #} 
FOLLOW(A) = {
    c, #} 
FOLLOW(B) = {
    #}

若输入为 a 则按照 aA 展开;【产生式,很好理解,这是FIRST集中的a】
若输入为 b 则按照 bA;【产生式,很好理解,这是FIRST集中的b】
若输入为 c 或#则按照ε展开。【A产生式展开不出c或#开头的,那就展开成ε,要给剩下的非终结符展开去匹配。这就是FOLLOW集的意义。】