【编译、链接、装载三】编译器——语法分析、词法分析、语义分析、编译器后端

news2024/11/29 9:39:55

【编译和链接三】编译器——语法分析、词法分析、语义分析、编译器后端

  • 内容总结
  • 一、词法分析(Lexical Analysis)
  • 二、语法分析 (Syntactic Analysis, or Parsing)
  • 三、语义分析(Semantic Analysis)
  • 四、编译器的后端实现技术

内容总结

  • 词法分析是把程序分割成一个个 Token 的过程。
  • 语法分析是把程序的结构识别出来,并形成一棵便于由计算机处理的抽象语法树。
  • 语义分析是消除语义模糊,给这棵树生成一些属性信息.
  • 编译器后端是把这棵树生成汇编代码。

一、词法分析(Lexical Analysis)

通常,编译器的第一项工作叫做词法分析。就像阅读文章一样,文章是由一个个的中文单词组成的。程序处理也一样,只不过这里不叫单词,而是叫做“词法记号”,英文叫 Token。
在这里插入图片描述

举个例子,看看下面这段代码,如果我们要读懂它,首先要怎么做呢?
在这里插入图片描述

  • 我们会识别出 if、else、int 这样的关键字,main、printf、age 这样的标识符,+、-、= 这样的操作符号,还有花括号、圆括号、分号这样的符号,以及数字字面量、字符串字面量等。这些都是 Token。

  • 那么,如何写一个程序来识别 Token 呢?可以看到,英文内容中通常用空格和标点把单词分开,方便读者阅读和理解。但在计算机程序中,仅仅用空格和标点分割是不行的。比如“age >= 45”应该分成“age”“>=”和“45”这三个 Token,但在代码里它们可以是连在一起的,中间不用非得有空格。

  • 这和汉语有点儿像,汉语里每个词之间也是没有空格的。但我们会下意识地把句子里的词语正确地拆解出来。比如把“我学习编程”这个句子拆解成“我”“学习”“编程”,这个过程叫做“分词”

  • 其实,我们可以通过制定一些规则来区分每个不同的 Token,我举了几个例子,你可以看一下。

    • 识别 age 这样的标识符。它以字母开头,后面可以是字母或数字,直到遇到第一个既不是字母又不是数字的字符时结束。
    • 识别 >= 这样的操作符。 当扫描到一个 > 字符的时候,就要注意,它可能是一个 GT(Greater Than,大于)操作符。但由于 GE(Greater Equal,大于等于)也是以 > 开头的,所以再往下再看一位,如果是 =,那么这个 Token 就是 GE,否则就是 GT。
    • 识别 45 这样的数字字面量。当扫描到一个数字字符的时候,就开始把它看做数字,直到遇到非数字的字符。
  • 有限自动机(Finite-state Automaton,FSA,or Finite Automaton)”。
    有限自动机是有限个状态的自动机器。我们可以拿抽水马桶举例,它分为两个状态:“注水”和“水满”。摁下冲马桶的按钮,它转到“注水”的状态,而浮球上升到一定高度,就会把注水阀门关闭,它转到“水满”状态。
    在这里插入图片描述

  • 词法分析器也是一样,它分析整个程序的字符串,当遇到不同的字符时,会驱使它迁移到不同的状态。例如,词法分析程序在扫描 age 的时候,处于“标识符”状态,等它遇到一个 > 符号,就切换到“比较操作符”的状态。词法分析过程,就是这样一个个状态迁移的过程。
    在这里插入图片描述

有一个叫做lex的程序可以实现词法扫描,它会按照用户之前描述好的词法规则将输入的字符串分割成一个个记号。因为这样一个程序的存在,编译器的开发者就无须为每个编译器开发一个独立的词法扫描器,而是根据需要改变词法规则就可以了。
在这里插入图片描述

另外对于一些有预处理的语言,比如C语言,它的宏替换和文件包含等工作一般不归入编译器的范围而交给一个独立的预处理器。

二、语法分析 (Syntactic Analysis, or Parsing)

  • 接下来语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree)。

整个分析过程采用了上下文无关语法(Context-free Grammar)的分析手段,如果你对上下文无关语
法及下推自动机很熟悉,那么应该很好理解。否则,可以参考一些计算理论的资料,一般都会有很详细的介绍。此处不再赘述。

  • 简单地讲,由语法分析器生成的语法树就是以表达式(Expression)为节点的树。我们知道,C语言的一个语句是一个表达式,而复杂的语句是很多表达式的组合。上面例子中的语句就是一个由赋值表达式、加法表达式、乘法表达式、数组表达式、括号表达式组成的复杂语句。
array[index] = (index + 4) * (2 + 6)

上面代码,它在经过语法分析器以后形成如图2-3所示的语法树
在这里插入图片描述
从图2-3中我们可以看到,整个语句被看作是一个赋值表达式;赋值表达式的左边是一个数组表达式,它的右边是一个乘法表达式;数组表达式又由两个符号表达式组成,等等。

  • 程序也有定义良好的语法结构,它的语法分析过程,就是构造这么一棵树。一个程序就是一棵树,这棵树叫做抽象语法树(Abstract Syntax Tree,AST)。树的每个节点(子树)是一个语法单元,这个单元的构成规则就叫“语法”。每个节点还可以有下级节点。层层嵌套的树状结构,是我们对计算机程序的直观理解。计算机语言总是一个结构套着另一个结构,大的程序套着子程序,子程序又可以包含子程序。

