用Java语言实现预测分析法,设计与实现的算法和方法说明、源代码,对运行结果进行必要在分析与说明。首先判断任一给定文法是否为LL(1)文法,然后构造其预测分析表和预测分析程序。 输入:一个文法、一个字符串。 输出:预测分析表、判定结果: (1)是LL1文法,则同时输出分析结果。 (2)不是LL1文法。
时间: 2024-03-12 09:44:45 浏览: 121
LL(1)文法预测分析法 实现及演示
以下是一个简单的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)文法,构造其预测分析表,并使用预测分析程序对输入的字符串进行判断。
阅读全文