FIRST集合、FOLLOW集合及LL(1)文法求法
FIRST集合
定义
可从α推导得到的串的首符号的集合,其中α是任意的文法符号串。
规则
计算文法符号 X 的 FIRST(X),不断运用以下规则直到没有新终结符号或 ε可以被加入为止 :
(1)如果 X 是一个终结符号,那么 FIRST(X) = X。
(2)如果 X 是一个非终结符号,且 X ->Y1 Y2 … Yk是一个产生式,其中 k≥1,那么如果对于某个i,a在 FIRST(Y1)、FIRST(Y2)… FIRST(Yi-1)中,就把a加入到 FIRST(X) 中。
(3)如果 X ->ε是一个产生式,那么将ε加入到 FIRST(X)中。
以上是书上的官方规则,不仅读起来很拗口,理解也很累。
下面看一下精简版的规则(从别人 @樱草书 那里看来的,感觉很棒,这里引用一下):
(1)如果X是终结符,则FIRST(X) = { X } 。
(2)如果X是非终结符,且有产生式形如X → a…,则FIRST( X ) = { a }。
(3) 如果X是非终结符,且有产生式形如X → ABCdEF…(A、B、C均属于非终结符且包含 ε,d为终结符),需要把FIRST( A )、FIRST( B )、FIRST( C )、FIRST( d )加入到 FIRST( X ) 中。
(4)如果X经过一步或多步推导出空字符ε,将ε加入FIRST( X )。
实践
记得,曾经有人说过:
只读,就会白给
下面以这个文法为例讲解一波,会用精简版规则,更容易理解一些:
E -> T E'
E' -> + T E' | ε
T -> F T'
T' -> * F T' | ε
F -> ( E ) | id
- 1
- 2
- 3
- 4
- 5
- FIRST(E) = FIRST(T) 根据规则3,很容易理解,这里要注意的由于T不含ε,所以遍历到T就停止了,E’不会加入进来
- FIRST(E’) = FIRST(+) ∪ FIRST(ε)= { +, ε } 根据规则2和4,,很好理解
- FIRST(T) = FIRST(F) 根据规则3,和第一条推导过程一样
- FIRST(T’) = FIRST() ∪ FIRST(ε)= { , ε } 根据规则2和4,和第二条推导一样
- FIRST(F) = FIRST( ( ) ∪ FIRST(id)= { ( , id } 根据规则2
结果:
FIRST(E) = FIRST(T) = FIRST(F) = { ( , id }
FIRST(E') = FIRST(+) ∪ FIRST(ε)= { + , ε }
FIRST(E') = FIRST(*) ∪ FIRST(ε)= { * , ε }
- 1
- 2
- 3
FOLLOW集合
定义
对于非终结符号A,FOLLOW(A) 被定义为可能在某些句型中紧跟在A右边的终结符号集合。
规则
计算文法符号 X 的 FOLLOW(X) ,不断运用以下规则直到没有新终结符号可以被加入任意FOLLOW集合为止 :
(1)将$加入到FOLLOW(X)中,其中S是开始符号,而$是输出右端的结束标记。
(2)如果存在一个产生式S->αXβ,那么将集合FIRST(β)中除ε外的所有元素加入到FOLLOW(X)当中。
(3)如果存在一个产生式 S->αX , 或者S->αXβ且FIRST(β)中包含ε , 那么将集合FOLLOW(S)中的所有元素加入到集合FOLLOW(X)中。
实践
还是用之前的例子来做
E -> T E'
E' -> + T E' | ε
T -> F T'
T' -> * F T' | ε
F -> ( E ) | id
- 1
- 2
- 3
- 4
- 5
- FOLLOW(E) ,根据规则1,首先把$加入进来,根据规则2,可以得出 FOLLOW(E) = { ) , $ }
- FOLLOW(E’) = FOLLOW(E) = { ) , $ } 根据规则3
- FOLLOW(T) = FIRST(E’) ∪ FOLLOW(E) = { + , ) , $ } 根据规则2
- FOLLOW(T’) = FOLLOW(T) = { + , ) , $ } 根据规则3
- FOLLOW(F) = FOLLOW(T) ∪ FIRST(T’) = { * , + , ) , $ } 根据规则2和3
结果:
FOLLOW(E) = FOLLOW(E') = { ) , $ }
FOLLOW(T) = FOLLOW(T') = { + , ) , $ }
FOLLOW(F) = { * , + , ) , $ }
- 1
- 2
- 3
LL(1)文法
解释
LL(1) 中第一个“L”表示从左向右扫描输入,第二个“L”表示产生最左推导,而“1”表示在每一步中只需要向前看一个输入符号来决定语法分析动作。
定义
对于文法LL(1)文法G,当且仅当G的任意两个不同产生式 A -> α | β
(1)不存在终结符号a使得α和β都能推导出以a开头的串。
(2)α和β中最多只有一个可以推导出空串。
(3)如果 β=》ε ,那么α不能推导出任何以FOLLOW(A)中某个终结符号开头的串。
可能很多人看的云里雾里,解释一下:
(1)和(2)意思是α和β的FIRST集合相交。(3)是指如果FIRST(α)中有 ε,那么FIRST(β)和FOLLOW(A)是不相交的集合,反之一样。
预测分析表的构建
方法:
对于文法G的每个产生式 A->α ,进行如下处理
(1)对于FIRST(α)中每个终结符号a,将 A->α 加入到 M[A,a] 中。
(2)如果 ε在FIRST(α)中,那么对于FOLLOW(A)中每个终结符号b,将 A->α 加入到 M[A,b] 中。如果 ε在FIRST(α),且$在FOLLOW(A)中,也将 A->α 加入到 M[A,$] 中。
还是以之前的例子示例
E -> T E'
E' -> + T E' | ε
T -> F T'
T' -> * F T' | ε
F -> ( E ) | id
- 1
- 2
- 3
- 4
- 5
1.先求FIRST和FOLLOW集合:
FIRST(E) = FIRST(T) = FIRST(F) = { ( , id }
FIRST(E') = FIRST(+) ∪ FIRST(ε)= { + , ε }
FIRST(T') = FIRST(*) ∪ FIRST(ε)= { * , ε }
FOLLOW(E) = FOLLOW(E') = { ) , $ }
FOLLOW(T) = FOLLOW(T') = { + , ) , $ }
FOLLOW(F) = { * , + , ) , $ }
- 1
- 2
- 3
- 4
- 5
- 6
2.然后构建一个这样的表

3.然后依次填入非终结符号

4.按照规则1填写其余内容

5.按照规则2填写内容

至此整个构建全部完成
</div>
FIRST集合、FOLLOW集合及LL(1)文法求法的更多相关文章
- FIRST集合、FOLLOW集合、SELECT集合以及预测分析表地构造
FIRST集合.FOLLOW集合.SELECT集合以及预测分析表地构造 FIRST集合的简单理解就是推导出的字符串的开头终结符的集合. FOLLOW集合简单的理解就对于非终结符后面接的第一个终结符. ...
- first集合follow集的求法
FIRST集的定义 : 设G=(VT,VN,P,S)是上下文无关文法 FIRST(a)={a|a=>*ab,a∈VT, a,b∈V*} 若a=>*ε则规定ε∈FIRST (a) FIRST ...
- 【BZOJ-4199】品酒大会 后缀数组 + 并查集合并集合
4199: [Noi2015]品酒大会 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 436 Solved: 243[Submit][Status] ...
- Linq to 泛型集合查询集合包括大写M和年龄小于等于18
#region Linq to 泛型集合查询集合包括大写M和年龄小于等于18 //List<Student> list = new List<Student&g ...
- IT第二十一天 - Collections、ArrayList集合、LinkedList集合、Set集合、HashMap集合、集合的操作注意【修20130828】
NIIT第二十一天 上午 集合 1. 集合Collection存储数据的形式是单个存储的,而Map存储是按照键值对来存储的,键值对:即键+值同时存储的,类似align="center&quo ...
- 数组转集合、集合转数组、字符串数组与int型、long型数组等的转换
在项目中经常会遇到数组转集合.集合转数组.数组之间类型转换等操作 1.数组转集合 为了实现把一个数组转换成一个ArrayList,很多Java程序员会使用如下的代码: String str[] = { ...
- 廖雪峰Java5集合-1Java集合简介-1Java结合简介
1.集合 定义:集合就是一堆东西.集合里的东西,称为元素Element 数学中的集合: 有限集合: * 一个班所有的学生组成的集合 * 一个网站所有的商品组成的集合 无限集合: * 全体自然数集合 * ...
- Java集合 -- ArrayList集合及应用
JAVA集合 对象数组 集合类之ArrayList 学生管理系统 斗地主案例 NO.one 对象数组 1.1 对象数组描述 A:基本类型的数组:存储的元素为基本类型 int[] arr={1,2,3, ...
- Java集合----Set集合
Set集合 Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败. Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法 Ha ...
随机推荐
- 网络通信机制:Socket、TCP/IP、HTTP
13.1.1 TCP/IP协议 讲的很抽象,没具体看懂什么是TCP协议,什么是IP协议.IP协议保证消息从一个主机传送到另一个主机,消息在传送的过程中被分割成一个个小包,TCP协议会让两台相互连接的计 ...
- 手牵手,从零学习Vue源码 系列一(前言-目录篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 手牵手,从零学习Vue源码 系列三(虚拟DOM篇) 陆续更新中... 预计八月中旬更新 ...
- 第四章 常用API(下)
4.1.String类 描述:该类代表字符串 构造方法: 方法 描述 public String() 初始化构造一个空白字符串 public String(char[] value) 通过字符数组初始 ...
- Ubuntu Linux markdown编辑工具 typora 安装
Typora简介 Typora是一款轻便简洁的Markdown编辑器,支持即时渲染技术,这也是与其他Markdown编辑器最显著的区别.即时渲染使得你写Markdown就想是写Word文档一样流畅自如 ...
- IDEA解决MAVEN下载插件慢问题
原文链接:https://blog.csdn.net/qq_25983579/article/details/104398915 使用阿里的maven镜像 右键项目选中maven选项,然后选择“ope ...
- Webpack 原理浅析
作者: 凹凸曼 - 风魔小次郎 背景 Webpack 迭代到4.x版本后,其源码已经十分庞大,对各种开发场景进行了高度抽象,阅读成本也愈发昂贵.但是为了了解其内部的工作原理,让我们尝试从一个最简单的 ...
- 线程_使用multiprocessing启动一个子进程及创建Process 的子类
from multiprocessing import Process import os # 子进程执行的函数 def run_proc(name): print("子进程运行中,名称:% ...
- Numpy创建数组
# 导入numpy 并赋予别名 np import numpy as np # 创建数组的常用的几种方式(列表,元组,range,arange,linspace(创建的是等差数组),zeros(全为 ...
- Python os.tmpnam() 方法
概述 os.tmpnam() 方法用于为创建一个临时文件返回一个唯一的路径.高佣联盟 www.cgewang.com 语法 tmpnam()方法语法格式如下: os.tmpnam 参数 无 返回值 返 ...
- PHP date_get_last_errors() 函数
------------恢复内容开始------------ 实例 返回解析日期字符串时的警告和错误: <?phpdate_create("gyuiyiuyui%&&/ ...