2.1~2.2词法分析的任务,词法分析器的手工构造

2024-04-05 04:32

本文主要是介绍2.1~2.2词法分析的任务,词法分析器的手工构造,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

编译器的阶段

在这里插入图片描述

阶段:

在这里插入图片描述
编译器可以分成若干个阶段,包含 frontend(前端) backend(后端)
前端接收源程序,产生中间表示 IR,它处理的是和源语言程序相关的属性。
后端接收中间表示,继续生成目标程序,处理一般是具体的结构和目标机器相关的数据
我们把这部分成为编译器的阶段划分。

前端
在这里插入图片描述

例如:
c 语言程序[源程序] ,传入字符流,经过词法分析器,到记号流 ,记号流继续传递输入给语法分析器,产生抽象语法树,继续传递给语义分析器(类型检查器)检查正确性后输出中间表示。

词法分析器的任务

在这里插入图片描述
读入程序员写的程序,产生 字符流,然后对字符流做切分,产生一个记号流(或叫单词流)
例:

if(x > 5)y == "hello";
elsez == 1;实际输入流以第一行为例:  if空格(x空格>空格5)\r\n    实际上编译器得到的和我们看到的有不同的地方
在 第四行 z==1; 程序结束后要有一个 EOF 结束符(-1)词法分析:
IF LPAREN IDENT(x) GT INT(5) RPARENIDENT(y) ASSIGN  STRING("hello") SEMICOLON
ELSEIDENT(Z) ASSIGN INT(1) SEMICOLON EOFLPAREN 这类的词语叫做 记号或单词

我们将字符流转换到记号流,首先要有一个数据结构,然后还需要有一个字符流到记号流转换的算法,也就是需要
1.数据结构的定义
2.算法的实现

记号的数据结构定义

enum kind { IF, LPAREN, ID, INTLIT,...};
struct token{enum kind k;char *lexeme;
}

Kind 是词法分析器所能识别的所有记号的分类。

例:

输入字符流:
if(x > 5)伪代码:
token {k = IF,lexeme = 0};
token {k = LPAREN,lexeme = 0};
token {k = IDENT,lexeme = "x"};
token {k = GT,lexeme = 0};
token {k = INT,lexeme = "5"};
token {k = RPAREN,lexeme = 0};

小结
词法分析器的任务: 字符流到记号流

  • 字符流:和被编译的语言密切相关(ACSII,Unicode,or …
  • 记号流:编译器内部定义的数据结构,编码所识别出来的词法单元

词法分析器的实现方法
至少两种实现方案

1.手工编码实现法

纯手工书写程序代码,来实现输入输出接口的功能,缺点 代码量大相对复杂,而且容易出错,但是目前非常流行的实现方法例如:GCC,LLVM 好处 对各个部分有精确的控制,效率会比较高

2.词法分析器的生成器
他是自动化的方法,程序员仅仅需要写一些关于词法规则的声明,然后就有词法分析器的生成器的这样一类工具可以把词法分析器给自动生成出来,从概念上来讲程序员不需要写特别多的代码,所以这样的一类方法 优点 是, 可快速原型,代码量较少缺点 相对于手工方式,因为是自动生成的细节较难控制

理解手工构造词法分析器的核心问题是转移图的概念

所有的需要识别的符号:"<=" ">="  "<>"  "<"  "="  ">"
首先从待分析的程序中读第一个字符进来,有可能是 < = > 
读第一个字符在 0 好节点,记作 c1
如果是 < 号 我们就 就走向 1号节点,再继续读 下一个符号, 如果是 = 号就继续走向 2号 节点
如果读到了 2好节点 我们就识别完成 <= 这个符号 2号节点不同与 0号;1号节点,是双圆圈,代表接受;识别 状态
即一个识别已经结束了,return 返回语句,返回所识别出来的词法符号的内部数据结构, relop 和 LE 是组织成员的内部数据结构
4号 识别状态的 * 号 ,其实是 1号节点中所识别到数据的字符回滚,也就是一个回退,返回1号识别到的标号 < 

在这里插入图片描述
转移图算法(伪代码实现):

token 返回的数据结构,也就是记号或单词token nextToken()c = getChar(); //首先读入字符'c'switch(c)case '<'   : //说明我们来到了 1号 节点上,我们需要再读入字符做判断c = getChar();switch(c)case '=' : return LE; //返回值 '<='case '>' : return NE; //返回值 '<>'defalut: roollback()/*把刚刚读到的c重新扔回到刚刚分析程序中*/ return LT ; // 返回值 '<'case '=' : return EQ;case '>' : c = nextChar();switch(c)://similar

其他代码符号的识别

首先科普下标识符的概念:
以字母或下划线开头后面跟0个或多个字母或下划线数字。

从状态 0 开始读入第一个字符,它应该是 字母或下划线
在状态 1 上面再读一个字符就要进行如果还是字母数字或下划线的话那么进行循环回编,指向1节点自身
在状态 1 上面如果读到了其他的符号(other),既不是字母数字下划线,就转移到状态 2 
在状态 2 它是一个接受(识别)状态返回已经识别的 ID 同时这有一个*号,也就是要把刚刚都进来多读的 other 扔回到程序中去

在这里插入图片描述
标识符和关键字的交际
从词法分析的角度看,关键字是标识符的一部分。
以C语言为例:
标识符:以字母或者下划线开头,后跟零个或多个字母,下划线或数字
关键字:if,while,else,…

识别关键字
有两种方案可以选择:
1.由原来的状态转移图中拓展新的节点和边

在这里插入图片描述

在状态 0 中增加了新的边,此时状态 0 就发生了变化,变成了 [a-h j-z  A-z] 这里把 i 字母抠出来 单独放出来 i,
也就是它单独放到一个节点,它识别到 i 的话就回从 0 节点走向 3 节点。
在节点 3 也继续向下计数
在节点 4 是状态,也需要继续向下判断,是否是标识符 ifxy 这种就不是关键字

2.关键字表算法

  • 对给定语言中的所有的关键字,构造关键字构造的哈希表H。(因为我们知道对任意一个语言来说他们的关键字都是有限的确定集合)。
  • 对所有所有的标识符和关键字,先统一按标识符的转移图进行识别,识别完成后进一步查看表H中是否包含当前所识别的关键字。
  • 通过合理构造哈希表H(完美哈希)可以O(1)的时间来完成

这篇关于2.1~2.2词法分析的任务,词法分析器的手工构造的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/877632

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Python Invoke自动化任务库的使用

《PythonInvoke自动化任务库的使用》Invoke是一个强大的Python库,用于编写自动化脚本,本文就来介绍一下PythonInvoke自动化任务库的使用,具有一定的参考价值,感兴趣的可以... 目录什么是 Invoke?如何安装 Invoke?Invoke 基础1. 运行测试2. 构建文档3.

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五