构造LR预测分析表:FIRST与FOLLOW集

news2024/7/7 16:40:39

1. FIRST 集

顾名思义,“第一个” + “集合”,也就是

FIRST(A) 表示 A 所能推导出的串的首终结符构成的集合

举个例:

有文法:
	A ——> aB
那么 FIRST(A) = {a},因为
	A ——> a...

那么如何求解呢?分三种情况:

  • 能推出空串:

    本文中我用 ‘’ 表示空串

    A ——> B | ''
    那么 '' 应该被加入到 FIRST(A) 中
    
    注:
    如果有
    	A ——> B
    	B ——> ''
    那么 A 也能推出空串,也就是说:
    '' 应该被加入到 FIRST(A) 中。
    
  • 产生式体的首字符为非终结符:

    A ——> B
    A 能推导出的串显然依赖于 B,因此
    FIRST(B) 应该被加入到 FIRST(A) 中
    或者说 FIRST(A) = FIRST(B)
    
  • 产生式体的首字符为终结符:

    A ——> aB
    无论 B 能推导出什么,显然 
    A 能推导出的串的首字符一定是 a;
    因此 a 应该被加入到 FIRST(A) 中。
    
    '这也可以换一种理解方式'FIRST(A) = FIRST(aB) =
    FIRST(a) = { a }
    

来个综合的例子:

(0) E ——> TG
(1) G ——> +TG | ''
(2) T ——> FU 
(3) U ——> *FU | ''
(4) F ——> (E) | id

对于(1)式,由于 E 的产生式体的首字符为非终结符 T,因此有 FIRST(E) = FIRST(T)
同理(2)式有 FIRST(T) = FIRST(F),也就是

FIRST(E) = FIRST(T) = FIRST(F)

