Atitti. 语法树AST、后缀表达式、DAG、三地址代码

抽象语法树的观点认为任何复杂的语句嵌套情况都可以借助于树的形式加以描述。确实,不得不承认应用抽象语法树可以使语句翻译变得相对容易,它很好地描述了语句、表达式之间的联系。不过,由于Neo Pascal并不会显式构造抽象语法树,所以不得不借助于其他数据结构实现。根据先前的经验,栈结构就是不二之选。

DAG(有向无环图)

后缀表达式:也称为逆波兰表达式,这种形式简单明晰,便于存储。在处理表达式翻译时,后缀表达式有着其他形式无法比拟的优势。不过,由于后缀表达式的应用领域比较单一,所以很少独立作为一个实际编译器的IR存在。

1. 后缀表达式

编辑

不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *

作者::  ★(attilax)>>>   绰号:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿尔 拉帕努伊 ) 汉字名:艾龙,  EMAIL:1466519819@qq.com

转载请注明来源: http://www.cnblogs.com/attilax/

1.1. 前缀记法、中缀记法和后缀记法

它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。

举例:
(3 + 4) × 5 - 6 就是中缀表达式
- × + 3 4 5 6 前缀表达式
3 4 + 5 × 6 - 后缀表达式

中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。

三地址代码:也称为"四元组",即操作符和三个操作数地址。这是一种最为常见的IR。甚至有些书籍认为IR就是中间代码(即三地址代码

所谓的三地址,指的就是每一行代码通常包含三个地址信息,即操作数1、操作数2、结果操作数。例如,(ADD  A,1,C )这行三地址代码的含义就是A+1→C。这种形式初看与汇编语言有点类似

当然,三地址代码也不是完美的,由于它是相对离散的,在分析源程序结构方面,它就不及语法树便捷

三地址代码的理由如下:三地址代码是一种线性IR。由于输入源程序及输出目标程序都是线性的,因此,线性IR有着其他形式无法比拟的优势。另外,相对于其他表示形式而言,程序员对于线性表示形式通常会有一种莫名的亲切感,编译器设计者当然也不例外。早期编译器设计者往往都是汇编语言程序设计的高手,可以非常自然、流畅地阅读线性的三地址代码形式。同时,线性表示形式也会降低输入输出的实现难度。随着编译器"端"、"遍"等概念的出现,IR已经不仅仅是一种存储在内存中的数据结构。有时它也需要以文件形式转存输出,作为接口供其他系统读取使用。

为什么将其设计为"三地址"的形式呢?实际上,这是计算机科学家经过多年实践探索后才得到共识的。三地址代码并不是唯一的线性IR,只能说是最为常见的而已。在编译技术领域,二地址代码、单地址代码(即栈式机代码)都曾出现过,也曾在某些应用领域盛行一时,尤其是单地址代码。

然而,单地址代码的情况则截然不同了,在现代编译器设计中,单地址代码也是应用比较广泛的一种IR。尤其是近年随着混合语言的日渐壮大,单地址代码也重新进入了人们的视野。由于执行单地址代码程序的栈式机架构相对比较简单,可以非常方便地构造相关的解释器或虚拟机,所以单地址代码深受混合语言设计者的欢迎。读者熟悉的Java字节码、.NET的IL都是单地址代码

三地址代码是在二地址代码的基础上发展而来的。二地址代码的不足之处在于它通常会给其中一个源操作分量带来一定副作用。当然,这种设计的灵感最初是来源于x86指令系统的,但是却忘了一个重要的区别:x86指令中往往都是以寄存器作为暂存空间的。而暂存空间对于二地址代码却是一个棘手的问题。为了解决二地址代码的不足,人们提出了一个对源操作分量不产生任何副作用的形式,那就是三地址代码。也就是说,在一行三地址代码中,任何运算都不会改变两个源操作分量。这是三地址代码与二地址代码的主要区别。这个特性是非常重要的,它将使得编译器更自由地复用名字与值,不必考虑代码带来的副作用。

最后,再来谈谈IR的级别,即IR依赖于目标机的程度。按级别分类,可将IR分成三类:高级形式(HIR)、中级形式(MIR)、低级形式(LIR),也可称为高级中间语言、中级中间语言、低级中间语言。

高级形式(HIR)是一种尽可能保持了源语言程序结构的IR,这种形式能较好地保留源程序的原始语义信息。由于高级形式太接近源语言程序结构,所以很少有编译器将其独立作为IR传递给后端。

中级形式(MIR)既要以一种与语言无关的方式在一定程度上反映源语言的特性,又要能够适应多种体系结构的IR。中级形式是一种比较常用的IR,它兼顾了源语言、目标机的特性,又能适用于大多数优化算法。当一个编译器仅设计一种IR时,中级形式是较理想的选择。

低级形式(LIR)就是在一定程度上包含某些目标机特性的IR,比目标语言稍高级,常作为一些机器相关的优化算法的输入。不过,实际上,除了一些较大型的编译器需要使用低级形式之外,低级形式并不是很常见。因为更多编译器设计者更愿意直接基于目标语言作优化。

表5-6  if语句的翻译方案

if语句

翻 译 方 案

if <表达式> then

<语句1>

else

<语句2>

<表达式翻译>

(JNT                   , <表达式结果> , null , __L1 )

<语句1>

(JMP                   , __L2 , null , null )

(LABEL              , __L1 , null , null )

<语句2>

(LABEL              , __L2 , null , null )

如果省略了else部分,那么只需将翻译方案中第4~6行语句省略,并将第7行的"__L2"替换为"__L1"即可。semantic068、semantic069、semantic070主要的功能就是根据翻译方案翻译输入的if语句。也就是说,试图依靠这三个语义子程序,完成翻译方案中黑体语句的生成。在上述翻译方案中,可以暂且将"__L1"称为"假分支标号",而将"__L2"称为"出口标号"。另外,需注意一点,当输入语句是if-then结构时,第7行语句的标号不应该取出口标号,而应该取假分支标号,因为此时并不存在真正意义的假分支,因此,可以将假分支标号当作出口标号使用。

while语句的翻译方案

while语句

翻译方案

while <表达式> do

<语句>

(LABEL ,__L1,null,null)

<表达式翻译>

(JNT               ,<表达式结果>,null,__L0)

<语句>

(JMP               ,__L1,null,null)

(LABEL ,__L0,null,null)

5.1.2 IR设计及其级别 - 51CTO.COM.html

Atitti. 语法树AST、后缀表达式、DAG、三地址代码的更多相关文章

  1. javascript编写一个简单的编译器(理解抽象语法树AST)

    javascript编写一个简单的编译器(理解抽象语法树AST) 编译器 是一种接收一段代码,然后把它转成一些其他一种机制.我们现在来做一个在一张纸上画出一条线,那么我们画出一条线需要定义的条件如下: ...

  2. 理解Babel是如何编译JS代码的及理解抽象语法树(AST)

    Babel是如何编译JS代码的及理解抽象语法树(AST) 1. Babel的作用是?   很多浏览器目前还不支持ES6的代码,但是我们可以通过Babel将ES6的代码转译成ES5代码,让所有的浏览器都 ...

  3. 抽象语法树(AST)

    AST描述 在计算机科学中,抽象语法树(AST)或语法树是用编程语言编写的源代码的抽象语法结构的树表示.树的每个节点表示在源代码中出现的构造.语法是“抽象的”,因为它不代表真实语法中出现的每个细节,而 ...

  4. Atitti.java exp ast java表达式语法ast构造器

    Atitti.java exp ast java表达式语法ast构造器 /atiplat_cms/src/com/attilax/lang/AstParser.java 原理 分割tokens_sli ...

  5. Clang之语法抽象语法树AST

    语法分析器的任务是确定某个单词流是否能够与源语言的语法适配,即设定一个称之为上下文无关语言(context-free language)的语言集合,语法分析器建立一颗与(词法分析出的)输入单词流对应的 ...

  6. 从零写一个编译器(九):语义分析之构造抽象语法树(AST)

    项目的完整代码在 C2j-Compiler 前言 在上一篇完成了符号表的构建,下一步就是输出抽象语法树(Abstract Syntax Tree,AST) 抽象语法树(abstract syntax ...

  7. 造轮子系列(三): 一个简单快速的html虚拟语法树(AST)解析器

    前言 虚拟语法树(Abstract Syntax Tree, AST)是解释器/编译器进行语法分析的基础, 也是众多前端编译工具的基础工具, 比如webpack, postcss, less等. 对于 ...

  8. Java抽象语法树AST,JCTree 分析

    JCTree简要分析文章目录JCTree简要分析JCAnnotatedTypeJCAnnotationJCArrayAccessJCArrayTypeTreeJCAssertJCAssignJCAss ...

  9. AST抽象语法树 Javascript版

    在javascript世界中,你可以认为抽象语法树(AST)是最底层. 再往下,就是关于转换和编译的"黑魔法"领域了. 现在,我们拆解一个简单的add函数 function add ...

随机推荐

  1. nodejs第一个练习:用Node.js建HTTP服务器

    这是官方的一个例子, 在F盘建立一个tinyphp.js文件,内容: var http = require('http'); http.createServer(function (req, res) ...

  2. Objective-C]入门 (xcode helloworld程序 创建类

    一:objective-c简介 Objective-C是进行iPhone软件开发的语言 Objective-C语言是C语言的一个扩展集 Objective-C是一种面向对象的语言 大小写敏感 程序语句 ...

  3. 通过命名管道协议方式访问群集SQL的一个小问题

    原来的单机实例SQL如果开放命名管道协议访问可以在.Net程序的连接字符串中增加“;Net=dbnmpntw"以通过命名管道协议方式访问,但是当迁移到群集SQL后,.net通过它可能无法正常 ...

  4. [转]在Excel中使用SQL语句实现精确查询

    本文转自:http://blog.sina.com.cn/s/blog_5fc375650102e1g5.html 今天在微博上看到@数据分析精选 分享的一篇文章,是关于<在Excel中使用SQ ...

  5. 判断客户端是PC还是手持设备的JS代码【转】

    1.第一种: 复制代码代码如下: function IsPC() {    var userAgentInfo = navigator.userAgent;    var Agents = [&quo ...

  6. python之epoll服务器源码分析

    #!/usr/bin/env python # -*- coding: utf8 -*- import socket, select EOL1 = b'/r/n' EOL2 = b'/r/n/r/n' ...

  7. jquery 获取标签名(tagName)

    如果是为了取到tagName后再进行判断,那直接用下面的代码会更方便: $(element).is('input') 如果是要取到标签用作到别的地方,可以使用一下代码: $(element)[0].t ...

  8. 百度编辑器同一id重复调用不能生效的办法

    在使用js 调用表单组件模板的时候,表单内有一个编辑框 第一次调出的时候,百度编辑器正常显示,关闭后,再打开,百度编辑器不能显示 原因:第一次使用的时候, UE.getEditor('node_con ...

  9. (转)如何将本地git仓库中的代码上传到github

    1,  在github上新建一个仓库,比如为:CSS3Test,仓库地址为:https://github.com/hyuanyuanlisiwei/CSS3Test 2,本地git仓库中的文件项目为C ...

  10. Java命令学习系列(2):Jstack

    转载:http://www.importnew.com/18176.html 原文出处: Hollis(@Hollis_Chuang) jstack是java虚拟机自带的一种堆栈跟踪工具. 功能 js ...