用Java语言实现预测分析法,设计与实现的算法和方法说明、源代码,对运行结果进行必要在分析与说明。首先判断任一给定文法是否为LL(1)文法,然后构造其预测分析表和预测分析程序。 输入:一个文法、一个字符串。 输出:预测分析表、判定结果: (1)是LL1文法,则同时输出分析结果。 (2)不是LL1文法。

时间: 2024-03-12 19:44:45 浏览: 37
以下是一个简单的Java算法实现,实现了LL(1)文法的判断、预测分析表的构造和预测分析程序的实现。值得注意的是,这个实现只考虑了非终结符和终结符都是单个字符的情况,如果需要考虑复杂的符号串,需要进行相应的修改。 ```java import java.util.*; public class LL1Parser { // 文法,使用Map存储 private Map<Character, List<String>> productions; // 非终结符集合 private Set<Character> nonTerminals; // 终结符集合 private Set<Character> terminals; // 预测分析表,使用Map存储 private Map<Character, Map<Character, String>> predictionTable; public LL1Parser(Map<Character, List<String>> productions) { this.productions = productions; // 初始化非终结符和终结符集合 this.nonTerminals = new HashSet<>(); this.terminals = new HashSet<>(); for (Character nonTerminal : productions.keySet()) { nonTerminals.add(nonTerminal); for (String production : productions.get(nonTerminal)) { for (char symbol : production.toCharArray()) { if (!nonTerminals.contains(symbol)) { terminals.add(symbol); } } } } terminals.remove('ε'); } // 判断是否是LL(1)文法 public boolean isLL1Grammar() { // 遍历所有非终结符 for (Character nonTerminal : productions.keySet()) { // 获取该非终结符的所有产生式 List<String> productionList = productions.get(nonTerminal); // 构造FIRST集合 Set<Character> firstSet = new HashSet<>(); for (String production : productionList) { // 如果产生式以终结符开头,将该终结符加入FIRST集合 if (terminals.contains(production.charAt(0))) { firstSet.add(production.charAt(0)); } // 如果产生式以非终结符开头,将该非终结符的FIRST集合加入FIRST集合 else { Set<Character> subFirstSet = getFirstSetOfSymbol(production.charAt(0)); // 如果FIRST集合包含ε,则将后续的FIRST集合也加入集合中 if (subFirstSet.contains('ε')) { subFirstSet.remove('ε'); firstSet.addAll(subFirstSet); // 如果后续的FIRST集合还包含ε,则将ε也加入集合中 if (production.length() > 1) { subFirstSet = getFirstSetOfSymbol(production.charAt(1)); if (subFirstSet.contains('ε')) { firstSet.add('ε'); } } } // 如果FIRST集合不包含ε,则将后续的FIRST集合也加入集合中 else { firstSet.addAll(subFirstSet); } } } // 如果两个产生式的FIRST集合有交集,则不是LL(1)文法 int productionCount = productionList.size(); for (int i = 0; i < productionCount; i++) { for (int j = i + 1; j < productionCount; j++) { Set<Character> firstSet1 = getFirstSetOfProduction(productionList.get(i)); Set<Character> firstSet2 = getFirstSetOfProduction(productionList.get(j)); if (!Collections.disjoint(firstSet1, firstSet2)) { return false; } } } // 构造FOLLOW集合 Set<Character> followSet = new HashSet<>(); for (Character tempNonTerminal : productions.keySet()) { for (String production : productions.get(tempNonTerminal)) { int index = production.indexOf(nonTerminal); if (index >= 0 && index < production.length() - 1) { Set<Character> subFirstSet = getFirstSetOfSymbol(production.charAt(index + 1)); if (subFirstSet.contains('ε')) { subFirstSet.remove('ε'); followSet.addAll(getFollowSet(tempNonTerminal)); } followSet.addAll(subFirstSet); } else if (index == production.length() - 1) { followSet.addAll(getFollowSet(tempNonTerminal)); } } } // 如果产生式的FIRST集合包含ε,则将FOLLOW集合加入集合中 if (firstSet.contains('ε')) { firstSet.remove('ε'); followSet.addAll(getFollowSet(nonTerminal)); } // 如果FOLLOW集合与其他非终结符的FIRST集合有交集,则不是LL(1)文法 for (Character tempNonTerminal : productions.keySet()) { if (tempNonTerminal.equals(nonTerminal)) { continue; } for (String production : productions.get(tempNonTerminal)) { if (getFirstSetOfProduction(production).containsAll(followSet)) { return false; } } } } return true; } // 构造预测分析表 public void constructPredictionTable() { predictionTable = new HashMap<>(); for (Character nonTerminal : productions.keySet()) { predictionTable.put(nonTerminal, new HashMap<>()); for (String production : productions.get(nonTerminal)) { Set<Character> firstSet = getFirstSetOfProduction(production); for (Character terminal : firstSet) { if (terminal == 'ε') { for (Character followTerminal : getFollowSet(nonTerminal)) { predictionTable.get(nonTerminal).put(followTerminal, production); } } else { predictionTable.get(nonTerminal).put(terminal, production); } } } } } // 预测分析程序 public boolean parse(String input) { Stack<Character> stack = new Stack<>(); stack.push('$'); stack.push(getStartSymbol()); int index = 0; while (!stack.isEmpty() && index < input.length()) { char symbol = stack.pop(); if (symbol == '$') { return input.charAt(index) == '$'; } if (symbol == input.charAt(index)) { index++; } else if (terminals.contains(symbol)) { return false; } else { String production = predictionTable.get(symbol).get(input.charAt(index)); if (production == null) { return false; } for (int i = production.length() - 1; i >= 0; i--) { if (production.charAt(i) != 'ε') { stack.push(production.charAt(i)); } } } } return stack.isEmpty() && index == input.length(); } // 获取给定符号的FIRST集合 private Set<Character> getFirstSetOfSymbol(char symbol) { Set<Character> firstSet = new HashSet<>(); if (terminals.contains(symbol)) { firstSet.add(symbol); } else { for (String production : productions.get(symbol)) { Set<Character> subFirstSet = getFirstSetOfProduction(production); if (subFirstSet.contains('ε')) { subFirstSet.remove('ε'); firstSet.addAll(subFirstSet); if (production.length() > 1) { subFirstSet = getFirstSetOfSymbol(production.charAt(1)); if (subFirstSet.contains('ε')) { firstSet.add('ε'); } } } else { firstSet.addAll(subFirstSet); } } } return firstSet; } // 获取给定产生式的FIRST集合 private Set<Character> getFirstSetOfProduction(String production) { Set<Character> firstSet = new HashSet<>(); for (char symbol : production.toCharArray()) { Set<Character> subFirstSet = getFirstSetOfSymbol(symbol); if (subFirstSet.contains('ε')) { subFirstSet.remove('ε'); firstSet.addAll(subFirstSet); if (production.length() > 1) { subFirstSet = getFirstSetOfSymbol(production.charAt(1)); if (subFirstSet.contains('ε')) { firstSet.add('ε'); } } } else { firstSet.addAll(subFirstSet); break; } } return firstSet; } // 获取给定非终结符的FOLLOW集合 private Set<Character> getFollowSet(char nonTerminal) { Set<Character> followSet = new HashSet<>(); if (nonTerminal == getStartSymbol()) { followSet.add('$'); } for (Character tempNonTerminal : productions.keySet()) { for (String production : productions.get(tempNonTerminal)) { int index = production.indexOf(nonTerminal); while (index >= 0) { if (index < production.length() - 1) { Set<Character> subFirstSet = getFirstSetOfSymbol(production.charAt(index + 1)); followSet.addAll(subFirstSet); if (subFirstSet.contains('ε')) { index = production.indexOf(nonTerminal, index + 1); } else { break; } } else { followSet.addAll(getFollowSet(tempNonTerminal)); break; } } } } return followSet; } // 获取开始符号 private char getStartSymbol() { return productions.keySet().iterator().next(); } public static void main(String[] args) { Map<Character, List<String>> productions = new HashMap<>(); productions.put('S', Arrays.asList("aBa", "bAb", "ε")); productions.put('A', Arrays.asList("a", "b")); productions.put('B', Arrays.asList("c", "d")); LL1Parser parser = new LL1Parser(productions); if (parser.isLL1Grammar()) { parser.constructPredictionTable(); System.out.println("预测分析表:"); System.out.print(" "); for (char terminal : parser.terminals) { System.out.print(terminal + " "); } System.out.println("$"); for (char nonTerminal : parser.nonTerminals) { System.out.print(nonTerminal + " "); for (char terminal : parser.terminals) { String production = parser.predictionTable.get(nonTerminal).get(terminal); System.out.print((production == null ? " " : production) + " "); } String production = parser.predictionTable.get(nonTerminal).get('$'); System.out.println((production == null ? " " : production) + " "); } String input = "abdc$"; System.out.println("输入串:" + input); if (parser.parse(input)) { System.out.println("属于该文法"); } else { System.out.println("不属于该文法"); } } else { System.out.println("不是LL1文法"); } } } ``` 以上代码实现了一个简单的LL(1)文法预测分析器,可以判断一个文法是否为LL(1)文法,构造其预测分析表,并使用预测分析程序对输入的字符串进行判断。

相关推荐

最新推荐

recommend-type

算法设计与分析-期末考核论文.docx

我也是it界的一枚小萌新,自己对照课本以及网上资源完成的期末小论文,代码为课本源码。若有错误,请指正,大家互相学习
recommend-type

python实现AHP算法的方法实例(层次分析法)

主要给大家介绍了关于python实现AHP算法(层次分析法)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
recommend-type

编译原理实验二——算符优先分析法设计与实现

用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
recommend-type

算法设计与分析实验报告(动态规划问题)

算法设计与分析实验报告,python写的,附源码 问题描述:矩阵连乘算法实现; 给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积...
recommend-type

算法设计与分析经典题目源代码!

这个文档里包含了算法设计与分析-C++语言描述(电子工业出版社出版)课程里需要做的典型实验题的源代码及实现,包括找零钱问题,0-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的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。