那么看 F 的产生式(4)式,由于其产生式体首字符都是终结符,因此 FIRST(F) = { (, id },也就是说

FIRST(E) = FIRST(T) = FIRST(F) = { (, id }

现在还剩(1)、(3)式,两个产生式形式基本相同:产生式体首字符是终结符,能推导出空串,因此:

FIRST(G) = { +, ‘’ }
FIRST(U) = { *, ‘’ }

FIRST集计算完毕。


2. FOLLOW 集

**“跟在后面的” + “集合”,也就是

FOLLOW(A) 表示能出现在 A 的后面的第一个终结符集合

比如

A ——> Ba
对于 B 而言,在这个产生式中,
B 后面紧跟的第一个终结符为 a,
因此 a 应加入 FOLLOW(B)

求解方式分四种:

  • 应将 $ 加入开始符号的 FOLLOW 集

    $ 表示输入结束标记字符

    S ——> A
    A ——> a
    那么 $ 应加入 FOLLOW(S)
    
  • 后面紧跟着终结符

    S ——> Aa
    那么 a 应加入 FOLLOW(A)
    
  • 后面紧跟着非终结符

    S ——> AB
    由于 A 后面是 B,那么
    FIRST(B) 应加入 FOLLOW(A)
  • 产生式体末尾是非终结符

    S ——> ABC
    C ——> ''
    
    1. FOLLOW(S) 应加入到 FOLLOW(C) 中;
    
    由于 S ——> ABC,那么 S 等价于就是 ABC,
    显然 FOLLOW(S) 应加入到 FOLLOW(C); 
    但注意 FOLLOW(S) 不一定等于 FOLLOW(C)"一种理解方式":
    S 和 C 都是 S 文法定义的语言的某语法成分,
    但是 S 显然比 C 更大;
    如果 C 只出现在 S 的末尾,
    那么 FOLLOW(C) = FOLLOW(S);
    但如果 C 还出现在了 S 的中间,比如
    	S ——> ACBC
    那么可能有 FOLLOW(S) < FOLLOW(B) 
    
    2. 如果 
    	C 能推出空串 (或者 '' 属于 FIRST(C))
    那么 
    	FOLLOW(S) 应加入 FOLLOW(B) 中。
    
    当 C ——> '' 时,那么 S 等价于 AB,因此 
    FOLLOW(B) 应加入到 FOLLOW(A) 中。
    
    3. 依次类推,直到出现
       第一个不能推出空串的非终结符
    

同样的例子:

(0) E ——> TG
(1) G ——> +TG | ''
(2) T ——> FU 
(3) U ——> *FU | ''
(4) F ——> (E) | id

FOLLOW集 的分析比 FIRST集 复杂得多,一不小心就容易漏掉个别情况。对此我建议采用以下方法进行求解:

  • 先将 $ 加入 FOLLOW(开始符号)
  • 分析产生式右部
  • 分析产生式整体
  • 从 (0) - (4) 依次分析,如果有 FOLLOW集 改变,执行依次更新操作
  • 将 $ 加入 FOLLOW(开始符号)

    FOLLOW(E) = { $ }

  • 分析产生式(0)的右部

    TG
    

    由于 T 后面紧跟的是非终结符 G,因此 FIRST(G) = { +, ‘’ } 应加入 FOLLOW(T)

    FOLLOW(T) = { + }

  • 分析产生式 (0) 的整体

    E ——> TG
    

    由于 E 相当于 TG,因此 FOLLOW(E) 应加入 FOLLOW(G)

    FOLLOW(G) = { $ }
    为了避免忘记,你自己在分析时做相应的标记,方便后续的分析

    此外,由于 G 能推出空串,因此 E 也相当于 T,所以 FOLLOW(E) 应加入 FOLLOW(T)

    FOLLOW(T) = { $, + }

  • 分析产生式(1)

    +TG | ''
    空串在 FOLLOW集 中没有分析的必要,因此只需要分析:
    +TG
    

    由于 “+TG” 与 “TG” 在形式上基本相同(G都紧跟在T后面,并且G都在末尾),因此(1)的分析结果与(0)的分析结果相同,跳过

    你可以自行验证

  • 分析(2)的右部

    FU 
    

    与(0)的右部分析类似:FIRST(U) = { *, ‘’ } 应加入 FOLLOW(F)

    FOLLOW(F) = { * }

  • 分析(2)的整体

    T ——> FU 
    

    与(0)的整体分析类似:FOLLOW(T) 应加入 FOLLOW(U),FOLLOW(T) 应加入 FOLLOW(F)

    FOLLOW(U) = { $, + }
    FOLLOW(F) = { $, +, * }

  • 分析(3)
    分析结果同(2),跳过

  • 分析(4)的右部

    (E) | id
    'id' 只有终结符,因此不参与分析 
    

    由于 E 后面为终结符 ),因此加入 FOLLOW(E)

    **FOLLOW(E) = { $, ) }

    这里你会发现个问题,我们第一个求解的是 FOLLOW(E),而 FOLLOW(E) 又会被加入到其他的 FOLLOW集 中(比如 FOLLOW(T) 等),那么这时候就需要更新对应的 FOLLOW集,这也是为什么要记录 “谁加入谁的原因”。 但是此时还没分析完,还有一步:分析(4)的整体,因此在分析完一遍后再进行更新操作

  • 分析(4)的整体

    F ——> (E) | id
    

    由于产生式右部的末尾都是终结符,因此没有分析的必要,跳过

  • 更新操作:

    • FOLLOW(E) 应加入 FOLLOW(G)
    • FOLLOW(E) 应加入 FOLLOW(T)
    • FOLLOW(T) 应加入 FOLLOW(U)
    • FOLLOW(T) 应加入 FOLLOW(F)

    因此最后的结果为

    FOLLOW(E) = { $, ) }
    FOLLOW(G) = { $, ) }
    FOLLOW(T) = { $, ), + }
    FOLLOW(U) = { $, ), + }
    FOLLOW(F) = { $, ), +, * }


3. 预测分析表

为了更好地理解此部分,你应该知道如何使用 预测分析表 进行 LR分析

先看两个例子:

