写出相应的java代码
时间: 2024-12-14 10:01:56 浏览: 3
根据提供的文档内容,以下是使用Java实现消除文法左递归的代码:
```java
import java.util.*;
class Node {
String left;
Set<String> right;
public Node(String left, Set<String> right) {
this.left = left;
this.right = right;
}
}
public class EliminateLeftRecursion {
private List<Node> productions = new ArrayList<>();
private List<String> nonTerminals = new ArrayList<>();
public static void main(String[] args) {
EliminateLeftRecursion elr = new EliminateLeftRecursion();
elr.getProductions();
elr.getNonTerminals();
elr.myOperate();
System.out.println("消除一切左递归后的结果为:");
for (Node production : elr.productions) {
System.out.print(production.left + " -> ");
Iterator<String> it = production.right.iterator();
while (it.hasNext()) {
System.out.print(it.next());
if (it.hasNext()) {
System.out.print("; ");
}
}
System.out.println();
}
}
public void getProductions() {
Scanner scanner = new Scanner(System.in);
System.out.println("若一个非终结符可推出多个结果,请直接以11分隔,不必分开输入");
System.out.println("输入产生式,以$为结束标志:");
String input;
while (!(input = scanner.nextLine()).equals("$")) {
String[] parts = input.split("->");
String left = parts[0].trim();
String[] rights = parts[1].split("\\|\\|");
Set<String> rightSet = new HashSet<>(Arrays.asList(rights));
productions.add(new Node(left, rightSet));
}
}
public void getNonTerminals() {
Set<String> tempSet = new HashSet<>();
for (Node production : productions) {
tempSet.add(production.left);
}
nonTerminals.addAll(tempSet);
}
public boolean isAllTerminal(String str) {
for (char c : str.toCharArray()) {
if (Character.isUpperCase(c)) {
return false;
}
}
return true;
}
public void eraseDirect(int posi) {
Set<String> right = productions.get(posi).right;
boolean hasLeftRecursion = false;
for (String production : right) {
if (production.startsWith(productions.get(posi).left)) {
hasLeftRecursion = true;
break;
}
}
if (!hasLeftRecursion) {
return;
}
Set<String> alpha = new HashSet<>();
Set<String> beta = new HashSet<>();
for (String production : right) {
if (production.startsWith(productions.get(posi).left)) {
alpha.add(production.substring(productions.get(posi).left.length()));
} else {
beta.add(production + productions.get(posi).left + "'");
}
}
productions.get(posi).right.clear();
productions.get(posi).right.addAll(beta);
Set<String> newRight = new HashSet<>();
newRight.addAll(alpha.stream().map(a -> a + productions.get(posi).left + "'").collect(Collectors.toSet()));
newRight.add("ε");
productions.add(new Node(productions.get(posi).left + "'", newRight));
}
public void myOperate() {
for (int i = 0; i < nonTerminals.size(); i++) {
for (int j = 0; j < i; j++) {
int posi = -1, posj = -1;
for (int k = 0; k < productions.size(); k++) {
if (productions.get(k).left.equals(nonTerminals.get(i))) {
posi = k;
break;
}
}
for (int k = 0; k < productions.size(); k++) {
if (productions.get(k).left.equals(nonTerminals.get(j))) {
posj = k;
break;
}
}
if (posi == -1 || posj == -1) {
continue;
}
Set<String> newRight = new HashSet<>();
for (String production : productions.get(posi).right) {
if (production.contains(productions.get(posj).left)) {
for (String replacement : productions.get(posj).right) {
newRight.add(production.replaceFirst(productions.get(posj).left, replacement));
}
} else {
newRight.add(production);
}
}
productions.get(posi).right.clear();
productions.get(posi).right.addAll(newRight);
}
eraseDirect(i);
}
}
}
```
### 代码说明:
1. **Node类**:表示文法的一个产生式,包含左部和右部集合。
2. **EliminateLeftRecursion类**:
- `getProductions`方法:读取用户输入的产生式并存储。
- `getNonTerminals`方法:提取所有的非终结符。
- `isAllTerminal`方法:判断一个字符串是否全部由终结符组成。
- `eraseDirect`方法:消除直接左递归。
- `myOperate`方法:主逻辑,按照文档中的步骤进行处理。
3. **main方法**:程序入口,调用上述方法并输出结果。
### 使用说明:
1. 运行程序后,按提示输入文法的产生式,每条产生式以`->`分隔左部和右部,多个右部之间用`||`分隔。
2. 输入完成后,以`$`结束输入。
3. 程序会输出消除左递归后的文法。
阅读全文