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块等. 一个区只能在 ...
随机推荐
- Angular 18+ 高级教程 – 学以致用
前言 读这么多原理,到底为了什么?真实项目中真的会用得到吗? 你正在疑惑 "知识的力量" 吗? 本篇会给一个非常非常好的案例,让你感悟 -- 知识如何用于实战. 记住,我的目的是让 ...
- DOM & BOM – 用 Canvas 修图
前言 以前有写过一篇关于 canvas 处理图片的文章. 非常乱, 这篇做一个整理. 参考 Stack Overflow – HTML5 Canvas Rotate Image Stack Overf ...
- 面试官的几句话,差点让我挂在HTTPS上
作为软件测试,大家都知道一些常用的网络协议是我们必须要了解和掌握的,比如 HTTP 协议,HTTPS 协议就是两个使用非常广泛的协议,所以也是面试官问的面试的时候问的比较多的两个协议:而且因为这两个协 ...
- Qt中一些关于中文的使用
本文包含以下内容: 中文编码 按中文字典排序 中文首字母查找 版本:Qt5.14.2 中文编码 在一些老项目中,发现项目中使用的文件是GBK编码,而新项目使用的是Unicode编码,在有一些操 ...
- 解决 SHADERed无法打开,报错 缺失XINPUT1_4.DLL 文件的办法
起因: 在给某个不知名的同事安装软件时遇到的一个问题,安装完成后打开软件报错:SHADERed无法打开,报错 缺失XINPUT1_4.DLL ,C++依赖项均已打上,卸载C++插件后依然报错只能找缺失 ...
- Java poi 读取 word 、 pdf
从各个博客 CV 出来的,不好意思 pom <dependency> <groupId>org.apache.poi</groupId> <artifactI ...
- k8s的容器的webssh实现
Vite2.x + Vue3.x + Xtermjs4 相关信息 编程语言:TypeScript 4.x + JavaScript 构建工具:Vite 2.x 前端框架:Vue 3.x 路由工具:Vu ...
- JSP+Java编程资源
<JSP+Servlet+Tomcat应用开发从零开始学(第2版)>源码课件视频下载地址: https://pan.baidu.com/s/1HkFRul3wYBxe-skXCoQPwg ...
- 一款基于Uniapp开发的开源低代码平台
rtvue-lowcode低代码开发平台 rtvue-lowcode一款基于uniapp框架和uview组件库的低代码开发平台,项目提供可视化拖拽编辑器,采用MIT开源协议,适用于app.小程序等项目 ...
- 墨天轮国产数据库沙龙 | 张玮绚:TDengine,高性能、分布式、支持SQL的时序数据库
分享嘉宾:张玮绚(Wade Zhang)北京涛思数据科技有限公司(TDengine)研发VP 整理:墨天轮 导读 TDengine 是一款高性能.分布式.支持 SQL 的时序数据库,让大量设备.数据采 ...