热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

【编译原理】引论

文章目录编译原理引论(一)认识编译程序(二)编译过程概述1、阶段划分2、编译程序的结构3、编译程序的生成编译原理引论&#x


文章目录

  • 编译原理引论
    • (一)认识编译程序
    • (二)编译过程概述
      • 1、阶段划分
      • 2、编译程序的结构
      • 3、编译程序的生成


编译原理引论


(一)认识编译程序

什么是编译程序?

这要从翻译程序、解释程序以及编译程序的联系与区别说起:

翻译程序:把一种语言程序(称为源语言程序)等价地转换成另一种语言程序(称为目标语言程序)的程序。
在这里插入图片描述

编译程序是一种特殊的翻译程序,编译程序特指把某一种高级语言程序等价地转换成另一种低级语言程序(如汇编语言或者机器语言程序)的程序。
在这里插入图片描述

在翻译程序中,有一种方式和编译程序不太一样,即解释程序:把源语言写的源程序作为输入、但不产生目标程序,而是边解释边执行源程序本身。

根据不同的用途和侧重,编译程序还可进一步分类。


  • 诊断编译程序:专门用于帮助程序开发和调试的编译程序称为诊断编译程序
  • 优化编译程序:着重于提髙目标代码效率的编译程序
  • 如果一个编译程序产生不同于其宿主机的机器代码, 则称它为交叉编译程序
  • 如果不需重写编译程序中与机器无关的部分就能改变目标机,则称该编译程序为可变目标编译程序

编译程序运行的平台叫做宿主机
编译后产生的目标代码运行的平台叫做目标机
通常这两种平台在同一台机器上。



(二)编译过程概述


1、阶段划分

编译过程是一种语言的翻译过程,它的工作过程类似于外文的翻译过程。

比如英文句子翻译成中文句子的大致过程是:


  1. 词法分析:根据英语的词法规则,从由字母、空格字符和各种标点符号所组成的字符串中识别出一个一个的英文单词。
  2. 语法分析:根据英语的语法规则,对词法分析后的单词串进行分析、识别,并做语法正确性检查,看其是否组成一个符合英语语法的句子。
  3. 语义分析:对正确的英文句子分析其含义并用汉语表示出来.
  4. 根据上下文的关系以及汉语语法的有关规则对词句做必要的修饰工作。
  5. 最后翻译成中文。

编译过程一般分为以下五个阶段(与自然语言翻译过程对比):


  1. 词法分析
  2. 语法分析
  3. 语义分析与中间代码产生
  4. 优化
  5. 目标代码生成

(1)词法分析(扫描器)


  • 任务:源程序 → 单词符号串 (线性分析)。 即输人源程序,对构成源程序的字符串进行扫描和分解,识别出一个个的单词(亦称单词符号或简称符号),如基本字、标识符、常数、算符和界符(标点符号、左右括号等等)。

  • 依据:语言的词法规则

  • 描述词法规则的工具:正则式、正则文法、有限自动机

(2)语法分析


  • 任务:单词符号串 → 各类语法范畴 (层次结构分析)。 即在词法分析的基础上,根据语言的语法规 则,把单词符号串分解成各类语法单位(语法范畴),如“短语”、“子句”、“句子”(“语句”)、 “程序段”和“程序”等。通过语法分析,确定整个输人串是否构成语法上正确的“程序”
  • 依据:语言的语法规则
  • 描述语法规则的工具:上下文无关文法、确定的下推自动机

(3)语义分析与中间代码产生


  • 任务:语法范畴 → 初步翻译、产生中间代码。 即对语法分析所识别出的各类语法范畴,分析其含义,并进行初步翻译(产生中间代码)。这一阶段通常包括两个方面的工作。首先,对每种语法范畴进行静态语义检查,例如,变量是否定义、类型是否正确等等。如果语义正确,则进行另一方面工作,即进行中间代码的翻译。
  • 中间代码:独立于具体硬件的记号系统,四元式、三元式、逆波兰式等。(介于高级语言和低级语言之间)
  • 依据:语言的语义规则
  • 描述语义规则的工具:属性文法

(4)优化


  • 任务:中间代码 → 高效的中间代码。 即在于对前段产生的中间代码进行加工变换,以期在最后阶段能产生出更为髙效(省时间和空间)的目标代码。优化的主要方面有:公共子表达式的提取、循环优化、删除无用代码等等。有时,为了便于“并行运算”,还可以对代码进行并行化处理。
  • 依据:等价变换规则
  • 变换方法:公共子表达式的提取、循环优化、删除无用代码、并行处理等

(5)目标代码生成


  • 任务:把中间代码(或经优化处理之后)变换成特定机器上的低级语言代码。这阶段实现了最后的翻译,它的工作有赖于硬件系统结构和机器指令含义。

这阶段工作非常复杂,涉及的主要问题:


  • 指令的选择
  • 内存的分配
  • 寄存器的分配
  • 目标代码的形式:
    • 绝对指令代码:这种目标代码可立即执行
    • 汇编指令代码:需汇编器汇编之后才能运行
    • 可重定位的指令代码(现代多数的情况):在运行前必须借助于一个连接装配程序把各个目标模块(包括系统提供的库模块)连接在一起,确定程序变量(或常数)在主存中的位置, 装入内存中指定的起始地址,使之成为一个可以运行的绝对指令代码程序。

目标代码形式为可重定位的指令代码的背后其实支撑的是源代码的模块化。


2、编译程序的结构

(1)编译程序总框

