编译原理4——自上而下的分析方法

  1. 消除左递归
  2. 消除回溯
  3. FIRST集合
    列写文法的FIRST集合
  4. FOLLOW集合
    列写文法的FOLLOW集合
  5. LL(1)文法
    判断是否是LL(1)文法
  6. LL(1)分析法
    根据FIRST集合写LL(1)分析树
    写分析子程序
    写预测分析表

4.1 语法分析器的功能

任务:在词法分析器识别出单词符号串的基础上,分析并判定语法结构是否符合语法规则

  1. 自上而下分析法
    归约,算符优先算法,LR分析法
  2. 自下而上分析法
    推导(第5章内容)

4.2 自上而下分析面临的问题

自上而下分析:
对任何输入串,试图用一切可能的办法,从文法开始符号(根结)出发,自上而下地为输入串建立一棵语法树
⋆ \star 实质上是一种不断试错的过程

  1. 回溯
    当新发展的子树无法满足字符串时,需要退掉子树,看是否还有其他候选
  2. 左递归
    类似 P ⇒ + P α P\xRightarrow{+}P\alpha P+ Pα的结构将使得分析陷入死循环
    简单说,当 P P P的其他子树无法满足字符串时,则 P P P会选择 P ⇒ + P α P\xRightarrow{+}P\alpha P+ Pα子树,但该子树的开头仍是 P P P,问题得不到根本解决,于是下一个 P P P又选择 P ⇒ + P α P\xRightarrow{+}P\alpha P+ Pα,开始死循环
  3. 选配成功是暂时的,如用 α ∗ ∗ β \alpha**\beta αβ去匹配 α ∗ i β \alpha*i\beta αiβ,需要复杂的回溯解决该问题
  4. 无法知道出错的确切位置
    ⋆ \star 上下文无关文法:2型文法
    ⋆ \star 有限自动机:3型文法

4.3 LL(1)分析法

自上而下的分析,试错过程占大头,LL(1)分析法就是要每次发展子树都明确应该发展哪个

  1. 问题留给本层
    1. 问题是留给子还是留给兄(留给兄,该子树发展 ε \varepsilon ε)(子兄选择不冲突FIRST和FOLLOW)
  2. 问题留给下一层子树
    1. 留给哪个子树(左提公共因子)(FIRST)
    2. 是否会绕一圈再抛回给自己(消除直接/间接左递归)

4.3.1 左递归的消除

  1. 消除直接左递归:
    P → P α ∣ β P\rightarrow P\alpha|\beta PPαβ
    替换为:
    P → β P ′ P ′ → α P ′ ∣ ε \begin{matrix}P\rightarrow\beta P'\\P'\rightarrow\alpha P'|\varepsilon\end{matrix} PβPPαPε
  2. 消除间接左递归:
    1. 间接左递归变直接左递归
    2. 消除直接左递归
      例:
      间接左递归语言: S → Q c ∣ c Q → R b ∣ b R → S a ∣ a \begin{matrix}S\rightarrow Qc|c\\Q\rightarrow Rb|b\\R\rightarrow Sa|a\end{matrix} SQccQRbbRSaa
      存在: S ⇒ Q c ⇒ R b c ⇒ S a b c S\Rightarrow Qc\Rightarrow Rbc\Rightarrow Sabc SQcRbcSabc(间接回溯)
      修改为: S → S a b c ∣ a b c ∣ b c ∣ c S\rightarrow Sabc|abc|bc|c SSabcabcbcc
      消除直接左递归: S → a b c S ′ ∣ b c S ′ ∣ c S ′ S ′ → a b c S ′ ∣ ε \begin{matrix}S\rightarrow abcS'|bcS'|cS'\\S'\rightarrow abcS'|\varepsilon\end{matrix} SabcSbcScSSabcSε

4.3.2 消除回溯、提左因子

