【编译原理】课程一:编译原理入门

news2024/12/28 3:19:17

目录

1.为什么要学习编译原理

2.什么是编译原理

3.编译与计算机程序设计语言的关系

3.1.程序设计语言的转换方式

3.2.编译的转换过程

3.3.编译器在语言处理系统中的位置

3.4.编译系统的结构

3.4.1.词法分析(扫描)

3.4.2.语法分析(parsing)

3.4.1.1.语法分析的定义

3.4.1.2.语法分析的规则

3.4.1.3.语法分析的方法

3.4.1.4.语法树

3.4.1.4.语义分析

3.4.1.4.1. 收集标识符的属性信息

3.4.1.4.2. 语义检查

3.4.3.中间代码生成

3.4.3.1.常用的中间代码表示形式

3.4.4.代码优化

3.4.5.目标代码生成

3.4.6.其他

3.4.6.1.出错处理

3.4.6.2.遍

3.4.7.编译程序生成

4.参考


1.为什么要学习编译原理

        作为程序员,不管是前端开发工程师还是后端开发工程师,编译技术都与我们的工作息息相关。在实际工作中也经常会碰到需要编译技术的场景。比如,前端开发工程师想要了解TypeScript是如何把一门语言翻译成另一门语言的,以及babel是如何编译JavaScript的等等。学习编译技术有助于提升我们的职场竞争力,更有助于程序员在技术的道路上走的更远。 那么学习完本篇文章你会对编译原理有个初步的认识,比如:

  • 知道为什么要学习编译
  • 了解编译原理和我们日常开发中使用的开发语言的关系
  • 了解编译在语言系统中所处的位置及编译系统的结构
  • 了解词法分析、语法分析、语义分析这些我们工作中经常听到的概念等等
  • 更重要的是知道我们编写的代码是如何被计算机识别并执行的。

2.什么是编译原理

        编译原理是介绍如何将高级程序设计语言转换成计算机硬件能识别的机器语言,以便计算机进行处理

3.编译与计算机程序设计语言的关系

        日常开发过程中我们使用的语言一般都是高级语法比如 JAVA、Python、PHP、JavaScript等等,但是计算机只能识别0、1这样的机器码。那么这些高级语言是如何翻译成机器能识别的0、1等呢?这就用的了编译,首先我们通过下面这幅图看下编译与计算机程序语言的关系,有助于我们直观的了解编译的作用。

注意:每种机器都对应一种汇编语言

3.1.程序设计语言的转换方式

翻译:指把某种语言的源程序,在不改变语义的条件下,转换成另一种语言程序即目标语言程序

真正的实现有两种方式,编译及解释

  • 编译:专指由高级语言转换为低级语言,整个程序翻译。常用的例如: c、c++,delphi,Fortran、Pascal、Ada
  • 解释:接受某种高级语言的一个语句输入,进行解释并控制计算机执行,马上得到这个句子的执行结果,然后再接受下一个语句。类似口译,一句一句进行解释。常用的例如:python

解释以源程序作为输入,不产生目标程序,一边解释一边执行。优点:直观易懂,结构简单,易于实现人机对话。缺点:效率低(不产生目标程序,每次都需要重新执行,速度慢)

3.2.编译的转换过程

  • 编译->运行
  • 编译->汇编->运行

3.3.编译器在语言处理系统中的位置

        了解了编译与程序设计语言的关系,那么我们接下来再来看下编译器在语言处理系统中所处位置,如下图

3.4.编译系统的结构

        那么机器是如何把高级语言翻译为汇编语言程序或机器语言程序的呢?

        我们先来看下人工进行英文翻译的例子,这里引用的哈工大编译原理中的图示

图中的中间表示很重要主要起到了一个桥梁的作用,比如图中的中间表示可以使用各种语言表示。

根据上图可以看出要进行语义分析首先需要划分句子成分,那么我们是如何划分句子成分的呢?

  1. 首先通过词法分析分析出句子中各个单词的词性或者词类
  2. 接下来通过语法分析识别出句子中的各类短语从而获得句子的结构
  3. 然后进行语义分析根据句子结构分析出句子中各个短语在句子中充当什么成分,从而确定各个名词性成分同各个核心谓语动词间的关系语意关系
  4. 最后给出中间表示形式

        实际上编译器在工作的时候也是经过了以上几个步骤,我们成为阶段(计算机的逻辑组织方式,在实现过程中多个阶段可能会被组合在一起实现),可以分为两大部分:分析源语言、生成目标代码,在编译器中他们分别对应编译器的前端和后端两个部分。编译器的结构如下图

        了解了编译器的结构,让我们从编译器的前端开始讲起,看看词法分析、语法分析、语义分析等各个阶段都做了什么。

