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

2023-12-23 08:04

本文主要是介绍编译原理----算符优先级的分析(自底向上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

算符优先分析

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

(一)若有文法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...,则a\epsilonFIRSTVT(T)

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

LASTVT:

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

(2)若a\epsilonLASTVT(R),且产生式T->...R,则a\epsilonLASTVT

(三)设有一个不含\varepsilon产生式的算符文法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集合)

这篇关于编译原理----算符优先级的分析(自底向上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/527296

相关文章

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

找不到Anaconda prompt终端的原因分析及解决方案

《找不到Anacondaprompt终端的原因分析及解决方案》因为anaconda还没有初始化,在安装anaconda的过程中,有一行是否要添加anaconda到菜单目录中,由于没有勾选,导致没有菜... 目录问题原因问http://www.chinasem.cn题解决安装了 Anaconda 却找不到 An

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

C++ 各种map特点对比分析

《C++各种map特点对比分析》文章比较了C++中不同类型的map(如std::map,std::unordered_map,std::multimap,std::unordered_multima... 目录特点比较C++ 示例代码 ​​​​​​代码解释特点比较1. std::map底层实现:基于红黑

Spring、Spring Boot、Spring Cloud 的区别与联系分析

《Spring、SpringBoot、SpringCloud的区别与联系分析》Spring、SpringBoot和SpringCloud是Java开发中常用的框架,分别针对企业级应用开发、快速开... 目录1. Spring 框架2. Spring Boot3. Spring Cloud总结1. Sprin

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

kotlin中的模块化结构组件及工作原理

《kotlin中的模块化结构组件及工作原理》本文介绍了Kotlin中模块化结构组件,包括ViewModel、LiveData、Room和Navigation的工作原理和基础使用,本文通过实例代码给大家... 目录ViewModel 工作原理LiveData 工作原理Room 工作原理Navigation 工