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

自顶向下与自底向上语法分析方法


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

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

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

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

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

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

  1. 要素:由一组过程组成,每个非终结符对应一个过程
  2. 过程:以非终结符 A → X 1 X 2 , … , X k A{\to}X_1X_2,{\ldots},X_k AX1X2,,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. 公共前缀:同一非终结符的多个候选式存在共同前缀,将导致回溯
    示例文法: S->aAd|aBe, A->c, B->b
    示例输入: abe
    回溯过程: S->aAd->acd❌开始回溯, S->aBe->abe✅匹配成功
    
  2. 无限循环:左递归文法会使递归下降分析器陷入无限循环
    示例文法: 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 SSAa AaABb BbaBSc 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 AAαβ等价于 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βAAαAε,示例如下
      image-20250616202420707
    • 一般形式 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 AAα1Aα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...βmAAα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 SAab,AAcSdε,将 S S S的定义带入 A A A产生式得 A → A c ∣ A a d ∣ b d ∣ ε A{\to}Ac{\mid}Aad{\mid}bd{\mid}\varepsilon AAcAadbdε
    • 消除:遵循对直接左递归的处理方式,得到 { 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} AbdAAAcAadAε

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综合示例
    image-20250616235649908

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示例
    image-20250617000245249

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

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集:
      image-20250617000245249
    • 预测分析表:
      image-20250617000741767

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

1️⃣递归的预测分析法

  1. 示例:考虑如下的文法
    (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
      program DESCENT;
      	GETNEXT(TOKEN);
      	PROGRAM(TOKEN);
      	GETNEXT(TOKEN);
      	if TOKEN≠’$’ then ERROR;
         if TOKEN=’$’ then SUCCESS;
      
    • 处理<PROGRAM>产生式
      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>产生式
      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>产生式
      procedure TYPE(TOKEN);
      	if TOKEN≠’real’ or TOKEN≠’int’
      	then ERROR;
      

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

  1. PDA \text{PDA} PDA:即下推自动机,就是有穷自动机 + {+} +一个栈(用于记忆输入内容),用于非递归的预测
    image-20250617115008915
  2. 示例:参考如下文法及其预测分析表
    • 文法的 SELECT \text{SELECT} SELECT
      image-20250617000245249
    • 预测分析表
      image-20250617000741767
    • 基于 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} E$TE$FTE$idTE$TE$E$+TE$TE$FTE$idTE$TE$*FTE$FTE$idTE$TE$E$$剩余输入id+id*id$id+id*id$id+id*id$id+id*id$+id*id$+id*id$+id*id$id*id$id*id$id*id$*id$*id$id$id$$$$行为开始符入栈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预测分析表 输出产生式ETE栈顶T+指针id预测分析表 输出产生式TFT栈顶F+指针id预测分析表 输出产生式Fid栈顶T+指针+预测分析表 输出产生式Tε栈顶E+指针+预测分析表 输出产生式E+TE栈顶T+指针id预测分析表 输出产生式TFT栈顶F+指针id预测分析表 输出产生式Fid栈顶T+指针*预测分析表 输出产生式T*FT栈顶F+指针id预测分析表 输出产生式Fid栈顶T+指针$预测分析表 输出产生式Tε栈顶E+指针$预测分析表 输出产生式Eε分析结束
  3. 补充:非递归的预测分析的错误检测与恢复(恐慌模式)
    • 同步词法单元:可将非终结符的 FOLLOW \text{FOLLOW} FOLLOW集作为同步词法单元集,放入预测分析表
      image-20250617144115842
    • 分析表的使用:如何处理三种情况的错误
      错误描述操作
      类型 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} E$E$TE$FTE$idTE$TE$*FTE$FTE$TE$E$+TE$TE$FTE$idTE$TE$E$$剩余输入+id*+id$id*+id$id*+id$id*+id$id*+id$*+id$*+id$+id$+id$+id$+id$id$id$id$$$$行为开始符入栈忽略+指针右移E出栈TE入栈T出栈FT入栈F出栈id入栈id匹配故出栈T出栈*FT入栈*匹配故出栈弹出栈顶FT出栈无入栈E出栈+TE入栈+匹配故出栈T出栈FT入栈F出栈id入栈id匹配故出栈T出栈无入栈E出栈无入栈输出栈顶E+指针+预测分析表 {}栈顶E+指针id预测分析表 产生式ETE栈顶T+指针id预测分析表 产生式TFT栈顶F+指针id预测分析表 产生式Fid栈顶T+指针*预测分析表 产生式T*FT栈顶F+指针+预测分析表 synch栈顶T+指针+预测分析表 产生式Tε栈顶E+指针+预测分析表 产生式E+TE栈顶T+指针id预测分析表 产生式TFT栈顶F+指针id预测分析表 产生式Fid栈顶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} EE+E/EE*/E(E)/Eid
  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} $$id$E$E+$E+($E+(id$E+(E$E+(E+$E+(E+id$E+(E+E$E+(E$E+(E)$E+E$E剩余输入id+(id+id)$+(id+id)$+(id+id)$(id+id)$id+id)$+id)$+id)$id)$)$)$)$$$$行为移入规约移入移入移入规约移入移入规约规约移入规约规约结束规约的产生式EidEidEidEE+EE(E)EE+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+E$$E$

