编译原理笔记8:语法分析(2)上下文无关文法 CFG

news2024/11/20 3:36:37

目录

    • CFG 概述及其四元组表示
    • 产生式集合表示 CFG
    • CFG,用推导,产生语言
      • 直接推导
      • 由 CFG 产生语言
        • 在?为啥从右往左叫规范?凭什么歧视左?
      • 总结一下这些奇奇怪怪的东西

前几篇博客中说到的词法分析,做的是从 【x+y → id+id】 的工作,也就是要将源代码变成一个记号流。语法分析,就是要通过为这个记号流序列(在“龙书”中,该序列被称为“词法单元序列”)构造一棵语法分析树,构造该树的方式就是“推导”(事实上,分析树其实是推导的图形化表示)。

若能够进行这样的推导: E=>E+E=>id+E=>id+id,即由 E 推出了 id+id,与从词法分析器那里得到的 id+id 相同,则说明语法结构正确。

CFG 概述及其四元组表示

CFG 是什么 ? CFG 是描述语言语法的工具,CFG 通过推导的方式产生语言。 我们使用这个工具来对定义我们的语法,然后可以使用一些算法来基于它构造我们想要的词法分析器!这个分析器能够将我们的记号流构造为合法的语法树。

 类似于我们在这里学过的很多其他东西,CFG 也一样可以使用四元组表示:

 CFG G=(N, T, P, S)

 该四元组中的 N、T、P 都是集合,分别是 非终结符(Nonterminals)、终结符(Terminals)、产生式(Productions) 的集合。S(Start Symbol) 是文法的开始符号,是一个特殊的非终结符。

其中:

  • N 和 T 没有交集;
  • P 的形式是 A→a,A∈N,a∈(N∪T)*(终结符或非终结符组成的一个串),箭头左侧的被称为左部,右侧的被称为右部
与 CFG 相对的,还有一种文法叫做“上下文有关文法”即 CSG(Context Sensitive Grammar),

int i;
i = 10; // 这就叫CSG,下面 i 的值要和上面声明的相关
下面这种就是 CFG:
int i;
i = “abc”;

然而,CFG 也可以使用符号表来处理上下文有关的情况。例如,当我们读到 “int i;” 时,就将 i 放入符号表中存储下来,当我们后面遇到 “i=10;” 时,就要到符号表中查找是否有已经声明过的 i 存在。注意,这种处理上下文有关的方式不属于语法分析的方法。

例子:简单的算术表达式的 CFG 表示:

在这里插入图片描述

产生式中的 “ → ” 读作“定义为” / “导出为”,例如 “ E→E+E ” 读作 “E 导出为 E+E”,其表示 “算术表达式定义为两个算术表达式相加”。

注意,CFG 一旦定义完成,语法也随之定义完成了。因此,对于一个句子的合法性检查,就要根据我们定义的 CFG 来做。比如,如果按照上面这个例子的语法定义来看,“- - - - - id” 就是一个合法的句子,而 “ id - id ” 却不合法。若想要其合法,我们需要在产生式中追加 “ E→ E - E ” 。

产生式集合表示 CFG

然而,用四元组来表示 CFG 还是太麻烦,因此大佬们提出了这样一个简化的表达方式——只写产生式集合,然后其他的部分我们可以通过一些预先约定好的规定来通过产生式集合求出来。这样一来,我们就可以省略很多东西了,就像下面这个:

P:	E → E + E	(1)
	E → E * E	(2)
	E → (E)		(3)
	E → -E		(4)
	E → id		(4)

使用该表示方法的前提是文法本身没有错误(似乎是废话?)。我们做预先约定好的规定如下:

  1. CFG 的开始符号 S ,是第一个产生式的左部——这就把四元组的最后一项 S 定义出来了;

  2. N 是可以出现在产生式左边符号的集合——这就把四元组的第一项 N(非终结符) 定义出来了;

  3. T 是绝不出现在产生式左边的符号集合——这就把四元组第二项 P 定义出来了。
    注意,是只在右面出现的。像下面这种情况:

    E -> ID
    ID -> ab
    

    尽管上面的 ID 在第一行出现在了右边,到第二行却出现在左边,因此 ID 也是非终结符。在且仅在产生式右面的符号,才能叫作终结符。

因此,只要我们写出来 P ,整个四元组就都定义出来了——因为四元组中的其他三元都可以根据定义来从 P 中分类找出来

