自上而下的语法分析

面临的问题

文法左递归

一个文法是含有左递归的,如果存在非终结符P

PPαP\to P\alpha

image-20211013153056686

当产生左递归时,词法分析流没有向前进行任何的推进,而语法树却在不断地进行扩展,此时会使得分析器陷入死循环,故需要避免左递归。

回溯问题

每一步的语法分析,都面临这多个侯选式的选取问题,分析过程中,当一个非终结符用某个候选匹配成功时,这种匹配只是暂时的,当下一步出错时且无路可选时,不得不进行“回溯”操作,而这种回溯操作需要恢复先前的分析结果比较消耗性能。

构造不带回溯的自上而下的分析算法

消除文法左递归

直接左递归消除

image-20211013153719766

PPαβP\to P\alpha|\beta

其中αβ(VTVN)\alpha、\beta\in(V_T\cup V_N)^*β\beta不以A打头

则可改写为如下右递归形式

PβPP\to\beta P'

PαPεP'\to \alpha P'|\varepsilon

推广

假定关于P的全部产生式为

PPα1Pα2...Pαmβ1β2...βnP\to P\alpha_1|P\alpha_2|...|P\alpha_m|\beta_1|\beta_2|...|\beta_n

(每个α\alpha都不等于ε\varepsilon,每个β\beta都不以P开头)

则可改写为如下右递归形式

Pβ1Pβ2P...β1PP\to \beta_1P'|\beta_2P'|...|\beta_1 P'

Pα1Pα2P...αmPP'\to \alpha_1P'|\alpha_2P'|...|\alpha_mP'|

习题

给定文法G(E):
EE+TTE \to E+T|T

TTFFT \to T*F|F

F(E)iF\to(E)|i

消除该文法的直接左递归:

ETEE\to TE'

E+TEεE'\to +TE'|\varepsilon

TFTT\to FT'

TFTεT'\to *FT'|\varepsilon

F(E)iF\to(E)|i

间接左递归消除

文法能够消除左递归的条件
  • 不含有以ε\varepsilon为右部的产生式
  • 不含回路P+PP\overset{+}\to P(+代表一步以上的推导,*代表任意次推导)
习题

给定文法G[S]:
SQccS\to Qc|c
QRbbQ\to Rb|b
RSaaR\to Sa|a
不存在直接左递归,但S、Q、R都是左递归的

SQcRbcSabcS\to Qc \to Rbc \to Sabc

image-20211013190746604

SSABS\to SA|B

AabcA\to abc

BabcbccB\to abc|bc|c

SBSabcSbcScSS\to BS'\to abcS'|bcS'|cS'

SASεabcSεS'\to AS'|\varepsilon \to abcS'|\varepsilon

即消除左递归后为:

SabcSbcScSS\to abcS'|bcS'|cS'

SabcSεS' \to abcS'|\varepsilon

消除回溯

对于如下推导,选取AαiA\to\alpha_i使得此次候选所匹配的工作结果是确信的无误的,便可以消除回溯。若其中的某次匹配错误,那么可以确定,输入的串不是S的句子。

image-20211013194021217

故现在需要根据当前IP指针指向的词法Token去选取一个适当的产生式进行推导。

选取规则如下:

  • 若产生式的推导以终结符a开头

  • 若产生式的推导以非终结符开头,但未来能推导出以a开头

FIRST集合

故可以定义FIRST集合如下:

令G是一个不含左递归的文法,对G的所有非终结符的每个候选α\alpha定义它的终结首符集FIRST(α)FIRST(\alpha)为:

FIRST(α)={ααα...,αVT}FIRST(\alpha) = \{ \alpha|\alpha \overset*\Rightarrow \alpha...,\alpha \in V_T\}

特别地,若αε\alpha\overset{*}{\Rightarrow}\varepsilon,则规定εFIRST(α)\varepsilon\in FIRST(\alpha)

若非终结符A的所有候选首符集两两不相交,即对于A的任意两个不同的候选αi,αj\alpha_i,\alpha_j

FIRST(αi)FIRST(αj)=ϕFIRST(\alpha_i)\cap FIRST(\alpha_j) = \phi

则可以从Aα1α2...αnA\to \alpha_1|\alpha_2|...|\alpha_n中精确地选取一个候选式去执行任务。

提取公共左因子

假定关于A的规则是

Aδβ1δβ2...δβnγ1γ2...γmA\to\delta\beta_1|\delta\beta_2|...|\delta\beta_n|\gamma_1|\gamma_2|...|\gamma_m

那么,可以将这些规则改写为
AδAγ1γ2...γmA\to \delta A'|\gamma_1|\gamma_2|...|\gamma_m

Aβ1β2β1A'\to \beta_1|\beta_2|\beta_1|
经过反复提取左因子,就能够把每个非终结符的所有候选首符集变成为两两不相交。

FOLLOW集合

未完待续