3️⃣潜在问题:

  1. 描述:存在一些情况可以识别出多个句柄(句柄识别冲突),无法识别出正确的句柄会导致分析失败
    • 文法:<S> -> var<IDS>:<T> / / /<IDS> -> i / / /<IDS> -> <IDS>,i / / /<T> -> real|int
    • 分析:左边为错误的句柄识别,右边为正确的
      image-20250617170524822 image-20250617170620427
  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. 总体结构:栈分为了状态栈 + + +符号栈,分析表分为了动作表 + + +转移表
    image-20250617190804409
    • 分析表的构建: 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...Xm$X1X2...Xmai剩余的输入序列a1a2...aiai+1...an$aiai+1...an$ai+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 AXm(k1)...Xm规约,加状态 GOTO [ s m − k , A ] = y \text{GOTO}[s_{m-k},A]{=}y GOTO[smk,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[smk,A]=y状态栈s0s0s1...smk...sms0s1...smks0s1...smky符号栈$$X1X2...Xmk...Xm$X1X2...XmkA$X1X2...XmkA剩余的输入序列a1...aiai+1...an$aiai+1...an$aiai+1...an$aiai+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 SBB/BaB/Bb,输入 b a b bab bab
    • 分析表内容
      image-20250617193609951
    • 分析全过程
      状态栈 符号栈 输入 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符号栈$$b$B$B$Ba$Bab$BaB$BaB$BB$BB$S$S输入bab$ab$ab$ab$b$$$$$$$$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/状态4Bb/出一状态状态2传输a/状态3传输b/状态4Bb/状态4状态6BaB/出两状态状态5SBB/出两状态状态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 SbBB S → b ⋅ B B S{\to}b{\cdot}BB SbBB S → b B ⋅ B S{\to}bB{\cdot}B SbBB S → b B B ⋅ S{\to}bBB{\cdot} SbBB
    • 后继项目:同一个产生式中将圆点右移一个,例如 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 SS,从而使得分析器只有一个接收状态,示例如下
    产生式项目
    S ′ → S S'{\to}S SS S ′ → ⋅ S / S ′ → S ⋅ S'{\to}{\cdot}S/S'{\to}S{\cdot} SS/SS
    S → B B S{\to}BB SBB S → ⋅ B B / S → B ⋅ B / S → B B ⋅ S{\to}{\cdot}BB/S{\to}B{\cdot}B/S{\to}BB{\cdot} SBB/SBB/SBB
    B → a B B{\to}aB BaB B → ⋅ a B / B → a ⋅ B / B → a B ⋅ B{\to}{\cdot}aB/B{\to}a{\cdot}B/B{\to}aB{\cdot} BaB/BaB/BaB
    B → b B{\to}b Bb B → ⋅ b / B → b ⋅ B{\to}{\cdot}b/B{\to}b{\cdot} Bb/Bb
  2. 初始 / / /接收项目:增广文法中唯一的 S ′ → ⋅ S S'{\to}{\cdot}S SS以及 S ′ → S ⋅ S'{\to}S{\cdot} SS

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 SBB,考虑产生式 B → a B B{\to}aB BaB B → b B{\to}b Bb,则 B → ⋅ a B B{\to}{\cdot}aB BaB B → ⋅ b B{\to}{\cdot}b Bb等价(同理得下表)
      状态内核项目项目集闭包
      I 0 I_0 I0 S ′ → ⋅ S S'{\to}{\cdot}S SS 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)={SS/SBB/BaB/Bb}
      I 1 I_1 I1 S ′ → S ⋅ S'{\to}S{\cdot} SS CLOSURE ( I 1 ) = { S ′ → S ⋅ } \text{CLOSURE}{(I_1)}{=}\{S'{\to}S{\cdot}\} CLOSURE(I1)={SS}
      I 2 I_2 I2 S → B ⋅ B S{\to}B{\cdot}B SBB 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)={SBB/BaB/Bb}
      I 3 I_3 I3 B → a ⋅ B B{\to}a{\cdot}B BaB 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)={BaB/BaB/Bb}
      I 4 I_4 I4 B → b ⋅ B{\to}b{\cdot} Bb CLOSURE ( I 4 ) = { B → b ⋅ } \text{CLOSURE}{(I_4)}{=}\{B{\to}b{\cdot}\} CLOSURE(I4)={Bb}
      I 5 I_5 I5 S → B B ⋅ S{\to}BB{\cdot} SBB CLOSURE ( I 5 ) = { S → B B ⋅ } \text{CLOSURE}{(I_5)}{=}\{S{\to}BB{\cdot}\} CLOSURE(I5)={SBB}
      I 6 I_6 I6 B → a B ⋅ B{\to}aB{\cdot} BaB CLOSURE ( I 6 ) = { B → a B ⋅ } \text{CLOSURE}{(I_6)}{=}\{B{\to}aB{\cdot}\} CLOSURE(I6)={BaB}
    • 补充:自动机的状态的集合就是项集族,此处为 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α的项目,把每个的圆点右移一位,进入新状态
    • 示例:示例文法所有的状态 + \text{+} +转换,构成的自动机
      image-20250617235954248

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α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 SSIi 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. 构建示例:
    image-20250618003121601

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

  1. LR(0) \text{LR(0)} LR(0)分析过程中的冲突
    • 移进 / / /归约冲突:自动机的某个状态,可以进行规约也可以进行移进,如图红色部分
    • 归约 / / /归约冲突:自动机的某一个状态,可以进行多种方式的规约,如图中左下角
      image-20250618004202386
  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αiaiβ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) aFOLLOW(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α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) aFOLLOW(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 SSIi 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}$
    image-20250618110113802

    • 在状态 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) aFOLLOW(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) aFOLLOW(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 Aa进行规约

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}) bFIRST(β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 SS/SL=R/SR/LR/Lid/RL,状态 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加入操作[SS,$][SL=R,$]/[SR,$][LR,=]/[Lid,=][RL,$][LR,$]/[Lid,$]说明初始项目,其后必跟$基于[SS,$]考虑S俩产生式,S后为空故继承$基于[SL=R,$]考虑L俩产生式,L后为=故生=基于[SR,$]考虑R产生式,R后为空故继承$基于[RL,$]考虑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α项目,把圆点右移一位(展望符不变),进入新状态
    • 示例:示例文法所有的状态 + \text{+} +转换,构成的自动机
      image-20250618124533712
    • 补充:除展望符外两个 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]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 SSIi N/A \text{N/A} N/A ACTION [ i , \text{ACTION}[i, ACTION[i,$ ] = a c c ]{=}acc ]=acc
  2. 构建示例:上图自动机的分析表(节选)
    image-20250618131418378

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)中相同核心的项集:所谓相同核心,即状态中刨除展望符外构成的集合一样
    image-20250618134804470
    • 如图中 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. 合并具有相同核心的项集:如图所示
    image-20250618135248771
    同心项集待替换原状态转移(消除)替换后状态转移是否要构造
    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)别无二致
    image-20250618141840704

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

  1. 合并项集的影响
    • 可能会产生规约 - \text{-} -规约冲突,如下图 I 9 / I 6 I_9/I_6 I9/I6的合并;但不会带来规约 - \text{-} -移进的冲突
      image-20250618142848312
    • 当输入错误串,较未合并的 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} EE+E/EEE/E(E)/Eid,其中$\text{FOLLOW}(E){=}{{+},{*},{)},$}$
  2. 自动机:以 I 7 I_7 I7为例,出现移入规约冲突
    image-20250618145639435
    • 例如状态 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)压入栈
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值