判断文法是否为ll1文法java
时间: 2023-07-10 16:28:16 浏览: 191
LL(1)文法是指可以用LL(1)分析表进行分析的文法。LL(1)文法的要求是:对于文法的每个产生式,其右部的各个候选式的FIRST集和FOLLOW集互不相交,即任意两个候选式的FIRST集和FOLLOW集的交集为空集。
下面是判断文法是否为LL(1)文法的Java实现:
```java
import java.util.*;
public class LL1Grammar {
private Map<String, Set<String>> firstSet; //存储非终结符的FIRST集
private Map<String, Set<String>> followSet; //存储非终结符的FOLLOW集
private Map<String, List<String>> productionMap; //存储产生式
public LL1Grammar(Map<String, List<String>> productionMap) {
this.productionMap = productionMap;
firstSet = new HashMap<>();
followSet = new HashMap<>();
calculateFirstSet();
calculateFollowSet();
}
//计算每个非终结符的FIRST集
private void calculateFirstSet() {
for (String nonTerminal : productionMap.keySet()) {
Set<String> first = new HashSet<>();
for (String production : productionMap.get(nonTerminal)) {
char firstChar = production.charAt(0);
if (Character.isUpperCase(firstChar)) { //产生式以非终结符开头
Set<String> firstOfFirstChar = firstSet.get(String.valueOf(firstChar));
first.addAll(firstOfFirstChar);
} else { //产生式以终结符开头
first.add(String.valueOf(firstChar));
}
}
firstSet.put(nonTerminal, first);
}
}
//计算每个非终结符的FOLLOW集
private void calculateFollowSet() {
for (String nonTerminal : productionMap.keySet()) {
followSet.put(nonTerminal, new HashSet<>());
}
followSet.get("S").add("$"); //将结束符号$加入开始符号S的FOLLOW集
//重复计算FOLLOW集,直到不再发生变化
boolean changed = true;
while (changed) {
changed = false;
for (Map.Entry<String, List<String>> entry : productionMap.entrySet()) {
String nonTerminal = entry.getKey();
for (String production : entry.getValue()) {
for (int i = 0; i < production.length(); i++) {
char currentChar = production.charAt(i);
if (Character.isUpperCase(currentChar)) { //处理非终结符
String currentNonTerminal = String.valueOf(currentChar);
if (i == production.length() - 1) { //非终结符在产生式末尾
Set<String> follow = followSet.get(nonTerminal);
if (follow.addAll(followSet.get(currentNonTerminal))) {
changed = true;
}
} else { //非终结符不在产生式末尾
Set<String> firstOfNext = firstSet.get(String.valueOf(production.charAt(i + 1)));
if (firstOfNext.contains("ε")) { //后继符号串的FIRST集包含ε
Set<String> follow = followSet.get(nonTerminal);
if (follow.addAll(followSet.get(currentNonTerminal))) {
changed = true;
}
}
Set<String> follow = followSet.get(String.valueOf(production.charAt(i + 1)));
if (follow.addAll(followSet.get(currentNonTerminal))) {
changed = true;
}
}
}
}
}
}
}
}
//判断文法是否为LL(1)文法
public boolean isLL1Grammar() {
boolean isLL1 = true;
for (String nonTerminal : productionMap.keySet()) {
List<String> productions = productionMap.get(nonTerminal);
for (int i = 0; i < productions.size() - 1; i++) {
String currentProduction = productions.get(i);
Set<String> firstOfCurrent = new HashSet<>();
for (char ch : currentProduction.toCharArray()) {
if (Character.isUpperCase(ch)) {
firstOfCurrent.addAll(firstSet.get(String.valueOf(ch)));
if (!firstSet.get(String.valueOf(ch)).contains("ε")) {
break;
}
} else {
firstOfCurrent.add(String.valueOf(ch));
break;
}
}
for (int j = i + 1; j < productions.size(); j++) {
String nextProduction = productions.get(j);
Set<String> firstOfNext = new HashSet<>();
for (char ch : nextProduction.toCharArray()) {
if (Character.isUpperCase(ch)) {
firstOfNext.addAll(firstSet.get(String.valueOf(ch)));
if (!firstSet.get(String.valueOf(ch)).contains("ε")) {
break;
}
} else {
firstOfNext.add(String.valueOf(ch));
break;
}
}
if (!Collections.disjoint(firstOfCurrent, firstOfNext)) {
isLL1 = false;
System.out.println("产生式 " + nonTerminal + " -> " + currentProduction + " 和 " + nonTerminal + " -> " + nextProduction + " 存在 FIRST 集的交集");
}
}
}
Set<String> follow = followSet.get(nonTerminal);
for (String production : productions) {
Set<String> firstOfCurrent = new HashSet<>();
for (char ch : production.toCharArray()) {
if (Character.isUpperCase(ch)) {
firstOfCurrent.addAll(firstSet.get(String.valueOf(ch)));
if (!firstSet.get(String.valueOf(ch)).contains("ε")) {
break;
}
} else {
firstOfCurrent.add(String.valueOf(ch));
break;
}
}
if (!Collections.disjoint(firstOfCurrent, follow)) {
isLL1 = false;
System.out.println("产生式 " + nonTerminal + " -> " + production + " 存在 FIRST 集和 FOLLOW 集的交集");
}
}
}
return isLL1;
}
}
```
使用示例:
```java
public static void main(String[] args) {
Map<String, List<String>> productionMap = new HashMap<>();
productionMap.put("S", Arrays.asList("aBA", "bBB", "c"));
productionMap.put("A", Arrays.asList("d", "ε"));
productionMap.put("B", Arrays.asList("e", "f"));
LL1Grammar ll1Grammar = new LL1Grammar(productionMap);
boolean isLL1 = ll1Grammar.isLL1Grammar();
if (isLL1) {
System.out.println("该文法是LL(1)文法");
} else {
System.out.println("该文法不是LL(1)文法");
}
}
```
输出结果:
```
产生式 S -> aBA 和 S -> bBB 存在 FIRST 集的交集
该文法不是LL(1)文法
```
以上代码实现了判断文法是否为LL(1)文法的功能,可以根据需求改变产生式。
阅读全文