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. Angular 18+ 高级教程 – EventManagerPlugin & Hammer.js Gesture

    前言 今天来揭秘一下 Angular 的 Event Listening,看看它底层有什么好玩的地方. (keydown.enter) 语法 在 Component 组件 の Template Bin ...

  2. SpringBoot——项目快速启动

    SpringBoot项目快速启动 对SpringBoot项目打包(执行Maven构建指令package)    执行后会生成对应的项目 jar包,在文件夹找到该文件    在对应文件夹下即可执行  j ...

  3. Hive--hbase--spark

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

  4. 【赵渝强老师】史上最详细的PostgreSQL体系架构介绍

    PostgreSQL是最像Oracle的开源数据库,我们可以拿Oracle来比较学习它的体系结构,比较容易理解.PostgreSQL的主要结构如下: 一.存储结构 PG数据存储结构分为:逻辑存储结构和 ...

  5. HarmonyOS NEXT 底部选项卡功能

    在HarmonyOS NEXT中使用ArkTS实现一个完整的底部选项卡功能,可以通过以下几个步骤来完成: 创建Tabs组件:使用Tabs组件来创建底部导航栏,并通过barPosition属性设置其位置 ...

  6. vue前端开发仿钉图系列(2)左侧图层列表的开发详解

    项目开发前还是特别说明一下组件库的重要性,谢谢饿了么团队分享的element组件库,大大节省了页面的开发成本.左侧图层列表核心功能有1.根据图层类型展示点线面2.开关控制右侧地图上点线面的展示和隐藏3 ...

  7. DDD之领域服务与应用服务

    领域服务: 聚合中的实体没有业务逻辑代码,只有对象的创建,对象的初始化,状态管理等个体相关的代码: 对于聚合内的业务逻辑,我们编写领域服务Domain service 而对于聚合协作以及聚合与外部系统 ...

  8. element的upload 图片上传主函数

    /** 图片上传 */ async UploadImage (event, file, filelist) { // 清空坐标 this.formModel.ITEM_XY = [0, 0] this ...

  9. 25. http 常见状态码

    状态码的分类: 2xx:表明请求被成功接收并处理 : 3xx:表示要完成请求,需要进一步操作. 通常,这些状态代码用来重定向 :重定向就是 从 a 地址跳转到 b 地址 : 4xx:客户端错误,请求错 ...

  10. 基于 KubeSphere 的运管系统落地实践

    作者:任建伟,某知名互联网公司云原生工程师,容器技术信徒,云原生领域的实践者. 背景介绍 在接触容器化之前,我们团队内部的应用一直都是基于虚拟机运管,由开发人员自行维护. 由于面向多开发部门服务,而开 ...