目的:使得分析器能够根据面临输入符号准确指派执行任务(使得能根据待匹配字符去发展子树)

  1. F I R S T ( α ) FIRST(\alpha) FIRST(α)
    F I R S T ( α ) = { a ∣ α ⇒ ∗ a ⋯   , a ∈ V T } FIRST(\alpha)=\{a|\alpha\xRightarrow{*}a\cdots,a\in V_{T}\} FIRST(α)={aα a,aVT}
    ⋆ \star α ⇒ ∗ ε \alpha\xRightarrow{*}\varepsilon α ε,则 ε ∈ F I R S T ( α ) \varepsilon\in FIRST(\alpha) εFIRST(α)
    1. 消除回溯的条件
      F I R S T ( α i ) ∩ F I R S T ( α j ) = ϕ FIRST(\alpha_i)\cap FIRST(\alpha_j)=\phi FIRST(αi)FIRST(αj)=ϕ
  2. 提取公共左因子
    例:
    回溯语言: A → δ β 1 ∣ δ β 2 ∣ ⋯ ∣ δ β n ∣ γ 1 ∣ γ 2 ∣ ⋯ γ m A\rightarrow\delta\beta_1|\delta\beta_2|\cdots|\delta\beta_n|\gamma_1|\gamma_2|\cdots\gamma_m Aδβ1δβ2δβnγ1γ2γm
    提左因子: A → δ A ′ ∣ γ 1 ∣ γ 2 ∣ ⋯ ∣ γ m A ′ → β 1 ∣ β 2 ⋯ ∣ β n \begin{matrix}A\rightarrow\delta A'|\gamma_1|\gamma_2|\cdots|\gamma_m\\A'\rightarrow\beta_1|\beta_2\cdots|\beta_n\end{matrix} AδAγ1γ2γmAβ1β2βn

4.3.3 LL(1)分析条件

  1. F O L L O W ( A ) FOLLOW(A) FOLLOW(A)
    F O L L O W ( A ) = { a ∣ S ⇒ ∗ ⋯ A a ⋯   , a ∈ V T } FOLLOW(A)=\{a|S\xRightarrow{*}\cdots Aa\cdots,a\in V_T\} FOLLOW(A)={aS Aa,aVT}
    ⋆ \star S ⇒ ∗ ⋯ A S\xRightarrow{*}\cdots A S A,则 # ∈ F O L L O W ( A ) \#\in FOLLOW(A) #FOLLOW(A)
  2. 不带回溯的自上而下分析的文法(LL(1)文法)
    构造条件
    1. 不含左递归(出问题时不能把问题抛给子树中的自己)
    2. A → α 1 ∣ α 2 ∣ ⋯ ∣ α n A\rightarrow\alpha_1|\alpha_2|\cdots|\alpha_n Aα1α2αn,则 F I R S T ( α i ) ∩ F I R S T ( α j ) = ϕ FIRST(\alpha_i)\cap FIRST(\alpha_j)=\phi FIRST(αi)FIRST(αj)=ϕ(匹配上时只有一条子树可走)
    3. 若非终结符 A A A的某个候选首符集包含 ε \varepsilon ε,则 F I R S T ( A ) ∩ F O L L O W ( A ) = ϕ FIRST(A)\cap FOLLOW(A)=\phi FIRST(A)FOLLOW(A)=ϕ(必须明确给子还是给兄弟解决)
      策略
    4. a ∈ F I R S T ( α i ) a\in FIRST(\alpha_i) aFIRST(αi),则指派 α i \alpha_i αi去执行任务
    5. a a a不属于任何一个候选首符集,则:
      1. ε \varepsilon ε属于 F I R S T ( α i ) FIRST(\alpha_i) FIRST(αi) a ∈ F O L L O W ( A ) a\in FOLLOW(A) aFOLLOW(A),则让 A A A ϵ \epsilon ϵ自动匹配
      2. 否则, a a a出现是一种语法错误

4.4 递归下降分析程序构造