现有文法:
	S ——> aA 
	S ——> ''
那么 
	FIRST(S) = { a, '' }
	FOLLOW(S) = { $ }
1. 如果现在输入为 a...,
   需要使用 S 进行分析,
   那么应该使用 
   	   S ——> aA 
   进行语法分析
   
2. 如果现在输入结束了,
   相当于输入为 $,
   需要使用 S 进行分析,
   由于 '' 属于 FIRST(S),
   并且 $ 属于 FOLLOW(S),
   因此因使用
   	   S ——> ''
   进行语法分析
'可以这么理解':
   因为使用 S 去进行分析,但是输入
   却是 FOLLOW(S),也就是说,没有
   遇到 S 能推导出的
       首终结符 (FIRST(S)),
   遇到的是 S 后面'紧跟'的
	   首终结符(FOLLOW(S))
   那么 S 应该被'忽略',也就是
       S 应该换为空串,同时
   由于 S 可以推空串,因此使用 
	   S ——> ''
   进行语法分析

3. 如果输入为 b,
   既不属于 FIRST(S),
   也不属于 FOLLOW(S),
   因此语法分析错误
现有文法:
	S ——> aA
那么 
	FIRST(S) = { a }
	FOLLOW(S) = { $ }
1. 如果现在输入字符为 a ...
   并且需要使用 S 进行分析,
   那么你就知道应该用 
	   S ——> aA
   去进行语法分析

2. 如果输入字符为 $
   需要用 S 进行分析,
   虽然 $ 属于 FOLLOW(S),
   但是 S 不能推空串,
   因此语法分析错误
 
3. 如果输入为 c ...
   需要使用 S 进行分析,
   由于 FIRST(S) 中没有 c
   因此语法分析错误

看了上面两个例子,相信的你对如何构造预测分析表有了基本的理解。下面使用之前的例子以及求出的 FIRST集 与 FOLLOW集 来构造 预测分析表。

基本思路:对文法的每一个产生式的右部 (非终结符),针对不同的终结符,使用对应的 FIRST、FOLLOW集 进行构造


  • 文法

    (0) E ——> TG
    (1) G ——> +TG | ''
    (2) T ——> FU 
    (3) U ——> *FU | ''
    (4) F ——> (E) | id
    
  • FIRST集

    FIRST(E) = FIRST(T) = FIRST(F) = { (, id }
    FIRST(G) = { +, ‘’ }
    FIRST(U) = { *, ‘’ }

  • FOLLOW集

    FOLLOW(E) = FOLLOW(G) = { $, ) }
    FOLLOW(T) = FOLLOW(U) = { $, ), + }
    FOLLOW(F) = { $, ), +, * }

规定:预测分析表横轴为终结符,纵轴为非终结符,中间的元素为指定的产生式(比如 表[S][$] = S —> ‘’,表示当 S 遇到输入字符 $ 时应使用 S —> ‘’ 来进行语法分析)

$
SS —> ‘’

算法:对于每个产生式:A —> B

  • 对于 FIRST(B) 的每个终结符 a,将 A —> B 加入 表[A][a]
  • 如果 ‘’ 属于 FIRST(B),对于 FOLLOW(B) 中的每个终结符 b,将 A —> ‘’ 加入 表[A][b]
  • 其他都是空,表示语法分析错误

  • 先找出所有的终结符

    { id, (, ), +, *, $ }

  • (0) E —> TG
    首先有

    FIRST(E) = { (, id }
    FOLLOW(E) = { $, ) }

    因为 E 与 TG 等效(E —> TG),那么 FIRST(E) = FIRST(TG) = { (, id },因此对于 FIRST(TG) 中的每一个终结符 a,将 E ——> TG 加入 表[E][a](即 表[ E ][ ( ]、表[ E ][ id ])
    故有

    id()+*$
    EE —> TGE —> TG

    由于不存在 E —> ‘’ ,所以不需要考虑 FOLLOW(E)

  • (1) G ——> +TG | ‘’
    首先有

    FIRST(G) = { +, ‘’ }
    FOLLOW(G) = { $, ) }

    同理由于 FIRST(+TG) = { + },因此将 G —> +TG 加入 表[ G ][ + ];
    现在 ‘’ 属于 FIRST(G)了,需要考虑 FOLLOW(G):
    **对于 FOLLOW(G) 中的每一个终结符 b,将 G —> ‘’ 加入 表[ G ] [ b ](也就是 表[ G ][ $ ]、表[ G ][ ) ])

    id()+*$
    GG —> ‘’G —> +TGG —> ‘’
  • 其余的自行分析
    最后结果为

    id()+*$
    EE —> TGE —> TG
    GG —> ‘’G —> +TGG —> ‘’
    TT—> FUT —> FU
    UU —> ‘’U —> ‘’U —> *FUU —> ‘’
    FF —> idF —> (E)

