在此,我们将介绍 Operator Precedence Parser 的概述,并主要关注 Operator Precedence Parser 的作用。并且还将介绍构建优先级函数的算法,最后将讨论运算符优先级解析中的错误恢复。让我们一一讨论。
介绍 :
为运算符优先文法构造的运算符优先级解析器。运算符优先语法是一种不包含 epsilon 产生式并且在任何产生式的 RHS 上不包含两个相邻非终结符的语法。运算符优先文法提供了优先规则。运算符优先级语法可以是二义性的,也可以是无二义性的。
运算符优先级解析器算法:
1. If the front of input $ and top of stack both have $, it's done
else
2. compare front of input b with ⋗
if b! = '⋗'
then push b
scan the next input symbol
3. if b == '⋗'
then pop till ⋖ and store it in a string S
pop ⋖ also
reduce the poped string
if (top of stack) ⋖ (front of input)
then push ⋖ S
if (top of stack) ⋗ (front of input)
then push S and goto 3
组件运算符图:
例子 –
下面我们通过一个例子来理解运算符优先级的作用。
E-> E+T/T
T-> T*V/V
V->a/b/c/d
string= "a+b*c*d"
上述算法对字符串“a+b*c*d”的实现如下。
Stack | Input | Stack Top | Current Input | Action |
---|---|---|---|---|
$ | a+b*c*d$ | $ | a | shift a |
$a | +b*c*d$ | A | + | reduce using A->a |
$V | +b*c*d$ | V | + | reduce using T->V |
$T | +b*c*d$ | T | + | reduce using E->T |
$E | +b*c*d$ | E | + | shift + |
$E+ | b*c*d$ | b | * | reduce using V->b |
$E+V | b*c*d$ | V | * | reduce using T->V |
$E+T | *c*d$ | T | * | shift * |
$E+T* | c*d$ | * | c | shift c |
$E+T*c | *d$ | c | * | reduce using V->c |
$E+T*V | *d$ | V | * | reduce using T->T*V |
$E+T | *d$ | T | * | shift * |
$E+T* | d$ | * | d | shift d |
$E+T*d | $ | d | $ | reduce using V->d |
$E+T*V | $ | V | $ | reduce using T->T*v |
$E+T | $ | T | $ | reduce using E->E+T |
$T | $ | E | $ | accept |
构建优先函数的算法:
- 为每个语法终结符 a 和字符串符号的结尾生成一个函数Xa。
- 将符号分成组,如果 a ≐ b,则 Xa 和 Yb 是相同的组。
- 生成节点在组中的有向图,对于每个符号 a 和 b,如果 a ⋖ b,则从 Yb 的组中放置一条边到 Xa 的组,否则如果 a ⋗ b 从 Xa 的组中放置一条边到 Yb 的那个。
- 如果构造的图具有循环,则不存在过程函数。当没有循环时,分别从 Xa 和 yb 的组中收集最长路径的长度。
例子 –
下面通过一个例子来理解优先函数的构造。
E -> E + E/E * E/( E )/id
在这里,您将看到运算符优先级关系表和优先级关系图。我们来看一下。
正如我们可以看到图中没有环也没有环,我们可以制作这个函数表如下。
列表示函数:
列代表函数Ya,行代表函数Xa –
它是通过从 Xid 到 X$ 和 Yid 到 Y$ 的最长路径来计算的。
fid -> g* -> f+ ->g+ -> f$
gid -> f* -> g* ->f+ -> g+ ->f$
- 运算符优先级关系表的缺点是,如果有“n”个符号,那么我们需要一个 n*n 的表来存储它们。另一方面,通过使用运算符函数表,为了容纳 n 个符号,我们需要一个 2*n 的表。运算符优先语法不能决定一元减号(词法分析器应该处理一元减号)。
- 使用 Operator Precedence Grammar 的优点是简单且足够强大,可用于编程语言中的表达。
运算符优先级解析中的错误恢复:
- 错误案例 –
1.栈顶的终结符和下一个输入符号之间没有关系。
2.找到一个手柄(还原步骤),但没有以该手柄为右侧的生产。 - 错误恢复——
1.每个空条目都填充有一个指向错误例程的指针。
2.确定弹出的手柄“看起来像”哪个右侧。并试图从这种情况中恢复过来。 - 处理移位/减少错误 –
为了处理此类错误,我们必须修改以下内容。
1.堆栈
2 .输入
3.或两者兼而有之