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. Identity – Permission Claims & UserClaimsPrincipalFactory

    前言 在 Identity – Authorize 有介绍过, Identity 的验证核心是 Claims. 在 Identity – Without Identity Framework 也看到了 ...

  2. Figma 学习笔记 – Scroll and Position Fixed

    Scroll Scroll 属于 prototype 的一部分. 当一个 Frame 的内容超出 Frame 的高度或宽度时, Frame 就具备了 scroll 的能力. 通过 uncheck cl ...

  3. 微信js-sdk接入原理

    1.有一个微信公众号,并获取到该公众号的AppID和AppSecret. 其中AppID是可以对外公开的,AppSecret是该公众号的密钥,是需要绝对保密的 2.向微信服务器发送一个GET请求,获取 ...

  4. Flutter 2.8 正式发布

    文/ Tim Sneath,Flutter & Dart 产品经理 Flutter 已经更新到 2.8 正式版,发布了多项新特性和改进以不断改善移动和 Web 端的开发体验,同时也正在将桌面端 ...

  5. [32](CSP 集训) CSP-S 模拟 3

    A 奇观 考虑到 CCF 可以拆开算,答案为 \((ans_c)^2\times ans_f\) 剩下的东西比较少,考虑 DP 我的 dp 是从爆搜改的,设 \(f_{i,j}\) 表示递归到第 \( ...

  6. [namespace hdk] diff.h

    Example cth.txt 12345 54321 114514 hdk.txt 12345 54321 114514 #include"diff.h" using names ...

  7. 第44天:WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式

    #PHP-MYSQL-SQL操作-增删改查 1.功能:数据查询 查询:SELECT * FROM news where id=$id 2.功能:新增用户,添加新闻等 增加:INSERT INTO ne ...

  8. Failed to connect to github.com port 443: Connection refused问题解决

    解决办法: 1.找到github的ip地址:查找链接 2.找到本地的hosts文件.我的hosts文件路劲为:C:\Windows\System32\drivers\etc 3.在hosts文件最后添 ...

  9. 如果读完这几百 Python 的书籍,能成编程大佬吗? #Python 入门 #编程 #编程学习 #知识分享

  10. AOT漫谈专题(第四篇): C#程序如何编译成Native代码

    一:背景 1. 讲故事 大家都知道所谓的.NET Native AOT即通过AOT编译器直接将C#代码编译成机器码,大家也习惯用C/C++的编译过程来类比,都是静态编译本质上都差不多,这篇我们借助工具 ...