最后

本文一部分来源于课本,一部分为自己的理解,如有错误,欢迎指正。

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

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

相关文章

华为5288 V5服务器安装BCLinux8U4手记

本文记录了华为5288 V5服务器安装BCLinux8U4操作系统的过程。 一、系统环境 1、服务器 华为FusionServer Pro 5288 V5服务器 2、操作系统 BCLinux-R8-U4-Server-x86_64-220725.iso 官网下载地址 sha256sum&#xff1a;1d31d3b8e02279e89965bd3bea61f14c65b9d32ad2ab6d4eb…

基于Java的壁纸网站设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

JavaFx基础知识

1.Stage 舞台 如此这样的一个框框&#xff0c;舞台只是这个框框&#xff0c;并不管里面的内容 public void start(Stage primaryStage) throws Exception {primaryStage.setScene(new Scene(new Group()));primaryStage.getIcons().add(new Image("/icon/img.png"))…

HQ-SAM

不建议复现

腾讯云COS分布式对象存储

腾讯云COS分布式对象存储 腾讯云对象存储&#xff08;Cloud Object Storage&#xff0c;COS&#xff09;是腾讯云提供的一种用于存储海量文件的分布式存储服务。 腾讯云 COS 适用于多种场景&#xff0c;如静态网站托管、大规模数据备份和归档、多媒体存储和处理、移动应用数据存…

电脑彻底删除的文件还能恢复吗怎么弄 电脑删除的文件怎么恢复 回收站也删了

实测可行的文件恢复方法&#xff0c;无论是彻底删除的文件&#xff0c;还是被清空的回收站文件&#xff0c;使用该方法都可以轻松找回。整个恢复过程操作简单&#xff0c;并且绝不会损伤电脑硬件。这意味着&#xff0c;您再也不用为误删文件而焦虑了。有关电脑彻底删除的文件还…

在windows上安装objection

安装命令pip install objection -i https://mirrors.aliyun.com/pypi/simple hook指定进程 objection -g 测试 explore 进程名不定是包名&#xff0c;也可能是app名字&#xff0c;如“测试”就是app的名字 若出现如下错误&#xff0c;说明python 缺少setuptools 直接安装setu…

编程语言中浅拷贝(Shallow Copy)和深拷贝(Deep Copy)

编程语言中浅拷贝&#xff08;Shallow Copy&#xff09;和深拷贝&#xff08;Deep Copy&#xff09; 编程语言中浅拷贝&#xff08;Shallow Copy&#xff09;和深拷贝&#xff08;Deep Copy&#xff09;概念及JavaScript、Python、C、Java深拷贝和浅拷贝情况介绍。 浅拷贝和深拷…

【Redis】三大Redis内存分析工具介绍(Redisinsight、RDR、RMA)

目录 一、RedisInsight工具介绍 1、工具概述 2、关键特性 3、版本与服务 4、实际应用 二、Redis Data Reveal工具介绍 1、简介 2、主要特性 3、使用方法 4、注意事项 5、总结 三、Redis Memory Analyzer (RMA)工具介绍 1、工具概述 2、技术特点 3、应用场景 4、…

