写这篇博客的原因,是因为考试前以为自己已经将这个问题弄清楚了,但是,考试的时候,发现自己还是不会,特别是求follow集合。虽然考试结束了,希望屏幕前的你,可以真正理解这个问题。

码字和做视频都不容易,可以三连吗?嗷呜~

讲解视频

博客对应的视频教程地址(一定要看看):https://www.bilibili.com/video/BV17K4y1a72M#reply4409274160

视频中的一些问题

下面列举的问题可以先不看,等到视频看完,再拉到对应的时间点看视频中小小的错误

视频的05:12 剪辑视频的时候写错了,正确的应该是First(β)
视频的07:11 忘记计算First(T)和Follow(T),笔记中补了
视频的12:03 First(E')和First(T')应该用逗号分隔



First集

官方定义

设G=(VT,VN,S,P)是上下文无关文法 ,则

理解定义

不求信达雅,但求“说人话”。官方定义看不懂?下面的描述比较通俗易懂。

FIRST(A)是以A的开始符的集合,A的所有可能推导的开头终结符或者是ε

例子

通过例子来加强理解。

  1. 后面跟的不是非终结符
...
A->aB|ε
A->c
...
First(A)={a,ε,c}
  1. 后面跟非终结符(一)
...
A->Ba
B->b
...
First(A)={b}
  1. 后面跟非终结符(二)
...
A->Bc
B->b|ε
...
First(A)={b,c}
  1. 后面跟非终结符(三)
...
A->BC
B->b|ε
C->c|ε
...
First(A)={b,c,ε}

Follow集

相对于First集,Follow集的理解会稍微难一点,但是认真听,还是简单的。

官方定义

这个是信达雅版本的定义

假定S是文法G的开始符号,对于G的任何非终结符A,我们定义

理解定义

这个是“说人话”版本的定义

Follow(A)为非终结符A后跟符号的集合,Follow(A)是所有句型中出现在紧接A之后的终结符或'#'

求解规则

(1)对于文法的开始符号S,置#于Follow(S)中;

(2)若A->αBβ是一个产生式,则把First(β) \ {ε} 加入到Follow(B)中

(3)若A->αB是一个产生式,或A->αBβ是一个产生式且β=>ε,则把Follow(A)加入到Follow(B)中

理解求解规则

(1)对于开始符号,首先将#放入Follow集中

(2)形如A->αBβ