其实也可以写得更简单——就是用 | (或)符号来连接各个产生式,以省略多余的 E

比如:

E → E+E
	|E*E
	|(E)
	|-E
	|id
或
E → E+E|E*E|(E)|-E|id

这种产生式表示也被称为“巴克斯范式”(BNF, Backus Naur Form),其中 → 用 ::= 表示。

这种书写方法中,每个右部的权利是相同的,因为当我们说 “ a 或 b ” 时,并没有同时表达出来 “ a 重要还是 b 重要 ”的意思,我们也不能简单地因为 a 在 b 的前面而推断 a 比 b 更重要。这里的“权利”与文法的二义性有关。

终结符与非终结符还可以用下面的不同写法进行区分:

  1. 大小写区分: E → id
  2. 用双引号区分:E → “id” E → E “+” E
  3. 用尖括号区分:E → <E> + <E>

CFG,用推导,产生语言

推导,实际上就是得到 CFG 所定义的语言的过程。

回忆正规式——写正规式的时候,就已经有“产生”的含义在里面了

在正规式的定义中,我们可以说

a|b是一个正规式,它表示的正规集是:a表示的语言和b表示的语言取并集

——注意看这句话——正规式表示正规集,正规集是两个语言的并集,那么也就是说正规式表示语言的集合。我们已经在定义正规式的时候把语言定义出来了!

正规式定义的时候,正规集这个语言就已经随之定义完了;但是在定义 CFG 的时候,我们可没有说“CFG产生的语言”这类的话,也就是说在我们写下 CFG 时,这个语言并没有被随 CFG 定义出来。

因此,我们要单独考虑怎么定义语言——语言,可以由 CFG 通过推导产生,我们通过推导得到 CFG 所定义的语言。

通俗地讲,产生式产生语言的过程,就是从 S 开始,对产生式左部的非终结符反复地使用产生式:将产生式左部的非终结符替换为右部的文法序列(用 => 表示展开产生式),直到得到一个终结符序列。
在这里插入图片描述

在这里插入图片描述

利用产生式产生句子。左侧是产生式,产生式定义语法。右侧是根据左侧的规则进行的几步推导过程。右边这几行式子的每一行推导符号右侧的符号序列就叫做“文法符号序列”。

直接推导

推导,就是把非终结符按照产生式一步步换成终结符的过程。

利用产生式产生句子的过程中,将产生式 A → γ 的右部代替文法符号序列 αAβ 中的 A 得到 αγβ 的过程,称 αAβ 直接推导出 αγβ ,记作 αAβ => αγβ

若对于任意文法符号序列 α1, α2, …αn,均有 α1=>α2=>…=>αn,则称此过程为零步或多步推导,记为 α1=*>αn,当 α1=αn 时称为零步推导。

若α1≠αn,即推导过程中至少使用一次产生式,则称此过程为 至少一步推导,记作 α1=+>αn

说白了。。根据产生式所描述的规则进行代入替换,这里分清楚两种箭头就行了:→描述推导可以使用的规则,=>描述推导的过程。

推导有自反性(对任意的 α,都有 α=*>α)和传递性(若 α=*>β, β=*>γ, 则 α=*>γ)。

推导,是一种二元关系

一个元素如果和它自己满足该二元关系,那么它就是自反的

即 aRa

由 CFG 产生语言

由 CFG G 产生的语言 L(G) 定义为:

  • L(G) = {ω | S=+> ω and ω∈ T* }

    其中:

    • S=+>ω:开始符号 S 经过至少一步推导,能够推出 ω
    • ω∈ T*:ω 是由终结符组成的一个串

    上面这两条合在一起,就可以保证我们能基于这套规则来从开始符号推出词法分析器给我们的那个终结符串。基于此推出来的集合,就是语法规则所描述的语言。

该 L(G) 被称为 上下文无关语言(Context Free Language,CFL),ω 被称为句子

  • 若 S=+>α ,α∈(N∪T)*,则称 α 为 G 的一个句型

    其中:

    • α∈(N∪T)*:推导过程中的 α 时终结符和非终结符组成的一个串。
    • 句型可含终结符、非终结符。而句子只能包含终结符,句子是句型的特例。

    (句型,是句子的模型,有句子的结构和特征,是句子的半成品)

在推导的过程中,若每次直接推导均替换句型中最左边的非终结符,则称为最左推导。由最左推导产生的句型被称为左句型。

