前面已经实现了SLR语法分析表,但是可能会出现即使语法不是二义性文法,也存在移入/规约冲突

状态 i 包含项[A ->α ],当状态 i 出现在栈顶时,栈中的可行前缀时βα且在任何最后句型中a都不可能跟在βA之后,

那么当输入a时不应该A->α进行规约

为了解决这个问题, 引入更强大的构造语法分析表方法:

1.规范LR(1)语法分析表

2.LALR语法分析表

一、规范LR(1)项

形式:[A -> α · β, a],a为一个终结符

作用:[A -> α · , a]只有在一下输入符号等于a时才要求按照A -> α进行规约

/**
* LR(1)项 P166
*/
public class LR1Item extends Item { /** 向前看符号 */
private List<Terminal> lookaheads; @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
LR1Item lr1Item = (LR1Item) o;
return Objects.equals(lookaheads, lr1Item.lookaheads);
} @Override
public int hashCode() {
return Objects.hash(super.hashCode(), lookaheads);
}
}

闭包函数

/**
* LR(1)项集族的构造方法 P167
* @param setOfItems
* @param grammar
* @return
*/
public SetOfItems closure(SetOfItems setOfItems, Grammar grammar) {
SetOfItems result = new SetOfItems(); Set<LR1Item> oldItems = setOfItems.getItems();
for (LR1Item item : oldItems) {
result.add(item);
} boolean hasAdd;
do {
hasAdd = false;
Set<LR1Item> items = new HashSet<>(result.getItems());
for (LR1Item item : items) {// I中的每个项[A → α·Bβ,a] Symbol symbolAfterDot = item.getSymbolAfterDot();// B
if (symbolAfterDot == null) {
continue;
} if (!(symbolAfterDot instanceof Nonterminal)) {
continue;
} List<Symbol> symbolAfter = item.getSymbolAfterDot1();//β
Set<Terminal> first = grammar.first(symbolAfter);// first(β) if (first.contains(Terminal.epsilon)) {
first.addAll(item.getLookaheads());
}
first.remove(Terminal.epsilon);// lookahead不包含ε List<Production> productionList = grammar.getProduction((Nonterminal) symbolAfterDot);
for (Production production : productionList) {
LR1Item newItem = LR1Item.of(production, 0, new ArrayList<>(first));
if (!result.contains(newItem)) {
result.add(newItem);
hasAdd = true;
}
}
} } while (hasAdd); return result;
}

构造SLR语法分析表

/**
* P161 算法4.46 构造一个SLR语法分析表
* @param grammar
* @param setList
* @return
*/
public ParsingTable buildParsingTable(Grammar grammar, List<SetOfItems> setList) {
ParsingTable result = new ParsingTable(); for (SetOfItems from : setList) { Set<LR1Item> items = from.getItems();
for (LR1Item item : items) { if (item.pos != item.getProduction().getBody().size()) {
continue;
} Nonterminal head = item.getProduction().getHead();
if (head.equals(grammar.start)) {
// 如果[S' -> S· $]在I中,那么将ACTION[i $]设置为接受
for (Terminal lookahead : item.getLookaheads()) {
result.addAction(from.getId(), lookahead, AcceptAction.of());
}
} else {
// 如果[A -> α· a]在I中,那么将ACTION[i a]设置为规约
for (Terminal symbol : item.getLookaheads()) {
result.addAction(from.getId(), symbol, ReduceAction.of(item.getProduction()));
}
}
} for (Map.Entry<Symbol, SetOfItems> entry : from.getGotoMap().entrySet()) {
Symbol symbol = entry.getKey();
SetOfItems to = entry.getValue(); // 如果[A -> α·aβ, b]在from中并且GOTO(from, a) = to,那么将Action[from,a]设置为移入to,a必须为一个终结符
if (symbol instanceof Terminal) {
result.addAction(from.getId(), symbol, ShiftAction.of(to.getId()));
} else {
result.addGoto(from.getId(), symbol, to.getId());
} }
} return result;
}