上述编译过程的五个阶段是编译程序工作时的动态特桩。编译程序的结构可以按照这五个阶段的任务分模块进行设计
在这里插入图片描述


  1. 词法分析器,又称扫描器,输人源程序,进行词法分析,输出单词符号。
  2. 语法分析器,简称分析器,对单词符号串进行语法分析(根据语法规则进行推导或归约),识别出各类语法单位,最终判断输入串是否构成语法上正确的“程序”
  3. 语义分析与中间代码产生器,按照语义规则对语法分析器归约出(或推导出)的语法单位进行语义分析并把它们翻译成一定形式的中间代码。
    有的编译程序在识别出各类语法单位后,构造并输出一棵表示语法结构的语法树,然后,根据语法树进行语义分析和中间代码产生。还有许多编译程序在识别出语法单位后并不真正构造语法树,而是调用相应的语义子程序。在这种编译程序中,扫描器、分析器和中间代码产生器三者并非是截然分开的,而是相互穿插的。
  4. 优化器,对中间代码进行优化处理。
  5. 目标代码生成器,把中间代码翻译成目标程序

除了上述五个功能模块外,一个完整的编译程序还应包括“表格管理”和“出错处理”两部分

(2)表格与表格管理

本质是一个数据结构,编译程序在工作过程中需要保持一系列的表格,以査记源程序的各类信息和编译各阶段的进展状况。

在编译程序使用的表格中,最重要的是符号表。它用来登记源程序中出现的每个名字以及名字的各种属性。

此外,还有与管理、构造、查找、更新有关的表格。

(3)出错处理

任务:发现并向用户指出源程序中错误的性质和位置。如果可以的话,自动校正错误。

错误有以下类型:
词法错误:不符合词法规则
语法错误:不符合语法规则


  • 非法字符、括号不匹配、缺少 ;、…

语义错误:不符合语义规则


  • 说明错误、作用域错误、类型不一致、…

(4)遍(pass):
遍:就是对源程序或源程序的中间结果从头至尾扫描一次,并作有关的加工处理,生成新的中间结果或目标程序的处理过程。

比如小明一天五节课(对应五个阶段),其中有一节是劳动课,课程内容是将垃圾运到垃圾处理区,第一次的路程(对应第一遍),将可回收垃圾运过去了,第二次的路程(对应第二遍)将不可回收垃圾运过去了。小明做这件事有了两次路程(对应两遍)
如果小明一次性都运过去了,那么这一节课就只有一次路程(对应一遍)。

可以把一个阶段分为若干遍,也可以把多个阶段合为一遍,通常有一遍和多遍编译程序。

一个编译程序究竟应分成几遍,如何划分,是与源语言、设计要求、硬件设备等诸因素有关的,因此难于统一划定。遍数多一点有个好处,即整个编译程序的逻辑结构可能清晰点(也可能有更多的优化)。但遍数多势必増加输人/输出所消耗的时间。因此,在主存可能的前提下,一般还是遍数尽可能少一点为好。应当注意的是,并不是每种语言都可以用单遍编译程序实现。

(5)编译的前端与后端:

前端(front end) :由与源语言有关但与目标机无关的部分组成。
后端(back end) :包括与目标机有关的部分。而一般不依赖于源语言,只与中间代码有关的编译阶段。

在这里插入图片描述


3、编译程序的生成

这个地方书写的非常拗口,其实理解很简单,就是我现在有一个简易的编译器A,它可以编译A语言,A语言的语法虽然简单,但是只要符合语法,编写出来的代码就能通过A编译器的编译,并能在计算机上执行。
这个时候,我希望语法更丰富点,我就用A语言写了一个编译器B,编译器B支持的语法更加丰富些,可以抽象成B语言,只要符合B语言的语法,编写出来的代码就能通过B的编译,最终能够在计算机上执行(本质上还是A的作用,只不过抽象了一层,编译过程做了更多转换的事情)。

这个就引出来一个方式、即自编译方式:先实现语言的内核编译再进行自编译扩展,先实现某语言的编译再用该语言实现另一语言的编译,即编译—>编译程序。

参考:陈火旺、刘春林等,《程序设计语言编译原理》,国防工业出版社,第三版


推荐阅读
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • Final关键字的含义及用法详解
    本文详细介绍了Java中final关键字的含义和用法。final关键字可以修饰非抽象类、非抽象类成员方法和变量。final类不能被继承,final类中的方法默认是final的。final方法不能被子类的方法覆盖,但可以被继承。final成员变量表示常量,只能被赋值一次,赋值后值不再改变。文章还讨论了final类和final方法的应用场景,以及使用final方法的两个原因:锁定方法防止修改和提高执行效率。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 分享2款网站程序源码/主题等后门检测工具
    本文介绍了2款用于检测网站程序源码和主题中是否存在后门的工具,分别是WebShellkiller和D盾_Web查杀。WebShellkiller是一款支持webshell和暗链扫描的工具,采用多重检测引擎和智能检测模型,能够更精准地检测出已知和未知的后门文件。D盾_Web查杀则使用自行研发的代码分析引擎,能够分析更为隐藏的WebShell后门行为。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • OO第一单元自白:简单多项式导函数的设计与bug分析
    本文介绍了作者在学习OO的第一次作业中所遇到的问题及其解决方案。作者通过建立Multinomial和Monomial两个类来实现多项式和单项式,并通过append方法将单项式组合为多项式,并在此过程中合并同类项。作者还介绍了单项式和多项式的求导方法,并解释了如何利用正则表达式提取各个单项式并进行求导。同时,作者还对自己在输入合法性判断上的不足进行了bug分析,指出了自己在处理指数情况时出现的问题,并总结了被hack的原因。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
author-avatar
风情万种791008
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有