请用java实现LR(0)分析表的构造及测试例子

时间: 2024-01-01 12:05:10 浏览: 23
好的,下面是LR(0)分析表的构造及测试例子的Java代码: ``` import java.util.*; public class LR0Parser { private List<String[]> productions; private Map<String, Set<String>> firstSets; private Map<String, Set<String>> followSets; private Map<String, Map<String, String>> actionTable; private Map<String, Map<String, Integer>> gotoTable; private String startSymbol; public LR0Parser(List<String[]> productions, String startSymbol) { this.productions = productions; this.startSymbol = startSymbol; this.firstSets = computeFirstSets(); this.followSets = computeFollowSets(); this.actionTable = computeActionTable(); this.gotoTable = computeGotoTable(); } public boolean parse(List<String> input) { Stack<String> stack = new Stack<>(); stack.push("0"); int inputIndex = 0; while (!stack.isEmpty()) { String state = stack.peek(); String symbol = inputIndex < input.size() ? input.get(inputIndex) : "$"; String action = actionTable.get(state).getOrDefault(symbol, ""); if (action.isEmpty()) { return false; } else if (action.startsWith("s")) { int nextState = Integer.parseInt(action.substring(1)); stack.push(symbol); stack.push(Integer.toString(nextState)); inputIndex++; } else if (action.startsWith("r")) { int productionIndex = Integer.parseInt(action.substring(1)); String[] production = productions.get(productionIndex); int numSymbolsToRemove = production[1].split("\\s+").length; for (int i = 0; i < numSymbolsToRemove * 2; i++) { stack.pop(); } String prevState = stack.peek(); String nonterminal = production[0]; int nextState = gotoTable.get(prevState).get(nonterminal); stack.push(nonterminal); stack.push(Integer.toString(nextState)); } else if (action.equals("acc")) { return true; } } return false; } private Map<String, Set<String>> computeFirstSets() { Map<String, Set<String>> firstSets = new HashMap<>(); for (String[] production : productions) { String nonterminal = production[0]; if (!firstSets.containsKey(nonterminal)) { firstSets.put(nonterminal, new HashSet<>()); } } boolean changed; do { changed = false; for (String[] production : productions) { String nonterminal = production[0]; String[] symbols = production[1].split("\\s+"); for (String symbol : symbols) { if (symbol.equals("epsilon")) { changed |= firstSets.get(nonterminal).add("epsilon"); break; } else if (isTerminal(symbol)) { changed |= firstSets.get(nonterminal).add(symbol); break; } else { Set<String> symbolFirstSet = firstSets.get(symbol); for (String symbolFirst : symbolFirstSet) { if (!symbolFirst.equals("epsilon")) { changed |= firstSets.get(nonterminal).add(symbolFirst); } } if (!symbolFirstSet.contains("epsilon")) { break; } } } } } while (changed); return firstSets; } private Map<String, Set<String>> computeFollowSets() { Map<String, Set<String>> followSets = new HashMap<>(); for (String[] production : productions) { String nonterminal = production[0]; if (!followSets.containsKey(nonterminal)) { followSets.put(nonterminal, new HashSet<>()); } } followSets.get(startSymbol).add("$"); boolean changed; do { changed = false; for (String[] production : productions) { String nonterminal = production[0]; String[] symbols = production[1].split("\\s+"); for (int i = 0; i < symbols.length; i++) { String symbol = symbols[i]; if (isNonterminal(symbol)) { Set<String> symbolFirstSet = firstSets.get(symbol); for (String symbolFirst : symbolFirstSet) { if (!symbolFirst.equals("epsilon")) { changed |= followSets.get(symbol).add(symbolFirst); } } if (symbolFirstSet.contains("epsilon") || i == symbols.length - 1) { Set<String> nonterminalFollowSet = followSets.get(nonterminal); for (String nonterminalFollow : nonterminalFollowSet) { changed |= followSets.get(symbol).add(nonterminalFollow); } } } } } } while (changed); return followSets; } private Map<String, Map<String, String>> computeActionTable() { Map<String, Map<String, String>> actionTable = new HashMap<>(); for (int i = 0; i < productions.size(); i++) { String[] production = productions.get(i); String nonterminal = production[0]; String[] symbols = production[1].split("\\s+"); Set<String> followSet = followSets.get(nonterminal); for (String symbol : followSet) { if (!actionTable.containsKey(Integer.toString(i))) { actionTable.put(Integer.toString(i), new HashMap<>()); } actionTable.get(Integer.toString(i)).put(symbol, "r" + i); } } for (int i = 0; i < productions.size(); i++) { String[] production = productions.get(i); String[] symbols = production[1].split("\\s+"); for (int j = 0; j < symbols.length; j++) { String symbol = symbols[j]; if (isNonterminal(symbol)) { int nextState = findNextState(i, symbol); if (!actionTable.containsKey(Integer.toString(i))) { actionTable.put(Integer.toString(i), new HashMap<>()); } if (actionTable.get(Integer.toString(i)).containsKey(symbol)) { if (!actionTable.get(Integer.toString(i)).get(symbol).equals("s" + nextState)) { throw new RuntimeException("Reduce/shift conflict detected."); } } else { actionTable.get(Integer.toString(i)).put(symbol, "s" + nextState); } } else if (isTerminal(symbol)) { int nextState = findNextState(i, symbol); if (!actionTable.containsKey(Integer.toString(i))) { actionTable.put(Integer.toString(i), new HashMap<>()); } if (actionTable.get(Integer.toString(i)).containsKey(symbol)) { if (!actionTable.get(Integer.toString(i)).get(symbol).equals("s" + nextState)) { throw new RuntimeException("Reduce/shift conflict detected."); } } else { actionTable.get(Integer.toString(i)).put(symbol, "s" + nextState); } } } } for (int i = 0; i < productions.size(); i++) { if (!actionTable.containsKey(Integer.toString(i))) { actionTable.put(Integer.toString(i), new HashMap<>()); } if (productions.get(i)[0].equals(startSymbol)) { actionTable.get(Integer.toString(i)).put("$", "acc"); } } return actionTable; } private Map<String, Map<String, Integer>> computeGotoTable() { Map<String, Map<String, Integer>> gotoTable = new HashMap<>(); for (int i = 0; i < productions.size(); i++) { String[] production = productions.get(i); String[] symbols = production[1].split("\\s+"); for (int j = 0; j < symbols.length; j++) { String symbol = symbols[j]; if (isNonterminal(symbol)) { int nextState = findNextState(i, symbol); if (!gotoTable.containsKey(Integer.toString(i))) { gotoTable.put(Integer.toString(i), new HashMap<>()); } gotoTable.get(Integer.toString(i)).put(symbol, nextState); } } } return gotoTable; } private int findNextState(int state, String symbol) { for (int i = state + 1; i < productions.size(); i++) { String[] production = productions.get(i); if (production[0].equals(symbol)) { return i; } } return -1; } private boolean isTerminal(String symbol) { return !isNonterminal(symbol); } private boolean isNonterminal(String symbol) { return symbol.matches("[A-Z].*"); } } ``` 下面是一个测试例子,假设我们有以下文法: ``` S -> E E -> E + T E -> E - T E -> T T -> T * F T -> T / F T -> F F -> ( E ) F -> id ``` 我们可以使用以下代码来测试: ``` import java.util.*; public class Main { public static void main(String[] args) { List<String[]> productions = new ArrayList<>(); productions.add(new String[] { "S", "E" }); productions.add(new String[] { "E", "E + T" }); productions.add(new String[] { "E", "E - T" }); productions.add(new String[] { "E", "T" }); productions.add(new String[] { "T", "T * F" }); productions.add(new String[] { "T", "T / F" }); productions.add(new String[] { "T", "F" }); productions.add(new String[] { "F", "( E )" }); productions.add(new String[] { "F", "id" }); LR0Parser parser = new LR0Parser(productions, "S"); List<String> input = Arrays.asList("id", "+", "id", "*", "id", "$"); if (parser.parse(input)) { System.out.println("Accepted"); } else { System.out.println("Rejected"); } } } ``` 这个测试例子中,我们使用了一个包含加减乘除和括号的简单的表达式,用来测试LR(0)分析表的构造和使用。

