编译原理-至下而上的语法分析

至下而上分析的基本问题

归约

用一个寄存符号的先进后出栈,把输入符号一个一个地移进栈里,当栈顶形成某个产生式的一个候选式时,即把栈顶的这一部分归约成该产生式的左部符号

\[{E -> i|E + E|E-E|E*E|E/E|(E)} \]

输入符号串:

\[{i*i+i} \]

归约过程

\[{E*i+i} \quad \quad (1) \]

\[{E*E+i} \quad \quad (2) \]

\[{E+i} \quad \quad (3) \]

\[{E+E} \quad \quad (4) \]

\[{E} \quad \quad (5) \]

例子:设文法G(S):
\({S->aAcBe}\)
\({A->b}\)
\({A->Ab}\)
${b->d} \( 试对\){abbcde}$进行移进归约分析:
能进行归约就进行归约不能进行归约进行移进
image
image
image
image
此时我们进行归约的话就会出现矛盾,b是第二个推导的产生式,Ab是第二个产生式的候选式,这里我们选择第二种进行归约
image
image
image
image
在不能归约时我们就移进
image

短语

定义:令G是一个文法,S是文法的开始符号,假定\({\alpha \beta \delta}\)是文法G的一个句型,如果有:
image
就称\(\beta\)是句型\({\alpha \beta \delta}\)相对于非终结符\({A}\)的短语
如果有\({A => \beta}\),则称\(\beta\)是句型\({\alpha \beta \delta}\)相对于产生式\(A->B\)直接短语,一个句型的最左直接短语称为该句型的句柄
一个句型对应的语法树中

  1. 以某非终结符为根的两代以上的子树的所有末端结点从左到右排列就是相对于该非终结符的一个短语
  2. 如果子树只有两代,则改短语是直接短语

句柄可以被用来对句子进行归约

规范归约

定义:假定\(\alpha\)是文法\(G\)的一个句子,我们称序列

\[{\alpha_n, \quad \alpha_n-1, \quad ... \quad, \alpha_0} \]

\(\alpha\)的一个规范归约,如果此序列满足:
\({1. \alpha_n = \alpha}\)
\({2. \alpha_0为文法的开始符号,即\alpha_0=S}\)
\({3.对于任何i, 0 < i<= n,\alpha_{i - 1}是从\alpha_i经句柄替换成相应产生式左部符号而得到的}\)
规范推导:我们将规范归约的过程逆过来就是规范推导,规范推导也经常被称为最右推导
由规范推导推出来的句型被称为规范句型

符号栈的使用

  1. 栈是语法分析的一种基本数据结构,\(\#\)作为栈底符号
    文法\(G(E):\)
    \(E->T|E+T\)
    \(T->F|T*F\)
    \(F->(E)|i\)
    输入串为\(i_1*i_2+i_3\)的分析过程
    image
    image
    image

算符优先分析

  1. 算符优先就是定义算符之间(终结符之间)的某种优先关系,借助优先关系来寻找可归约串和进行归约
    考虑二义文法\(G(E) \quad: \quad i|E+E|E-E|E*E|E/E|(E)\)
    这个句子由几种不同的规范归约
    例如句子\(i+i-i*(i + i)\)的规约过程(按四则运算的优先顺序)

\[(1) \quad {i + i - i * (i + i)} \]

\[(2) \quad {E + i - i * (i + i)} \]

\[(3) \quad {E + E - i * (i + i)} \]

\[(4) \quad {E - i * (i + i)} \]

\[(5) \quad {E - E * (i + i)} \]

\[(6) \quad {E - E * (E + i)} \]

\[(7) \quad {E - E * (E + E)} \]

\[(8) \quad {E - E * (E)} \]

\[(9) \quad {E - E * E} \]

\[(10) \quad {E - E} \]

\[(11) \quad {E} \]

优先关系

image

算符文法及优先关表构造

算符文法:一个文法,如果它的任一产生式的右部都不含两个相继(并列)的非终结符,即不含如下形式的产生式右部:\(...QR...\),则我们称该文法为算符文法
约定:
\(a、b代表任意终结符\)
\(P、Q、R代表任意非终结符\)
\(...代表由终结符和非终结符组成的任意序列,包括空字\)

"等于":image
"小于":
image
"大于":
image
image
FIRSTYT:image

LASTVT:image
比较:
image
算符优先关系表
有了FIRSTVTLASTVT这两个概念后,我们就可以用算法构造优先关系表

image
我们只需对每个产生式检查一遍,把所有优先关系都找到就可以了

如何求FIRSTVT和LASTVT

image
image

算符优先分析算法

素短语:至少包含一个终结符,并且除了它自身外不包含任何更小的素短语,最左素短语就是句型最左边的素短语
我们考虑句型:

\[\# N_1 a_1 N_2 a_2 ... N_n a_n N_{n+1} \# \]

其中每一个\(a_i\)都是终结符,\(N_i\)都是可有可无的非终结符。
一个算符优先文法G的任何上述句型的最左素短语是满足如下条件的最左子串\({N_ja_j...N_ia_iN_{i + 1}}\)
image
算法
image

优先函数

我们在通常实现上面算法的时候在判断优先关系的时候一般不采用查表的方法而是用两个优先函数,优先函数可以将原来\(N * N\)的时间复杂度降低到\(2 * N\),缺点是原来可能两个符号不可比较优先级,但是经过优先函数之后会映射到自然数从而导致可以比较,这样会导致一些错误
image
f被称为栈优先函数
g被称为比较优先函数
如何构造优先函数(证明过程略)
image
经过构造完的优先函数需要我们进一步检验是否正确

posted @ 2023-11-13 15:35  cxy8  阅读(27)  评论(0编辑  收藏  举报