编译原理----算符优先级的分析(自底向上)

简介: 编译原理----算符优先级的分析(自底向上)

自底向上分析的分类如下所示:

算符优先关系表的构造

算符优先分析只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。

(一)若有文法G,如果G没有形如A->..BC..的产生式,其中B和C为非终结符,则称G为算符文法。

以下例子中G就是算符文法(没有连在一起的非终结符)

E->T|E+T|E-T

T->F|T*F|T/F

F->(E)|i

(二)



这里就用=,< 和 > 代替:


(1)a=b,当且仅当G中含有形如A--->..ab...或A---->...aBb...的产生式


(2)a<b,当且仅当G种含有形如A--->...aB...的产生式,且B能多步推导出右侧式子



(3)a>b,当且仅当G中含有形如A--->...Bb...的产生式,且B能多步推导出右侧式子



这里理解起来也很简单,a<b,那么a就要小于B推导出的式子中最前面的终结符b,a>b同理


这里的推导较为复杂,我们可以演化出下面这一方法:



这样a<b,a>b的定义就为:


a<b,当且仅当G种含有形如A--->...aB...的产生式,且a小于B的FIRSTVT集合中的所有终结符


a>b,当且仅当G中含有形如A--->...Bb...的产生式,且B的LASTVT的所有终结符大于b

构造规则:


FIRSTVT:


(1)若有T->a...或T->Ra...,则aFIRSTVT(T)


(2)若有aFIRSTVT(R),且有产生式T->R...,则aFIRSTVT(T)


LASTVT:


(1)若有T->...a或T->...aR,则aLASTVT(T)


(2)若aLASTVT(R),且产生式T->...R,则aLASTVT


(三)设有一个不含产生式的算符文法G,如果任一终结符对(a,b)之间至多只有<,>,=3种关系种的一种成立,则称G是一个算符优先文法。即,两个终结符之间的优先关系是有序的,允许有a>b,b<a同时存在,但是不允许有a<b,a>b,a=b3种关系中的任一两种关系同时存在。


示例:

FIRSTVT集合:


(1)首先根据E->E+T|T的E->E+T,可得(注:行代表终结符,列代表非终结符)



(2)再看E->E+T|T 的E->T,需要把T的FIRSTVT元素放到E中,但是此时T中没有✔元素,所以



(3)T->T*F|F中的T->T*F



(4)T->T*F|F中的T->F,而F没有✔项



(5)F->(E)|i 中的F->(E)



(6)F->(E)|i 中的F->i



这是第一遍遍历式子,因为表有变化,所以要继续进行遍历,直到表不变

(1)首先根据E->E+T|T的E->E+T,可得



(2)再看E->E+T|T 的E->T,需要把T的FIRSTVT元素放到E中



(3)T->T*F|F中的T->T*F



(4)T->T*F|F中的T->F,将F中的✔项放到T中



表依旧有改变,继续遍历,直到没有出现新的内容



所以得出结论:

E(FIRSTVT)={+,*,{,},i}


T(FIRSTVT)={*,(,i}


F(FIRSTVT)={(,i}

LASTVT的操作步骤同理,得到:



接下来继续回到算符优先关系中


竖列表示在前面的终结符,横列表示在后面的终结符



针对a=b


F->(E)|i,这里的“(”和“)”遵循a=b的定义,即A->..aBb...



针对a<b,就是要找到a后面跟的非终结符,这个非终结符中的FIRSTVT集合的元素就是满足要求的元素。


E->E+T|T中的+T,T(FIRSTVT)= {*,(,i}


T->T*F|F中的*F,F(FIRSYVT) = {(,i}


F->(E)|i中的(E,E(FIRSTVT)= {+,*,{,},i}



针对a>b,就是要找到a前面跟的非终结符,这个非终结符中的LASTVT集合的元素就是满足要求的元素:


E->E+T|T中的E+


T->T*F|F的T*


F->(E)|i 的E)

最终得到:

总结:

对于a<b,就要找终结符后面的非终结符(*F)的FIRSTVT集合(F的FIRSTVT集合)

对于a>b,就要找终结符前面的非终结符(F*)的LASTVT集合(F的LASTVT集合)

构造优先函数

例如:

其的优先函数为:这里假设列为f,行为g,接着由大的指向小的

构造优先函数表

对应的优先函数表如图所示,这里的数字代表的是可经过的结点数:

f+从f+出发,算一个经过的节点,再到g+,也算一个经过的节点,所以总数为2

f*可以经过以下4个节点

目录
相关文章
|
21天前
|
存储 算法 决策智能
《C 语言下模拟退火算法于组合优化的应用要点全解析》
组合优化问题是计算机科学与数学的交叉领域中的研究热点。模拟退火算法作为一种基于概率的随机搜索方法,通过模拟固体退火过程,能够在解空间中高效寻找全局最优或近似最优解。本文探讨了用C语言实现模拟退火算法的关键步骤,包括算法原理、数据结构设计、温度参数控制、邻域生成与搜索策略、接受准则、终止条件及性能评估与调优,旨在为解决组合优化问题提供有效途径。
62 11
|
7月前
|
C语言 C++ 容器
c++primer plus 6 读书笔记 第五章 循环和关系表达式
c++primer plus 6 读书笔记 第五章 循环和关系表达式
|
设计模式 安全 Go
Go中按次序交替打印1212...,你知道它背后的设计模式吗
Go中按次序交替打印1212...,你知道它背后的设计模式吗
|
编译器 C语言
【循环语句之三大分类】
【循环语句之三大分类】
126 0
|
机器学习/深度学习 人工智能 算法
Barrels (codeforces 1430B )(拆分思想和模拟控制)
Barrels (codeforces 1430B )(拆分思想和模拟控制)
58 0
|
C++
C++ Primer Plus 第五章答案 循环和关系表达式
只有聪明人才能看见的摘要~( ̄▽ ̄~)~
70 0
|
存储 算法 Go
周而复始,往复循环,递归、尾递归算法与无限极层级结构的探究和使用(Golang1.18)
所有人都听过这样一个歌谣:从前有座山,山里有座庙,庙里有个和尚在讲故事:从前有座山。。。。,虽然这个歌谣并没有一个递归边界条件跳出循环,但无疑地,这是递归算法最朴素的落地实现,本次我们使用Golang1.18回溯递归与迭代算法的落地场景应用。
周而复始,往复循环,递归、尾递归算法与无限极层级结构的探究和使用(Golang1.18)
|
SQL 缓存 安全
如何避免写重复代码:善用抽象和组合
通过抽象和组合,我们可以编写出更加简洁、易于理解和稳定的代码;类似于金字塔的建筑过程,我们总是可以在一层抽象之上再叠加一层,从而达到自己的目标。但是在日常的开发工作中,我们如何进行实践呢?本文将以笔者在Akka项目中的一段社区贡献作为引子分享笔者的一点心得。
165 0
如何避免写重复代码:善用抽象和组合
|
数据可视化 算法
大白话理解递归本质,可视化递归过程
大白话理解递归本质,可视化递归过程
227 0