正如前面词法分析有lex一样,语法分析也有一个现成的工具叫做yacc(Yet Another Compiler Compiler)。它也像lex一样,可以根据用户给定的语法规则对输入的记号序列进行解析,从而构建出一棵语法树。对于不同的编程语言,编译器的开发者只须改变语法规则,而无须为每个编译器编写一个语法分析器,所以它又被称为“编译器编译器(Compiler Compiler)”。在这里插入图片描述

三、语义分析(Semantic Analysis)

  • 接下来进行的是语义分析,由语义分析器(Semantic Analyzer)来完成。语法分析仅仅是完成了对表达式的语法层面的分析,但是它并不了解这个语句是否真正有意义。

比如C语言里面两个指针做乘法运算是没有意义的,但是这个语句在语法上是合法的;比如同样一个指针和一个浮点数做乘法运算是否合法等。

  • 编译器所能分析的语义是静态语义(Static Semantic),所谓静态语义是指在编译期可以确定的语义,与之对应的动态语义(Dynamic Semantic)就是只有在运行期才能确定的语义。

静态语义通常包括声明和类型的匹配,类型的转换。比如当一个浮点型的表达式赋值给一个整型的表达式时,其中隐含了一个浮点型到整型转换的过程,语义分析过程中需要完成这个步骤。比如将一个浮点型赋值给一个指针的时候,语义分析程序会发现这个类型不匹配,编译器将会报错。动态语义一般指在运行期出现的语义相关的问题,比如将0作为除数是一个运行期语义错误。

  • 经过语义分析阶段以后,整个语法树的表达式都被标识了类型,如果有些类型需要做隐式转换,语义分析程序会在语法树中插入相应的转换节点。

上面描述的语法树在经过语义分析阶段以后成为如图2-4所示的形式。
在这里插入图片描述

可以看到,每个表达式(包括符号和数字)都被标识了类型。我们的例子中几乎所有的表达式都是整型的,所以无须做转换,整个分析过程很顺利。语义分析器还对符号表里的符号类型也做了更新。

四、编译器的后端实现技术

编译器后端的任务就是生成目标代码(汇编代码),然后再由汇编器生成机器码,生成的文件叫目标文件,最后再使用链接器就能生成可执行文件或库文件了。
在这里插入图片描述

另外一种形式是生成字节码,保证代码的可移植性。在某些场景下,我们没法提前知道,程序运行的目标机器,所以,也就没有办法提前编译。

元语言,先编译成字节码,到了具体运行的平台上,再即时编译成目标代码来运行。

中间代码AST使得编译器可以被分为前端和后端。编译器前端负责产生机器无关的中间代码,编译器后端将中间代码转换成目标机器代码。这样对于一些可以跨平台的编译器而言,它们可以针对不同的平台使用同一个前端和针对不同机器平台的数个后端。
目标代码生成与优化
源代码级优化器产生中间代码标志着下面的过程都属于编辑器后端。编译器后端主要包括代码生成器(Code Generator)和目标代码优化器(Target Code Optimizer)。

参考
1、《程序员的自我修养链接装载与库》
2、其他资料

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

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

相关文章

chatgpt赋能python:Python取出元素详解

Python取出元素详解 在Python编程中,常见到需要取出某个列表、元组或字典中的元素。本文将详细介绍Python如何取出这些元素,并提供相关代码和案例。 取出列表元素 列表是Python编程中最常见的数据结构,下面是列表的定义方式: …

chatgpt赋能python:Python程序的暂停使用介绍

Python程序的暂停使用介绍 Python是一种高级编程语言,适用于各种应用程序,包括Web开发、数据分析、机器学习等领域。它是一个非常强大的工具,但很多人可能不知道Python是否可以被暂停。在这篇文章中,我们将探讨Python是否可以暂停…

总结8881

