语法分析

Baileys2022年5月5日
大约 6 分钟...

语法分析

1. 自顶向下分析概述

推导与归约
规范推导:最右推导
规范归约:最左规约

1.1 top_down步骤

  1. 消除歧义;
  2. 文法改造:
    消除左递归
    提取左公因子
  3. LL(1)文法的判定,确定性。

1.2 递归下降分析

模拟自顶向下建树过程,最左推导。

  1. 预测分析(确定的分析):LL(1)文法。
  2. 需要回溯的分析(不确定的分析)

2. 非递归的预测分析法

非递归预测分析不需要为每个非终结符编写递归下降过程,根据预测分析表构造自动机,也叫表驱动的预测分析。

2.1 文法转换

左递归文法会使递归下降分析器陷入无限循环。
直接左递归的文法:

AAαA{\rightarrow} A{\alpha}

经过两步或两步以上的推导产生的左递归是间接左递归的。

消除直接左递归:

AAαβ(aϵ,β不以A开头)A{\rightarrow}A{\alpha}|{\beta}(a\not=\epsilon,{\beta}\text{不以A开头})

替换为:

AβAA{\rightarrow}{\beta}A^{'}

AαAϵA^{'}{\rightarrow}{\alpha}A^{'}|\epsilon

消除左递归的一般形式:

AAa1Aa2...Aa3β1β2...βn(aiϵ,βj不以A开头)A{\rightarrow}Aa_{1}|Aa_{2}|...|Aa_{3}|{\beta}_{1}|{\beta}_{2}|...|{\beta}_{n}|(a_{i}\not=\epsilon,{\beta_{j}}\text{不以A开头})

替换为:

Aβ1Aβ2A...β3AA{\rightarrow}{\beta}_{1}A^{'}|{\beta}_{2}A^{'}|...|{\beta}_{3}A^{'}

Aa1Aa2A...anAϵA^{'}{\rightarrow}a_{1}A^{'}|a_{2}A^{'}|...|a_{n}A^{'}|\epsilon

消除间接左递归

SAabS{\rightarrow}Aa|b

AAcSdϵA{\rightarrow}Ac|Sd|\epsilon

此时将SS的定义代入AA-产生式,得:

AAcAadbdϵA{\rightarrow}Ac|Aad|bd|\epsilon

消除AA-产生式的直接左递归:

AbdAAA{\rightarrow}bdA^{'}|A^{'}

AcAadAϵA^{'}{\rightarrow}cA^{'}|adA^{'}|\epsilon

2.2 FIRST集、SELECT集、FOLLOW集

FIRSTFIRST集的对象是串。可以包含ϵ\epsilon
FOLLOWFOLLOW集的对象是非终结符。不可以包含ϵ\epsilon
SELECTSELECT集的对象是产生式。不可以包含ϵ\epsilon

  1. FIRSTFIRST
    个人理解:FIRST(A)FIRST(A)为A能够推导出来的所有的终结符串位于串首的终结符构成集合,还要考虑A是否能够推导ϵ\epsilon
    α{\alpha}的串首终结符集FIRST(α)FIRST({\alpha})集的定义为:
    可以从α{\alpha}推导出来的所有串首终结符构成的集合。 若αϵ{\alpha}{\rightarrow}\epsilon,那么ϵ\epsilon也在FIRST(α)FIRST({\alpha})中。

  2. SELECTSELECT
    个人理解:可以选用该产生式进行推导时对应的输入符号集合(终结符集合)。 若ϵFIRST(α){\epsilon}{\notin}FIRST({\alpha}),那么SELECT(Aα)=FIRST(α)SELECT(A{\rightarrow}{\alpha})=FIRST({\alpha})
    ϵFIRST(α){\epsilon}{\in}FIRST({\alpha}), 那么SELECT(Aα)=(FIRST(α){ϵ})FOLLOW(A)SELECT(A{\rightarrow}{\alpha})=(FIRST({\alpha})-{\{}{\epsilon}{\}}){\cup}FOLLOW(A)

  3. FOLLOWFOLLOW集 个人理解:FOLLOW(A)FOLLOW(A)为由A产生的句型中紧跟在A后面的终结符。
    定义:

FOLLOW(A)={aSαAaβ,aVT,α,β(VTVN)}FOLLOW(A)={\{}a|S{\rightarrow}{\alpha}Aa{\beta},a{\in}V_{T},{\alpha},{\beta}{\in}(V_{T}{\cup}V_{N})^{*}{\}}

A是某个句型最右符号,则将结束符"$"添加到FOLLOW(A)\text{若}A\text{是某个句型最右符号,则将结束符}"{\$}"\text{添加到FOLLOW}(A)\text{中}

算法:

  1. $\$放入FOLLOW(S)FOLLOW(S)中,其中SS为开始符号,$\$为输入右端的结束标记。
  2. 如果存在一个产生式AαBβA{\rightarrow}{\alpha}B{\beta},那么FIRST(β)FIRST({\beta})中除了ϵ\epsilon之外的所有符号都在FOLLOW(B)FOLLOW(B)中。
  3. 如果存在一个产生式AαBA{\rightarrow}{\alpha}B,或存在产生式AαBβA{\rightarrow}{\alpha}B{\beta},且FIRST(β)FIRST({\beta})包含ϵ\epsilon,那么FOLLOW(A)中的所有符号都在FOLLOW(B)FOLLOW(B)中。

2.3 LL(1)文法

简洁定义:

Aα1α2...αn{\forall}A{\rightarrow}{\alpha}_{1}|{\alpha}_{2}|...|{\alpha}_{n}

SELECT(Aα1)SELECT(Aα2)...SELECT(Aαn)==SELECT(A{\rightarrow}{\alpha}_{1}){\cap}SELECT(A{\rightarrow}{\alpha}_{2}){\cap}...{\cap}SELECT(A{\rightarrow}{\alpha}_{n})==\emptyset

文法G是LL(1)的,当且仅当G的任意两个具有相同左部的产生式AαβA{\rightarrow}{\alpha}|{\beta}满足以下条件 (同一非终结符的各个产生式的可选集互不相交):

  1. 不存在终结符aa使得α{\alpha}β{\beta}都能够推导出以aa开头的串。
  2. α{\alpha}β{\beta}至多有一个能推导出ϵ{\epsilon}
  3. βϵ{\beta}{\rightarrow}\epsilon,则FIRST(α)FOLLOW(A)=FIRST(\alpha){\cap}FOLLOW(A)=\emptyset
    αϵ{\alpha}{\rightarrow}\epsilon,则FIRST(β)FOLLOW(A)=FIRST(\beta){\cap}FOLLOW(A)=\emptyset

2.4 LL(1)文法非递归下降分析

根据SELECTSELECT集构造预测分析表,进而实现确定的下降分析。

3. 自底向上的语法分析

3.1 LR分析法

工作过程:
初始化及一般情况

  1. ACTION[sm,ai]=sxACTION[s_{m},a_{i}]=sx
    变化后的格局
  2. ACTION[sm,ai]=rxACTION[s_{m},a_{i}]=rx,则用第xx个产生式AXm(k1)...XmA{\rightarrow}X_{m-(k-1)}...X_{m}进行归约。
    变化后的格局
    GOTO[smk,A]=yGOTO[s_{m-k},A]=y
    进而有
    变化后的格局
  3. ACTION[sm,ai]=accACTION[s_{m},a_{i}]=acc,则表示分析成功。
  4. ACTION[sm,ai]=errorACTION[s_{m},a_{i}]=error,则表示出现语法错误。

3.2 增广文法

如果GG是一个以SS为开始符号的文法,则GG的增广文法GG^{'}就是在GG中加上新开始符号SS^{'}和产生式SSS^{'}{\rightarrow}S而得到的文法。
增广文法
目的:使文法开始符号仅出现在一个产生式的左边,从而使得分析器只有一个接收状态。

3.3 CLOSURE、GOTO函数及LR(0)项集族

计算给定项目集的闭包:

CLOUSURE(I)=I{BγAαBβCLOSURE(I),BγP}CLOUSURE(I)=I\cup{\{}B{\rightarrow}{\cdot}{\gamma}|A{\rightarrow}{\alpha}{\cdot}B{\beta}{\in}CLOSURE(I),B{\rightarrow}{\gamma}{\in}P{\}}

返回项目集I对应于文法符号X的后继项目集闭包:

GOTO(I,X)=CLOSURE({AαXβAαXβI})GOTO(I,X)=CLOSURE({\{}A{\rightarrow}{\alpha}X\cdot{\beta}|A{\rightarrow}{\alpha}X{\beta}{\in}I{\}})

规范LR(0)项集族:

C={I0}{IJC,XVNVT,I=GOTO(J,X)}C={\{}I_{0}{\}}{\cup}{\{}I|{\exists}J{\in}C,X{\exists}V_{N}{\cup}V_{T},I=GOTO(J,X)\}

3.4 LR(0)分析表构造算法

LR(0)分析表构造算法

3.5 SLR分析法

LR(0)存在移进归约冲突,可以根据FOLLOWFOLLOW集进行移进、归约操作。
与LR(0)的区别:SLR分析表,只有遇到他的FOLLOW集的元素才进行归约。
AαIiA{\rightarrow}{\alpha}{\cdot}{\in}I_{i}ASA{\neq}S^{'} LR(0)分析法中,采取归约动作,而SLR分析法中,仅仅对于FOLLOWFOLLOW集中的元素归约。
存在的问题:SLR仅简单的考察下一个输入符号b是否与归约项目AαA{\rightarrow}{\alpha}相关联的FOLLOW(A)FOLLOW(A),但bFOLLOW(A)b{\in}FOLLOW(A)只是归约α\alpha的一个必要条件,而非充分条件。

3.6 LR(1)分析法

不同位置,后继符号可能不同
在特定位置中,A的后继符号集合是FOLLOW(A)FOLLOW(A)的子集,如图,分析树中S的右节点R的后继符只能为$\$,而对于L的右节点,只有当下一个符号为=时,才能将L规约为R,我们采用LR,=L{\rightarrow}*R{\cdot},=
规范LR(1)项目:将一般形式为[Aαβ,a][A{\rightarrow}{\alpha}{\cdot}{\beta},a]称为LR(1)项,其中[Aαβ[A{\rightarrow}{\alpha}{\beta}是一个产生式,aa是一个终结符,($为一个特殊的终结符),他表示在当前状态下,AA后面必须紧跟终结符,称为该项的展望符。
Aαβ,aA{\rightarrow}{\alpha}{\cdot}{\beta},aβϵ{\beta}{\neq}{\epsilon}时,展望符没有任何作用
对于Aαβ,aA{\rightarrow}{\alpha}{\cdot}{\beta},a只有在下一个符号为a时,才能进行归约,a总是FOLLOW(a)FOLLOW(a)的子集,而且通常为真子集

构造算法:构造算法,对规约项目,只针对给定的后继符号归约。 LR(1)构造算法

评论
Powered by Waline v2.6.1