Skip to main content

语法分析

文法

正规式描述能力不够,能够定义一些简单的语言,表示给定结构的固定次数的重复或者灭有指定次数的重复,不能描述成对,配对或者嵌套的串,所以才有文法。

句型、句子、语言

单词:满足一定规则的字符串。

句子:满足一定规则的单词序列。

语言:满足一定规则的句子集合。

推导和分析树

推导

推导是指通过使用给定的文法推导出目标的句子,如下例中的 id * id + id。

image-20220515131057845

推导主要有两种,分别如下:

  • 最左推导:优先从左往右进行替换。
  • 最右推导(规范推导):优先从右往左进行替换。

image-20220515131306466

分析树

用树的形式表示句子的语法结构。

image-20220515150638809

文法的二义性

对于文法来说,有可能会产生二义性,也就是对于一个句型来说,同一个句型能够产生两棵不同的分析树。如下图:

image-20220515162023482

image-20220515162012575

句柄、短语

  • 句柄:最左直接短语,就是分析树中的叶子。
  • 短语:句子里面的其中一个式子。语法树中子树相对于根的短语。也就是一棵子树的叶子。

image-20220526221208337

自上而下的文法

递归文法

caution

消除递归记得补充上空串,在包含有递归的式子后。

image-20220515172957634

消除左递归的方法:

image-20220515183717052

蓝色框:递归重复的部分。

绿色框:递归的入口。

引入一个额外的字母 EE',分解成两条式子转换为右递归。将左边对应颜色部分进行对应即可。

消除间接左递归:

image-20220515184133504

红色框:递归入口的部分。

绿色框:递归重复的部分。

同样引入额外的字母,将带有方框的蓝色式子的颜色方框一一对应。

求解 First 集和 Follow 集

First 集

  • 对于首符号为终结符 VTV_T

    对于一个产生式 αabc...\alpha\stackrel{*}{\rarr} abc...,有:

    First 集为 First(α)={a}\text{First}(\alpha)=\{a\},只关注产生式产生的式子的首个符号,称为首符号集

    tip

    可能会存在 αabc...def......z\alpha\stackrel{*}{\rarr} abc... | def ... | ... | z 的情况,则需要把所有的情况考虑,故 First 集为:First(α)={a,d,...,z}\text{First}(\alpha)=\{a,d,...,z\}

  • 对于首符号为非终结符 VNV_N

    对于一个产生式 αABC...\alpha\rarr ABC...,有:

    • AϵA\rarr\epsilon,则 First(A)=First(A){ϵ}\text{First}(A)=\text{First}(A)\cup\{\epsilon\},即当首符号为同时要求解 First(B)\text{First}(B)
    • 否则,First(α)=First(α)(First(A){ϵ})\text{First}(\alpha)=\text{First}(\alpha)\cup (\text{First}(A)-\{\epsilon\}),这个过程是多次迭代的,直到找到终结符。

Follow 集

  1. 将 $ 加入到 Follow(S)\text{Follow}(S),其中 SS 是文法开始的符号。
  2. AαBβA\rarr \alpha B\beta,则 Follow(B)=Follow(B)(First(β){ϵ})\text{Follow}(B)=\text{Follow}(B)\cup(\text{First}(\beta)-\{\epsilon\}),即求 Follow 集只需要看产生式右侧所求符号的后继,将后继符号的 First 集加入到 Follow 集。
  3. AαBA\rarr \alpha BAαBβ, βϵA\rarr \alpha B\beta,\ \beta\rarr\epsilonFollow(B)=Follow(B)Follow(A)\text{Follow}(B)=\text{Follow}(B)\cup\text{Follow}(A),即若产生式右侧所求符号的后继为空,则求其产生式左侧符号的 Follow 集。

LL(1)

  1. 消除左递归、左公因子。

  2. 求每个候选式的 First 集和所有变量的 Follow 集

  3. 检查是否为 LL(1) 文法

    • 任意两个产生式 AαβA\rarr \alpha|\beta满足两个条件(只要看有或的产生式即可):
      • First(α)First(β)=\text{First}(\alpha)\cup \text{First}(\beta)=\varnothing
      • 如果 BϵB\rArr\epsilon,那么则看 First(α)Follow(β)=\text{First}(\alpha)\cup \text{Follow}(\beta)=\varnothing
  4. 构造 LL(1) 分析表

    表格式为:

    image-20220527135502472

    对候选式 Aa1a2...anA\rarr a_1|a_2|...|a_n的右侧求其 First 集,即 First(a1a2...an)\text{First}(a_1|a_2|...|a_n),最后将 First 集中包含的元素按终结符的列填入到 AA 对应的行,填入元素为 AaiA\rarr a_i

    如果 aja_j 的 First 集中包含空串,则 Follow(A)\text{Follow}(A) 中包含的元素也填入到 AA 对应的行,填入元素为 AajA\rarr a_j

  5. 分析句子

    1. 根据所给句子,从开始符出发(分析栈栈顶),从左往右开始,按照句子的符号在分析表中找对应的列,使用对应的语句。
    2. 用产生式右部替换分析栈栈顶(产生式右部的式子从右往左入栈)。
    3. 继续看栈顶查表使用对应的语句。
    4. 直到分析栈为空结束。

    image-20220526170600811

    image-20220526170617996

自下而上的文法

构造活前缀 DFA

image-20220527112101007

LR(0)

  1. 增广文法,添加产生式 SSS'\rarr S

  2. 构造活前缀 DFA。

  3. 判断是否为 LR(0) 文法。

  4. 构造 LR(0) 分析表。

    image-20220527112450494

  5. 基于分析表分析给定句子。

SLR(1)

  1. 增广文法,添加产生式 SSS'\rarr S

  2. 构造活前缀 DFA。

  3. 判断是否为 SLR(1) 文法。

  4. 构造 SLR(1) 分析表。(考虑 Follow 集)

    image-20220527112425060

  5. 基于分析表分析给定句子。

LR(1)

  1. 增广文法,添加产生式 SSS'\rarr S

  2. 构造活前缀 DFA。(加入第二分量)

    image-20220527150735377

  3. 判断是否为 LR(1) 文法。

  4. 构造 LR(1) 分析表。(考虑第二分量)image-20220527112407037

  5. 基于分析表分析给定句子。