编译原理学习之-一个简单的语法制导翻译器

2024-03-15 23:28

本文主要是介绍编译原理学习之-一个简单的语法制导翻译器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第二章 一个简单的语法制导翻译器

将具有代表性的程序设计语言语句翻译为三地址码(一种中间表示形式),本章的重点是编译器的前端,特别是词法分析,语法分析和中间代码生产。
建立一个中缀算术表达式转换为后缀表达式的语法制导翻译器

{int i; int j; float[100] a;float v;float x;while(true){do j = i+1;while(a[i]<v);do j = j-1;while(a[j]>v);if(i>=j) break;x = a[i]; a[i] = a[j]; a[j] = x;}
}

引言

编译器在分析阶段把一个源程序划分成各个组成部分,并生成源程序的内部表示形式。这种内部表示称为中间代码。然后编译器在合成阶段将这个中间代码翻译成目标程序。
分析阶段的工作是围绕着待编译语言的“语法”展开的,一个程序设计语言的语法(syntax)描述了该语言的程序的正确形式,而该语言的语义(semantics)则定义了程序的定义,即每个程序在运行时组做什么事情,接下来将给出一个广泛使用的表示方法来描述语法,这个方法就是上下文无关文法或BNF(Backus-Naur范式)。使用现有的语义表示方法来描述一个语言的语义的难度远远大于描述语言的语法的难度。因此,将结合非形式化描述和启发性的示例来描述语言的语义。
上下文无关法不仅可以描述一个语言的语法,还可以指导程序的翻译过程。接下来将介绍面向文法的编译技术,即语法制导翻译(syntax-directed translation)技术,或者说语法分析。

从中缀表达式到后缀表达式的语法制导翻译过程,后缀表达式是一种将运算符置于运算符置于运算分量之后的表示方法。
编译器前端模型
词法分析器使得翻译器可以处理由多个字符组成的构造,比如标识符。标识符由多个字符组成,但是在语法分析阶段被当做一个单元进行处理。这样的单元被称为词法单元(token)
中间代码生成,一种被称为抽象语法树(abstract synta tree),或者简称语法树(syntax tree),它表示了 源程序的层次化语法结构.

2.2 语法定义

用于描述程序设计语言语法的表示方法–‘上下文无关文法’或者简称“文法”。
文法自然地描述了大多数程序设计语言构造的层次化语法结构,例如if-else语句。

if (express) statement else statement
//用expr表示表达式,变量struct表示语句
struct->if(expr)stmt else stmt

其中箭头(->)可以读作“可以具有如下形式”,这样的规则称为产生式(production)像if和括号这样的词法元素称为终结符号(terminal),像expr和stmt这样的变量表示终结符号的序列,它们称为非终结符号。

2.2.1文法定义

一个上下文无关文法(context-free grammar)由四个元素组成

  1. 一个终结符号集合,它们有时候被称为“词法单元”。终结符号是该文法所定义的语言的基本符号的集合;
  2. 一个非终结符号合集,它们有时候也被称为“词法变量”。每个非终结符号表示一个终结符号串的集合
  3. 一个产生式集合,其中每个产生式包括一个称为产生式或者左部的非终结符号,一个箭头,和一个称为产生式体或右部的由终结符号及非终结符号组成的序列。产生式主要用来表示某个构造的某种书写形式。如果产生式头非终结符号组成的序列,那么该产生式体就代表了该构造的一种书写形式。
  4. 指定一个非终结符号为开始符号
    词法单元和终结单元

在编译器中,词法分析器读入源程序中的字符序列,将它们组织成为具有词法含义的词素,生成并输出代表这些词素的词法单元序列。词法单元由两个部分组成:名字和属性。词法单元的名字是语法分析器在进行语法分析时使用的抽象符号,我们常常把这些词法单元名字称为终结符号,因为他们在描述程序设计语言的文法中是以终结符号的形式出现的。如果词法单元具有属性值,那么这个值就是一个指向符号表的指针,符号表中包含了该词法单元的附加信息,这些附加信息不是文法的组成部分,因此在我们的讨论语法分析时,通常将词法单元和终结符号当做同义词。

以非终结符号list为头部的三个产生式可以等价地组合为:
list->list + digit|list - digit|digit

2.2.2 推导

根据文法推导符号串时,首先从开始符号出发,不断将某个非终结符号替换为该非终结符号的某个产生式的体。可以从开始符号推导得到的所有符号终结符号串的集合称为该文法定义的语言(language)。

语法分析(parsing)的任务是:接受一个终结符号串作为输入,找出从文法的开始符号推导出这个串的方法。如果不能从文法的开始符号推导得到该终结符号串的方法。如果不能从文法的开始符号推导得到该终结符号串,则报告该符号串中包含的语法错误。

2.2.3 语法分析树

语法分析树用图形方式展现了从文法的开始符号推导出相应语言中的符号串的过程。
给定一个上下文无关法,该文法的一颗语法分析树(parse tree)是具有以下性质的树:

  1. 根节点的标号为文法的开始符号;
  2. 每个叶子结点的标号为一个终结符号或e;
  3. 每个内部结点的标号为一个非终结符号;
  4. 如果非终结符号A是某个内部结点的标号,并且它的子结点的标号从左到右分为为X1,X2…Xn

关于树形结构的术语

树形结构在编译系统中起着重要的作用。

  • 一棵树由一个或者多个结点组成。结点可以带有标号(label)
  • 树有且只有一个根(root)节点。每个非根节点都有唯一的父(parent)节点。根结点没有父节点。
  • 如果节点N是结点M的父节点,那么M就是N的子结点(child)结点,一个结点的各个子结点彼此被称为兄弟(sibling)节点。它们之间是有序的,按照从左往右的方式排列
  • 没有子结点的节点称为叶子(leaf)节点,其他节点,即有一个或者多个子结点的节点,称为内部节点(interior node);
  • 节点N的后代(descendent)结点要么是结点N本身,要么是N的子结点。

这篇关于编译原理学习之-一个简单的语法制导翻译器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

MySQL中的MVCC底层原理解读

《MySQL中的MVCC底层原理解读》本文详细介绍了MySQL中的多版本并发控制(MVCC)机制,包括版本链、ReadView以及在不同事务隔离级别下MVCC的工作原理,通过一个具体的示例演示了在可重... 目录简介ReadView版本链演示过程总结简介MVCC(Multi-Version Concurr

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维