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语法分析表的更多相关文章

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

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

  2. 编译原理-第四章 语法分析-4.7 规范的LR分析

    规范的LR分析 一.规范LR(l)项 二.规范LR(l)项集族 1.构建项目集 2.例 三.规范LR(1)语法分析表 1.构造 2.例1 3.例2 四.LALR语法分析表 1.重要性 2.特点 3.构 ...

  3. 编译原理_P1004

    龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...

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

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

  5. 编译原理-第四章 语法分析-4.6 简单LR技术

    简单LR分析方法 一.LR语言分析器模型与算法 1.输入.输出.栈和方法 2.LR语法分析表 3.LR分析程序 4.例 例1: 例2: 二.LR语法分析算法 1.LR语法分析算法的定义和概念 定义: ...

  6. 【译】Python Lex Yacc手册

    本文是PLY (Python Lex-Yacc)的中文翻译版.转载请注明出处.这里有更好的阅读体验. 如果你从事编译器或解析器的开发工作,你可能对lex和yacc不会陌生,PLY是David Beaz ...

  7. 几个不常见但非常出色的 .NET 开源库

    NLog NLog 目前最为出色的 .NET 日志库,非常容易配置,且极具灵活性.最重要的是与 log4net 相比,NLog 的开发很活跃.顺带提一句,NLog 完全兼容 Mono. Mono.Ce ...

  8. Lex Yacc手册

    Python Lex Yacc手册 本文是PLY (Python Lex-Yacc)的中文翻译版.转载请注明出处.这里有更好的阅读体验. 如果你从事编译器或解析器的开发工作,你可能对lex和yacc不 ...

  9. first集合及follow集合

    前面那片文章生成的语法分析表并不是最优的,因为有些项在遇到错误输入的时候,并不是采取报错,而是执行规约,直到不能再规约的时候才报错.这是不科学的,我们需要在得到错误输入的时候立马报错,为了实现这个功能 ...

  10. oracle 初探内存结构

    数据库的存储机构 分为 逻辑存储结构 和 物理存储结构 逻辑存储结构: 数据库.表空间.段.区.块         物理存储结构: 数据库.控制文件.数据文件.初始化参数文件.OS块等. 一个区只能在 ...

随机推荐

  1. JavaScript Library – YouTube Embedded、YouTube Player API、YouTube Data API

    YouTube Embed Video 参考: Embed videos & playlists 它和 Google Maps Embed 类似,是通过 iframe 完成的. <ifr ...

  2. Angular 18+ 高级教程 – Dependency Injection 依赖注入

    前言 本来是想先介绍 Angular Component 的,但 Component 里面会涉及到一些 Dependency Injection (简称 DI) 的概念,所以还是先介绍 DI 吧. 温 ...

  3. CSS & JS Effect – Statistics Counter

    效果 当 scroll 到那些号码的时候, 号码从 0 开始跳动, 一直到最终的值. 实现思路 1. 一开始把号码 set to 0 2. 使用 IntersectionObserver 监听号码出现 ...

  4. Identity – Authorize

    前言 Authorize 授权和 Identity Framework 关系不是很大. 虽然 Framework 有帮忙处理 Role, Claims 这些, 但这些只是整个 Authorize 小部 ...

  5. Go runtime 调度器精讲(十一):总览全局

    原创文章,欢迎转载,转载请注明出处,谢谢. 0. 前言 前面用了十讲介绍了 Go runtime 调度器,这一讲结合一些图在总览下 Go runtime 调度器. 1. 状态转换图 首先是 Gorou ...

  6. Java发展到现在,哪些技术可以放弃了?

    各位好啊,我是会编程的蜗牛,作为java开发者,对于各类java开发技术.开发框架肯定是多少都要了解和知道的. 但是作为已经发展了几十年的java开发生态,各类技术层出不穷,有的新技术新框架已经对旧技 ...

  7. IP地址集中管控:从分配规划、现网管理到合规性监测、准入控制全周期监管

    当前,网络已成为企业必不可少的资源,企业网络系统也在不断扩展,IP地址数量不断增长,随之而来的是IP地址管理问题凸显.如何高效集中地管理网络中的IP地址,IP如何有效划分,成为影响企业网络可用性和质量 ...

  8. springboot的启动类必须和controller在同一层级

    springboot的启动类必须和controller在同一层级

  9. Chirpy+Github

    相关网址 Chirpy 示例:网页上有官方教程,我写的肯定不全 Chirpy 示例仓库:这个就是包含官方教程的那个示例的仓库 Chirpy 模板仓库:直接 fork 这个仓库,快速搭建,没有多余的东西 ...

  10. LiveData

    ViewModel 添加依赖 implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' activity_main.xml < ...