相关推荐

最新推荐

recommend-type

编译原理课程设计 LR(0)分析表和分析器的构造和程序实现

LR(0)分析表算法的程序实现 1. 对任意给定的文法 ,完成识别文法活前缀的 、 的状态转化矩阵及 项目集规范族的构造; 2. 判断该文法是否为 文法,实现 分析表的构造,并输出到指定文件中; 3. 实现 分析器总控程序...
recommend-type

4 实验四:LR分析程序的设计与实现

1、了解LR(0)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。 2、掌握LR(0)语法分析方法。
recommend-type

LR(0)语法分析的设计与实现.doc

内含代码片段。原理包含CLOSURE和GOTO函数的构造说明,前缀、项目、拓广文法的定义说明,文法项目集规范族的构造伪代码,判断文法是否为LR(0)文法的说明,以及分析表构造讲解与输入串合法性分析步骤。
recommend-type

LR(0)语法分析的实现

LR(0)语法分析的实现:对于所输入的LR(0)文法,不论对错,都应有明确的信息告诉外界。对于符合规则的LR(0)文法,将输出LR(0)分析表,并可以对输入的句子进行语法分析输出相应语法树。
recommend-type

编译原理LR(1)自动构造,自动分析输入语句

LR(1)分析表自动构造程序的实现,对输入语句分析 设计内容及要求:对任意给定的文法G构造LR(1)项目集规范族(要求实现CLOSURE(I)、GO(I,X)、FIRST;然后实现LR(1)分析表构造算法。构造并输出其LR(1)分析表。由分析表...
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

2. 通过python绘制y=e-xsin(2πx)图像

可以使用matplotlib库来绘制这个函数的图像。以下是一段示例代码: ```python import numpy as np import matplotlib.pyplot as plt def func(x): return np.exp(-x) * np.sin(2 * np.pi * x) x = np.linspace(0, 5, 500) y = func(x) plt.plot(x, y) plt.xlabel('x') plt.ylabel('y') plt.title('y = e^{-x} sin(2πx)') plt.show() ``` 运行这段
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。