rhanqtlnuse

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

语法分析

Parser 分为两类:

  • 基于推导 —— 自顶向下
  • 基于规约 —— 自底向上

自顶向下分析(Top-Down Parsing)

主要解决的问题:当一个产生式有多个可选项(Alternatives)时,应该选择哪一个

对文法的预处理:

  • 提取最大公共左因子:
    • 例如产生式 \(A \rightarrow \alpha\beta\)\ |\ \(\alpha\gamma\),其中 \(\alpha\) 就是最大公共左因子,可以将它拆分为:\(A \rightarrow \alpha B\)\(B \rightarrow \beta\ |\ \gamma\)\(\alpha,\beta,\gamma \in (V_T \cup V_N)^*\)
  • 消除左递归
    • 左递归:形如 \(A \rightarrow A\alpha\ |\ \beta\)
    • 原因:如果不消除左递归,那么对于上面的产生式,可以得到:\(A \Rightarrow \beta \alpha^n\)\(A \Rightarrow \beta\),我们会发现,二者有公共左因子 \(\beta\)
    • 左递归的几种形式
      • 直接左递归(立即左递归):\(A \rightarrow A\alpha\ |\ \beta\)
        • 方法:变换为如下产生式:\(A \rightarrow \beta R\)\(R \rightarrow \alpha R\ |\ \epsilon\)
      • 间接左递归:\(P \rightarrow Aa\ |\ b\)\(A \rightarrow Pc\ |\ d\)
        • 方法:规定优先级,非终结符只能使用自己或者更低优先级的非终结符表示
      • 混合左递归:\(S \rightarrow Qc\ |\ c\ |\ Sd\)\(Q \rightarrow Rb\ |\ b\)\(R \rightarrow Sa\ |\ a\ |\ Qe\)
        • 方法:画出依赖关系,按照 “从内到外,从左到右” 的顺序化简

预测分析

基本步骤:

  • 如果栈顶是非终结符,那么查表找到表项 PPT(A, a)(Predict Parse Table,预测分析表)。如果非空,将产生式的右部逆序入栈(注意不读取下一个 token!);否则,失败
  • 如果栈顶是终结符,那么将其与输入的 token 匹配。如果能够匹配,则弹出栈顶终结符,并且读取下一个 token;否则,匹配失败(或进入错误处理)

构建预测分析表

构建预测分析表需要两个关键的函数:FIRST 和 FOLLOW

  • FIRST
    • 作用
      • 有多个可选项时,使用哪个可选项
      • 何时(读取到哪些 token 时)使用当前产生式
    • 步骤(产生式 \(A \rightarrow \alpha_1 \alpha_2 \alpha_3 \cdots\)
      1. 如果 X 是一个终结符,那么 FIRST(X) =
      2. 如果 X 是一个非终结符,并且有产生式 \(X \rightarrow Y_1Y_2 \cdots Y_k\)(其中 \(k \ge 1\))。如果 \(\epsilon \notin FIRST(Y_1)\),那么 \(FIRST(X) = FIRST(Y_1)\);否则如果 \(\epsilon \notin FIRST(Y_2)\)\(FIRST(X) = (FIRST(Y_1) - \{\epsilon\}) \cup FIRST(Y_2)\),以此类推
      3. 如果有产生式 \(X \rightarrow \epsilon\),那么将 \(\epsilon\) 加入 FIRST(X)
  • FOLLOW
    • 作用:处理 \(\epsilon\) - 产生式
    • 步骤
      1. 将 $ 加入 FOLLOW(S),其中 $ 是输入右端的结束标记
      2. 如果有产生式 \(A \rightarrow \alpha B \beta\),那么 \(FIRST(\beta)\) 中除 \(\epsilon\) 之外的所有符号都在 FOLLOW(B) 中
      3. 如果有产生式 \(A \rightarrow \alpha B\),或者有产生式 \(A \rightarrow \alpha B \beta\) 并且 \(\epsilon \in FIRST(\beta)\),那么 FOLLOW(A) 中所有的符号都在 FOLLOW(B) 中
        3.1 假设有产生式 \(S \stackrel{+}{\Longrightarrow} \eta A \theta \Rightarrow \eta \alpha B \beta \theta\),如果 \(\beta\)\(\epsilon\),那么 \(FOLLOW(B) = FIRST(\theta) = FOLLOW(A)\)

注意,此处求解 FIRST 和 FOLLOW 都要遵循 “最小集合原则”。比如文法:

 E -> T E'
E' -> + T E' | epsilon
 T -> F T'
T' -> * F T' | epsilon
 F -> ( E ) | id

FOLLOW(E') = FOLLOW(E) \(\cup\) FOLLOW(E'),按照集合的计算,FOLLOW(E) \(\subset\) FOLLOW(E'),但在这里,FOLLOW(E') = FOLLOW(E),即 FOLLOW(E') 是满足 FOLLOW(E) \(\subset\) FOLLOW(E') 的最小的集合,所以 FOLLOW(E') = FOLLOW(E) = { ), $}

更多资料

[1] 《Parsing Techniques》
[2] 《Parsing Techniques》读书笔记 - 目录

posted on 2018-10-22 20:22  rhanqtlnuse  阅读(410)  评论(0编辑  收藏  举报