📜  运算符优先级解析器的作用

📅  最后修改于: 2021-09-28 09:33:22             🧑  作者: Mango

在此,我们将介绍 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

构建优先函数的算法:

  1. 为每个语法终结符 a 和字符串符号的结尾生成一个函数Xa。
  2. 将符号分成组,如果 a ≐ b,则 Xa 和 Yb 是相同的组。
  3. 生成节点在组中的有向图,对于每个符号 a 和 b,如果 a ⋖ b,则从 Yb 的组中放置一条边到 Xa 的组,否则如果 a ⋗ b 从 Xa 的组中放置一条边到 Yb 的那个。
  4. 如果构造的图具有循环,则不存在过程函数。当没有循环时,分别从 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.或两者兼而有之