3.4.1.词法分析(扫描)

        编译的第一个阶段,从左到右逐行扫描源程序的字符,识别出各个单词(是高级语言中有是在意义的最小语法单元,由字符构成),确定单词的类型。将识别的单词转换成统一的机内表示即词法单元 简称Token

token:<种别码,属性值>

名字解释

  • 一词一码:例如,关键字是唯一的且事先可以确定,为每个关键字分配一个种别码
  • 多词一码:例如,所有的标示符统一作为一类单词分配同一个种别码,为了区分不同的标示符,用token的第二个分量“属性值”存放不同标示符具体的字面值
  • 一型一码:不同类型的常量他们的构成方式是不同的,例如,我们为每种类型的常量分配一个种别码,为了区分同一类型下的不同常量,也用token的第二个分量“属性值”存放每个常量具体的值

下面图中是一个词法分析后得到的token序列的例子

描述词法规则的有效工具是正规式有限自动机正规式:用来确定单词是否和程序语言规范。有限自动机:通过有限自动机进行单词和正规式比较

3.4.2.语法分析(parsing)

3.4.1.1.语法分析的定义

语法分析器从词法分析器输出的token序列中识别出各类短语,并构造语法分析树(parse tree),语法分析树描述了句子的语法结构

3.4.1.2.语法分析的规则

语法规则又称文法,规定了单词如何构成短语、句子、过程和程序。

语法规则的标示如下,含义是A定义为B或者C

BNF:A::=BC

<句子>::=<主><谓><宾>

<主>::=<定><名>

来看下赋值语句的语法规则:

  • A::=V=E
  • E::=T|E+T
  • T::=F|T*F
  • F::=V|(E)|C
  • V::=标示符
  • C::=常数

即由标示符或者常数的表达式进行加减乘除运算

3.4.1.3.语法分析的方法

推导(derive)和归约(reduce)

  • 推导:最左推导、最右推导
  • 归约:最右归约、最左归约,推导的逆过程就是归约

最右推导、最左归约:

最左推导、最右归约:

3.4.1.4.语法树

        计算机通过语法树来进行分析,即语法分析过程也可以用一颗倒着的树来标示,这颗树叫语法树。正确的语法树叶子节点数必须是表达式的符号,例如

赋值语句的分析树:

变量声明语句的分析树:

首先看下变量声明语句的文法(文法是由一系列规则构成的):

<D> -> <T> <IDS>;
<T> -> int | real | char | bool
<IDS> -> id | <IDS>, id

3.4.1.4.语义分析

语义的任务主要有两个

3.4.1.4.1. 收集标识符的属性信息
  • 种属(Kind): 简单变量、复合变量(数组、记录、...)、过程、...
  • 类型 (Type):整型、实型、字符型、布尔型、指针型、...
  • 存储位置、长度

  • 作用域
  • 参数和返回值信息,参数个数、参数类型、参数传递方式、返回值类型、...

        语义分析阶段收集的标识符的信息都会存储在一个符号表里,每个标识符都对应符号表中的一条记录,记录的每个字段记录标识符的每个属性,符号表通常带有一个字符串表用来存放程序中用到的标识符和字符常数,Name 就会被分为两个部分,一部分存放标识符在字符串表中的起始位置,另一部分用来存储标识符的长度,符号表如下图:

除了符号表还有常量表(登记各类常量表);标号表(登记标号的定义和应用,不常用目标);入口名表(登记过程的层号、程序符号表入口等),各种表的生成大部分在词法分析阶段但是在后面各个阶段都有维护;中间代码表

3.4.1.4.2. 语义检查
  1. 变量或过程未经声明就使用
  2. 变量或过程名重复声明
  3. 运算分量类型不匹配
  4. 操作符与操作数之间的类型不匹配
  • 数组下标不是整数
  • 非数组变量使用数组访问操作符
  • 非过程名使用过程调用操作符
  • 过程调用的**参数类型或数目不匹配 **
  • 函数返回类型有误

3.4.3.中间代码生成

        通常和语义分析一起实现。对语法分析识别出的各类语法范畴,分析他的含义,进行初步翻译,产生介于源代码和目标代码质检的一种代码

3.4.3.1.常用的中间代码表示形式

  • 三地址码 (Three-address Code):三地址码由类似于汇编语言的指令序列组成,每个指令最多有三个操作数(operand)
  • 语法结构树/语法树 (Syntax Trees)
  • 逆波兰式