右句型与之对称,最右推导也被称为规范推导

例如:E => E+E => E+id // 规范推导

在?为啥从右往左叫规范?凭什么歧视左?

其实这个和语法分析的方式有关。有两种语法分析方式,分别是最左推导的自上而下方式和最右推导的自下而上方式。前者虽然与人的思考方式类似,但其实际的语法分析能力是比较差的,因此实际应用中主要从下向上构造语法树。

下图是自下而上构造分析树,推导方式是自下而上。

在这里插入图片描述

总结一下这些奇奇怪怪的东西

推导,就是得到 CFG 所定义的语言的过程。语言是一个集合,集合中的任何一个元素都是一个句子。推导过程中得到的串叫做句型,句型可以包含终结符和非终结符。

  • 语言,是以【从开始符号进行至少一步推导得到的】终结符串为元素的集合;
  • 推导,是 CFG 推导得到语言的过程,CFG 中的核心就是产生式;
  • 产生式,是用于描述非终结符替换规则的式子;
  • 分析语法,需要构造语法分析树;
  • “自上而下”、“自下而上” 都是语法分析的方式;

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

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

相关文章

驱动开发:内核注册表增删改查

注册表是Windows中的一个重要的数据库&#xff0c;用于存储系统和应用程序的设置信息&#xff0c;注册表是一个巨大的树形结构&#xff0c;无论在应用层还是内核层操作注册表都有独立的API函数可以使用&#xff0c;而在内核中读写注册表则需要使用内核装用API函数&#xff0c;如…

Spring Cloud灰度部署

1、背景(灰度部署) 在我们系统发布生产环境时&#xff0c;有时为了确保新的服务逻辑没有问题&#xff0c;会让一小部分特定的用户来使用新的版本&#xff08;比如客户端的内测版本&#xff09;&#xff0c;而其余的用户使用旧的版本&#xff0c;那么这个在Spring Cloud中该如何…

第五届双态IT北京用户大会回顾 | 基于运维数据治理的数智化转型

专题演讲人&#xff1a;擎创科技CTO 葛晓波 文末附有本场专题演讲视频 ●前言 各行业的云原生发展程度各有不同&#xff0c;并不是所有业务应用都适合云原生的形态&#xff0c;如若过度追求云原生化反而会使得企业运维压力骤增&#xff0c;运维成本激增。 从数字化转型的角度…

软考:软件工程:软件定义,特点,软件生命周期,软件危机,软件开发模型

软考&#xff1a;软件工程: 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &#xff08;1&#…

C++——vector容器模拟实现

目录 1. 基本成员函数 2. 默认成员函数 2.1 构造函数 2.2 析构函数 2.3 拷贝构造函数 2.4 赋值运算符重载函数 3. 容器访问相关函数 3.1 operator[ ]运算符重载 3.2 迭代器 3.3 范围for 4. vector空间增长问题 4.1 vector 容量和大小 4.2 vector扩容 4.3 重新定义…

均匀B样条采样从LiDAR数据中快速且鲁棒地估计地平面

文章&#xff1a;Fast and Robust Ground Surface Estimation from LiDAR Measurements using Uniform B-Splines 作者&#xff1a;Sascha Wirges, Kevin Rsch, Frank Bieder and Christoph Stiller 编辑&#xff1a;点云PCL 代码&#xff1a; https://github.com/KIT-MRT/poin…

全志V3S嵌入式驱动开发(编译器升级到7.5)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 看过我们文章的朋友都知道&#xff0c;前面为了做v3s的驱动&#xff0c;对linux kernel进行了两次升级。第一次升级是从4.10.y升级到4.14.y&#x…

【Python】open打开文件出现的错误解决

一、Python中关于打开open打开文件出现的错误解决 &#xff08;第一种&#xff09;UnicodeDecodeError: ‘utf-8’.......... &#xff08;第二种&#xff09;UnicodeDecodeError: ‘gbk’......... 二、问题解决 两种解决方式针对不同错误&#xff0c;实际应用中可以都试试…

PCB设计实验|第五周|LED显示电路PCB库设计|3月27日

目录 实验四 LED显示电路PCB库设计 一、实验原理 二、实验环境 三、实验结果 四、实验总结 实验四 LED显示电路PCB库设计 一、实验原理 LED(Light- Emitting-Diode中文意思为发光二极管)是一种能够将电能转化为可见光的半导体&#xff0c;它改变了白炽灯钨丝发光与节能…

