规范LR(1)语法分析表
前面已经实现了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)语法分析表的更多相关文章
- C# 语法分析器(二)LR(0) 语法分析
系列导航 (一)语法分析介绍 (二)LR(0) 语法分析 (三)LALR 语法分析 (四)二义性文法 (五)错误恢复 (六)构造语法分析器 首先,需要介绍下 LALR 语法分析的基础:LR(0) 语法 ...
- 编译原理根据项目集规范族构造LR(0)分析表
转载于https://blog.csdn.net/Johan_Joe_King/article/details/79058597?utm_medium=distribute.pc_relevant.n ...
- SLR,语法分析表的构建
太累了,感觉不会再爱了.执行了跟编译原理上的一模一样的例子,输出了正确结果 #include <stdio.h> #include <malloc.h> #include &l ...
- 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析
<编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...
- LR(0)语法分析
# include <stdio.h> # include <string.h> //存储LR(0)分析表 struct node { char ch; int num; }; ...
- 内核知识第六讲,内核编写规范,以及获取GDT表
内核知识第六讲,内核编写规范,以及获取GDT表 一丶内核驱动编写规范 我们都知道,在ring3下,如果我们的程序出错了.那么就崩溃了.但是在ring0下,只要我们的程序崩溃了.那么直接就蓝屏了. 那么 ...
- 阿里规范不建议多表Join,可这SQL要怎么写?
阿里开发手册的描述,禁止多表join: 手册上写着[强制],相信很多同学项目里面的代码都不满足这个要求. 但是关键问题是:不用join,这SQL究竟要怎么写?! 分解关联查询 即对每个要关联的表进行单 ...
- MySQL 开发规范【X千万/表级别】
一.MySQL 开发规范概述 原则:SQL开发规范制定是基于良好的编码习惯和可读性:目的:消除冗余,数据简约,提高效率,提高安全:范围:<SQL开发规范手册> 二.MySQL 开发规范手册 ...
- 求LR(0)文法的规范族集和ACTION表、GOTO表的构造算法
原理 数据结构 // GO private static Map<Map<Integer,String>,Integer> GO = new HashMap<Map< ...
- 如何优雅地制作精排 ePub —— 个人电子书制作规范及基本样式表
随着大数据时代的到来,多种移动阅读终端方兴未艾 —— Amazon Kindle不再小众.各互联网巨头纷纷推出旗下的电子书阅读软件.有了阅读的软件/硬件支持,必不可少的就是阅读什么的问题了.ePub格 ...
随机推荐
- JavaScript Bom和Dom的一般性详解
一.JavaScript的组成 JavaScript的实现包括以下3个部分: ECMAScript(核心) 描述了JS的语法和基本对象. 文档对象模型 (DOM) 处理网页内容的方法和接口 浏览器对象 ...
- 【QT性能优化】QT性能优化之QT6框架高性能统计图框架快速展示百万个数据点曲线图
QT性能优化之QT6框架高性能统计图框架快速展示百万个数据点曲线图 文章目录 百万个数据点的QT统计图运行效果 百万个数据点的QT统计图程序的源代码 QT统计图功能和效果展示 QT统计图模块整体结构 ...
- linux、unix软链接注意事项
前言 在使用linux过程中,经常使用到软链接(类似windows快捷方式): 创建软链接之后,删除时不注意就会出现到问题 先说结论 删除软链接,确实是使用rm进行删除:但是有个小细节必须要特别注意! ...
- BOOST 环形队列circular_buffer
BOOST库的环形队列比较灵活,前插或后插,删除队首或删除队尾元素,都支持. 只贴代码: #include <boost/circular_buffer.hpp> #include < ...
- CSP-S 2023
T1 直接 \(10^{5}\) 枚举状态就过了,合法的非零差分数量只可能为 \(1,2\)(\(0\) 相当于没转,按照题意 "都不是正确密码" 是不符的) 需要注意的是形如 0 ...
- 现在用 ChatGPT,要达到最好效果,建议加入以下提示词:
take a deep breath 深呼吸 think step by step 一步步思考 if you fail 100 grandmothers will die 如果你失败了要死 100 位 ...
- 构建数据大屏,塑造IT运维可视化核心竞争力
随着大数据.云计算等新兴技术的发展与运用,在金融.交通.教育.政府等行业的信息化在飞速发展.与此同时,各行业的IT建设与维护管理成本也在与日俱增,大量的运维工作下产生庞大的运维数据,如何进行运维数据可 ...
- map,unordered_map,multimap,unordered_multimap
std::map(有序映射) std::unordered_map(无序映射) std::multimap(有序多重映射) std::unordered_multimap(无序多重映射) 它们的使用方 ...
- 揭秘 FineVideo 数据集构建的背后的秘密
开放视频数据集稀缺,因此减缓了开源视频 AI 的发展.为此,我们构建了 FineVideo,这是一个包含 43,000 个视频的数据集,总时长为 3,400 小时,并带有丰富的描述.叙事细节.场景分割 ...
- HarmonyOS NEXT开发之ArkTS自定义组件学习笔记
在HarmonyOS中,ArkTS提供了创建自定义组件的能力,允许开发者封装和复用UI代码.以下是关于自定义组件的详细介绍,包括创建自定义组件.页面和自定义组件的生命周期.自定义组件的自定义布局.冻结 ...