编译原理 (二)词法分析、语法分析、语义分析以及中间代码生成器的基本概念

简介: 编译原理 (二)词法分析、语法分析、语义分析以及中间代码生成器的基本概念

1.词法分析

词法分析的过程中,源代码程序被输入到了一个叫做扫描器的东西中,扫描器的任务就是进行词法分析。他应用了一种叫做有限状态机的算法把源代码分割成一个一个的记号,举例比如array[index] = (index + 4) * (2 + 3)这行代码,经过扫描就会变成如下的一个个记号:

记号 类型
array 标识符
[ 左方括号
index 标识符
] 右方括号
= 赋值
( 左圆括号
index 标识符
+ 加号
4 数字
) 左圆括号
* 乘号
( 左圆括号
2 数字
+ 加号
3 数字
) 右圆括号


以上的这些记号一般有以下几类:关键字、标识符、字面量(数字、字符串等)和特殊符号。

单词类型 种别 种别码
关键字 if、else、for…… 一词一码
标识符 变量名、数组名…… 多词一码
常量 整型、浮点型、字符…… 一型一码
运算符 算术(+ - * / %)、关系(> < =)、逻辑(& | ~) 一词一码
界限符 ; ( ) [ ] { } 一词一码


在识别这些标志的同时,扫描器也同时把标识符存放到了符号表,将数字、字符串常量存放到文字表,以备后续步骤使用。对于C语言的预处理,他的宏替换和文件包含等工作不交给编译器范围而是交给独立的预处理器处理。


2.语法分析

语法分析则由分析器去扫描扫描器产生的那些记号去进行语法分析,产生语法树,整个过程采用了上下文无关语法的分析手段,由语法分析树生成的树是以表达式为节点的树,如下所示:

这个数的左分支是array[index]右分支是(index + 4) * (2 + 3)左分支和右分支又可以再拆开,形成语法树

通过语法树我们可以看到很多运算符号的优先级和含义也被确定了下来。对于有多重含义的符号,比如*可以做乘法,也可以作为指针,语法分析阶段,要去确定他们的含义来进行区分,出现了不合法的表示方式,则会抛出语法错误。


3.语义分析

语义分析由语义分析器来完成,语法分析器仅完成了语法的对错,他并不去关心代码实现的含义,在C语言中两个指针相乘是没有意义的,但是在语法层面确是合法的。编译器能分析的语义是静态语义,即编译期可以确定的语义,相反,动态语义则是在运行的时候才确定的语义。


静态语义包括声明类型和类型的匹配、转换。比如当一个浮点数赋值给整型的时候,隐藏了一个过程,就是浮点型到整型转换的过程。但是将浮点数赋值给指针的时候,在语法层面可以,但是语义阶段,会发现,类型不匹配则会报错。

经过语义分析后,整个语法数表达式都被标志了类型,如下:

该表达式中基本所有的类型都是整型,并不需要做类型转换,有些需要做转换的会在语法树上插入转换节点


4.z中间语言生成

目前的编译器都会有很多优化,在源代码中就会有一些优化过程,比如以上的(2+6)就会在编译的时候进行优化,优化后就直接变成了一个数字5

其实直接在语法树上边做优化比较困难,所以源代码优化器往往把整个语法树转换成中间代码,跟目标机器和运行环境无关,他不包含数据的尺寸、变量地址和寄存器的名字。常见的中间代码有三地址码,P-代码等。比如x = y op z,该三地址码表示将变量y和z进行op操作后赋值给x,比如x = y + z;一下是常用的三地址表示方式

指令类型 指令形式
赋值操作 x = y op z 、 x = op y
复制指令 x = y
条件跳转 if x op y goto z
非条件跳转 goto z
参数传递 param z
过程调用 call p, n
过程返回 return x
数组引用 x = y[ i ]
数组赋值 y[ i ] = x
地址以及指针操作 x = &y 、x = *y 、*x = y

我们把上述的例子的语法树翻译成三地址码如下

t1 = 2 + 3
t2 = index + 4
t3 = t1 * t2
array[index] = t3

在三地址码基础上进行优化,会把2+3的结果计算出来,得到t1 = 5然后把t1换成5。这样三地址码就变成了如下

t2 = index + 4
t2 = t2 * 8
array[index] = t2

中间代码把编译器分成了前端和后端(此前后端非彼前后端),前端负责生成与机器无挂的中间代码,后端则是将中间代码变成目标代码。这样对于一些跨平台的编译器而言,可以针对不同平台使用同一个前端,然后对应不同机器开发不同后端。


参考资料《编译原理》、《程序员的自我修养(链接、装载与库)》

相关文章
|
自然语言处理 编译器
编译原理复习五:属性文法与三地址码的生成(附题目与答案 超详细)
编译原理复习五:属性文法与三地址码的生成(附题目与答案 超详细)
1354 0
|
存储 自然语言处理 前端开发
编译原理 - 语义分析
编译原理 - 语义分析
432 1
|
自然语言处理 编译器 C语言
软考:区分词法分析、语法分析、语义分析
本文解释了编译过程中的词法分析、语法分析和语义分析三个阶段的区别,并提供了相关练习题,帮助读者理解各阶段在编译过程中的作用和重要性。
1097 4
|
Linux 开发工具 git
【Git】Git 完全指南:从入门到精通
Git 是一种强大的版本控制工具,掌握了其基本命令和高级特性后,可以大大提高开发效率并方便团队协作。通过本篇文章,你已经学会了 Git 的核心命令及其使用方法,希望你能够灵活运用 Git 在实际项目中进行版本管理。
4728 4
|
Ubuntu 网络协议 Linux
【附安装包】CentOS7(Linux)详细安装教程(手把手图文详解版)
【附安装包】CentOS7(Linux)详细安装教程(手把手图文详解版)
7326 2
|
Java Maven Spring
如何在idea中创建Springboot项目? 手把手带你创建Springboot项目,稳!
文章详细介绍了在IDEA中创建Spring Boot项目的过程,包括选择Spring Initializr、配置项目属性、选择Spring Boot版本、导入依赖、等待依赖下载以及项目结构简介。
19546 1
|
网络协议 Windows
【IntelliJ IDEA】idea plugins搜索不出来,如何找到插件的解决方案
【IntelliJ IDEA】idea plugins搜索不出来,如何找到插件的解决方案
14349 0
DFA与NFA的区别,由正规表达式构造DFA,以及DFA的相关化简
DFA与NFA的区别,由正规表达式构造DFA,以及DFA的相关化简
2314 1
DFA与NFA的区别,由正规表达式构造DFA,以及DFA的相关化简
|
前端开发 JavaScript 关系型数据库
基于Python+Vue开发的旅游景区管理系统
该项目是为大学生课程设计开发的旅游景区管理系统,采用Python+Vue技术栈,实现前后端分离。主要功能涵盖景区、类型、用户管理等,并支持统计分析、消息发布、订单处理及个性化推荐。开发环境基于Python 3.8 + Django 3.2、Vue + JavaScript及MySQL 5.7。通过该项目,学生可深入学习相关技术,增强实践能力,为职业发展奠定基础。[在线演示](https://travel2.gitapp.cn) | [源码](https://github.com/net936/python_travel2) | 管理员默认账号: admin123 / admin123.
507 2
编译原理-----逆波兰表示法,四元式,三元式,间接三元式
编译原理-----逆波兰表示法,四元式,三元式,间接三元式
814 0

热门文章

最新文章