编译器-FIRST集合
语法分析器的两个重要函数 FIRST和FOLLOW
FIRST的定义
FIRST(α),可从α推导得到的串的首符号的集合
1.如果X是一个终结符,那么FIRST(X) = X
2.如果X是一个非终结符,且X -> Y1Y2...Yk 是一个产生式,
1)如果Y1..Yj-1=>ε 那么 FIRST(Yj) 添加到 FIRST(X)
2)如果Y1...Yk=>ε,那么ε添加到FIRST(X)
3.如果X->ε是一个产生式,那么ε添加到FIRST(X)
代码实现
1.符号类
import java.util.Objects; /**
* 符号
*/
public class Symbol { protected String name; @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Symbol symbol = (Symbol) o;
return Objects.equals(name, symbol.name);
} @Override
public int hashCode() {
return Objects.hash(name);
}
}
2.终结符
public class Terminal extends Symbol {
public static Terminal of(String name) {
Terminal result = new Terminal();
result.name = name;
return result;
}
}
3.非终结符
/**
* 非终结符
*/
public class Nonterminal extends Symbol { public static Nonterminal of(String name) {
Nonterminal result = new Nonterminal();
result.name = name;
return result;
}
}
4.产生式
import java.util.List;
import java.util.Objects; /**
* 产生式
*/
public class Production { /** 产生式头 */
private Nonterminal head;
/** 产生式体 */
private List<Symbol> body; public Nonterminal getHead() {
return head;
} public List<Symbol> getBody() {
return body;
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Production that = (Production) o;
return Objects.equals(head, that.head) && Objects.equals(body, that.body);
} @Override
public int hashCode() {
return Objects.hash(head, body);
}
}
5.文法
package com.kashin.grammar.model; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set; /**
* 文法
*/
public class Grammar { /** 开始符号 */
private Nonterminal start;
/** 产生式 */
private List<Production> productions; }
6.FIRST函数
/**
* P140 FIRST(X)集合
* @param token
* @return
*/
public Set<Terminal> first(Symbol token) { Set<Terminal> result = new HashSet<>(); // X 是一个终结符号
// 1) if X is a terminal, then FIRST(X) = {X}
if (token instanceof Terminal) {
result.add((Terminal) token);
return result;
} List<Production> productionList = getProduction((Nonterminal) token);
for (Production production : productionList) { // 如果 X->ε是一个产生式,那么将ε加入到FIRST(X)
if (production.getBody().size() == 1 && production.getBody().get(0).equals(Terminal.of("ε"))) {
result.add(Terminal.of("ε"));
} else {
Set<Terminal> firstSet = first(production.getBody());
result.addAll(firstSet);
}
} return result;
}
/**
* P140 FIRST(X)集合
* @param tokens
* @return
*/
public Set<Terminal> first(List<Symbol> tokens) { // 是否全部包含ε
boolean allContainsEpsilon = true;
Set<Terminal> result = new HashSet<>();
for (Symbol token : tokens) { Set<Terminal> firstSet = first(token);
for (Terminal terminal : firstSet) {
if (terminal.equals(Terminal.of("ε"))) {
continue;
}
result.add(terminal);
} if (!firstSet.contains(Terminal.of("ε"))) {
allContainsEpsilon = false;
break;
}
} // 如果对于所有的j=1,2,...,k,ε在FIRST(Yj)中,那么将ε加入到FIRST(X)
if (allContainsEpsilon) {
result.add(Terminal.of("ε"));
} return result;
}
编译器-FIRST集合的更多相关文章
- Java集合框架——容器的快速报错机制 fail-fast 是什么?
前言:最近看 java 集合方面的源码,了解到集合使用了 fail-fast 的机制,这里就记录一下这个机制是什么,有什么用,如何实现的. 一.fail-fast 简介 fail-fast 机制,即快 ...
- g++编译器的使用
关于g++ g++ 是GNU组织开发出的编译器软件集合(GCC)下的一个C++编译器.它是Unix 和 Linux 系统下标配的 基于命令行的 C++编译器.如果你的系统是Windows,可以按照 ...
- g++编译器的使用(转载)
关于g++ g++ 是GNU组织开发出的编译器软件集合(GCC)下的一个C++编译器.它是Unix 和 Linux 系统下标配的 基于命令行的 C++编译器.如果你的系统是Windows,可以按照 ...
- cc 和gcc编译器
从名字上看,老的unix系统的CC程式叫做C Compiler.但GCC这个名字按GNU的说法叫做Gnu Compiler Collection.因为gcc包含非常多编译器(C, C++, Objec ...
- Android.mk 文件语法详解
0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build Syst ...
- GCC的gcc和g++区别
看的Linux公社的一篇文章,觉得不错,内容复制过来了. 其实在这之前,我一直以为gcc和g++是一个东西,只是有两个不同的名字而已,今天在linux下编译一个c代码时出现了错误才找了一下gcc和g+ ...
- Android.mk 文件语法详解 转:http://blog.sina.com.cn/s/blog_602f8770010148ce.html
0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build Syst ...
- Android NDK开发之Android.mk文件
Android NDK开发指南---Android.mk文件 博客分类: Android NDK开发指南 Android.mk文件语法详述 介绍: ------------ 这篇文档是用来描述你的 ...
- Android.mk文件语法规范及使用模板
Android.mk文件语法详述 介绍:------------这篇文档是用来描述你的C或C++源文件中Android.mk编译文件的语法的,为了理解她们我们需要您先看完docs/OVERVIEW.h ...
- 【转】configure/make/make install的使用说明
这些都是典型的使用GNU的AUTOCONF和AUTOMAKE产生的程序的安装步骤. ./configure是用来检测你的安装平台的目标特征的.比如它会检测你是不是有CC或GCC,并不是需要CC或GCC ...
随机推荐
- CSS & JS Effect – FAQ Accordion & Slide Down
效果 参考: Youtube – Responsive FAQ accordion dropdown | HTML and CSS Tutorial 几个难点 1. 如何 align left for ...
- 利用AutoGpt将任何模型支持o1模型的推理实现
利用AutoGpt将任何模型支持o1模型的推理实现 相信大家都对于OpenAI最新出的o1模型都非常关注,它已经能通过推理让回复的效果更加理想, 但是目前o1的限制太大,而且使用o1至少也是需要购买O ...
- mysql后台导入sql文件-设定字符集
需求描述:有一个user_info.sql 的文件里面都是插入user_info表的insert语句数据,数据量500M,要求快速插入mysql的数据库中. 解决方法: 1.利用客户端工具加载文件插入 ...
- 【赵渝强老师】Oracle数据库的内存结构
首先,我们通过一张图片来了解一下Oracle数据库的内存结构,如下: 每个数据库实例有两个关联的内存结构-系统全局区(SGA),程序全局区(PGA). 系统全局(SGA):一组共享的内存结构(称为SG ...
- 逆向 Virustotal 搜索接口 X-VT-Anti-Abuse-Header
逆向 Virustotal 搜索接口 X-VT-Anti-Abuse-Header 搜索示例 搜索 123,网页地址为:https://www.virustotal.com/gui/search/12 ...
- yarn 命令大全
npm install yarn -g npm install --global yarnyarn 中文网:https://yarn.bootcss.com/docs/install/#windows ...
- 淘宝程序员没活硬整?在 Excel 和 VSCode 中购物!
大家好,我是程序员鱼皮,最近某宝网站的改进,属实是有点 "新" 了. 你敢相信这是一个购物网站么? 你可以在 Excel 表格中挑选商品进行购物,还原度极高,这两个图表更是点睛之笔 ...
- 11 Self-Attention相比较 RNN和LSTM的优缺点
博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...
- DIY Matter Bridge 和智能锁简单联动的实践
一. 写在前面 在之前的博客文章 <基于乐鑫 ESP32-C3 的 Matter Light 实践>中,我们利用乐鑫的硬件和 SDK 方案实现了简单的 Light 例程,并对 Matter ...
- 云原生爱好者周刊:KubeKey v2.1.0 alpha 版发布!
KubeKey v2.1.0-alpha.0 发布啦!该版本的主要特性: 支持三种使用场景的 Etcd 集群(二进制部署,Kubeadm 部署,连接外置已存在的 Etcd 集群). 支持部署 Cont ...