学习目标: 月目标:6月(线性代数强化9讲2遍,背诵15篇短文,考研核心词过三遍) 周目标:线性代数强化1讲,英语背3篇文章并回诵,检测 每日必复习(5分钟&#xff…

MySQL数据库基础(基础命令详解)

1、数据库操作 1.1、显示当前的数据库 SHOW DATABASES; 1.2、创建数据库 CREATE DATABASE IF NOT EXISTS 库名; 1.3、使用数据库 USE 库名; 1.4、删除数据库 DROP DATABASE IF EXISTS 库名; 说明:数据库删除之后,内部看不到对应…

javaNIO -- ByteBuffer 原理机制

说明 author blog.jellyfishmix.com / JellyfishMIX - githubLICENSE GPL-2.0 概述 ByteBuffer 可以理解为是一个 byte 数组,用于读取与写入。ByteBuffer 通过一些精巧的属性和方法, 更高效地使用内存空间。java NIO 中有 8 种缓冲区: ByteBuffer, CharBuffer, D…

SpringBoot+MyBatis 搭建项目基本框架

参考资料:mall整合SpringBootMyBatis搭建基本骨架 一 背景 做的项目多了,就会发现,每次新项目起步,都是一样的。应该整理一个通用的模板来进行快速启动新项目。 二 使用到的框架简介 1.SpringBoot SpringBoot可以让你快速构建基于Spring…

【实践经验】Latex 表格列间距调整

目录 背景命令 背景 有时候表格列之间的空白区域很大,超出了页面宽度。这时候如果调整表格列与列之间的间隔,无需调整字体大小就能解决这个问题。 命令 \setlength\tabcolsep{3pt} 注意,需要将以上命令,插入到 \begin{table} …

【项目总结2023年6月3日记】:总结最近项目

项目总结,记录一下成长,欢迎大家一起学习,一起交流技术,谢谢支持。 项目:从车多色二维码识别,讲究的就是一个不差,识别的准准的 从车多色二维码识别,讲究的就是一个不差,…

javaScript蓝桥杯----回文字符串

目录 一、介绍二、准备三、目标四、代码五、完成 一、介绍 有言曰:“回文诗,回复读之,皆歌而成文也”。回文诗,是使用词序回环往复的方式所成的诗,通俗来讲就是正读或者倒读都能成为诗句。历经数代诗人的创新&#xf…

chatgpt赋能python:Python取值:介绍

Python取值:介绍 Python是一种非常流行的高级编程语言,适用于各种任务,包括数据科学、机器学习、Web开发和自动化。它被广泛使用,因为它易于学习、易于使用、易于阅读和易于维护。Python中的取值对于程序员来说是一个极其有用的工…

《商用密码应用与安全性评估》第四章密码应用安全性评估实施要点4.6测评报告编制报送和监督检查

目录 测评报告管理要求 测评报告编制 测评报告审核 测评报告批准和签发 测评报告存档 测评报告更正 测评报告作废和销毁 保密要求 测评报告体例 测评相关信息报送 1.基本要求 ①测评报告的备案 ②被测信息系统密码应用数据的采集报送 2.测评信息的采集、报送 1&a…

RVOS环境搭建-01

RVOS环境搭建-01 背景介绍操作系统的定义操作系统的分类典型的 RTOS 介绍课程系统RVOS简介 Hello WorldQEMU介绍QEMU-virt 地址映射 系统引导引导程序要做哪些事情如何判断当前hart是不是第一个hart?如何初始化栈? 如何在屏幕输出Hello World通过串口输出UART特点UART的物理接…

无线通信技术

无线通信网包括面向语言通信的移动电话系统以及面向数据传输的无线局域网和无线广域网。 蜂窝通信系统: 1978年,美国贝尔实验室开发了高级移动电话系统(AMPS)。 AMPS采用模拟制式的频分双工(FDD)技术 第…

mysql数据类型有哪几种

Mysql支持的多种数据类型主要有:数值数据类型、日期/时间类型、字符串类型。 整数 浮点数&定点数 注:定点数以字符串形式存储,对精度要求高时使用decimal较好;尽量避免对浮点数进行减法和比较运算。 时间/日期类型 字符串类型…

Temporal.Duration 规范用法

后端突然告诉我返回给我的时间用了一个新的规范,我展示的时候突然发现这个规范蛮有意思,算是一个新的规范,展示到页面的时候也思考了很多,记录一下子~(注:此 blog 主要目的仅是供自己记录,所以写…

chatgpt赋能python:Python取出列表中的某个数

Python取出列表中的某个数 在Python中,列表是一种非常重要的数据类型,它可以用来存储一系列有序的元素。在实际的开发中,经常会需要从列表中取出某个特定的数值,本文将介绍如何在Python中完成这个操作。 1. 使用index方法 Pyth…

AI实战营:MMPose开源算法库

RTMPose关键点检测全流程 MMPose预训练模型预测-命令行 预测单张图 # HRNet python .\demo\topdown_demo_with_mmdet.py .\demo\mmdetection_cfg\faster_rcnn_r50_fpn_coco.py https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faste…

chatgpt赋能python:Python反转语句:实用技巧提升编程能力

Python反转语句:实用技巧提升编程能力 Python是一门流行的编程语言,许多开发者都会选择Python作为主要的开发语言。其中一个原因是Python的语法简单易学,不仅适合初学者入门,也能被经验丰富的开发者用来构建复杂应用程序。在本文…

【网络原理】数据链路层 和 应用层 重点协议

✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 目 录 🍀一. 以太网协议(数据链路层)🌻二. DNS (应用层)🌿三. 网络原理知识面试总结 &#x1f34…

【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)

全方位渗透和探究SpringMVC的核心原理和运作机制 SpringMVC简介Spring Web MVC是什么Spring Web MVC的工作模式Spring Web MVC能帮我们做什么SpringMVC的底层依赖 SpringMVC工作流程SpringMVC中的组件DispatcherServlet前端控制器DispatcherServlet的职责和作用 HandlerMapping…