规范LR(1)语法分析表的更多相关文章

  1. C# 语法分析器(二)LR(0) 语法分析

    系列导航 (一)语法分析介绍 (二)LR(0) 语法分析 (三)LALR 语法分析 (四)二义性文法 (五)错误恢复 (六)构造语法分析器 首先,需要介绍下 LALR 语法分析的基础:LR(0) 语法 ...

  2. 编译原理根据项目集规范族构造LR(0)分析表

    转载于https://blog.csdn.net/Johan_Joe_King/article/details/79058597?utm_medium=distribute.pc_relevant.n ...

  3. SLR,语法分析表的构建

    太累了,感觉不会再爱了.执行了跟编译原理上的一模一样的例子,输出了正确结果 #include <stdio.h> #include <malloc.h> #include &l ...

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

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

  5. LR(0)语法分析

    # include <stdio.h> # include <string.h> //存储LR(0)分析表 struct node { char ch; int num; }; ...

  6. 内核知识第六讲,内核编写规范,以及获取GDT表

    内核知识第六讲,内核编写规范,以及获取GDT表 一丶内核驱动编写规范 我们都知道,在ring3下,如果我们的程序出错了.那么就崩溃了.但是在ring0下,只要我们的程序崩溃了.那么直接就蓝屏了. 那么 ...

  7. 阿里规范不建议多表Join,可这SQL要怎么写?

    阿里开发手册的描述,禁止多表join: 手册上写着[强制],相信很多同学项目里面的代码都不满足这个要求. 但是关键问题是:不用join,这SQL究竟要怎么写?! 分解关联查询 即对每个要关联的表进行单 ...

  8. MySQL 开发规范【X千万/表级别】

    一.MySQL 开发规范概述 原则:SQL开发规范制定是基于良好的编码习惯和可读性:目的:消除冗余,数据简约,提高效率,提高安全:范围:<SQL开发规范手册> 二.MySQL 开发规范手册 ...

  9. 求LR(0)文法的规范族集和ACTION表、GOTO表的构造算法

    原理 数据结构 // GO private static Map<Map<Integer,String>,Integer> GO = new HashMap<Map< ...

  10. 如何优雅地制作精排 ePub —— 个人电子书制作规范及基本样式表

    随着大数据时代的到来,多种移动阅读终端方兴未艾 —— Amazon Kindle不再小众.各互联网巨头纷纷推出旗下的电子书阅读软件.有了阅读的软件/硬件支持,必不可少的就是阅读什么的问题了.ePub格 ...

随机推荐

  1. 深入理解JNDI注入—RMI/LDAP攻击

    目录 前言 JNDI 注入简单理解 透过Weblogic漏洞深入理解 RMI与LDAP的区别 JNDI+RMI 漏洞代码触发链 lookup触发链 JNDI+LDAP 前言 本篇文章初衷是在研究log ...

  2. Hive--hbase--spark

    hive创建hbase表 create external table events.hb_train( row_key string, user_id string, event_id string, ...

  3. 深入理解Redis锁与Backoff重试机制在Go中的实现

    目录 Redis锁的深入实现 Backoff重试策略的深入探讨 结合Redis锁与Backoff策略的高级应用 具体实现 结论 在构建分布式系统时,确保数据的一致性和操作的原子性是至关重要的.Redi ...

  4. centos 下安装pip pip3

    centos 下安装pip pip3 上一篇说过了如何在centos7 上安装python3 并与python2.7共存. 这篇说一下 安装python2.7 下安装的pip 以及python3 下的 ...

  5. KubeSphere 社区双周报| 2024.07.19-08.01

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  6. shiro 框架基本讲解【转载】

    shiro 框架基本讲解[转载] 什么是权限管理: 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而 ...

  7. 使用LayUI实现文件上传的一个误区

    1.HTML 2.JS 3.后端处理(注意:参数 file) 这里传入的参数名只能是 file LayUI文件上传官方文档: https://www.layui.com/doc/modules/upl ...

  8. P3571 [POI2014] SUP-Supercomputer 题解

    P3571「POI2014」SUP-Supercomputer 题解 一道 "较" 水的黑题 (可一开始苦思冥想还是不会). 本蒟蒻的第一篇黑题题解,求赞. 题意简化 给定一棵 \ ...

  9. 容器部署DNS你会吗?

    docker快速部署DNS,实现快速上线 概念 环境介绍 部署DNS 下载相关镜像 创建并启动DNS容器 简单介绍三种创建方式 容器启动停止 创建dns交互式容器 配置DNS容器相关配置 测试 修改客 ...

  10. 自建家庭 KTV,在家想嗨就嗨

    现在用户最多.曲库最多的 K 歌软件是全民K歌,基本上想唱的歌都有,而且基本上每首歌都有 MV 或视频,使用体验也还不错,但是收费太贵了,对于一个月唱不了几次的打工人来说,唱一首歌就是"天价 ...