Cyan's Blog

Search

Search IconIcon to open search

Compiler-3_算符优先分析

Last updated Oct 30, 2021 Edit Source

# Operator-precedence grammar

2021-10-30

Tags: #Compiler #Course #FormalLanguage

# 算符优先文法

# Main differences with respect to LR parsers

  • There is no explicit state associated to the parser (and thus no state pushed on the stack)
  • The decision of whether to shift or reduce is taken based solely on the symbol on the top of the stack and the next input symbol (and stored in a shift-reduce table)
  • In case of reduction, the handle is the longest sequence at the top of stack matching the RHS of a rule

# 算符优先文法的核心特征

有几个概念我感到很难理解:

  • 算符优先分析法是仿效四则运算的计算过程而构造的一种语法分析方法。算符优先分析法的关键是比较两个相继出现的终结符的优先级而决定应采取的动作。1
  • “仿效四则运算的计算过程” - 何以见得?

我们首先定义"括号文法(parenthesis grammar)":

那么我们可以这样理解优先级文法:

一个"优先级文法"产生的句子是一串嵌套的括号. 一个素短语便是一对括号, 我们不断消除最左边的素短语, 暴露下面的(栈里面的)素短语 嵌套的"越深"的括号"堆的越高", 我们parse的过程便是不断让这个山变矮的过程.

综上, 结合"算符"文法和"优先级"文法, 便有了"算符优先文法"

# History

Robert W. Floyd. 1963. Syntactic Analysis and Operator Precedence. J. ACM 10, 3 (July 1963), 316–333. DOI:https://doi.org/10.1145/321172.321179

没有细致的考证过出处, 只是谷歌搜索到的, 但是根据文章内容猜测应当是出处.

在文章里面, 我理解到了以下概念:

# 算符优先级

a ⋖ b This means a “yields precedence to” b.
a ⋗ b This means a “takes precedence over” b.
a ≐ b This means a “has same precedence as” b.

# 怎么确定优先级

# 分析步骤

前三步都是在进行准备工作, 即构造后面要用到的算符优先表, 同时, 确定优先级的过程也是验证这个文法是不是算符优先文法的过程

# 检查是否有ε-产生式

# FIRSTVT(NT), LASTVT(NT)

# 如何构造 FIRSTVT(NT), LASTVT(NT)

# FIRSTVT(B)

这样的话可能会套很多层, 书上采用的方法是用一个栈:

理解FIRSTVT(B) 500 理解这种"栈中元素对"的更新方式 500

# LASTVT(B)

类似的

# 构造优先级表

注意区分: 这个表是构造FIRSTVT 和 LASTVT 的, 不是优先级表 300

然后我们根据FIRSTVT 和 LASTVT 来构造优先级表 500 600 构造出来长这样

# 特别注意!

算符优先级不满足交换律, 所以$a\lessdot b\nRightarrow b\gtrdot a$
所以这个表格并不是反对称矩阵!! 要分清横纵轴, 在课本和课件里面, 都是 300

课本里我们引入#符号表示句子的括号 即一开始 在文法中添加E→#E# , E为开始符号, 容易推出:

  • # ⋖ FIRSTVT(E)
  • LASTVT(E) ⋗ #
  • # ≐ # %%> 400%% 课件里面没有写, 但是在分析具体的句型的时候需要记住

# 最左素短语—算符优先分析中的可归约串

句型是这种形式是算符文法的定义造成的, 算符文法不允许出现两个连续的非终结符.

一个例子: 500 直观上这样理解: 500

# Start Parsing!

算符优先算法 解析 一个具体的例子: Operator_Precedence_Parse

需要注意的是:

易错:

# 优先函数

实际应用中, 考虑到存储优先表的开销太大, 我们常常用优先函数代替优先表:

函数f 称为入栈优先函数, g 称为比较优先函数

注意:

400

# 怎么画

可以证明: 若$a≐b$, 则$f(a)=g(b)$; 若$a⋖ b$, 则$f(a)<g(b)$; 若$a⋗b$, 则$f(a)>g(b)$


课件上完全没有讲出错处理


  1. https://moyangsensei.github.io/2019/05/20/%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86%EF%BC%9A%E7%AE%97%E7%AC%A6%E4%BC%98%E5%85%88%E5%88%86%E6%9E%90/ ↩︎

  2. https://www.cs.oberlin.edu/~bob/cs331/Class%20Notes/February/February%2017/Precedence%20Grammars.pdf ↩︎

  3. 不要混淆了"算术基本定理"与"代数基本定理"哦 ↩︎

  4. 我觉得, 这是一个很奇怪的称呼, 完全没有必要又造一个专有名词出来 ↩︎

  5. https://www.geeksforgeeks.org/role-of-operator-precedence-parser/ ↩︎