笔记 | 编译原理L2:词法分析(lexical analysis)

news2024/12/21 23:39:40

1 概述

词法分析(lexical analysis),也称scanning, 编译程序的第一阶段,其作用是识别单词(程序意义上)并找出词法错误. 读入源程序的输入字符、将它们拆分成词素,生成并输出一个词法单元序列,每个词法单元对应于一个词素

image.png|500

回顾词法分析在整个编译过程的位置

![[【笔记】编译原理L1#^53d248| 回顾编译原理的各个模块顺序]]

1.1 词法分析的常见做法

  • 由语法分析器调用,需要的时候不断读取、生成词法单元。这样可以避免额外的输入输出。
  • 词法分析可以使用:[[【笔记】编译原理L2:词法分析(lexical analysis)#3.2 正则表达式 | RE]] 和 [[【笔记】编译原理L2:词法分析(lexical analysis)#3.4 正则语言(RL)| RL]]

Note:在识别出词法单元之外,还会完成一些不需要生成词法单元的简单处理,比如删除注释、将多个连续的空白字符压缩成一个字符

1.2 一些经典名词

词素(Lexeme)词法单元 (Token) <词法单元名、属性值(可选)>词性划分
源程序中的字符序列,它和某类词法单元的模式匹配,被词法分析器识别为该词法单元的实例。单元名是表示词法单位种类的抽象符号,语法分析器通过单元名即可确定词法单元序列的结构, 是有意义最小的程序单位。属性值通常用于语义分析之后的阶段image.png根据作用对程序子串进行分类image.png
  1. 词法分析的输出是单词(token)的序列<词法单元名、属性值(可选)>:
    image.png
  2. Token序列将作为语法分析程序的输入:
  3. 一个具体的示例:
    image.png

2 语言的定义

2.1 什么是语言

  1. 作用:沟通,交流,传递信息
  2. 自然语言:英语,中文,日语

2.2 你如何定义语言?

  1. 无限的集合
  2. 抽象地来看:字符组成了单词; 单词组成了句子; 句子携带了信息
  • 语言是形式化的内容提取——单词、句子、语言:是三种不同的语言
单词(Token)句子(Sentence)语言(Language)
满足一定规则的字符(Character)串满足一定规则的单词序列满足一定条件的句子集合

示例:程序设计语言:形式化的内容提取

程序设计语言(Programming Language)程序(Program)语句(Sentence)单词(Token)
组成程序的所有语句的集合。满足语法规则的语句序列满足语法规则的单词序列。满足词法规则的字符串
  • 语言是字和组成字的规则
    “doge”(it’s not a word ): reserved words and some rules forwords (词法)
    “Long time no see”(It’s not a correct sentence): rules forsentences(语法)
    检查单词错误是词法负责的范畴,检查句子错误是语法负责的范畴

  • 语言是用有限的规则来描述的无限集

  • 语言的组成部分

符号 (Symbol/Character)字母表符号串(字符串)
语言中不可再分的单位符号的非空有穷集合,Σ,V或其它大写字母, 其中的元素可称为字母、符号、字符。例如:V1 = {a, b, c}, V2 = {+, -, 0, 1, …,9}, Σ= {x|x∈ASCII字符}某字母表上的符号的有穷序列。a, b, c, abc, bc,…:V1上的符号串; 1250, +2, -1835,…:V2上的符号串。空串(ε):不含任何符号的串
  1. 语句: 字母表上符合某种构成规则的符号串序列。
  2. 语言 L:某字母表上的语句的集合: L(Σ); 注意:定义在同一个字母表上的语言有很多!
    比如:Σ定义了语言中允许出现的全部符号;若Σ = 英文字母,L(Σ)是英文句子, 若Σ = ASCII字符, L(Σ)可以定义成C语言程序,但也可以定义成Java程序或者其他的程序语言,这里就可以构成多种语言。(此现象产生的原因:L(Σ)是字符串集合,但不是包含Σ上任意的字符串,而是满足某种规则的字符串——引出了我们要如何定义规则?

2.3 如何定义规则

文法(G, Grammar): 四元组G = ( V N V_{N} VN , V T V_{T} VT , S S S, P P P ),其中:

V N V_{N} VN V T V_{T} VT S S S P P P
一个非空有限的非终结符号集合,它的每个元素称为非终结符,一般用大写字母表示,它是可以被取代的符号;一个非空有限的终结符号集合,它的每个元素称为终结符,一般用小写字母表示, 是一个语言不可再分的基本符号一个特殊的非终结符号,称为文法的开始符号或识别符号, S S S V N V_{N} VN, 开始符号S必须至少在某个产生式的左部出现一次;image.png
产生式的有限集合。所谓的产生式,也称为产生规则或简称为规则,是按照一定格式书写的定义语法范畴的文法规则。词法、语法都是这样定义的
  • 描述形式——文法
  1. 语法——语句:语句的组成规则。描述方法:BNF范式、产生式
  2. 词法——单词:单词的组成规则。描述方法:BNF范式、产生式、正规式

[!Note]- 文法示例
(1)自然语言文法示例:
image.png
image.png
image.png
(2) 程序语言文法示例:
image.png
image.png

  • 文法规则的递归定义:

    • 非终结符的定义中包含了非终结符自身
    • 设Σ={0,1}; <整数>-><数字><整数>|<数字>; <数字>->0 | 1
    • 使用递归定义时要谨慎,要有递归出口,否则可能永远产生不出句子
  • 扩充的BNF表示
    image.png

2.4 符号串的基本概念

符号串连接符号串方幂符号串前缀后缀符号串子串符号串子序列
x和y的连接xy是把y的所有符号顺序地接在x的符号之后所得到的符号串设x是字母表∑上的符号串,把x自身连接n次得到的符号串z, 即z = xx…xx(n个x),称作符号串x的n 次幂,记作 z = x n z = x^{n} z=xn设x、y、z是某一字母表上的符号串,x = yz,则y是x 的前缀,z 是x的后缀; z≠ε 时y是x的真前缀, y≠ε时z 是 x 的真后缀非空字符串x,删去它的一个前缀和一个后缀后所得到的字符串称为 x 的子字符串,简称子串。如果删去的前缀和后缀不同时为ε,则称该子串为真子串从s中删去零或多于零个符号(这些符号不要求连续),这里也体现了符号串子串是要求连续的。
符号串逆转(用SR表示)符号串长度符号串集合(语言)的积字符串集合(语言)的方幂
将S中的符号按相反次序写出而得到的符号串是该符号串中的符号的数目。例如|aab|=3,|ε|=0image.png
image.png
字符串集合(语言)的Kleene闭包字符串集合(语言)的正闭包
image.png
image.png
**语言L(Σ)就是其字母表(把字母表看作是由Σ

3 正则文法

image.png|375

3.1 Chomsky 3型文法:正规(正则)文法

image.png

也称为正规文法RG、线性文法:若所有产生式均是左线性,则称为左线性文法;若所有产生式均是右线性,则称为右线性文法。

注意:产生式要么均是右线性产生式,要么是左线性产生式,不能既有左线性产生式,又有右线性产生式。

3.2 正则表达式

  1. 定义正则语言(regular languages, RL)的标准工具
  2. 其定义的集合叫做正则集合(regular set)
  3. 词法单元的规约
  4. 识别3型语言的自动机称为有限状态自动机(FA)。
3.2.1 正则表达式中的四种运算的作用
括号®或运算 |连接运算 ·*运算
不改变r表示,主要是用于确定运算优先关系表示“或”关系表示连接,经常省略,如r·s也可表示为rsr*表示对r所描述的文本进行0到若干次循环连接
3.2.2 定义正则表达式

image.png

  • 实际应用中也会扩充很多正则表达式的运算,比如:
    r + r^{+} r+也是 ∑ \sum 上的正则表达式,表示的正则集 L ( r + ) = ( L ( r ) ) + L(r^{+}) = (L(r))^{+} L(r+)=(L(r))+.
    +代表前面的字符至少出现一次,而*代表前面的字符可以不出现,也可以出现一次或者多次

  • 运算符的优先级:* > 连接符 > |, 示例:(a)|((b)*©) 可写为 a|b*c

  • 正则表达式的作用和产生式等价

强调一下Σ的含义:表示的是语言中允许出现的全部符号

3.2.3 正则定义(类似define)

给正则表达式起个名字,避免过长的RE定义

示例:定义整数的正则表达式:

Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Integer = Digit+

理解:有点像C++中的宏定义define,可以简化表达。

3.2.4 正则文法示例(邮箱地址)

image.png

PS: 在使用regular识别工具时,.需要转义。另外,可以有一些简化写法,例如使用^和$识别开头结尾

3.2.5 正则表达式运算的性质

image.png

3.3 正则表达式和正则文法的关系

两者等价,可以互相转化

3.4 正则语言(RL)

概念:正则语言(regular language, RL):可用一个正则表达式定义的语言叫做正则语言, 一般地,程序设计语言的单词是正则语言,可用RE定义

正则表达式局限性:RE 不能定义具有对称结构嵌套结构的语言

image.png

4 有限状态自动机

4.1 有限状态自动机概述

正则表达式 – specification(便于书写理解);有限自动机 –Implementation(便于计算机执行)。有限自动机是描述有限状态系统的数学模型. 在很多领域,如网络协议分析、形式验证、代码安全、排版系统等有重要应用。

[!info]- 什么是有限系统?
状态:是将事物区分开的一种标识
具有离散状态的系统:如数字电路(0,1);电灯开关(on,off);十字路口的红绿灯;其状态数是有限的。
具有连续状态的系统:水库的水位、室内的温度等可以连续发生变化;可以有无穷个状态.
有限状态系统是离散状态系统。

有限自动机FA可以理解成状态控制器

  • FA有有限个状态,其中有初始状态,终止状态
  • 起始:处于初始状态,读头位于输入带开头
  • 中间:从左到右依次读取字符,发生状态迁移
  • 结束:读头到达输入带末尾,状态到达终态

4.2 有限自动机例子——经典的过河问题

一个人带着一头狼,一头羊,以及一棵白菜处于河的左岸。人和他的伴随品都希望渡到河的右岸。有一条小船,每摆渡一次,只能携带人和其余三者之一。如果单独留下狼和羊,狼会吃羊;如果单独留下羊和白菜,羊会吃菜。怎样才能渡河,而羊和白菜不会被吃掉呢?

image.png

从图中找出初始状态到目标状态的一条有向路,就是这个问题的一个解

4.3 有限自动机的五要素

  • 有限状态集 SS — 结点
  • 有限输入符号集 Σ
  • 转移函数 δ ( s , a ) = t \delta (s,a) = t δ(s,a)=t
  • 一个开始状态s0
  • 一个终止状态集 TS
  1. 输入:字符串
  2. 输出:若输入字符串结束,且到达终止状态,则接受,否则拒绝

image.png

例如:“101” 输出拒绝,“1010”输出接受。

词法分析器扫描输入串过程中,寻找和某个模式匹配的次数,转换图中每个状态代表一个可能在这个过程中出现的情况.

image.png

有穷自动机是识别器,只能对每个可能的输入串回答:是 或 否

4.4 确定有限自动机DFA

image.png

4.4.1 DFA的两种转换形式

状态转换图 :用有向图表示自动机,比较直观,易于理解;

image.png

状态转换矩阵:用二维数组描述自动机,易于程序的自动实现;

image.png

转换表的优点是能够很容易地确定和一个给定状态和一个输入符号相对应的转换。缺点是如果输入字母表很大,且大多数状态在大多数输入字符上没有转换的时候,转换表要占用大量空间。

注意转换矩阵中,初始状态和终止状态需要用特殊符号表示。

4.4.2 DFA的确定性
  • 形式定义
    • 初始状态唯一:S0
    • 转换函数是单值函数,即对任一状态和输入符号,唯一地确定了下一个状态
    • 没有输入为 ε \varepsilon ε空边,即不接受没有任何输入就进行状态转换的情况
  • 转换表上的体现
    • 初始状态唯一:第一行
    • 表元素唯一
  • 转换图上的体现
    • 初始状态唯一:
    • 每个状态最多发出n条边,n是字母表中字母的个数,且发出的任意两条边上标的字母都不同
4.4.3 DFA接受的字符串

image.png

DFA M接受的所有串的集合,称为M定义的语言,记为 L(M)

一些特殊情况:

image.png

4.4.4 DFA的实现
转换表方式转换图方式
是通用的算法,不同的语言,只需改变输入的转换表,识别程序不需改变不需要存储转换表(通常转换表是很大的),但当语言改变即自动机的结构改变时,整个识别程序都需要改变

4.5 非确定有限自动机

image.png

与DFA的区别:不要求转化函数是单值函数。不过NFA也可以用状态转换图或状态转换矩阵表示

4.5.1 NFA接受的字符串

image.png

转换路径中的 ε \varepsilon ε将被忽略,因为空串不会影响构建得到的字符串,NFA所能接受的串与DFA是相同的,但NFA实现起来很困难, NFA M接受的所有串的集合,称为M定义的语言,记为 L(M)

4.6 NFA v.s. DFA

4.6.1 总体区别

image.png

  • 对于确定的输入串,DFA只有一条路径接受它
  • NFA则可能需要在多条路径中进行选择!
  • NFA和DFA都可以模拟RE,NFA可转换成DFA
4.6.2 两者接受的字符串(可以等价)

image.png

4.6.3 由NFA构造DFA

构造方法:

image.png

4.6.3.1 子集法

image.png

核心思想:找出当N读入某个输入串之后可能位于的所有状态集合

  1. ε \varepsilon ε-closure(T): 对于给定的 NFA A, 和它的一个状态集合 T, T的空闭包计算如下:

image.png

  1. Move(T, a):对于NFA N中的给定状态集合T和符号 a, Move(T, a) = {s | 对于状态集T中的一个状态s1, 如果A中存在一条从s1到s的a转换边}

image.png

  1. 构造Dtran
    • 我们需要找出当N读入了某个输入串之后可能位于的所有状态集合。
    • 首先,在读入第一个输入符号之前,N可以位于集合 ε \varepsilon ε-closure(s0)中的任何状态上,其中s0是N的开始状态。下面进行归纳定义。
    • 假定N在读入输入串x之后可以位于集合T中的状态上。如果下一个输入符号是a,那么N可以立即移动到move(T,a)中的任何状态。然而,N可以在读入a后再执行几个8转换,因此N在读入a之后可位于 ε \varepsilon ε-closure(move(T,a))中的任何状态上

4.7 RE v.s. NFA/DFA

对∑上的每一个正则表达R,存在一个∑上的非确定有限自动机N,使得 L(N) = L®, N可以通过子集法得到与之等价的确定有限自动机D

image.png

4.7.1 从RE生成FA,用来模拟RE的实现

方法一:RE -> NFA -> DFA -> 最小DFA

image.png

归纳规则:

  1. 对于r = s | t

image.png

  1. r = st

image.png

  1. r = s ∗ r = s^* r=s

image.png

方法二:RE -> DFA -> 最小DFA

  1. 首先先构造语法分析树,并标记位置
  2. (a|b)*abb -> (a|b)*abb# (增广正则表达式(r)#)

image.png

  1. NFA的重要状态:NFA状态有一个标号非 ε \varepsilon ε的离开转换,则称该状态为重要状态(important state) — 子集法在计算move(T, a)的时候,只使用了重要状态
  2. 计算四个函数nullable, firstpos, lastpos, followpos
    1. nullable(n) returns true or false:表示以n为根结点推导出的句子集合是否包括空串,“是”则nullable(n)=true;“否”则nullable(n)=false
    2. firstpos(n)定义了以结点n为根推导出的某个句子的第一个符号的位置集合
    3. lastpos(n)定义了以结点n为根推导出的某个句子的最后一个符号的位置集合—规则在本质上和计算firstpos的规则相同,但是在针对cat结点的规则中,左右子树的角色要对调

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

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

相关文章

jpa分页插件对象Pageable出现了错误异常如何解决?

jpa分页插件对象Pageable出现了错误异常如何解决&#xff1f;&#xff01; 一般来说&#xff0c;遇到这种的错误异常情况&#xff0c;通常情况 下&#xff0c;都是因为程序员把传递的分页页码数字写错了。 正常情况下&#xff0c;分页页码起始数字应该是0&#xff1b;而不是1…

OpenCASCADE(OCC)读入含中文汉字标签的内容后乱码的解决方法

笔者在导入一个由SolidWorks生成的step文件的时候&#xff0c;节点名称是中文&#xff0c;于是乎生成的节点树的名称都是乱码了&#xff0c;经过多次的排查调研&#xff0c;最后的解决办法如下&#xff1a; 1.老版本的occ库&#xff0c;是无法兼容读入中文编码的step文件的&am…

Linux 学习之路 -- 进程篇 -- 进程控制

目录 一、进程终止 <1>使用语言和系统自带的方法&#xff0c;进行转换 <2>自定义错误码 <3>小结&#xff1a; <2>两个接口exit / _exit 二、进程等待 <1>简单了解 <2>wait调用 <3>waitpid调用 <4>status <1>W…

Laravel 6 - 第十四章 响应

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

debian配置distcc分布式编译

前言 distcc 是一个用于在网络上的多台机器上分发 C、C、Objective C 或 Objective C 代码构建的程序。 distcc 应始终生成与本地构建相同的结果&#xff0c;易于安装和使用&#xff0c;并且通常比本地编译快得多。 distcc 不要求所有机器共享文件系统、同步时钟或安装相同的…

【目录】Armv8/Armv9付费专栏

快速链接: . &#x1f449;&#x1f449;&#x1f449; ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; 付费专栏-付费课程 【购买须知】:联系方式-加入交流群 ----联系方式-加入交流群 个人博客笔记导读目录(全部) 目录 【Arm基础】【指令和寄…

在AI工业变革的拐点,迎来AI智算“安卓时刻”

今天&#xff0c;我们正在进入AI的工业变革拐点期。所谓AI的工业变革&#xff0c;主要指以大模型AI所引发的通用AI和以通用AI为目标构建的工业标准化AI智算基础设施。 在通用计算时代&#xff0c;X86所代表的工业标准化技术体系造就了企业IT、互联网与云数据中心。而在智算时代…

Mysql索引详解(索引分类)

文章目录 概述索引对查询速度的影响索引的优缺点索引类型一级索引和二级索引的区别MySQL 回表联合索引&#xff08;最左前缀原则主键索引和唯一索引的区别BTree索引和Hash索引的区别 覆盖索引索引下推加索引能够提升查询效率原因MySQL 索引结构采用 B树原因索引失效的场景MySQL…

油管评论抓取软件,专为文科生、小白用户开发!

我用Python开发的youtube评论采集软件&#xff0c;爬取到的字段包含&#xff1a; 评论id、评论内容、评论时间、评论作者昵称、评论作者频道、点赞数 软件界面效果&#xff1a; 采集结果数据&#xff1a; 软件使用注意事项&#xff1a; 详细讲解文章&#xff1a; https://…

1-35 集合框架

一 集合的介绍 1.集合是 Java 提出用来进行多个数据存储的 "容器" , 那数组同样具备这样的功能 , 为什么还要有集合 , 数组一旦创建长度固定 , 只能存放一种数据类型 , 不够灵活,因此 Java提出更灵活的操作 , 存放任意引用数据类型 的 容器 -- 集合 2.分类 ①单列…

变电站的组成、作用及功能

变电站的组成、作用及功能 变电站是电力系统的重要组成部分&#xff0c;主要用于实现电力输送、配电和转换的功能。它是将高压电力系统变成低压电力系统的中间站点&#xff0c;它可以将高压输电线路传输的电能通过变压器进行调整&#xff0c;将电能变成适应于城市、乡村和工矿企…

STM32F103单片机C语言模块化编程实战:按键控制LED灯并串口打印详解与示例

一、开发环境 硬件&#xff1a;正点原子 STM32F1精英版 开发板 单片机&#xff1a;STM32F103ZET6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F1 V1.8.5 虽然这里演示的是STM32F103&#xff0c;但是STM32F40…

STM32cubemx和HAL库的使用入门--点亮一颗LED

一&#xff1a;流程介绍 &#xff08;1&#xff09;环境搭建 1 &#xff1a;stm32cubemx安装 2 &#xff1a;stm32xxFW安装 3 &#xff1a;MDK5安装 4 &#xff1a;生成MDK版本project &#xff08;2&#xff09;stm32cubemx创建工程&#xff0c;选择芯片型…

Python中pyside2出现的pyside2 qt platform plugin could be in错误及其解决方法

系统平台&#xff1a;Win10 64bit python版本&#xff1a; python 3.8 使用pip install pyside2安装 pyside2 这是找不到QT平台的插件&#xff0c;这是环境变量QT_QPA_PLATFORM_PLUGIN_PATH出现错误 具体解决方法&#xff1a; 我们可以在每一段程序开始之前设定环境变量&…

Shader实战(3):贴图像素化风格实现

话不多说&#xff0c;将以下shader赋给材质贴上贴图即可。 Shader "HQY/Shader2" //自己改名 {Properties{_Diffuse ("Diffuse", Color) (1,1,1,1)_MainTex ("MainTex", 2D) "white" {}_Specular("Specular", Color) (…

JavaScript 数学对象 Math

Math对象其实就是数学对象&#xff0c;它给我们提供了各种各样的数学功能。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</title> </head><body><script type"text/javascript"&g…

1.3 初探Spring AOP

本次课&#xff0c;我们深入了解了Spring框架中的AOP&#xff08;面向切面编程&#xff09;概念&#xff0c;它是一种编程范式&#xff0c;用于处理那些在多个类中重复出现、与业务逻辑无关的横切关注点&#xff0c;如日志记录、事务管理等。AOP与OOP&#xff08;面向对象编程&…

【Linux系列】 离线安装vnc 可视化桌面

离线安装vnc 可视化桌面 缘下载安装vnc初始化链接 缘 项目需要下载 下载地址&#xff1a; http://mirror.centos.org/centos/7/updates/x86_64/Packages/tigervnc-license-1.8.0-31.el7_9.noarch.rpm http://mirror.centos.org/centos/7/os/x86_64/Packages/libXfont2-2.0.…

38. UE5 RPG 修改火球术的攻击方向以及按住Shift攻击

在前面&#xff0c;我们实现了火球术火球的制作&#xff0c;能够在释放火球术时&#xff0c;角色将播放释放技能动画&#xff0c;并实现了对火球的目标的服务器同步功能。 我们先回忆一下之前完成的内容。 在前面&#xff0c;我们先做了一个Actor&#xff0c;用于承载发射的火…

《九》Qt各种对话框之QColorDialog

前言 QColorDialog类继承于QDialog&#xff0c;是一个设计用来选择颜色的对话框部件。 QColorDialog 在介绍 QColorDialog 之前&#xff0c;我们先简单介绍一下 QColor 类。QColor 类用于表示颜色&#xff0c;支持 RGB&#xff08;红绿蓝&#xff09;三原色表示&#xff0c;也…