三地址指令的表示:

  • 四元式 (Quadruples),(op, y, z, x)
  • 三元式 (Triples)
  • 间接三元式(Indirect triples)

下面图中展示了一个中间代码生成的例子

3.4.4.代码优化

        对前面生成的中间代码进行加工变换,以便在最后极端产生更为高效的目标代码 ,需要遵循等价变换的原则,优化的方面包括:公共子表达式的提取、合并已知量、删除无用语句、循环优化。

3.4.5.目标代码生成

把经过优化的中间代码转化成特定机器上的低级语言

目标代码的形式:

  • 绝对指令代码:可立即执行的目标代码
  • 汇编指令代码:汇编语言程序,需要经过汇编程序汇编后才能运行
  • 可重定位指令代码:先将各目标模块连接起来,确定变量、常数在主存中的位置,装入主存后才能成为可以运行的绝对指令代码

3.4.6.其他

3.4.6.1.出错处理

        如果源程序有错误,编译程序应设法发现错误并报告给用户。由专门的出错处理程序来完成。 错误类型:

  • 语法错误:在词法分析和语法分析阶段检测出来
  • 语义错误:一般在语义分析阶段检测
  • 逻辑错误:不可检测,比如死循环,一般不处理因为没办法在编译阶段检测出来

3.4.6.2.遍

        指对源程序或源程序的中间结果从头到尾扫描一次,并做有关的加工处理,生成新的中间结果或目标代码。遍与阶段的含义毫无关系

        多遍扫描: 优点:节省内存空间,提高目标代码的质量,使编译的逻辑结构清晰。缺点:编译时间长。在内存许可的情况下还是遍数尽可能少较好

3.4.7.编译程序生成

  1. 直接用机器语言编写编译程序
  2. 用汇编语言编写编译程序,编译程序核心部分常用汇编语言编写
  3. 用高级语言编写编译程序,这也是普遍采用的方法
  4. 自编译
  5. 编译工具 LEX(语法分析)与YACC(用于自动生成LALR分析表)
  6. 移植(同种语言的编译程序在不同类型的机器之 间移植)

在某机器上为某种语言构造编译程序要掌握以下三方面:

  • 源语言
  • 目标语言
  • 编译方法

4.参考

想初步了解编译原理?看这篇文章就够了 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/949917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四轴飞行器的电池研究(MatlabSimulink仿真)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Python教程(11)——Python中的字典dict的用法介绍

dict的用法介绍 创建字典访问字典修改字典删除字典字典的相关函数 列表虽然好&#xff0c;但是如果需要快速的数据查找&#xff0c;就必须进行需要遍历&#xff0c;也就是最坏情况需要遍历完一遍才能找到需要的那个数据&#xff0c;时间复杂度是O(n)&#xff0c;显然这个速度是…

Canvas实现3D效果

3D 球 效果图 代码 var canvas document.getElementById("cas"),ctx canvas.getContext("2d"),vpx canvas.width / 2,vpy canvas.height / 2,Radius 150,balls [],angleX Math.PI / 1000,angleY Math.PI / 1000,factor 0.0001 //旋转因子var An…

解决方案 | 法大大电子签为保险行业加个“双保险”

近年来&#xff0c;人们自我保障意识的不断增强&#xff0c;带动了保险行业的蓬勃发展&#xff1b;数字化进程的加快&#xff0c;也让保险签署更加便捷高效。但与此同时&#xff0c;对于保险企业的安全合规化要求也在不断提升&#xff0c;电子签作为企业数字化转型的重要抓手&a…

vue3集成bpmn.js

1 安装依赖 npm install bpmn-js npm install bpmn-js-properties-panel npm install camunda-bpmn-moddle 注意依赖会有冲突&#xff0c;最好按照下列版本来安装&#xff1a; "bpmn-js": "^7.3.1", "bpmn-js-properties-panel": "^0.37.…

量子计算机使模拟化学反应减慢了1000亿倍!

悉尼大学(University of Sydney)的科学家们首次利用量子计算机设计并直接观测了化学反应中的一个关键过程&#xff0c;将其速度减慢了1000亿倍。 “Direct observation of geometric-phase interference in dynamics around a conical intersection” 主要作者Vanessa Olaya Ag…

免费可商用的高清视频素材库分享~

找视频素材绝对不能错过这个6个网站&#xff0c;免费可商用&#xff0c;视频剪辑、自媒体必备&#xff0c;赶紧收藏~ 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库不仅是一个设计网站&#xff0c;它还有非常丰富的视频和音频素材&#xff0c;视频素材…

[JDK8下的HashMap类应用及源码分析] 数据结构、哈希碰撞、链表变红黑树