简单说就是按照上面的构造明确如何按照句子自上而下发展LL(1)语法分析树
另外引入了一个扩充巴克斯范式

  1. 递归下降分析器
    例:
    存在 E ′ → T E ′ ∣ ε E'\rightarrow TE'|\varepsilon ETEε
    1. E ′ E' E在匹配字符串的时候查询 F I R S T ( T ) FIRST(T) FIRST(T) F I R S T ( ε ) FIRST(\varepsilon) FIRST(ε),发现字符串待匹配首字母在 F I R S T ( T ) FIRST(T) FIRST(T)中,选择定义 E ′ → T E ′ E'\rightarrow TE' ETE
    2. 调用函数 T T T对字符串进行匹配
      1. T T T的终结符与字符串相互抵消
      2. T T T根据 F I R S T FIRST FIRST调用其定义(及定义其的非终结符)对字符串进行匹配
  2. 扩充的巴斯克范式
    巴克斯范式:
    1. → \rightarrow :定义为
    2. ∣ | :或
      ([[2.3 程序语言的语法描述]])
      扩充:
    3. 用花括号 { α } \{\alpha\} {α}表示闭包运算 α ∗ \alpha^* α
      ([[2.3 程序语言的语法描述]])
    4. { α } n 0 \{\alpha\}^0_n {α}n0表示任意重复 0 0 0次至 n n n次, { α } 0 0 = α 0 = ε \{\alpha\}_0^0=\alpha^0=\varepsilon {α}00=α0=ε
    5. 用方括号 [ α ] [\alpha] [α]表示 { α } 1 0 \{\alpha\}_1^0 {α}10,即表示 α \alpha α的出现可有可无(等价于 α ∣ ε \alpha|\varepsilon αε
      例:
      实数: d e c i m a l → [ s i g n ] i n t e g e r . { d i g i t } [ e x p o n e n t ] e x p o n e n t → E [ s i g n ] i n t e r g e r i n t e r g e r → d i g i t { d i g i t } s i g n → + ∣ − \begin{matrix}decimal\rightarrow[sign]integer.\{digit\}[exponent]\\exponent\rightarrow E[sign]interger\\interger\rightarrow digit\{digit\}\\sign\rightarrow +|-\end{matrix} decimal[sign]integer.{digit}[exponent]exponentE[sign]intergerintergerdigit{digit}sign+
      第一行定义浮点数整体
      第二行定义科学计数法部分
      第三行定义整数/小数的纯数字串部分
      第四行定义符号部分

4.5 预测分析程序

本质上就是4.4的延伸

  1. 分析表
    结构:
    1. 横坐标:待匹配的符号类型
    2. 纵坐标:待定义的非终结符
    3. 表内容:非终结符的定义/ERROR

  2. 符号栈:用于存放定义得来的待抵消的非终结符/终结符字符串
  3. 预测分析程序

4.5.1 预测分析程序工作过程

  1. 符号栈顶为终结符
    1. 符号栈顶终结符与字符串首进行抵消
  2. 符号栈顶为非终结符
    以字符串首字母为横坐标,以符号栈顶非终结符为纵坐标,查询预测分析表
    1. 内容为定义式
      弹出非终结符,从右向左读取定义,并压入符号栈
    2. 内容为空
      ERROR,匹配失败
  3. 符号栈顶为#,输入串为#
    匹配成功

4.5.2 预测分析表的构造

本质上是根据定义的 F I R S T FIRST FIRST来确定位置,如果 E E E的某一定义 P P P F I R S T FIRST FIRST中有终结符 α \alpha α,则将分析表中 ( α , E ) (\alpha,E) (α,E)位置设置为 P P P
具体操作:

  1. X ∈ V T X\in V_T XVT,则 F I R S T ( X ) = { X } FIRST(X)=\{X\} FIRST(X)={X}
  2. X ∈ V N X\in V_N XVN,且有产生式 X → a ⋯ X\rightarrow a\cdots Xa,则把 a a a加入到 F I R S T ( X ) FIRST(X) FIRST(X)中;若 X → ε X\rightarrow\varepsilon Xε也是一条产生式,则将 ε \varepsilon ε也加到 F I R S T ( X ) FIRST(X) FIRST(X)
  3. X → Y ⋯ X\rightarrow Y\cdots XY是一个产生式且 Y ∈ V N Y\in V_N YVN,则把 F I R S T ( Y ) FIRST(Y) FIRST(Y)中所有非 ε \varepsilon ε-元素都加到 F I R S T ( X ) FIRST(X) FIRST(X)中;若 X → Y 1 Y 2 ⋯ Y k X\rightarrow Y_1Y_2\cdots Y_k XY1Y2Yk是一个产生式, Y 1 , ⋯   , Y i − 1 Y_1,\cdots,Y_{i-1} Y1,,Yi1都是非终结符且 F I R S T FIRST FIRST中含有 ε \varepsilon ε,则将 F I R S T ( Y i ) FIRST(Y_i) FIRST(Yi)中的元素加入 F I R S T ( X ) FIRST(X) FIRST(X)中;若 Y 1 , ⋯   , Y k Y_1,\cdots,Y_{k} Y1,,Yk都是非终结符且 F I R S T FIRST FIRST中含有 ε \varepsilon ε,则将 ε \varepsilon ε加入 F I R S T ( X ) FIRST(X) FIRST(X)
    重复上述操作至集合不再发生变化
    递归查找各个非终结符的产生式也行
    ⋆ \star 如果已知文法是无二义的,则无需查看 F O L L O W FOLLOW FOLLOW集合
    ⋆ \star 如果文法 G G G是左递归或二义的,则 M M M至少含有一个多重入口

4.6 LL(1)分析中的错误处理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值