笔记分享: 哈尔滨工业大学CS31002编译原理——02. 语法分析

文章目录

  • [1. \textbf{1. } 1. 自顶向下分析](#1. \textbf{1. } 1. 自顶向下分析)
    • [1.0. \textbf{1.0. } 1.0. 概述](#1.0. \textbf{1.0. } 1.0. 概述)
    • [1.1. \textbf{1.1. } 1.1. 第一步: 文法转换](#1.1. \textbf{1.1. } 1.1. 第一步: 文法转换)
    • [1.2. \textbf{1.2. } 1.2. 第二步: `FOLLOW/SELECT/FIRST`集](#1.2. \textbf{1.2. } 1.2. 第二步: FOLLOW/SELECT/FIRST集)
    • [1.3. \textbf{1.3. } 1.3. 第三步: 判定 LL(1) \textbf{LL(1)} LL(1)文法](#1.3. \textbf{1.3. } 1.3. 第三步: 判定 LL(1) \textbf{LL(1)} LL(1)文法)
    • [1.4. \textbf{1.4. } 1.4. 第四步: LL(1) \textbf{LL(1)} LL(1)文法的预测分析](#1.4. \textbf{1.4. } 1.4. 第四步: LL(1) \textbf{LL(1)} LL(1)文法的预测分析)
  • [2. \textbf{2. } 2. 自底向上分析](#2. \textbf{2. } 2. 自底向上分析)
    • [2.1. \textbf{2.1. } 2.1. 总论](#2.1. \textbf{2.1. } 2.1. 总论)
      • [2.1.1. \textbf{2.1.1. } 2.1.1. 移入规约分析](#2.1.1. \textbf{2.1.1. } 2.1.1. 移入规约分析)
      • [2.1.2. LR \textbf{2.1.2. LR} 2.1.2. LR分析法概述](#2.1.2. LR \textbf{2.1.2. LR} 2.1.2. LR分析法概述)
    • [2.2. \textbf{2.2. } 2.2. 分析法](#2.2. \textbf{2.2. } 2.2. 分析法)
      • [2.2.1. LR(0) \textbf{2.2.1. LR(0)} 2.2.1. LR(0)分析](#2.2.1. LR(0) \textbf{2.2.1. LR(0)} 2.2.1. LR(0)分析)
      • [2.2.2. SLR \textbf{2.2.2. SLR} 2.2.2. SLR分析](#2.2.2. SLR \textbf{2.2.2. SLR} 2.2.2. SLR分析)
      • [2.2.3. LR(1) \textbf{2.2.3. LR(1)} 2.2.3. LR(1)分析](#2.2.3. LR(1) \textbf{2.2.3. LR(1)} 2.2.3. LR(1)分析)
      • [2.2.4. LALR \textbf{2.2.4. LALR} 2.2.4. LALR分析](#2.2.4. LALR \textbf{2.2.4. LALR} 2.2.4. LALR分析)
    • [2.3. \textbf{2.3. } 2.3. 补充](#2.3. \textbf{2.3. } 2.3. 补充)

编译原理哈工大(陈鄞)第四章

1. \textbf{1. } 1. 自顶向下分析

1.0. \textbf{1.0. } 1.0. 概述

1️⃣最左 & \& &最右推导

  1. 最左推导:总选句型中最左边的非终结符进行替换,开始符 S S S最左推导得到的 S ⇒ l m ∗ α S{{\Rightarrow}^*_{lm}\alpha} S⇒lm∗α称为最左句型 α \alpha α
  2. 最右推导:总选句型中最右边的非终结符进行替换( aka \text{aka} aka规范推导),同样得到的句型称为最右句型
  3. 唯一性:给定一个分析树其对应的推导不一定唯一,但是对应的最左 / / /最右推导一定唯一

3️⃣递归下降分析:计算机处理自顶向下分析的通用形式

  1. 要素:由一组过程组成,每个非终结符对应一个过程
  2. 过程:以非终结符 A → X 1 X 2 , ... , X k A{\to}X_1X_2,{\ldots},X_k A→X1X2,...,Xk为例,便利 X 1 X_1 X1到 X k X_k Xk分为三种情况处理
    • X i X_i Xi是非终结符:递归地调用非终结符 X i X_i Xi对应的过程
    • X i X_i Xi是终结符:分为两种情况
      • X i X_i Xi等于当前的输入符号串:读取下一个输入符号
      • X i X_i Xi不是当前的输入符号串:发生错误,需要回溯到 A A A尝试 A A A的另一个候选式
  3. 判定:从开始符 S S S不断递归调用文法中非终结符对应的过程,如果能成功扫描完某串则语法分析成功

4️⃣预测分析:递归下降分析的一个特例

  1. 第一步:构造文法 + \text{+} +文法转换,后者是为了消除二义性 / / /左递归 / / /回溯
  2. 第二步:得到每个产生式的 SELECT \text{SELECT} SELECT集,这一过程涉及对每个变量 FIRST/FOLLOW \text{FIRST/FOLLOW} FIRST/FOLLOW集的计算
  3. 第三步:检查是不是 LL(1) \text{LL(1)} LL(1)文法,若是则构造预测分析表
  4. 第四步:递归或者非递归的预测分析

1.1. \textbf{1.1. } 1.1. 第一步: 文法转换

1️⃣自顶向下分析中遇到的问题

  1. 公共前缀:同一非终结符的多个候选式存在共同前缀,将导致回溯

    txt 复制代码
    示例文法: S->aAd|aBe, A->c, B->b
    示例输入: abe
    回溯过程: S->aAd->acd❌开始回溯, S->aBe->abe✅匹配成功
  2. 无限循环:左递归文法会使递归下降分析器陷入无限循环

    txt 复制代码
    示例文法: E->E+T|E-T|T, T->T*F|T/F|F, F->(E)|id
    示例输入: id+id*id
    递推示例: E⇒E+T⇒E+T+T⇒E+T+T+T....
    • 直接左递归:文法含有A->Aα形式产生式,即经过一步推导能产生左递归
    • 间接左递归:文法通过两步及以上推导能产生左递归,例如 S ⇒ S → A a A a ⇒ A → B b B b a ⇒ B → S c S c b a S{\xRightarrow{S{\to}Aa}}Aa{\xRightarrow{A{\to}Bb}}Bba{\xRightarrow{B{\to}Sc}}Scba SS→Aa AaA→Bb BbaB→Sc Scba
    • 左递归文法:文法中 A A A(直接或间接)导出以 A A A为前缀的串,即 A ⇒ + A a A{\xRightarrow{+}}Aa A+ Aa(其中 ⇒ + {\xRightarrow{+}} + 表示一或多步推导)

2️⃣左递归的消除

  1. 消除直接左递归:将左递归变右递归
    • 简单形式: A → A α ∣ β A{\to}A\alpha{\mid}\beta A→Aα∣β等价于 A ⇒ β α α . . . α A{{\Rightarrow}}\beta\alpha\alpha{...}\alpha A⇒βαα...α等价于 { A → β A ′ A ′ → α A ′ ∣ ε \begin{cases}A{\to}\beta{}A'\\\\ A'{\to}\alpha{A'}{\mid}\varepsilon\end{cases} ⎩ ⎨ ⎧A→βA′A′→αA′∣ε,示例如下
    • 一般形式 A → A α 1 ∣ A α 2 ∣ . . . ∣ A α n ∣ β 1 ∣ β 2 ∣ . . . ∣ β m A{\to}A\alpha_1{\mid}A\alpha_2{\mid}...{\mid}A\alpha_n{\mid}\beta_1{\mid}\beta_2{\mid}...{\mid}\beta_m A→Aα1∣Aα2∣...∣Aαn∣β1∣β2∣...∣βm等价于 { A → β 1 A ′ ∣ β 2 A ′ ∣ . . . ∣ β m A ′ A ′ → α 1 A ′ ∣ α 2 A ′ ∣ . . . ∣ α n A ′ ∣ ε \begin{cases}A{\to}\beta_1{}A'{\mid}\beta_2{}A'{\mid}...{\mid}\beta_m{}A'\\\\A'{\to}\alpha_1{A'}{\mid}\alpha_2{A'}{\mid}...{\mid}\alpha_n{A'}{\mid}\varepsilon\end{cases} ⎩ ⎨ ⎧A→β1A′∣β2A′∣...∣βmA′A′→α1A′∣α2A′∣...∣αnA′∣ε
  2. 消除间接左递归:用代入法转化为直接左递归,示例如下
    • 代入:对产生式 S → A a ∣ b , A → A c ∣ S d ∣ ε S{\to}Aa{\mid}b,A{\to}Ac{\mid}Sd{\mid}\varepsilon S→Aa∣b,A→Ac∣Sd∣ε,将 S S S的定义带入 A A A产生式得 A → A c ∣ A a d ∣ b d ∣ ε A{\to}Ac{\mid}Aad{\mid}bd{\mid}\varepsilon A→Ac∣Aad∣bd∣ε
    • 消除:遵循对直接左递归的处理方式,得到 { A → b d A ′ ∣ A ′ A ′ → c A ′ ∣ a d A ′ ∣ ε \begin{cases}A{\to}bdA'{\mid}A'\\\\ A'{\to}c{A'}{\mid}ad{A'}{\mid}\varepsilon\end{cases} ⎩ ⎨ ⎧A→bdA′∣A′A′→cA′∣adA′∣ε

3️⃣公共前缀的消除:提取左公因子

  1. 一般形式: A → α β 1 ∣ α β 2 ∣ . . . ∣ α β n ∣ γ 1 ∣ γ 2 ∣ . . . ∣ γ m A{\to}\alpha\beta_1{\mid}\alpha\beta_2{\mid}...{\mid}\alpha\beta_n{\mid}\gamma_1{\mid}\gamma_2{\mid}...{\mid}\gamma_m A→αβ1∣αβ2∣...∣αβn∣γ1∣γ2∣...∣γm等价于 { A → α A ′ ∣ γ 1 ∣ γ 2 ∣ . . . ∣ γ m A ′ → β 1 ∣ β 2 ∣ . . . ∣ β n \begin{cases}A{\to}\alpha{A'}{\mid}\gamma_1{\mid}\gamma_2{\mid}...{\mid}\gamma_m\\\\A'{\to}\beta_1{\mid}\beta_2{\mid}...{\mid}\beta_n\end{cases} ⎩ ⎨ ⎧A→αA′∣γ1∣γ2∣...∣γmA′→β1∣β2∣...∣βn
  2. 核心思想:改写产生式来推迟决定,等读入了足够多的输入再做出正确的选择

1.2. \textbf{1.2. } 1.2. 第二步: FOLLOW/SELECT/FIRST

1️⃣文法符号串 α \alpha α(即终结符 / / /非终结符序列)的串首终结符集 FIRST ( α ) \text{FIRST}(\alpha) FIRST(α)

  1. FIRST ( α ) \text{FIRST}(\alpha) FIRST(α)意义:考虑从 α \alpha α出发导出的所有字符串, FIRST ( α ) \text{FIRST}(\alpha) FIRST(α)即这些串的第一个终结符的集

    • 特殊情况:如果 α ⇒ ∗ ε \alpha{{\Rightarrow}^*}\varepsilon α⇒∗ε则将 ε \varepsilon ε加入 FIRST ( α ) \text{FIRST}(\alpha) FIRST(α)
  2. FIRST ( α ) \text{FIRST}(\alpha) FIRST(α)规则:取串首终结符,若可推导出空则顺延看下一个

    规则 触发条件 计算规则
    规则 1 1 1 α \alpha α为单终结符 a a a或 ε \varepsilon ε FIRST ( α ) = { a } \text{FIRST}(\alpha) {= }\{a\} FIRST(α)={a}或 { ε } \{\varepsilon\} {ε}
    规则 2 2 2 α \alpha α为单非终结符 A A A 遍历 A A A产生式 A → β 1 ∣ β 2 ∣ . . . A{\to}β_1{\mid}β_2{\mid}... A→β1∣β2∣..., FIRST ( A ) = ⋃ i FIRST ( β i ) \text{FIRST}(A) {=} \bigcup_i \text{FIRST}(β_i) FIRST(A)=⋃iFIRST(βi)
    规则 3 3 3 α \alpha α为符号串 X 1 X 2 . . . X_1X_2... X1X2... 1. FIRST ( α ) ← 无条件 加入 FIRST ( X 1 ) ∖ { ε } \text{FIRST}(\alpha){\xleftarrow[无条件]{加入}}\text{FIRST}(X_1){\setminus}\{\varepsilon\} FIRST(α)加入 无条件FIRST(X1)∖{ε} 2. FIRST ( α ) ← 若 ε ∈ FIRST ( X 1 ) 加入 FIRST ( X 2 ) ∖ { ε } \text{FIRST}(\alpha){\xleftarrow[若\varepsilon{\in}\text{FIRST}(X_1)]{加入}}\text{FIRST}(X_2){\setminus}\{\varepsilon\} FIRST(α)加入 若ε∈FIRST(X1)FIRST(X2)∖{ε} 3. FIRST ( α ) ← 若 ε ∈ FIRST ( X 1 ) 且 ε ∈ FIRST ( X 2 ) 加入 FIRST ( X 3 ) ∖ { ε } \text{FIRST}(\alpha){\xleftarrow[\substack{若\varepsilon{\in}\text{FIRST}(X_1)\\且\varepsilon{\in}\text{FIRST}(X_2)}]{加入}}\text{FIRST}(X_3){\setminus}\{\varepsilon\} FIRST(α)加入 若ε∈FIRST(X1)且ε∈FIRST(X2)FIRST(X3)∖{ε} 4. FIRST ( α ) ← 到 ε ∉ FIRST ( X i ) 停止加入 FIRST ( X i ) ∖ { ε } \text{FIRST}(\alpha){\xleftarrow[到\varepsilon{\notin}\text{FIRST}(X_i)]{停止加入}}\text{FIRST}(X_i){\setminus}\{\varepsilon\} FIRST(α)停止加入 到ε∈/FIRST(Xi)FIRST(Xi)∖{ε} 5. FIRST ( α ) ← 所有FIRST ( X i ) 都包含 ε 加入 { ε } \text{FIRST}(\alpha){\xleftarrow[所有\text{FIRST}(X_i)都包含\varepsilon]{加入}}\{\varepsilon\} FIRST(α)加入 所有FIRST(Xi)都包含ε{ε}

2️⃣非终结符 A A A的后继符号集 FOLLOW ( A ) \text{FOLLOW}(A) FOLLOW(A)

  1. FOLLOW ( A ) \text{FOLLOW}(A) FOLLOW(A)意义:文法推导中,紧跟在非终结符 A A A后面的终结符集合

  2. FOLLOW ( A ) \text{FOLLOW}(A) FOLLOW(A)规则:起始加$, 向右看FIRST, 到头继承父FOLLOW

    规则 触发条件 加入 FOLLOW ( A ) \textbf{FOLLOW}\boldsymbol{(A)} FOLLOW(A)
    规则 1 1 1 A A A是开始符 / / /某个句型的最右符号 \\texttt{}$
    规则 2 2 2 B → α A β B{\to}\alpha{A}\beta B→αAβ FIRST ( β ) \ { ε } \text{FIRST}(\beta)\backslash\{\varepsilon\} FIRST(β)\{ε}
    规则 3 3 3 B → α A β B{\to}\alpha{A}\beta B→αAβ且 FIRST ( β ) \text{FIRST}(\beta) FIRST(β)包含 ε \varepsilon ε FOLLOW ( B ) \text{FOLLOW}(B) FOLLOW(B)
    规则 4 4 4 B → α A B{\to}\alpha{A} B→αA FOLLOW ( B ) \text{FOLLOW}(B) FOLLOW(B)
  3. 示例:文法的 FIRST / FOLLOW \text{FIRST}/\text{FOLLOW} FIRST/FOLLOW综合示例

3️⃣产生式 A → β A{\to}\beta A→β的可选集 SELECT ( A → β ) \text{SELECT}(A{\to}\beta) SELECT(A→β)

  1. SELECT ( A → β ) \text{SELECT}(A{\to}\beta) SELECT(A→β)意义:一个终结符集合,当输入流读到集合中的终结符时,必须用 A → β A{\to}\beta A→β推导

  2. SELECT ( A → β ) \text{SELECT}(A{\to}\beta) SELECT(A→β)规则:右部不含空取 FIRST \text{FIRST} FIRST,若含空则并上 FOLLOW \text{FOLLOW} FOLLOW

    规则 触发条件 SELECT ( A → β ) \textbf{SELECT}\boldsymbol{(A{\to}\beta)} SELECT(A→β)
    规则 1 1 1 ε ∉ FIRST ( β ) \varepsilon{\notin}\text{FIRST}(\beta) ε∈/FIRST(β) FIRST ( β ) \text{FIRST}(\beta) FIRST(β)
    规则 2 2 2 ε ∈ FIRST ( β ) \varepsilon{\in}\text{FIRST}(\beta) ε∈FIRST(β) ( FIRST ( β ) \ { ε } ) ∪ FOLLOW ( A ) (\text{FIRST}(\beta)\backslash\{\varepsilon\}){\cup}\text{FOLLOW}(A) (FIRST(β)\{ε})∪FOLLOW(A)
  3. 示例:同样文法每个产生式的 SELECT \text{SELECT} SELECT示例

1.3. \textbf{1.3. } 1.3. 第三步: 判定 LL(1) \textbf{LL(1)} LL(1)文法

txt 复制代码
S-文法 ⊂ q-文法 ⊂ LL(1)文法 ⊂ 无二义性文法 ⊂ 上下文无关文法 ⊂ 所有文法

1️⃣ S - S\text{-} S-文法:

  1. 限制:产生式右部以终结符开始,同一非终结符 A A A的各候选式的首个终结符相异
  2. 意义:文法无二义性(分析过程无需回溯),无法包含空产生式(严重限制了处理能力)

2️⃣ q - q\text{-} q-文法:

  1. 限制:每个产生式的右部或为 ε \varepsilon ε或以不同终结符开始,最多只能有一个产生式右部为 ε \varepsilon ε
  2. 意义:保留无二义性且表达能力更强(允许空产生式),但仍无法处理左递归文法

3️⃣ LL(1) \text{LL(1)} LL(1)文法:

  1. 限制:具有相同左部的产生式的 SELECT \text{SELECT} SELECT集互不相交

  2. 意义:实现高效 / / /确定 / / /无回溯的自顶向下预测分析,名称具体意义见下表

    名称 含义
    第一个 L L L 从左到右扫描分析输入的字符串
    第二个 L L L 优先替换当前句型中最左边的那个非终结符,即最左推导
    ( 1 ) (1) (1) 解析的每一步,解析器只需要向前看 1 1 1个输入符号,即确定所选产生式
  3. 补充: LL(1) \text{LL(1)} LL(1)的预测分析表,即非终结符 + {+} +输入符号 → 预测 SELECT集 \xrightarrow[预测]{\text{SELECT}集} SELECT集 预测所采用的产生式

    • 文法的 SELECT \text{SELECT} SELECT集:
    • 预测分析表:

1.4. \textbf{1.4. } 1.4. 第四步: LL(1) \textbf{LL(1)} LL(1)文法的预测分析

1️⃣递归的预测分析法

  1. 示例:考虑如下的文法

    txt 复制代码
    (1) <PROGRAM>  ->  program<DECLIST>:<TYPE>;<STLIST>end
    (2) <DECLIST>  ->  id<DECLISTN>
    (3) <DECLISTN> ->  ,id<DECLISTN>
    (4) <DECLISTN> ->  ε
    (5) <STLIST>   ->  s<STLISTN>
    (6) <STLISTN>  ->  ;s<STLISTN>
    (7) <STLISTN>  ->  ε
    (8) <TYPE>     ->  real
    (9) <TYPE>     ->  int
  2. 核心:如果符号是终结符则与当前输入符号对比(不匹配则报错),如果是非终结符则调用其对应过程

    • 处理整个输入 TOKEN \text{TOKEN} TOKEN

      C 复制代码
      program DESCENT;
      	GETNEXT(TOKEN);
      	PROGRAM(TOKEN);
      	GETNEXT(TOKEN);
      	if TOKEN≠'$' then ERROR;
         if TOKEN='$' then SUCCESS;
    • 处理<PROGRAM>产生式

      C 复制代码
      procedure PROGRAM(TOKEN);
      	if TOKEN≠'program' then ERROR;
      	GETNEXT(TOKEN);
          
      	DECLIST(TOKEN);
      	GETNEXT(TOKEN);
          
      	if TOKEN≠':' then ERROR;
      	GETNEXT(TOKEN);
          
      	TYPE(TOKEN);
      	GETNEXT(TOKEN);
          
      	if TOKEN≠';' then ERROR;
      	GETNEXT(TOKEN);
          
      	STLIST(TOKEN);
      	GETNEXT(TOKEN);
          
      	if TOKEN≠'end' then ERROR;
    • 处理<DECLISTN>产生式

      C 复制代码
      procedure DECLISTN(TOKEN);
      	if TOKEN =',' then
      		GETNEXT(TOKEN);
      		if TOKEN≠'id' then ERROR;
      		if TOKEN='id' then CONTINUE;
      		GETNEXT(TOKEN);
      		DECLISTN(TOKEN);
      	else if TOKEN≠':' then ERROR; //<DECLISTN>->ε的SELECT集为{:}
    • 处理<TYPE>产生式

      C 复制代码
      procedure TYPE(TOKEN);
      	if TOKEN≠'real' or TOKEN≠'int'
      	then ERROR;

2️⃣非递归的预测分析法

  1. PDA \text{PDA} PDA:即下推自动机,就是有穷自动机 + {+} +一个栈(用于记忆输入内容),用于非递归的预测
  2. 示例:参考如下文法及其预测分析表
    • 文法的 SELECT \text{SELECT} SELECT集
    • 预测分析表
    • 基于 PDA \text{PDA} PDA的过程:输出的产生式序列就是一个最左推导
      栈 剩余输入 行为 输出 E id+id\*id 开始符入栈 栈顶 E + 指针 id → 预测分析表 输出产生式 E → T E ′ T E ′ id+id\*id E 出栈 T E ′ 入栈 栈顶 T + 指针 id → 预测分析表 输出产生式 T → F T ′ F T ′ E ′ id+id\*id T 出栈 F T ′ 入栈 栈顶 F + 指针 id → 预测分析表 输出产生式 F → id id T ′ E ′ id+id\*id F 出栈 id 入栈 T ′ E ′ +id\*id id 匹配故 id 出栈 栈顶 T ′ + 指针 + → 预测分析表 输出产生式 T ′ → ε E ′ +id\*id T ′ 出栈无进栈 栈顶 E ′ + 指针 + → 预测分析表 输出产生式 E ′ → + T E ′ + T E ′ +id\*id T ′ 出栈 + T E ′ 进栈 T E ′ id\*id + 匹配故 + 出栈 栈顶 T + 指针 id → 预测分析表 输出产生式 T → F T ′ F T ′ E ′ id\*id T 出栈 F T ′ 进栈 栈顶 F + 指针 id → 预测分析表 输出产生式 F → id id T ′ E ′ id\*id F 出栈 id 入栈 T ′ E ′ \*id id 匹配故 id 出栈 栈顶 T ′ + 指针 * → 预测分析表 输出产生式 T ′ → * F T ′ * F T ′ E ′ \*id T ′ 出栈 * F T ′ 进栈 F T ′ E ′ id * 匹配故 * 出栈 栈顶 F + 指针 id → 预测分析表 输出产生式 F → id id T ′ E ′ id F 出栈 id 入栈 T ′ E ′ id 匹配故 id 出栈 栈顶 T ′ + 指针 → 预测分析表 输出产生式 T ′ → ε E ′ T ′ 出栈无入栈 栈顶 E ′ + 指针 → 预测分析表 输出产生式 E ′ → ε E ′ 出栈无入栈 分析结束 \begin{array}{rrll} \hline\text{栈} & \text{剩余输入} & \text{行为} & \text{输出} \\ \hline E\texttt{\} \& \\texttt{id+id\*id} \\texttt{\\} &开始符入栈& 栈顶E{+}指针\texttt{id}{\xrightarrow{预测分析表}}输出产生式E{\to}TE'\\ TE'\texttt{\} \& \\texttt{id+id\*id} \\texttt{\\} &E出栈TE'入栈&栈顶T{+}指针\texttt{id}{\xrightarrow{预测分析表}}输出产生式T{\to}FT' \\ FT'E'\texttt{\} \& \\texttt{id+id\*id} \\texttt{\\} & T出栈FT'入栈 &栈顶F{+}指针\texttt{id}{\xrightarrow{预测分析表}}输出产生式F{\to}\texttt{id}\\ \texttt{id}T'E'\texttt{\} \& \\texttt{id+id\*id} \\texttt{\\} & F出栈\texttt{id}入栈 &\\ T'E'\texttt{\} \& \\texttt{+id\*id} \\texttt{\\} & \texttt{id}匹配故\texttt{id}出栈 & 栈顶T'{+}指针\texttt{+}{\xrightarrow{预测分析表}}输出产生式T'{\to}\varepsilon \\ E'\texttt{\} \& \\texttt{+id\*id} \\texttt{\\} & T'出栈无进栈 & 栈顶E'{+}指针\texttt{+}{\xrightarrow{预测分析表}}输出产生式E'{\to}\texttt{+}TE' \\ \texttt{+}TE'\texttt{\} \& \\texttt{+id\*id} \\texttt{\\} &T'出栈\texttt{+}TE'进栈 \\ TE'\texttt{\} \& \\texttt{id\*id} \\texttt{\\} & \texttt{+}匹配故\texttt{+}出栈& 栈顶T{+}指针\texttt{id}{\xrightarrow{预测分析表}}输出产生式T{\to}FT' \\ FT'E'\texttt{\} \& \\texttt{id\*id} \\texttt{\\} &T出栈FT'进栈&栈顶F{+}指针\texttt{id}{\xrightarrow{预测分析表}}输出产生式F{\to}\texttt{id} \\ \texttt{id}T'E'\texttt{\} \& \\texttt{id\*id} \\texttt{\\} &F出栈\texttt{id}入栈 \\ T'E'\texttt{\} \& \\texttt{\*id} \\texttt{\\} &\texttt{id}匹配故\texttt{id}出栈& 栈顶T'{+}指针\texttt{*}{\xrightarrow{预测分析表}}输出产生式T'{\to}\texttt{*}FT' \\ \texttt{*}FT'E'\texttt{\} \& \\texttt{\*id} \\texttt{\\} &T'出栈\texttt{*}FT'进栈& \\ FT'E'\texttt{\} \& \\texttt{id} \\texttt{\\} &\texttt{*}匹配故\texttt{*}出栈& 栈顶F{+}指针\texttt{id}{\xrightarrow{预测分析表}}输出产生式F{\to}\texttt{id}\\ \texttt{id}T'E'\texttt{\} \& \\texttt{id} \\texttt{\\} & F出栈\texttt{id}入栈\\ T'E'\texttt{\} \& \\texttt{\\} &\texttt{id}匹配故\texttt{id}出栈& 栈顶T'{+}指针\texttt{\}{\\xrightarrow{预测分析表}}输出产生式T'{\\to}\\varepsilon \\\\ E'\\texttt{\\} & \texttt{\} \& T'出栈无入栈\&栈顶E'{+}指针\\texttt{\\}{\xrightarrow{预测分析表}}输出产生式E'{\to}\varepsilon \\ \texttt{\} \& \\texttt{\\} & E'出栈无入栈 & 分析结束\\ \hline\end{array} 栈ETE′FT′E′idT′E′T′E′E′+TE′TE′FT′E′idT′E′T′E′\*FT′E′FT′E′idT′E′T′E′E′剩余输入id+id\*idid+id*idid+id\*idid+id*id+id\*id+id*id+id\*idid*idid\*idid*id\*id*ididid$$$$行为开始符入栈E出栈TE′入栈T出栈FT′入栈F出栈id入栈id匹配故id出栈T′出栈无进栈T′出栈+TE′进栈+匹配故+出栈T出栈FT′进栈F出栈id入栈id匹配故id出栈T′出栈*FT′进栈*匹配故*出栈F出栈id入栈id匹配故id出栈T′出栈无入栈E′出栈无入栈输出栈顶E+指针id预测分析表 输出产生式E→TE′栈顶T+指针id预测分析表 输出产生式T→FT′栈顶F+指针id预测分析表 输出产生式F→id栈顶T′+指针+预测分析表 输出产生式T′→ε栈顶E′+指针+预测分析表 输出产生式E′→+TE′栈顶T+指针id预测分析表 输出产生式T→FT′栈顶F+指针id预测分析表 输出产生式F→id栈顶T′+指针*预测分析表 输出产生式T′→*FT′栈顶F+指针id预测分析表 输出产生式F→id栈顶T′+指针预测分析表 输出产生式T′→ε栈顶E′+指针预测分析表 输出产生式E′→ε分析结束
  3. 补充:非递归的预测分析的错误检测与恢复(恐慌模式)
    • 同步词法单元:可将非终结符的 FOLLOW \text{FOLLOW} FOLLOW集作为同步词法单元集,放入预测分析表

    • 分析表的使用:如何处理三种情况的错误

      错误 描述 操作
      类型 1 1 1 栈顶的终结符和输入符号不匹配 弹出栈顶的终结符
      类型 2 2 2 栈顶非终结符和输入定位到分析表空单元 忽略输入符号
      类型 3 3 3 栈顶非终结符和输入定位到分析表synch 弹出栈顶的非终结符
    • 分析示例:
      栈 剩余输入 行为 输出 E +id\*+id 开始符入栈 栈顶 E + 指针 + → 预测分析表 { } E id\*+id 忽略 + 指针右移 栈顶 E + 指针 id → 预测分析表 产生式 E → T E ′ T E ′ id\*+id E 出栈 T E ′ 入栈 栈顶 T + 指针 id → 预测分析表 产生式 T → F T ′ F T ′ E ′ id\*+id T 出栈 F T ′ 入栈 栈顶 F + 指针 id → 预测分析表 产生式 F → id id T ′ E ′ id\*+id F 出栈 id 入栈 T ′ E ′ \*+id id 匹配故出栈 栈顶 T ' + 指针 * → 预测分析表 产生式 T ′ → * F T ′ * F T ′ E ′ \*+id T ′ 出栈 * F T ′ 入栈 F T ′ E ′ +id * 匹配故出栈 栈顶 F + 指针 + → 预测分析表 synch T ′ E ′ +id 弹出栈顶 F 栈顶 T ′ + 指针 + → 预测分析表 产生式 T ′ → ε E ′ +id T ′ 出栈无入栈 栈顶 E ′ + 指针 + → 预测分析表 产生式 E ′ → + T E ′ + T E ′ +id E ′ 出栈 + T E ′ 入栈 T E ′ id + 匹配故出栈 栈顶 T + 指针 id → 预测分析表 产生式 T → F T ′ F T ′ E ′ id T 出栈 F T ′ 入栈 栈顶 F + 指针 id → 预测分析表 产生式 F → id id T ′ E ′ id F 出栈 id 入栈 T ′ E ′ id 匹配故出栈 栈顶 T ′ + 指针 → 预测分析表 产生式 T ′ → ε E ′ T ′ 出栈无入栈 栈顶 E ′ + 指针 → 预测分析表 产生式 E ′ → ε E ′ 出栈无入栈 分析结束 \begin{array}{rrll} \hline\text{栈} & \text{剩余输入} & \text{行为} & \text{输出} \\ \hline E\texttt{\} \& \\texttt{+id\*+id} \\texttt{\\} &开始符入栈& \textcolor{red}{栈顶E{+}指针\texttt{+}{\xrightarrow{预测分析表}}\{\}}\\ E\texttt{\} \& \\texttt{id\*+id} \\texttt{\\} &忽略\texttt{+}指针右移& 栈顶E{+}指针\texttt{id}{\xrightarrow{预测分析表}}产生式E{\to}TE'\\ TE'\texttt{\} \& \\texttt{id\*+id} \\texttt{\\} &E出栈TE'入栈& 栈顶T{+}指针\texttt{id}{\xrightarrow{预测分析表}}产生式T{\to}FT'\\ FT'E'\texttt{\} \& \\texttt{id\*+id} \\texttt{\\} &T出栈FT'入栈& 栈顶F{+}指针\texttt{id}{\xrightarrow{预测分析表}}产生式F{\to}\texttt{id}\\ \texttt{id}T'E'\texttt{\} \& \\texttt{id\*+id} \\texttt{\\} &F出栈\texttt{id}入栈& \\ T'E'\texttt{\} \& \\texttt{\*+id} \\texttt{\\} &\texttt{id}匹配故出栈&栈顶T'{+}指针\texttt{*}{\xrightarrow{预测分析表}}产生式T'{\to}\texttt{*}FT' \\ \texttt{*}FT'E'\texttt{\} \& \\texttt{\*+id} \\texttt{\\} &T'出栈\texttt{*}FT'入栈&\\ FT'E'\texttt{\} \& \\texttt{+id} \\texttt{\\} &\texttt{*}匹配故出栈&\textcolor{red}{栈顶F{+}指针\texttt{+}{\xrightarrow{预测分析表}}\texttt{synch}}\\ T'E'\texttt{\} \& \\texttt{+id} \\texttt{\\} &弹出栈顶F&栈顶T'{+}指针\texttt{+}{\xrightarrow{预测分析表}}产生式T'{\to}\varepsilon\\ E'\texttt{\} \& \\texttt{+id} \\texttt{\\} &T'出栈无入栈&栈顶E'{+}指针\texttt{+}{\xrightarrow{预测分析表}}产生式E'{\to}\texttt{+}TE'\\ \texttt{+}TE'\texttt{\} \& \\texttt{+id} \\texttt{\\} &E'出栈\texttt{+}TE'入栈&\\ TE'\texttt{\} \& \\texttt{id} \\texttt{\\} &\texttt{+}匹配故出栈&栈顶T{+}指针\texttt{id}{\xrightarrow{预测分析表}}产生式T{\to}FT'\\ FT'E'\texttt{\} \& \\texttt{id} \\texttt{\\} &T出栈FT'入栈&栈顶F{+}指针\texttt{id}{\xrightarrow{预测分析表}}产生式F{\to}\texttt{id}\\ \texttt{id}T'E'\texttt{\} \& \\texttt{id} \\texttt{\\} &F出栈\texttt{id}入栈&\\ T'E'\texttt{\} \&\\texttt{\\} &\texttt{id}匹配故出栈&栈顶T'{+}指针\texttt{\}{\\xrightarrow{预测分析表}}产生式T'{\\to}\\varepsilon \\\\ E'\\texttt{\\} & \texttt{\} \& T'出栈无入栈\&栈顶E'{+}指针\\texttt{\\}{\xrightarrow{预测分析表}}产生式E'{\to}\varepsilon \\ \texttt{\} \& \\texttt{\\} & E'出栈无入栈 & 分析结束\\\hline \end{array} 栈EETE′FT′E′idT′E′T′E′*FT′E′FT′E′T′E′E′+TE′TE′FT′E′idT′E′T′E′E′剩余输入+id\*+idid*+idid\*+idid*+idid\*+id*+id\*+id+id+id+id+idididid$$$$行为开始符入栈忽略+指针右移E出栈TE′入栈T出栈FT′入栈F出栈id入栈id匹配故出栈T′出栈*FT′入栈*匹配故出栈弹出栈顶FT′出栈无入栈E′出栈+TE′入栈+匹配故出栈T出栈FT′入栈F出栈id入栈id匹配故出栈T′出栈无入栈E′出栈无入栈输出栈顶E+指针+预测分析表 {}栈顶E+指针id预测分析表 产生式E→TE′栈顶T+指针id预测分析表 产生式T→FT′栈顶F+指针id预测分析表 产生式F→id栈顶T'+指针*预测分析表 产生式T′→*FT′栈顶F+指针+预测分析表 synch栈顶T′+指针+预测分析表 产生式T′→ε栈顶E′+指针+预测分析表 产生式E′→+TE′栈顶T+指针id预测分析表 产生式T→FT′栈顶F+指针id预测分析表 产生式F→id栈顶T′+指针预测分析表 产生式T′→ε栈顶E′+指针预测分析表 产生式E′→ε分析结束

2. \textbf{2. } 2. 自底向上分析

2.1. \textbf{2.1. } 2.1. 总论

2.1.1. \textbf{2.1.1. } 2.1.1. 移入规约分析

1️⃣整体流程:

  1. 操作:将输入符号逐个加入栈中,直到栈顶可以并进行规约(本质上是在最左规约 / / /最右推导逆过程)
  2. 输出:不断重复以上过程,直至输出接收(栈只剩开始符)或错误(其他情况)

2️⃣流程示例:

  1. 文法: E → E + E / E → E * / E → ( E ) / E → id E{\to}E\texttt{+}E/E{\to}E\texttt{*}/E{\to}\texttt{(}E\texttt{)}/E{\to}\texttt{id} E→E+E/E→E*/E→(E)/E→id
  2. 过程:见下表
    栈 剩余输入 行为 规约的产生式 规约的句柄 规范句型 id+(id+id) 移入 id+(id+id) id +(id+id) 规约 E → id id id+(id+id) E +(id+id) 移入 E +(id+id) E + (id+id) 移入 E +(id+id) E +( id+id) 移入 E +(id+id) E +(id +id) 规约 E → id id E +(id+id) E +( E +id) 移入 E +( E +id) E +( E + id) 移入 E +( E +id) E +( E +id ) 规约 E → id id E +( E +id) E +( E + E ) 规约 E → E + E E + E E +( E + E ) E +( E ) 移入 E +( E ) E +( E ) 规约 E → ( E ) ( E ) E +( E ) E + E 规约 E → E + E E + E E + E E 结束 E \begin{array}{lrll}\hline \text{栈} & \text{剩余输入} & \text{行为} & \text{规约的产生式}& \text{规约的句柄} & \text{规范句型}\\ \hline \texttt{\} \& \\texttt{id+(id+id)} \\texttt{\\} &移入& &&\texttt{\id+(id+id)\\} \\ \texttt{\id} \& \\texttt{+(id+id)} \\texttt{\\} &规约& E{\to}\texttt{id}&\texttt{id} &\texttt{\id+(id+id)\\}\\ \texttt{\}E \& \\texttt{+(id+id)} \\texttt{\\} &移入& & &\texttt{\}E\\texttt{+(id+id)\\}\\ \texttt{\}E\\texttt{+} \& \\texttt{(id+id)} \\texttt{\\} &移入& &&\texttt{\}E\\texttt{+(id+id)\\} \\ \texttt{\}E\\texttt{+(} \& \\texttt{id+id)} \\texttt{\\} &移入& &&\texttt{\}E\\texttt{+(id+id)\\} \\ \texttt{\}E\\texttt{+(id} \& \\texttt{+id)} \\texttt{\\} &规约& E{\to}\texttt{id}&\texttt{id} &\texttt{\}E\\texttt{+(id+id)\\}\\ \texttt{\}E\\texttt{+(}E \& \\texttt{+id)} \\texttt{\\} &移入& &&\texttt{\}E\\texttt{+(}E\\texttt{+id)\\} \\ \texttt{\}E\\texttt{+(}E\\texttt{+} \& \\texttt{id)} \\texttt{\\} &移入&&&\texttt{\}E\\texttt{+(}E\\texttt{+id)\\} \\ \texttt{\}E\\texttt{+(}E\\texttt{+id} \& \\texttt{)} \\texttt{\\} &规约& E{\to}\texttt{id}&\texttt{id} &\texttt{\}E\\texttt{+(}E\\texttt{+id)\\} \\ \texttt{\}E\\texttt{+(}E\\texttt{+}E \& \\texttt{)} \\texttt{\\} &规约& E{\to}E\texttt{+}E&E\texttt{+}E&\texttt{\}E\\texttt{+(}E\\texttt{+}E\\texttt{)\\} \\ \texttt{\}E\\texttt{+(}E\\texttt{}\& \\texttt{)\\} &移入&&&\texttt{\}E\\texttt{+(}E\\texttt{)\\} \\ \texttt{\}E\\texttt{+(}E\\texttt{)}\& \\texttt{\\} &规约& E{\to}\texttt{(}E\texttt{)}&\texttt{(}E\texttt{)} &\texttt{\}E\\texttt{+(}E\\texttt{)\\}\\ \texttt{\}E\\texttt{+}E\& \\texttt{\\} &规约& E{\to}E\texttt{+}E&E\texttt{+}E &\texttt{\}E\\texttt{+}E\\texttt{\\}\\ \texttt{\}E\& \\texttt{\\} &结束&&&\texttt{\}E\\texttt{\\} \\\hline\end{array} 栈$$idEE+E+(E+(idE+(EE+(E+E+(E+idE+(E+EE+(EE+(E)E+EE剩余输入id+(id+id)+(id+id)+(id+id)(id+id)id+id)+id)+id)id))))$$$$行为移入规约移入移入移入规约移入移入规约规约移入规约规约结束规约的产生式E→idE→idE→idE→E+EE→(E)E→E+E规约的句柄idididE+E(E)E+E规范句型id+(id+id)id+(id+id)E+(id+id)E+(id+id)E+(id+id)E+(id+id)E+(E+id)E+(E+id)E+(E+id)E+(E+E)E+(E)E+(E)E+EE

3️⃣潜在问题:

  1. 描述:存在一些情况可以识别出多个句柄(句柄识别冲突),无法识别出正确的句柄会导致分析失败
    • 文法:<S> -> var<IDS>:<T> / / /<IDS> -> i / / /<IDS> -> <IDS>,i / / /<T> -> real|int
    • 分析:左边为错误的句柄识别,右边为正确的
  2. 解决:选择句型的最左直接短语,作为句柄
    • 句型:栈中的内容 + + +剩余的输入串,此处为$var<IDS>,i_B:real$
    • 短语:直接短语的集合 ⊆ \subseteq ⊆产生式右部集合,此直接短语从左到右<IDS>,i_B / / /i_B / / /real
    • 最左:句型中存在多个直接短语时,只取最左边的那个,此处为<IDS>,i_B即为所选定的句柄

2.1.2. LR \textbf{2.1.2. LR} 2.1.2. LR分析法概述

1️⃣ LR \text{LR} LR文法的基本概念

  1. LR \text{LR} LR文法的意义:最大的,可以构造出相应移入归约语法分析器的文法类

  2. LR ( k ) \text{LR}(k) LR(k)的含义:

    成分 含义
    L L L 对输入进行从左到右的扫描
    R R R 反向构造出一个最右推导序列
    ( k ) (k) (k) 需要向前看 k k k个输入符号,默认 k = 1 k{=}1 k=1

2️⃣ LR \text{LR} LR分析器(自动机):即 itemDFA \text{itemDFA} itemDFA

  1. 总体结构:栈分为了状态栈 + + +符号栈,分析表分为了动作表 + + +转移表
    • 分析表的构建: LR(0)/LR(1)/SLR/LALR \text{LR(0)/LR(1)/SLR/LALR} LR(0)/LR(1)/SLR/LALR分析
  2. 工作过程:根据栈顶 s s s与当前指针 a a a查阅 ACTION \text{ACTION} ACTION和 GOTO \text{GOTO} GOTO表中的内容
    • ACTION [ s m , a i ] = s x \text{ACTION}[s_m,a_i]{=}sx ACTION[sm,ai]=sx时 a i a_i ai移入符号串, x x x压入状态栈
      状态 状态栈 符号栈 剩余的输入序列 初始状态 s 0 a 1 a 2 . . . a i a i + 1 . . . a n 一般状态 s 0 s 1 . . . s m X 1 X 2 . . . X m a i a i + 1 . . . a n ACTION [ s m , a i ] = s x s 0 s 1 . . . s m x X 1 X 2 . . . X m a i a i + 1 . . . a n \begin{array}{cllr}\hline\text{状态}& \text{状态栈} & \text{符号栈} & \text{剩余的输入序列}\\ \hline 初始状态&s_0&\texttt{\}\&a_1a_2...a_ia_{i+1}...a_n\\texttt{\\}\\ 一般状态&s_0s_1...s_m&\texttt{\}X_1X_2...X_m\&a_ia_{i+1}...a_n\\texttt{\\}\\ \text{ACTION}[s_m,a_i]{=}sx&s_0s_1...s_mx&\texttt{\}X_1X_2...X_ma_i\&a_{i+1}...a_n\\texttt{\\} \\\hline\end{array} 状态初始状态一般状态ACTION[sm,ai]=sx状态栈s0s0s1...sms0s1...smx符号栈$$X1X2...XmX1X2...Xmai剩余的输入序列a1a2...aiai+1...anaiai+1...anai+1...an
    • ACTION [ s m , a i ] = r x \text{ACTION}[s_m,a_i]{=}rx ACTION[sm,ai]=rx时用第 x x x产生式 A → X m − ( k − 1 ) . . . X m A{\to}X_{m-(k-1)}...X_m A→Xm−(k−1)...Xm规约,加状态 GOTO [ s m − k , A ] = y \text{GOTO}[s_{m-k},A]{=}y GOTO[sm−k,A]=y
      状态 状态栈 符号栈 剩余的输入序列 初始状态 s 0 a 1 . . . a i a i + 1 . . . a n 一般状态 s 0 s 1 . . . s m − k . . . s m X 1 X 2 . . . X m − k . . . X m a i a i + 1 . . . a n ACTION [ s m , a i ] = r x s 0 s 1 . . . s m − k X 1 X 2 . . . X m − k A a i a i + 1 . . . a n GOTO [ s m − k , A ] = y s 0 s 1 . . . s m − k y X 1 X 2 . . . X m − k A a i a i + 1 . . . a n \begin{array}{cllr}\hline\text{状态}& \text{状态栈} & \text{符号栈} & \text{剩余的输入序列}\\ \hline 初始状态&s_0&\texttt{\}\&a_1...a_ia_{i+1}...a_n\\texttt{\\}\\ 一般状态&s_0s_1...s_{m-k}...s_m&\texttt{\}X_1X_2...X_{m-k}...X_m\&a_ia_{i+1}...a_n\\texttt{\\}\\ \text{ACTION}[s_m,a_i]{=}rx&s_0s_1...s_{m-k}&\texttt{\}X_1X_2...X_{m-k}A\&a_ia_{i+1}...a_n\\texttt{\\}\\ \text{GOTO}[s_{m-k},A]{=}y&s_0s_1...s_{m-k}y&\texttt{\}X_1X_2...X_{m-k}A\&a_ia_{i+1}...a_n\\texttt{\\} \\\hline\end{array} 状态初始状态一般状态ACTION[sm,ai]=rxGOTO[sm−k,A]=y状态栈s0s0s1...sm−k...sms0s1...sm−ks0s1...sm−ky符号栈$$X1X2...Xm−k...XmX1X2...Xm−kAX1X2...Xm−kA剩余的输入序列a1...aiai+1...anaiai+1...anaiai+1...anaiai+1...an
    • ACTION [ s m , a i ] = acc/err \text{ACTION}[s_m,a_i]{=}\text{acc/err} ACTION[sm,ai]=acc/err,表示分析成功或者出现语法错误
  3. 工作示例:文法 S → B B / B → a B / B → b S{\to}BB/B{\to}aB/B{\to}b S→BB/B→aB/B→b,输入 b a b bab bab
    • 分析表内容
    • 分析全过程
      状态栈 符号栈 输入 ACTION GOTO 操作 0 b a b ACTION[0,b]=s4 传输b/状态4进 04 b a b ACTION[4,a]=r3 B → b 约/出一状态 0 B a b GOTO[0,B]=2 状态2进 02 B a b ACTION[2,a]=s3 传输a/状态3进 023 B a b ACTION[3,b]=s4 传输b/状态4进 0234 B a b ACTION[4, \]=r3 B → b 约/状态4出 023 B a B GOTO\[3,B\]=6 状态6进 0236 B a B ACTION\[6, ]=r2 B → a B 约/出两状态 02 B B GOTO[2,B]=5 状态5进 025 B B ACTION[5, \]=r1 S → B B 约/出两状态 0 S GOTO\[0,S\]=1 状态1进 01 S ACTION\[1, ]=acc 接收 \begin{array}{llrlll}\hline\text{状态栈} & \text{符号栈} & \text{输入} & \text{ACTION} & \text{GOTO} & \text{操作} \\\hline0 & \texttt{\} \& bab\\texttt{\\} & \text{ACTION[0,b]=s4} & & \text{传输b/状态4进} \\04 & \texttt{\}b \& ab\\texttt{\\} & \text{ACTION[4,a]=r3} & & B{\to}b \text{约/出一状态} \\0 & \texttt{\}B \& ab\\texttt{\\} & & \text{GOTO[0,B]=2} & \text{状态2进} \\02 & \texttt{\}B \& ab\\texttt{\\} & \text{ACTION[2,a]=s3} & & \text{传输a/状态3进} \\023 & \texttt{\}Ba \& b\\texttt{\\} & \text{ACTION[3,b]=s4} & & \text{传输b/状态4进} \\0234 & \texttt{\}Bab \& \\texttt{\\} & \text{ACTION[4,\texttt{\}\]=r3} \& \& B{\\to}b \\text{约/状态4出} \\\\023 \& \\texttt{\\}BaB & \texttt{\} \& \& \\text{GOTO\[3,B\]=6} \& \\text{状态6进} \\\\0236 \& \\texttt{\\}BaB & \texttt{\} \& \\text{ACTION\[6,\\texttt{\\}]=r2} & & B{\to}aB \text{约/出两状态} \\02 & \texttt{\}BB \& \\texttt{\\} & & \text{GOTO[2,B]=5} & \text{状态5进} \\025 & \texttt{\}BB \& \\texttt{\\} & \text{ACTION[5,\texttt{\}\]=r1} \& \& S{\\to}BB \\text{约/出两状态} \\\\0 \& \\texttt{\\}S & \texttt{\} \& \& \\text{GOTO\[0,S\]=1} \& \\text{状态1进} \\\\01 \& \\texttt{\\}S & \texttt{\} \& \\text{ACTION\[1,\\texttt{\\}]=acc} & & \text{接收} \\\hline\end{array} 状态栈0040020230234023023602025001符号栈$$bBBBaBabBaBBaBBBBBSS输入bababababb$$$$$$$$ACTIONACTION[0,b]=s4ACTION[4,a]=r3ACTION[2,a]=s3ACTION[3,b]=s4ACTION[4,\]=r3ACTION\[6,]=r2ACTION[5,\]=r1ACTION\[1,]=accGOTOGOTO[0,B]=2GOTO[3,B]=6GOTO[2,B]=5GOTO[0,S]=1操作传输b/状态4进B→b约/出一状态状态2进传输a/状态3进传输b/状态4进B→b约/状态4出状态6进B→aB约/出两状态状态5进S→BB约/出两状态状态1进接收

2.2. \textbf{2.2. } 2.2. 分析法

2.2.1. LR(0) \textbf{2.2.1. LR(0)} 2.2.1. LR(0)分析

1️⃣产生式的 LR(0) \text{LR(0)} LR(0)项目:

  1. 含义:产生式的右部某位置加上一圆圈如 A → α 1 ⋅ α 2 A{\to}\alpha_1{\cdot}\alpha_2 A→α1⋅α2,产生式右部长度为 n n n时其会有 n + 1 n{+}1 n+1个项目

  2. 意义:描述了句柄识别的状态,如下三种

    类型 移进项目 待约项目 待约项目 归约项目
    示例 S → ⋅ b B B S{\to}{\cdot}bBB S→⋅bBB S → b ⋅ B B S{\to}b{\cdot}BB S→b⋅BB S → b B ⋅ B S{\to}bB{\cdot}B S→bB⋅B S → b B B ⋅ S{\to}bBB{\cdot} S→bBB⋅
    • 后继项目:同一个产生式中将圆点右移一个,例如 A → α ⋅ X β A{\to}\alpha{\cdot}{X}\beta A→α⋅Xβ的后继是 A → α X ⋅ β A{\to}\alpha{X}{\cdot}\beta A→αX⋅β

2️⃣文法中的 LR(0) \text{LR(0)} LR(0)项目

  1. 增广文法:添加一个新的开始符 S ′ S' S′并且令 S ′ → S S'{\to}S S′→S,从而使得分析器只有一个接收状态,示例如下

    产生式 项目
    S ′ → S S'{\to}S S′→S S ′ → ⋅ S / S ′ → S ⋅ S'{\to}{\cdot}S/S'{\to}S{\cdot} S′→⋅S/S′→S⋅
    S → B B S{\to}BB S→BB S → ⋅ B B / S → B ⋅ B / S → B B ⋅ S{\to}{\cdot}BB/S{\to}B{\cdot}B/S{\to}BB{\cdot} S→⋅BB/S→B⋅B/S→BB⋅
    B → a B B{\to}aB B→aB B → ⋅ a B / B → a ⋅ B / B → a B ⋅ B{\to}{\cdot}aB/B{\to}a{\cdot}B/B{\to}aB{\cdot} B→⋅aB/B→a⋅B/B→aB⋅
    B → b B{\to}b B→b B → ⋅ b / B → b ⋅ B{\to}{\cdot}b/B{\to}b{\cdot} B→⋅b/B→b⋅
  2. 初始 / / /接收项目:增广文法中唯一的 S ′ → ⋅ S S'{\to}{\cdot}S S′→⋅S以及 S ′ → S ⋅ S'{\to}S{\cdot} S′→S⋅

3️⃣ LR(0) \text{LR(0)} LR(0)的自动机

  1. 自动机的状态:文法中所有等价的项目是为一个项目集闭包,一个项目集闭包对应一个状态
    • 方法:对项目 A → α ⋅ X β A{\to}\alpha{\cdot}{X}\beta A→α⋅Xβ与产生式 X → γ X{\to}\gamma X→γ,则 A → α ⋅ X β A{\to}\alpha{\cdot}{X}\beta A→α⋅Xβ与 X → ⋅ γ X{\to}{\cdot}\gamma X→⋅γ等价

    • 示例:对项目 S → ⋅ B B S{\to}{\cdot}BB S→⋅BB,考虑产生式 B → a B B{\to}aB B→aB与 B → b B{\to}b B→b,则 B → ⋅ a B B{\to}{\cdot}aB B→⋅aB与 B → ⋅ b B{\to}{\cdot}b B→⋅b等价(同理得下表)

      状态 内核项目 项目集闭包
      I 0 I_0 I0 S ′ → ⋅ S S'{\to}{\cdot}S S′→⋅S CLOSURE ( I 0 ) = { S ′ → ⋅ S / S → ⋅ B B / B → ⋅ a B / B → ⋅ b } \text{CLOSURE}{(I_0)}{=}\{S'{\to}{\cdot}S/S{\to}{\cdot}BB/B{\to}{\cdot}aB/B{\to}{\cdot}b\} CLOSURE(I0)={S′→⋅S/S→⋅BB/B→⋅aB/B→⋅b}
      I 1 I_1 I1 S ′ → S ⋅ S'{\to}S{\cdot} S′→S⋅ CLOSURE ( I 1 ) = { S ′ → S ⋅ } \text{CLOSURE}{(I_1)}{=}\{S'{\to}S{\cdot}\} CLOSURE(I1)={S′→S⋅}
      I 2 I_2 I2 S → B ⋅ B S{\to}B{\cdot}B S→B⋅B CLOSURE ( I 2 ) = { S → B ⋅ B / B → ⋅ a B / B → ⋅ b } \text{CLOSURE}{(I_2)}{=}\{S{\to}B{\cdot}B/B{\to}{\cdot}aB/B{\to}{\cdot}b\} CLOSURE(I2)={S→B⋅B/B→⋅aB/B→⋅b}
      I 3 I_3 I3 B → a ⋅ B B{\to}a{\cdot}B B→a⋅B CLOSURE ( I 3 ) = { B → a ⋅ B / B → ⋅ a B / B → ⋅ b } \text{CLOSURE}{(I_3)}{=}\{B{\to}a{\cdot}B/B{\to}{\cdot}aB/B{\to}{\cdot}b\} CLOSURE(I3)={B→a⋅B/B→⋅aB/B→⋅b}
      I 4 I_4 I4 B → b ⋅ B{\to}b{\cdot} B→b⋅ CLOSURE ( I 4 ) = { B → b ⋅ } \text{CLOSURE}{(I_4)}{=}\{B{\to}b{\cdot}\} CLOSURE(I4)={B→b⋅}
      I 5 I_5 I5 S → B B ⋅ S{\to}BB{\cdot} S→BB⋅ CLOSURE ( I 5 ) = { S → B B ⋅ } \text{CLOSURE}{(I_5)}{=}\{S{\to}BB{\cdot}\} CLOSURE(I5)={S→BB⋅}
      I 6 I_6 I6 B → a B ⋅ B{\to}aB{\cdot} B→aB⋅ CLOSURE ( I 6 ) = { B → a B ⋅ } \text{CLOSURE}{(I_6)}{=}\{B{\to}aB{\cdot}\} CLOSURE(I6)={B→aB⋅}
    • 补充:自动机的状态的集合就是项集族 ,此处为 C = { I 1 , I 2 , . . . , I 6 } C{=}\{I_1,I_2,...,I_6\} C={I1,I2,...,I6}

  2. 状态的转换: GOTO ( I , X ) \text{GOTO}(I,X) GOTO(I,X)表示从状态 I I I接收符号 X X X后所到达的新状态
    • 方法:找出 CLOSURE ( I ) \text{CLOSURE}(I) CLOSURE(I)中所有形如 A → α ⋅ X β A{\to}\alpha{\cdot}X\beta A→α⋅Xβ的项目,把每个的圆点右移一位,进入新状态
    • 示例:示例文法所有的状态 + \text{+} +转换,构成的自动机

4️⃣ LR(0) \text{LR(0)} LR(0)的分析表构

  1. 构建规则

    类型 第一个条件 第二个条件 对表的操作
    移进 / / /待约项目 A → α ⋅ a β ∈ I i A{\to}\alpha{\cdot}a\beta{\in}I_i A→α⋅aβ∈Ii GOTO ( I i , a ) = I j \text{GOTO}(I_i,a){=}I_j GOTO(Ii,a)=Ij ACTION [ i , a ] = s j \text{ACTION}[i,a]{=}sj ACTION[i,a]=sj
    移进/待约项目 A → α ⋅ B β ∈ I i A{\to}\alpha{\cdot}B\beta{\in}I_i A→α⋅Bβ∈Ii GOTO ( I i , B ) = I j \text{GOTO}(I_i,B){=}I_j GOTO(Ii,B)=Ij GOTO [ i , B ] = j \text{GOTO}[i,B]{=}j GOTO[i,B]=j
    归约项目 A → α ⋅ ∈ I i ( A ≠ S ′ ) A{\to}\alpha{\cdot}{\in}I_i(A{\ne}S') A→α⋅∈Ii(A=S′) A → α ∈ I i A{\to}\alpha{\in}I_i A→α∈Ii产生式编号为 k k k ACTION [ i , ] = r k \text{ACTION}[i,]{=}rk ACTION[i,]=rk
    接收项目 S ′ → S ⋅ ∈ I i S'{\to}S{\cdot}{\in}I_i S′→S⋅∈Ii N/A \text{N/A} N/A ACTION [ i , \text{ACTION}[i, ACTION[i,$ ] = a c c ]{=}acc ]=acc
    • ACTION [ i , ] = r k \text{ACTION}[i,]{=}rk ACTION[i,]=rk表示,将状态 i i i在 ACTION \text{ACTION} ACTION表中所对应的所有终结符都设为 r k rk rk
  2. 构建示例:

5️⃣ LR(0) \text{LR(0)} LR(0)文法的含义

  1. LR(0) \text{LR(0)} LR(0)分析过程中的冲突
    • 移进 / / /归约冲突:自动机的某个状态,可以进行规约也可以进行移进,如图红色部分
    • 归约 / / /归约冲突:自动机的某一个状态,可以进行多种方式的规约,如图中左下角
  2. LR(0) \text{LR(0)} LR(0)文法: LR(0) \text{LR(0)} LR(0)分析过程中不会产生冲突的文法,可见 LR(0) \text{LR(0)} LR(0)文法 ⊆ {\subseteq} ⊆上下文无关文法

2.2.2. SLR \textbf{2.2.2. SLR} 2.2.2. SLR分析

1️⃣核心思想:利用 FOLLOW \text{FOLLOW} FOLLOW集消解冲突

  1. 情形:在状 I I I中,有 m m m个( i ∈ [ 1 , m ] i{\in}[1,m] i∈[1,m])移进项目 A i → α i ⋅ a i β i A_i{\to}\alpha_i{\cdot}a_i\beta_i Ai→αi⋅aiβi,以及 n n n个( i ∈ [ 1 , n ] i{\in}[1,n] i∈[1,n])规约项目 B i → γ i ⋅ B_i{\to}\gamma_{i}{\cdot} Bi→γi⋅
  2. 操作:如果 { a 1 , a 2 , . . . , a m } \{a_1,a_2,...,a_m\} {a1,a2,...,am}和 FOLLOW ( B 1 ) , FOLLOW ( B 2 ) , . . . , FOLLOW ( B n ) \text{FOLLOW}(B_1),\text{FOLLOW}(B_2),...,\text{FOLLOW}(B_n) FOLLOW(B1),FOLLOW(B2),...,FOLLOW(Bn)互不相交
    • 对当前输入符号 a a a,若 a ∈ { a 1 , a 2 , . . . , a m } a{\in}\{a_1,a_2,...,a_m\} a∈{a1,a2,...,am}则移进 a a a
    • 对当前输入符号 a a a,若 a ∈ FOLLOW ( B i ) a{\in}\text{FOLLOW}(B_i) a∈FOLLOW(Bi)则用产生式 B i → γ i B_i{\to}\gamma_i Bi→γi规约

2️⃣ SLR \text{SLR} SLR分析表:构造算法与示例

  1. 构造算法:对规约项目,区别于将行中每个元素都规约,只将 FOLLOW ( A ) \text{FOLLOW}(A) FOLLOW(A)对应元素规约

    类型 第一个条件 第二个条件 对表的操作
    移进 / / /待约项目 A → α ⋅ a β ∈ I i A{\to}\alpha{\cdot}a\beta{\in}I_i A→α⋅aβ∈Ii GOTO ( I i , a ) = I j \text{GOTO}(I_i,a){=}I_j GOTO(Ii,a)=Ij ACTION [ i , a ] = s j \text{ACTION}[i,a]{=}sj ACTION[i,a]=sj
    移进/待约项目 A → α ⋅ B β ∈ I i A{\to}\alpha{\cdot}B\beta{\in}I_i A→α⋅Bβ∈Ii GOTO ( I i , B ) = I j \text{GOTO}(I_i,B){=}I_j GOTO(Ii,B)=Ij GOTO [ i , B ] = j \text{GOTO}[i,B]{=}j GOTO[i,B]=j
    归约项目 A → α ⋅ ∈ I i ( A ≠ S ′ ) A{\to}\alpha{\cdot}{\in}I_i(A{\ne}S') A→α⋅∈Ii(A=S′) A → α ∈ I i A{\to}\alpha{\in}I_i A→α∈Ii产生式编号为 k k k a ∈ FOLLOW ( A ) a{\in}\text{FOLLOW}(A) a∈FOLLOW(A) ACTION [ i , a ] = r k \text{ACTION}[i,a]{=}rk ACTION[i,a]=rk
    接收项目 S ′ → S ⋅ ∈ I i S'{\to}S{\cdot}{\in}I_i S′→S⋅∈Ii N/A \text{N/A} N/A ACTION [ i , \text{ACTION}[i, ACTION[i,$ ] = a c c ]{=}acc ]=acc
  2. 构造示例:其中\\text{FOLLOW}(S'){=}{}/\text{FOLLOW}(T){=}{,b}/\\text{FOLLOW}(B){=}{d}

    • 在状态 I 2 I_2 I2中,三个 FOLLOW \text{FOLLOW} FOLLOW集以及 { B , T , a } \{B,T,a\} {B,T,a}互不相交
    • 假设 B → ε B{\to}\varepsilon B→ε是第四条产生式,由于 FOLLOW ( B ) = { d } \text{FOLLOW}(B){=}\{d\} FOLLOW(B)={d},所以 ACTION [ 2 , d ] = r 4 \text{ACTION}[2,d]{=}r4 ACTION[2,d]=r4
    • 假设 T → ε T{\to}\varepsilon T→ε是第二条产生式,由于\\text{FOLLOW}(T){=}{,b} ,所以 ,所以 ,所以\text{ACTION}[2,/b\]{=}r2

3️⃣ SLR \text{SLR} SLR文法:无冲突

  1. SLR \text{SLR} SLR冲突: FOLLOW \text{FOLLOW} FOLLOW集与 { a 1 , a 2 , . . . , a m } \{a_1,a_2,...,a_m\} {a1,a2,...,am}间有交集,或者 FOLLOW \text{FOLLOW} FOLLOW集互相间有交集
  2. SLR \text{SLR} SLR文法: SLR \text{SLR} SLR分析过程中不会产生冲突的文法,可见 LR(0) \text{LR(0)} LR(0)文法 ⊆ SLR {\subseteq}\text{SLR} ⊆SLR文法

2.2.3. LR(1) \textbf{2.2.3. LR(1)} 2.2.3. LR(1)分析

0️⃣对 SLR \text{SLR} SLR的重新思考

  1. 潜在问题: SLR \text{SLR} SLR中当下一输入符 a ∈ FOLLOW ( A ) a{\in}\text{FOLLOW}(A) a∈FOLLOW(A)就用 A → α A{\to}\alpha A→α规约,但这只是规约的必要条件
  2. 潜在方案:特定位置 A A A后继可能是 FOLLOW ( A ) \text{FOLLOW}(A) FOLLOW(A)子集,故规约条件变为 a ∈ FOLLOW ( A ) a{\in}\text{FOLLOW}(A) a∈FOLLOW(A)子集

1️⃣规范 LR(1) \text{LR(1)} LR(1)项目

  1. 形式: [ A → α ⋅ β , a ] [A{\to}\alpha{\cdot}\beta,a] [A→α⋅β,a]其中 A → α β A{\to}\alpha\beta A→αβ是产生式, a a a是终结符(包括$$ ) ) )\text{aka} 展望符, 展望符, 展望符,a$长为 1 1 1即 LR(1) \text{LR(1)} LR(1)中 1 1 1来源
  2. 含义: a a a总是 FOLLOW ( A ) \text{FOLLOW}(A) FOLLOW(A)的真子集,在规约时起作用
    • 对移入项: [ A → α ⋅ β , a ] [A{\to}\alpha{\cdot}\beta,a] [A→α⋅β,a]且 β ≠ ε \beta{\neq}\varepsilon β=ε中,展望符 a a a没有任何作用
    • 对规约符: [ A → α ⋅ , a ] [A{\to}\alpha{\cdot},a] [A→α⋅,a],只有在下一个输入符号为 a a a时,才按照 A → a A{\to}a A→a进行规约

2️⃣ LR(1) \text{LR(1)} LR(1)的自动机

  1. 自动机的状态:文法中所有等价的项目是为一个项目集闭包,一个项目集闭包对应一个状态
    • 方法:对项目 [ A → α ⋅ B β , a ] [A{\to}\alpha{\cdot}{B}\beta,a] [A→α⋅Bβ,a]与产生式 B → γ B{\to}\gamma B→γ,则 [ A → α ⋅ B β , a ] [A{\to}\alpha{\cdot}{B}\beta,a] [A→α⋅Bβ,a]与 [ B → γ , b ] [B{\to}\gamma,b] [B→γ,b]等价, b b b值如下表

      条件 备注
      β ⇒ + ε \beta{{\Rightarrow}^+}\varepsilon β⇒+ε b = a b{=}a b=a直接继承 继承的后继符
      其他情况 b ∈ FIRST ( β a ) b{\in}\text{FIRST}(\beta{a}) b∈FIRST(βa) 自生的后继符
    • 示例:考虑文法 S ′ → S / S → L = R / S → R / L → ∗ R / L → id / R → L S'{\to}S/S{\to}L{=}R/S{\to}R/L{\to}{*}R/L{\to}\text{id}/R{\to}L S′→S/S→L=R/S→R/L→∗R/L→id/R→L,状态 I 0 I_0 I0构造如下
      步 加入操作 说明 1 [ S ′ → ⋅ S , \] 初始项目,其后必跟 2 [ S → ⋅ L = R , \] / \[ S → ⋅ R , ] 基于 [ S ′ → ⋅ S , \] 考虑 S 俩产生式, ⋅ S 后为空故继承 3 [ L → ⋅ ∗ R , = ] / [ L → ⋅ id , = ] 基于 [ S → ⋅ L = R , \] 考虑 L 俩产生式, ⋅ L 后为 = 故生 = 4 \[ R → ⋅ L , ] 基于 [ S → ⋅ R , \] 考虑 R 产生式, ⋅ R 后为空故继承 5 [ L → ⋅ ∗ R , \] / \[ L → ⋅ id , ] 基于 [ R → ⋅ L , \] 考虑 L 俩产生式, ⋅ L 后为空故继承 \begin{array}{cll}\hline\text{步} & \text{加入操作} & \text{说明} \\\hline1 & [S'{\to}{\cdot}S,\texttt{\}\] \& \\text{初始项目,其后必跟}\\texttt{\\} \\2 & [S{\to}{\cdot}L{=}R,\texttt{\}\]/\[S{\\to}{\\cdot}R,\\texttt{\\}] & \text{基于}[S'{\to}{\cdot}S,\texttt{\}\]\\text{考虑}S\\text{俩产生式,}{\\cdot}S\\text{后为空故继承}\\texttt{\\} \\3 & [L{\to}{\cdot}{*}R,{=}]/[L{\to}{\cdot}\text{id},{=}] & \text{基于}[S{\to}{\cdot}L{=}R,\texttt{\}\]\\text{考虑}L\\text{俩产生式,}{\\cdot}L\\text{后为}{=}\\text{故生}{=} \\\\4 \& \[R{\\to}{\\cdot}L,\\texttt{\\}] & \text{基于}[S{\to}{\cdot}R,\texttt{\}\]\\text{考虑}R\\text{产生式,}{\\cdot}R\\text{后为空故继承}\\texttt{\\} \\5 & [L{\to}{\cdot}{*}R,\texttt{\}\]/\[L{\\to}{\\cdot}\\text{id},\\texttt{\\}] & \text{基于}[R{\to}{\cdot}L,\texttt{\}\]\\text{考虑}L\\text{俩产生式,}{\\cdot}L\\text{后为空故继承}\\texttt{\\} \\\hline\end{array} 步12345加入操作[S′→⋅S,\]\[S→⋅L=R,]/[S→⋅R,\]\[L→⋅∗R,=\]/\[L→⋅id,=\]\[R→⋅L,][L→⋅∗R,\]/\[L→⋅id,]说明初始项目,其后必跟基于\[S′→⋅S,]考虑S俩产生式,⋅S后为空故继承基于\[S→⋅L=R,]考虑L俩产生式,⋅L后为=故生=基于[S→⋅R,\]考虑R产生式,⋅R后为空故继承基于[R→⋅L,\]考虑L俩产生式,⋅L后为空故继承

  2. 状态的转换:与 LR(0) \text{LR(0)} LR(0)完全一样, GOTO ( I , X ) \text{GOTO}(I,X) GOTO(I,X)表示从状态 I I I接收符号 X X X后所到达的新状态
    • 方法:找出 CLOSURE ( I ) \text{CLOSURE}(I) CLOSURE(I)中所有 A → α ⋅ X β A{\to}\alpha{\cdot}X\beta A→α⋅Xβ项目,把圆点右移一位(展望符不变),进入新状态
    • 示例:示例文法所有的状态 + \text{+} +转换,构成的自动机
    • 补充:除展望符外两个 LR(1) \text{LR(1)} LR(1)项目集相同,则这俩 LR(1) \text{LR(1)} LR(1)的项目集(状态)是同心的

3️⃣ LR(0) \text{LR(0)} LR(0)的分析表构

  1. 构建规则:

    类型 第一个条件 第二个条件 对表的操作
    待约项目 [ A → α ⋅ a β , b ] ∈ I i [A{\to}\alpha{\cdot}a\beta,b]{\in}I_i [A→α⋅aβ,b]∈Ii GOTO ( I i , a ) = I j \text{GOTO}(I_i,a){=}I_j GOTO(Ii,a)=Ij ACTION [ i , a ] = s j \text{ACTION}[i,a]{=}sj ACTION[i,a]=sj
    待约项目 [ A → α ⋅ B β , b ] ∈ I i [A{\to}\alpha{\cdot}B\beta,b]{\in}I_i [A→α⋅Bβ,b]∈Ii GOTO ( I i , B ) = I j \text{GOTO}(I_i,B){=}I_j GOTO(Ii,B)=Ij GOTO [ i , B ] = j \text{GOTO}[i,B]{=}j GOTO[i,B]=j
    归约项目 [ A → α ⋅ , a ] ∈ I i ( A ≠ S ′ ) [A{\to}\alpha{\cdot},a]{\in}I_i(A{\ne}S') [A→α⋅,a]∈Ii(A=S′) A → α ∈ I i A{\to}\alpha{\in}I_i A→α∈Ii产生式编号为 k k k ACTION [ i , a ] = r k \text{ACTION}[i,a]{=}rk ACTION[i,a]=rk
    接收项目 S ′ → S ⋅ ∈ I i S'{\to}S{\cdot}{\in}I_i S′→S⋅∈Ii N/A \text{N/A} N/A ACTION [ i , \text{ACTION}[i, ACTION[i,$ ] = a c c ]{=}acc ]=acc
  2. 构建示例:上图自动机的分析表(节选)

2.2.4. LALR \textbf{2.2.4. LALR} 2.2.4. LALR分析

0️⃣重新思考 LR(1) \text{LR(1)} LR(1)文法

  1. 核心:通过引入展望符,将原来在 LR(0) \text{LR(0)} LR(0)中只有一个的状态,分裂出了不同但同心的状态
  2. 问题:状态数量会直接爆炸,如果两个状态的行为不存在冲突,是否可进行合并 ? ? ?( LALR \text{LALR} LALR分析)

1️⃣ LALR \text{LALR} LALR分析的基本思想

  1. 找 LL(1) \text{LL(1)} LL(1)中相同核心的项集:所谓相同核心 ,即状态中刨除展望符外构成的集合一样

    • 如图中 I 4 / I 11 I_4/I_{11} I4/I11及 I 7 / I 13 I_7/I_{13} I7/I13及 I 8 / I 10 I_8/I_{10} I8/I10及 I 5 / I 12 I_5/I_{12} I5/I12
  2. 合并具有相同核心的项集:如图所示

    同心项集 待替换 原状态转移(消除) 替换后状态转移 是否要构造
    I 4 / I 11 I_4/I_{11} I4/I11 I 11 I_{11} I11 I 11 → ∗ I 11 I_{11}{\xrightarrow{*}}I_{11} I11∗ I11 I 4 → ∗ I 4 I_{4}{\xrightarrow{*}}I_{4} I4∗ I4
    I 4 / I 11 I_4/I_{11} I4/I11 I 11 I_{11} I11 I 6 → ∗ I 11 I_6{\xrightarrow{*}}I_{11} I6∗ I11 I 6 → ∗ I 4 I_6{\xrightarrow{*}}I_{4} I6∗ I4
    I 5 / I 12 I_5/I_{12} I5/I12 I 12 I_{12} I12 I 11 → id I 12 I_{11}{\xrightarrow{\text{id}}}I_{12} I11id I12 I 4 → id I 5 I_{4}{\xrightarrow{\text{id}}}I_{5} I4id I5
    I 5 / I 12 I_5/I_{12} I5/I12 I 12 I_{12} I12 I 6 → id I 12 I_{6}{\xrightarrow{\text{id}}}I_{12} I6id I12 I 6 → id I 5 I_{6}{\xrightarrow{\text{id}}}I_{5} I6id I5
    I 8 / I 10 I_8/I_{10} I8/I10 I 10 I_{10} I10 I 6 → L I 10 I_{6}{\xrightarrow{L}}I_{10} I6L I10 I 6 → L I 8 I_{6}{\xrightarrow{L}}I_{8} I6L I8
    I 7 / I 13 I_7/I_{13} I7/I13 I 13 I_{13} I13 I 11 → R I 13 I_{11}{\xrightarrow{R}}I_{13} I11R I13 I 4 → R I 7 I_{4}{\xrightarrow{R}}I_{7} I4R I7
    • 删除第二列所有状态 & \& &第三列所有转换,构建第三列所有转换,即完成了 LR(1) → LARA \text{LR(1)}{\to}\text{LARA} LR(1)→LARA转换
  3. 构建状态表:和 LR(1) \text{LR(1)} LR(1)别无二致

2️⃣ LARA \text{LARA} LARA的特点

  1. 合并项集的影响
    • 可能会产生规约 - \text{-} -规约冲突,如下图 I 9 / I 6 I_9/I_6 I9/I6的合并;但不会带来规约 - \text{-} -移进的冲突
    • 当输入错误串,较未合并的 LR(1) \text{LR(1)} LR(1)分析,会使得错误的发现更晚更繁琐(合并后决策精度更模糊)
  2. LARA \text{LARA} LARA对比:形式同 LR(1) \text{LR(1)} LR(1),大小减到和 LR(0)/SLR \text{LR(0)/SLR} LR(0)/SLR相当,分析力 SLR<LALR(1)<LR(1) \text{SLR<LALR(1)<LR(1)} SLR<LALR(1)<LR(1)

2.3. \textbf{2.3. } 2.3. 补充

1️⃣二义性文法的 LR \text{LR} LR分析

  1. 文法: E → E + E / E → E ∗ E / E → ( E ) / E → id E{\to}E{+}E/E{\to}E{*}E/E{\to}(E)/E{\to}\text{id} E→E+E/E→E∗E/E→(E)/E→id,其中\\text{FOLLOW}(E){=}{{+},{\*},{)},}$
  2. 自动机:以 I 7 I_7 I7为例,出现移入规约冲突
    • 例如状态 I 7 I_7 I7中当前输入为 + {+} +:可规约也可移入,但是强行设置只能规约,冲突解决
    • 例如状态 I 7 I_7 I7中当前输入为 ∗ {*} ∗:可规约也可移入,但是强行设置只能移入,冲突解决

2️⃣ LR \text{LR} LR分析的错误处理(恐慌模式)

  1. 情形:状态栈 s 0 , s 1 , . . . , s i , s i + 1 , . . . , s m s_0,s_1,...,s_i,s_{i+1},...,s_m s0,s1,...,si,si+1,...,sm,符号栈 X 1 , . . . , X i , A , . . . , X m X_1,...,X_i,A,...,X_m X1,...,Xi,A,...,Xm
  2. 第一步:遇到错误后从状态栈自顶向下扫描
    • 定位到 s i s_i si状态,定位的依据是 s i s_i si对应符号栈的非终结符 A A A出发的 GOTO \text{GOTO} GOTO的目标
    • 认为这个 A A A推导出的串包含错误
  3. 第二步:丢弃若干输入符号,直到输入可以合法地跟在 A A A之后的符号 a a a为止,例如 C \text{C} C中的;
  4. 第三步:强行修改状态,将 s i + 1 = GOTO ( s i , A ) s_{i+1}{=}\text{GOTO}(s_i,A) si+1=GOTO(si,A)压入栈
相关推荐
_Coin_-40 分钟前
算法训练营DAY27 第八章 贪心算法 part01
算法·贪心算法
董董灿是个攻城狮5 小时前
5分钟搞懂什么是窗口注意力?
算法
KhalilRuan5 小时前
Unity-MMORPG内容笔记-其三
笔记
kfepiza6 小时前
Debian的`/etc/network/interfaces`的`allow-hotplug`和`auto`对比讲解 笔记250704
linux·服务器·网络·笔记·debian
qqxhb7 小时前
零基础数据结构与算法——第四章:基础算法-排序(上)
java·数据结构·算法·冒泡·插入·选择
FirstFrost --sy8 小时前
数据结构之二叉树
c语言·数据结构·c++·算法·链表·深度优先·广度优先
森焱森9 小时前
垂起固定翼无人机介绍
c语言·单片机·算法·架构·无人机
搂鱼1145149 小时前
(倍增)洛谷 P1613 跑路/P4155 国旗计划
算法
Yingye Zhu(HPXXZYY)9 小时前
Codeforces 2021 C Those Who Are With Us
数据结构·c++·算法