系列文章目录 [Java基础] StringBuffer 和 StringBuilder 类应用及源码分析 [Java基础] 数组应用及源码分析 [Java基础] String&#xff0c;分析内存地址&#xff0c;源码 [JDK8环境下的HashMap类应用及源码分析] 第一篇 空构造函数初始化 [JDK8环境下的HashMap类应用及源码分…

Java 复习笔记 - 方法篇

文章目录 一&#xff0c;方法的定义二&#xff0c;最简单的方法定义和调用三&#xff0c;带参数的方法定义和调用四&#xff0c;带返回值方法的定义和调用五&#xff0c;小结六&#xff0c;方法的重载七&#xff0c;方法简单练习1&#xff0c;数组遍历2&#xff0c;数组最大值3…

【深入解读Redis系列】Redis系列(五):切片集群详解

首发博客地址 https://blog.zysicyj.top/ 系列文章地址[1] 如果 Redis 内存很大怎么办&#xff1f; 假设一台 32G 内存的服务器部署了一个 Redis&#xff0c;内存占用了 25G&#xff0c;会发生什么&#xff1f; 此时最明显的表现是 Redis 的响应变慢&#xff0c;甚至非常慢。 这…

Spring框架中如何处理事务管理

文章目录 **1. 声明式事务管理&#xff1a;****定义事务管理器&#xff1a;****配置事务通知&#xff1a;****将事务通知应用到方法&#xff1a;** **2. 编程式事务管理&#xff1a;****通过编程方式启动事务&#xff1a;** **3. 配置事务属性&#xff1a;** &#x1f388;个人…

S32K324芯片学习笔记-实时控制系统-ADC

文章目录 Analog-to-Digital Converter (ADC)用于内部供应监控的ANAMUXBCTU接口硬件触发ADC多路模式通道功能框图特点功能描述时钟转换正常触发注入触发BCTU接口BCTU Trigger modeBCTU Control mode 配置ADC时钟分压器和采样时间设置预采样启用每个通道的预采样 模拟看门狗功能…

阿里云轻量应用服务器Linux-Centos7下MySQL8.0.19的使用

初始环境&#xff1a;阿里云轻量应用服务器已经安装MySQL8.0.19 具体目标&#xff1a;使用MySQL 8.0.19 目录 第一步&#xff1a;初始化第二步&#xff1a;创建一些表第三步&#xff1a;添加一些数据第四步&#xff1a;详情一览第五步&#xff1a;检索数据第六步&#xff1a;排…

前端:js实现提示框(自动消失)

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&q…

正交实验如何进行方差分析?

一、案例介绍 欲研究温度&#xff08;℃&#xff09;、时间&#xff08;min&#xff09;、催化剂含量&#xff08;%&#xff09;对某物质转化率的影响&#xff0c;当前使用正交试验设计进行试验&#xff0c;试探究3个因素对转化率的影响是否显著&#xff0c;并找到能使转化率达…

Source Insight查看源码

新建一个工程 Project -> Synchnorize Files 有可能找不到文件 Options -> File Type Option 查看或者设置快捷键

IDEA新建SpringBoot项目时启动编译报错:Error:java: 无效的源发行版: 17

文章目录 原因检查解决步骤修改jdk修改SpringBoot版本 原因 出现这种错误的原因可能是&#xff1a; 本机默认使用&#xff08;编译&#xff09;的jdk与该项目所使用的jdk版本不同。 jdk版本不适用于这个Idea&#xff0c;很典型的一个例子就是使用的Idea是2020的&#xff0c;而…

C语言每日一练--------Day(11)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;找到数组中消失的数字 哈希表 &#x1f493;博主csdn个人主页&#xff…

【java】【项目实战】[外卖七]短信验证码、手机短信登录开发

目录 一、发送短信 1 短信服务介绍 2 阿里云短信服务&#xff08;个人现在不太好申请了&#xff09; 2.1 介绍 2.2 注册账号 2.3 设置短信签名 2.4 设置短信模版 2.5 设置AccessKey 3 代码开发 3.1 导包 3.2 短信发送工具类SMSUtils 二、手机验证码登录 1 需求分析 …

C++自创题目——第一期

一、题目描述&#xff1a; 在一段时间内&#xff0c;到达港口的船有n艘&#xff0c;其中每艘船的信息包括:到达时间t(表示第t秒)&#xff0c;船上乘客数k&#xff0c;以及k名乘客的国籍。输出前3600s内每艘船上国籍种数&#xff0c;并输出国籍种数最少的船只的到达时间。 二、…