LALR语法分析表
LALR语法分析表
1.LALR(向前看-LR)技术
2.在实践中常用,分析表比规范LR分析表小
LALR(1)项集族的内核的高效计算方法
1.构造G的LR(0)项集族的内核
2.确定自发生的符号
3.不断扫描所有项集的内核项,添加传播的符号
向前看符号的类型
public static class Determining {
public int setId;
public Production production;
public int pos;
public Terminal lookahead;
/** 1自发生符号2传播符号 */
public int type;
}
确定向前看符号
private List<Determining> determiningLookahead(Grammar grammar, Map<Integer, SetOfItems> setOfItemsResult,
SetOfItems setOfItems, Item item, Terminal lookaheadStart) { LR1 lr1 = new LR1(); List<Determining> determinings = new ArrayList<>();
LR1Item lr1Item = LR1Item.of(item.getProduction(), item.getPos(), lookaheadStart);
SetOfItems newSet = new SetOfItems();
newSet.add(lr1Item);
SetOfItems closure = lr1.closure(newSet, grammar); Set<LR1Item> closureItems = closure.getItems();
for (LR1Item closureItem : closureItems) {
Symbol symbolAfterDot = closureItem.getSymbolAfterDot();
if (symbolAfterDot == null) {
continue;
}
Integer gotoId = setOfItems.getGotoMap().get(symbolAfterDot);
if (gotoId == null) {
continue;
}
SetOfItems gotoLalrSet = setOfItemsResult.get(gotoId);
LR1Item old = (LR1Item) gotoLalrSet.getItem(closureItem.getProduction(), closureItem.getPos() + 1); for (Terminal lookahead : closureItem.getLookaheads()) {
Terminal find = CollectionUtil.find(old.getLookaheads(), lookahead);
if (find != null) {
continue;
} Determining determining = new Determining();
determining.lookahead = lookahead;
determining.pos = old.getPos();
determining.production = old.getProduction();
determining.setId = gotoLalrSet.getId(); if (lookahead.equals(lookaheadStart)) {
determining.type = 2;// 传播符号
} else {
determining.type = 1;// 自发生符号
} determinings.add(determining);
}
} return determinings;
}
LALR(1)项集族的内核高效计算方法
public List<SetOfItems> items(Grammar grammar) {
LR0 lr0 = new LR0();
LR1 lr1 = new LR1();
// 1) 构造LR0项集族的内核
List<SetOfItems> lr0SetOfItem = lr0.items(grammar);
Map<Integer, SetOfItems> lr0SetMap = new HashMap<>();
// 删除非内核项
for (SetOfItems setOfItems : lr0SetOfItem) {
setOfItems.deleteNonKernelItems(grammar);
SetOfItems pre = lr0SetMap.put(setOfItems.getId(), setOfItems);
if (pre != null) {
throw new RuntimeException("已经存在项集ID:" + setOfItems.getId());
}
}
// 用LR0项集初始化结果LALR项集
List<SetOfItems> result = new ArrayList<>();
Map<Integer, SetOfItems> setOfItemsResult = new HashMap<>();
for (SetOfItems setOfItems : lr0SetOfItem) {
System.err.println("LR0 项集:" + setOfItems.getId());
for (Item item : setOfItems.getItems()) {
System.err.println(item.toString());
}
SetOfItems lalrSet = new SetOfItems();
lalrSet.setId(setOfItems.getId());
lalrSet.getGotoMap().putAll(setOfItems.getGotoMap());
Set<Item> items = setOfItems.getItems();
for (Item item : items) {
if (item.getProduction().getHead().equals(grammar.start) && item.getPos() == 0) {
// 初始项的自发生成的向前看符号$
lalrSet.add(LR1Item.of(item.getProduction(), item.getPos(), Terminal.dollar));
} else {
lalrSet.add(LR1Item.of(item.getProduction(), item.getPos(), (Terminal) null));
}
}
result.add(lalrSet);
setOfItemsResult.put(lalrSet.getId(), lalrSet);
}
// 2)确定自发生成的符号
for (SetOfItems lr0set : lr0SetOfItem) {// 项集族的每个项集
Set<Item> items = lr0set.getItems();
for (Item item : items) {// 项集中每个项
List<Determining> determiningList = determiningLookahead(grammar, setOfItemsResult, lr0set, item, Terminal.sharp);
for (Determining determining : determiningList) {
if (determining.type != 1) {
continue;
}
SetOfItems lalrSet = setOfItemsResult.get(determining.setId);
LR1Item gotoItem = (LR1Item) lalrSet.getItem(determining.production, determining.pos);
gotoItem.addLookahead(determining.lookahead);
}
}
}
for (SetOfItems setOfItems : result) {
System.err.println("初始 项集:" + setOfItems.getId());
for (Item item : setOfItems.getItems()) {
System.err.println(item);
}
}
// 3)不断扫描所有项集的内核项
boolean hasNew;
int count = 0;
do {
hasNew = false;
count++;
System.err.println("第" + count + "趟扫描");
List<Determining> determinings = new ArrayList<>();
List<SetOfItems> tmpSets = new ArrayList<>(result);
for (SetOfItems lalrSet : tmpSets) {
Set<LR1Item> lalrItemSet = lalrSet.getItems();
for (LR1Item lalrItem : lalrItemSet) {
if (lalrItem.getLookaheads() == null) {
continue;
}
for (Terminal lookaheadStart : lalrItem.getLookaheads()) {
List<Determining> determiningList = determiningLookahead(grammar, setOfItemsResult, lalrSet, lalrItem, lookaheadStart);
for (Determining determining : determiningList) {
if (determining.type == 1) {
continue;
}
determinings.add(determining);
hasNew = true;
}
}
}
}
for (Determining determining : determinings) {
SetOfItems setOfItems = setOfItemsResult.get(determining.setId);
LR1Item old = (LR1Item) setOfItems.getItem(determining.production, determining.pos);
old.addLookahead(determining.lookahead);
System.err.println("状态" + determining.setId + "项" + old + "添加传播符号" + determining.lookahead);
}
for (SetOfItems setOfItems : result) {
System.err.println("项集:" + setOfItems.getId());
for (Item item : setOfItems.getItems()) {
System.err.println(item);
}
}
} while (hasNew);
// 将LALR(1)内核通过CLOSURE求闭包转换为LR(1)项集
List<SetOfItems> lr1Set = new ArrayList<>();
for (SetOfItems lalrSet : result) {
SetOfItems closure = lr1.closure(lalrSet, grammar);
closure.setId(lalrSet.getId());
closure.getGotoMap().putAll(lalrSet.getGotoMap());
lr1Set.add(closure);
}
return lr1Set;
}
LALR语法分析表的更多相关文章
- SLR,语法分析表的构建
太累了,感觉不会再爱了.执行了跟编译原理上的一模一样的例子,输出了正确结果 #include <stdio.h> #include <malloc.h> #include &l ...
- 编译原理-第四章 语法分析-4.7 规范的LR分析
规范的LR分析 一.规范LR(l)项 二.规范LR(l)项集族 1.构建项目集 2.例 三.规范LR(1)语法分析表 1.构造 2.例1 3.例2 四.LALR语法分析表 1.重要性 2.特点 3.构 ...
- 编译原理_P1004
龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...
- C# 语法分析器(二)LR(0) 语法分析
系列导航 (一)语法分析介绍 (二)LR(0) 语法分析 (三)LALR 语法分析 (四)二义性文法 (五)错误恢复 (六)构造语法分析器 首先,需要介绍下 LALR 语法分析的基础:LR(0) 语法 ...
- 编译原理-第四章 语法分析-4.6 简单LR技术
简单LR分析方法 一.LR语言分析器模型与算法 1.输入.输出.栈和方法 2.LR语法分析表 3.LR分析程序 4.例 例1: 例2: 二.LR语法分析算法 1.LR语法分析算法的定义和概念 定义: ...
- 【译】Python Lex Yacc手册
本文是PLY (Python Lex-Yacc)的中文翻译版.转载请注明出处.这里有更好的阅读体验. 如果你从事编译器或解析器的开发工作,你可能对lex和yacc不会陌生,PLY是David Beaz ...
- 几个不常见但非常出色的 .NET 开源库
NLog NLog 目前最为出色的 .NET 日志库,非常容易配置,且极具灵活性.最重要的是与 log4net 相比,NLog 的开发很活跃.顺带提一句,NLog 完全兼容 Mono. Mono.Ce ...
- Lex Yacc手册
Python Lex Yacc手册 本文是PLY (Python Lex-Yacc)的中文翻译版.转载请注明出处.这里有更好的阅读体验. 如果你从事编译器或解析器的开发工作,你可能对lex和yacc不 ...
- first集合及follow集合
前面那片文章生成的语法分析表并不是最优的,因为有些项在遇到错误输入的时候,并不是采取报错,而是执行规约,直到不能再规约的时候才报错.这是不科学的,我们需要在得到错误输入的时候立马报错,为了实现这个功能 ...
- oracle 初探内存结构
数据库的存储机构 分为 逻辑存储结构 和 物理存储结构 逻辑存储结构: 数据库.表空间.段.区.块 物理存储结构: 数据库.控制文件.数据文件.初始化参数文件.OS块等. 一个区只能在 ...
随机推荐
- CSS & JS Effect – Styling Input Radio
原生 Radio 的 Limitation <input type="radio" style="width: 25px; height: 25px; cursor ...
- ASP.NET Core – Byte, Stream, Directory, File 基础
前言 以前的文章: Stream 基础和常用 和 IO 常用. 这篇主要是做一个整理, 方便要用的时候 warm up. 之前有讲过 Bit, Byte 的基本概念: Bit, Byte, ASCII ...
- Spring —— 事务角色&&事务属性
事务角色 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法 事务属性: 事务传播行 ...
- QT6框架WebEngine模块之WebEngine总体介绍以及WebEngine能做什么?
QT6框架WebEngine模块之WebEngine总体介绍以及WebEngine能做什么? 简介 本文简略介绍QT6框架WebEngine模块之WebEngine总体介绍以及WebEngine能做什 ...
- [TK] Terrible Prime
题目链接 T415418 这道题严格的时间限制比较令人头疼,似乎需要一些高级的算法,但实际上是,想要用点基础知识通过这道题需要两种算法:费马小定理 (见下函数Miller_rabin) 用于subta ...
- 逆向WeChat(七)
上篇介绍了如何通过嗅探MojoIPC抓包小程序的HTTPS数据. 本篇逆向微信客户端本地数据库相关事宜. 本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/184235 ...
- 从SQL Server过渡到PostgreSQL:理解模式的差异
从SQL Server过渡到PostgreSQL:理解模式的差异 前言 随着越来越多的企业转向开源技术,商业数据库管理员和开发者也逐渐面临向PostgreSQL迁移的需求. 虽然SQL Server和 ...
- emmc寿命
EMMC器件寿命 1)先确认EMMC器件NAND FLASH类型,是MLC还是TLC,一般是TLC,器件手册标称1000-3000次,取平均值2000次作为评估: 2)在OS下查看EMMC器件当前使用 ...
- PostgreSQL 15新版本特性解读(含直播问答、PPT资料汇总)
2022年6月23日,墨天轮技术社区联合PostgreSQL中文社区共同举办[PostgreSQL 15 新特性解读]直播活动. 小编在这里整理了直播间的代表性问题,请老师为大家解答.并在文末附上视频 ...
- signalR的身份认证