(α可以是终结符或者非终结符或者直接为空,β可以是终结符或者非终结符,注意β不能为空,B后面要有东西注意β不能为空,B后面要有东西注意β不能为空,B后面要有东西

比如

A->aBC
A->aBd
A->BC
A->Bd

将First(β) \ {ε}(即First(β)除去ε) 加入到Follow(B)中

(3)形如A->αB(α可以是终结符或者非终结符或者直接为空)或者A->αBβ是一个产生式且β=>ε

比如

A->B
A->cB A->dBC
C->ε

将Follow(A)加入到Follow(B)中

综合例子

让我们通过例子来对上面的知识点进行梳理和再次的理解。

综合例子一

注意:[if] 是一个终结符,同理[b] [other] [else] [then]

G(S):S->IETSP|O
I->if
E->b
O->other
L->else
T->then
P->LS|ε
First Follow
First(S)={if,other} Follow(S)={#,else}
First(I)={if} Follow(I)={b}
First(E)={b} Follow(E)={then}
First(O)={other} Follow(O)={else,#}
First(L)={else} Follow(L)={if,other}
First(P)={else,ε} Follow(P)={else,#}
First(T)={then} Follow(T)={if,other}

综合例子一 中反馈的问题:

在求Follow(S)发现P->LS|ε也是存在的,那么follow(s)={#,else}+follow(p),而算到follow(p)发现follow(p)=follow(s) 就不知道怎么算了

解答:(很重要,认认真真的看)

我们需要同时满足
follow(s)={#,else}+follow(p)
follow(p)=follow(s)
将第二个式子带入一式得到
follow(s)={#,else}+follow(s)
注意:不能将follow(s)约掉,而是要想怎么样上面的等式仍然成立
那么,我们就会发现follow(s)只能等于{#,else}
因为 {#,else}={#,else}+{#,else}是成立的

综合例子二

G(E):E->TE'
E'->+TE'|ε
T->FT'
T'->*FT'|ε
F->(E)|i
First Follow
First(E)={(,i} Follow(E)={#,)}
First(E')={+,ε} Follow(E')={#,)}
First(T)={(,i} Follow(T)={+,#,)}
First(T')={*,ε} Follow(T')={+,#,)}
First(F)={(,i} Follow(F)={*,+,#,)}

综合例子三

G[S]: S→aH
H→aMd
H→d
M→Ab
M→ε
A→aM
A→e
First Follow
First(S)={a} Follow(S)={#}
First(H)={a,d} Follow(H)={#}
First(M)={a,e,ε} Follow(M)={d,b}
First(A)={a,e} Follow(A)={b}

综合例子四

G(E):E->TE'
E'->+E|ε
T->FT'
T'->T|ε
F->PF'
F'->*F'|ε
P->(E)|a|b|^
First Follow
First(E)={(,a,b,^} Follow(E)={#,)}
First(E')={+,ε} Follow(E')={#,)}
First(T)={(,a,b,^} Follow(T)={+,#,)}
First(T')={(,a,b,^,ε} Follow(T')={+,#,)}
First(F)={(,a,b,^} Follow(F)={(,a,b,^,+,#,)}
First(F')={*,ε} Follow(F')={(,a,b,^,+,#,)}
First(P)={(,a,b,^} Follow(P)={*,(,a,b,^,+,#)}

综合例子四中反馈的问题:

怎么求follow(E)和follow(E‘)?

根据G(E)和规则一,#加入follow(E)
根据P->(E)|a|b|^和规则二,)加入follow(E)
根据E'->+E|ε和规则三,将follow(E')到follow(E)里面 根据E->TE'和规则三得到将follow(E)到follow(E‘)里面 =>
Follow(E)={#,)}+Follow(E')
Follow(E')=Follow(E)
根据综合例子一中一样的分析方法
Follow(E)={#,)}+Follow(E)=>Follow(E)={#,)}

【编译原理】求First和Follow的更多相关文章

  1. 编译原理——求解First,Follow,Firstvt和Lastvt集合

    转载地址 http://dongtq2010.blog.163.com/blog/static/1750224812011520113332714/ 学编译原理的时候,印象最深的莫过于这四个集合了,而 ...

  2. 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

    近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIR ...

  3. 《编译原理》-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法

    <编译原理>-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 此编译原理确定某高级程序设计语言编译原理,理论基础,学习笔记 本笔记是对教材< ...

  4. 《编译原理》画 DAG 图与求优化后的 4 元式代码- 例题解析

    <编译原理>画 DAG 图与求优化后的 4 元式代码- 例题解析 DAG 图(Directed Acylic Graph)无环路有向图 (一)基本块 基本块是指程序中一顺序执行的语句序列, ...

  5. 《编译原理》求 FIRSTVT 集和 LASTVT 集的步骤 - 例题解析

    <编译原理>求 FIRSTVT 集和 LASTVT 集的步骤 - 例题解析 算符优先关系表的构造中涉及到求 FIRSTVT 集和 LASTVT 集. 表示及含义: FIRSTVT(T) 非 ...

  6. 编译原理简单语法分析器(first,follow,分析表)源码下载

    编译原理(简单语法分析器下载) http://files.cnblogs.com/files/hujunzheng/%E5%8A%A0%E5%85%A5%E5%90%8C%E6%AD%A5%E7%AC ...

  7. Compiler Theory(编译原理)、词法/语法/AST/中间代码优化在Webshell检测上的应用

    catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...

  8. 《编译原理》构造 LL(1) 分析表的步骤 - 例题解析

    <编译原理>构造 LL(1) 分析表的步骤 - 例题解析 易错点及扩展: 1.求每个产生式的 SELECT 集 2.注意区分是对谁 FIRST 集 FOLLOW 集 3.开始符号的 FOL ...

  9. 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析

    <编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...

  10. Java 实现《编译原理》简单-语法分析功能-LL(1)文法 - 程序解析

    Java 实现<编译原理>简单-语法分析功能-LL(1)文法 - 程序解析 编译原理学习,语法分析程序设计 (一)要求及功能 已知 LL(1) 文法为: G'[E]: E→TE' E'→+ ...

随机推荐

  1. SpringMVC-06 Ajax

    SpringMVC-06 Ajax Ajax 1.简介 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 是一种在无 ...

  2. 【Azure 微服务】PowerShell中,用Connect-ServiceFabricCluster命令无法连接到sf-test.chinaeast2.cloudapp.chinacloudapi.cn:19000 问题分析

    问题描述 Azure Service Fabric提供了PowerShell的指令来进行创建,管理资源,如Get-ServiceFabricClusterHealth 获取当前集群的健康状态,但这些命 ...

  3. 前端学习 node 快速入门 系列 —— 简易版 Apache

    其他章节请看: 前端学习 node 快速入门 系列 简易版 Apache 我们用 node 来实现一个简易版的 Apache:提供静态资源访问的能力. 实现 直接上代码. - demo - stati ...

  4. 基于Docker的MindSpore安装与使用基础介绍

    技术背景 MindSpore是一款新一代AI开源计算框架,其特色在于:创新编程范式,AI科学家和工程师更易使用,便于开放式创新:该计算框架可满足终端.边缘计算.云全场景需求,能更好保护数据隐私:可开源 ...

  5. HDU_6590 Code 【凸包】

    一.题目 Code 二.分析 题目描述了一大堆东西,就是想问二维空间里,能不能确定$d  w_1   w_2$使得函数满足$f(x_1,x_2) = y$,并且$sign(x)$函数是一个信号函数,只 ...

  6. GRU算法原理

    一.GRU算法 GRU(Gate Recurrent Unit,循环门单元)是循环神经网络(Recurrent Neural Network, RNN)的一种.和LSTM(Long-Short Ter ...

  7. [Fundamental of Power Electronics]-PART II-9. 控制器设计-9.5 控制器的设计

    9.5 控制器设计 现在让我们来考虑如何设计控制器系统,来满足有关抑制扰动,瞬态响应以及稳定性的规范或者说设计目标.典型的直流控制器设计可以用以下规范定义: 1.负载电流变化对输出电压调节的影响.当负 ...

  8. 封装一个处理 react 异常的最简 ErrorBoundary 组件 🎅

    前言 从 React 16 开始,引入了 Error Boundaries 概念,它可以捕获它的子组件中产生的错误,记录错误日志,并展示降级内容,具体 官网地址. 错误边界避免一个组件错误导致整个页面 ...

  9. 消息中间件-RabbitMQ持久化机制、内存磁盘控制

    RabbitMQ持久化机制 RabbitMQ内存控制 RabbitMQ磁盘控制 RabbitMQ持久化机制 重启之后没有持久化的消息会丢失 package com.study.rabbitmq.a13 ...

  10. Qt中检查槽函数connect是否正确

    环境:VS2017+Qt插件 一般情况下VS+QT环境下运行的QT程序输出信息需要在调试模式的输出栏可以看到,由于太多信息所以导致查看不方便(当然也可以在筛选选项中筛选信息). 有更方便查看输出信息的 ...