day02-统计数据

numpy统计学 1.求平均值[数组名.mean()/np.mean(数组名)] m1 np.arange(20).reshape((4,5))m1.mean() #9.5若想要求某一维的平均值&#xff0c;设置axis参数&#xff0c;多维数组元素指定&#xff1a; axis 0&#xff0c;将从上往下计算。axis 1&#xff0c;将从左往右计算…

使用getline()从文件中读取一行字符串

我们知道&#xff0c;getline() 方法定义在 istream 类中&#xff0c;而 fstream 和 ifstream 类继承自 istream 类&#xff0c;因此 fstream 和 ifstream 的类对象可以调用 getline() 成员方法。 当文件流对象调用 getline() 方法时&#xff0c;该方法的功能就变成了从指定文件…

最新抖音极速版双红包雨掘金助手

项目介绍&#xff1a; 抖音极速版目前小说里有双红包雨&#xff0c;单广告2000&#xff0c;金币1万比1&#xff0c;脚本自动看广告 设备需求&#xff1a; 安卓手机&#xff08;最高支持安卓13.0版本&#xff09; 购买后包含月卡脚本详细使用教程 百度网盘 请输入提取码百度…

SpringMVC 的工作流程和详细解释

Spring MVC&#xff08;Model-View-Controller&#xff09;框架是基于经典的 MVC 设计模式构建的&#xff0c;用于开发 Web 应用程序。下面是 Spring Boot MVC 的工作流程和详细解释&#xff1a; 1.客户端发起请求 1.客户端&#xff08;通常是浏览器&#xff09;发起 HTTP 请求…

中序遍历的两种实现——二叉树专题复习

递归实现&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right)…

K8s 集群(kubeadm) CA 证书过期解决方案

Author&#xff1a;Arsen Date&#xff1a;2024/07/04 目录 一、现象描述二、解决方案三、集群验证 一、现象描述 之前有篇文章《K8s Token 过期解决方案&#xff08;Kubeadm&#xff09;》提到了默认生成的 Token 有效期只有 24 小时&#xff0c;过期后 Token 将不可用&#…

Robust Test-Time Adaptation in Dynamic Scenarios--论文阅读

论文笔记 资料 1.代码地址 https://github.com/BIT-DA/RoTTA 2.论文地址 https://arxiv.org/abs/2303.13899 3.数据集地址 coming soon 1论文摘要的翻译 测试时间自适应(TTA)旨在使预先7训练的模型适用于仅具有未标记测试数据流的测试分布。大多数以前的TTA方法已经在…

实现统计n个数以下质数的个数

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h>int main() {int n 0;scanf("%d", &n);int sum 0;for (int i 1; i < n; i){for (int j 2; j < i; j) {if (i % j 0){sum;break;}}}printf("%d", n - sum-1);return 0; } n为输…

数字媒体技术基础之:DNG 文件

DNG&#xff08;Digital Negative&#xff09;文件是一种用于存储原始图像数据的文件格式&#xff0c;由 Adobe Systems 于2004年开发并推广。DNG 是一种开放的、非专利的原始图像格式&#xff0c;旨在为不同相机制造商提供一个统一的存储格式。DNG 文件保存了原始的、未处理的…

【C语言】刷题笔记 Day2

【笔记】 【1】局部变量不初始化&#xff0c;默认放的随机值。 1 int n0; 2 scanf("%d",&n); //13.141 【2】这里虽然输入的是一个浮点数&#xff0c;但是只取整数部分。 【3】3.156e7 表示的是3.156*10的7次方。 【4】多组输入&#xff0c;保存和不保存…

Studying-代码随想录训练营day29| 134. 加油站、135. 分发糖果、860.柠檬水找零、406.根据身高重建队列

第29天&#xff0c;贪心part03&#xff0c;快过半了(ง •_•)ง&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 134.加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列 134.加油站 文档讲解&#xff1a;代码随想录加油站 视频讲解&#xff1a;手撕加油站…