裁剪图片软件有哪些?这些图片裁剪工具很好用

有哪些好用的图片裁剪软件呢&#xff1f;有时候&#xff0c;将一张大图缩小到更小的尺寸可以改善图片的质量&#xff0c;因为它可以减少像素和噪点。这对于那些需要在网上展示高质量图片的人来说尤其重要。裁剪后的图片可能更清晰、更锐利&#xff0c;并且更适合在各种设备上观…

Alex-Net 与 VGG-16

Alex-Net 由加拿大多伦多大学的 Alex Krizhevsky、Ilya Sutskever(G. E. Hinton 的两位博士生)和 Geoffrey E. Hinton 提出&#xff0c;网络名“Alex-Net”即 取自第一作者名。 下图所示是 Alex-Net 的网络结构&#xff0c;共含五层卷积层和三层全连接层。其中&#xff0c;Ale…

03.SELF-INSTRUCT+Alpaca

文章目录 前言泛读储备知识提示学习提示工程Promt Engineering答案工程 背景介绍研究SELF-INSTRUCT的动机研究意义&贡献 精读Overview种子任务步骤1&#xff1a;定义指令数据步骤2&#xff1a;自动指令数据生成步骤2.1指令生成步骤2.2指令分类步骤2.3实例生成步骤2.4筛选和…

19.组件之间传递数据

不同组件传递数据的时候&#xff0c;最好不要直接传递复杂数据类型(比如对象&#xff0c;数组) 前端需要处理的数据层级一般不会很多&#xff0c;需要在多处使用的数据一般会被放到数据库中 目录 1 组件的关系 2 父向子传递数据-props 3 子向父传递数据-自定义事件 4 …

分布式任务调度平台 XXL-JOB 实战

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

Scrum敏捷估算

无论是团队研发一款产品或者开发某一个项目&#xff0c;我们都需要回答“我们大概什么时间能够完成&#xff1f;”&#xff0c; 或者到某一个时间点&#xff0c;我们能够做到什么程度&#xff0c; 因此和传统的开发模式一样&#xff0c;我们在工作开始之前需要对我们需要做的事…

Linux Vim基本操作(文件的打开和编辑)完全攻略(有图有真相)

首先学习如何使用 Vim 打开文件。 Vim 打开文件 使用 Vim 打开文件很简单&#xff0c;例如在命令行模式下打开一个自己编写的文件 /test/vi.test&#xff0c;打开方法如下&#xff1a; [rootitxdl ~]# vim /test/vi.test 刚打开文件时 Vim 处于命令模式&#xff0c;此时文件…

CTFshow-pwn入门-前置基础pwn26-pwn28

什么是ASLR 大多数的攻击都基于这样一个前提&#xff0c;即攻击者知道程序的内存布局&#xff0c;需要提前知道shellcode或者其他一些数据的位置。因此&#xff0c;引入内存布局的随机化能够有效增加漏洞利用的难度&#xff0c;其中一种技术就是ASLR&#xff08;Address Space…

无线wifi视频传输方案|基于qca9531方案SKW99的无线视频流云端推送方案

为满足物联网智慧校园&#xff0c;智能家居&#xff0c;智慧工厂&#xff0c;智能交通、智慧博物馆、培训机构等不同行业实时直播的需求。本篇以集成200万高清摄像头功能的高通方案qca9531 wifi模块SKW99为为例&#xff0c;简单介绍基于WiFi技术的无线视频流云端推送方案。 1、…

上位机与两台PLC之间无线PPI通信

在实际系统中&#xff0c;人机界面与PLC通常不在一起&#xff0c;中心计算机一般放置在控制室&#xff0c;而PLC安装在现场车间&#xff0c;二者之间距离往往从几十米到几千米。如果布线的话&#xff0c;需要挖沟施工&#xff0c;比较麻烦&#xff0c;这种情况下比较适合采用无…

0基础学习VR全景平台篇第47篇:底部菜单-场景/分组复制功能

大家好&#xff0c;欢迎观看蛙色VR官方系列——后台使用课程&#xff01; 本期为大家带来蛙色VR平台&#xff0c;底部菜单—场景/分组复制功能操作。 功能位置示意 一、本功能将用在哪里&#xff1f; 平台用户在编辑作品时可以使用本功能将作品中的某一分组或者某一场景进行复…