假如你是一个高级程序员,请用Java编写具体代码实现下面功能 创建一个 GUI 界面,让用户输入语法 G。您可以使用 Java Swing 来创建用户界面。 创建一个 CFG 类,用于处理输入语法 G 的左递归和公共左因子分解。在该类中,您可以添加方法来计算每个非终端符号的 FIRST 和 FOLLOW 集。 实现 LL(1) 解析器算法。您可以使用一个解析器类来实现此算法。该算法需要 LL(1) 解析表来预测下一个输入标记是哪个。可以使用一个二维数组来表示解析表。每个单元格都对应一个非终结符和一个终结符。解析表中的每个元素包含一个产生式,该产生式来标识生成哪个非终极符号的语法树。 将 CFG 类和解析器类与 GUI 类集成,以便用户可以输入要解析的句子,并且输出可以显示在屏幕上。您可以将 CFG 类和解析器类作为 GUI 类的成员变量,并在 GUI 类中添加按钮和文本框,以便用户可以输入要解析的句子并将打印出来的FIRST、FOLLOW集和预测分析表输出显示在屏幕上。
时间: 2024-03-10 18:45:55 浏览: 83
JAVA GUI编程
好的,以下是我给出的Java代码实现:
首先,我们创建一个GUI界面,使用Java Swing来创建。代码如下:
```java
import javax.swing.*;
import java.awt.*;
public class CFG_GUI {
private JFrame frame;
private JPanel panel;
private JLabel inputLabel;
private JTextField inputField;
private JButton submitButton;
private JTextArea outputArea;
private JScrollPane scrollPane;
public CFG_GUI() {
frame = new JFrame("CFG Parser");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new BorderLayout());
inputLabel = new JLabel("Input Grammar:");
inputField = new JTextField(50);
submitButton = new JButton("Parse");
outputArea = new JTextArea(30, 50);
outputArea.setEditable(false);
scrollPane = new JScrollPane(outputArea);
JPanel inputPanel = new JPanel();
inputPanel.add(inputLabel);
inputPanel.add(inputField);
inputPanel.add(submitButton);
panel.add(inputPanel, BorderLayout.NORTH);
panel.add(scrollPane, BorderLayout.CENTER);
frame.add(panel);
frame.setVisible(true);
}
public String getInput() {
return inputField.getText();
}
public void setOutput(String output) {
outputArea.setText(output);
}
public void addSubmitListener(ActionListener listener) {
submitButton.addActionListener(listener);
}
}
```
接下来,我们创建一个CFG类,用于处理输入语法G的左递归和公共左因子分解,并添加方法来计算每个非终端符号的FIRST和FOLLOW集。代码如下:
```java
import java.util.*;
public class CFG {
private Map<String, List<String>> productions;
public CFG(String input) {
productions = new HashMap<>();
String[] lines = input.split("\n");
for (String line : lines) {
String[] tokens = line.split(" -> ");
String nonterminal = tokens[0];
String[] rhs = tokens[1].split("\\|");
List<String> productionsList = new ArrayList<>(Arrays.asList(rhs));
productions.put(nonterminal, productionsList);
}
}
public Map<String, Set<String>> getFirst() {
Map<String, Set<String>> first = new HashMap<>();
for (String nonterminal : productions.keySet()) {
first.put(nonterminal, new HashSet<>());
}
boolean changed;
do {
changed = false;
for (String nonterminal : productions.keySet()) {
for (String production : productions.get(nonterminal)) {
String[] symbols = production.split("\\s+");
int i = 0;
while (i < symbols.length) {
String symbol = symbols[i];
if (isTerminal(symbol)) {
changed |= first.get(nonterminal).add(symbol);
break;
} else {
Set<String> firstOfSymbol = first.get(symbol);
changed |= first.get(nonterminal).addAll(firstOfSymbol);
if (!firstOfSymbol.contains("")) {
break;
}
}
i++;
}
if (i == symbols.length) {
changed |= first.get(nonterminal).add("");
}
}
}
} while (changed);
return first;
}
public Map<String, Set<String>> getFollow(Map<String, Set<String>> first) {
Map<String, Set<String>> follow = new HashMap<>();
for (String nonterminal : productions.keySet()) {
follow.put(nonterminal, new HashSet<>());
}
follow.get("S").add("$");
boolean changed;
do {
changed = false;
for (String nonterminal : productions.keySet()) {
for (String production : productions.get(nonterminal)) {
String[] symbols = production.split("\\s+");
for (int i = 0; i < symbols.length; i++) {
String symbol = symbols[i];
if (isNonterminal(symbol)) {
Set<String> followOfSymbol = follow.get(symbol);
int j = i + 1;
while (j < symbols.length) {
Set<String> firstOfNextSymbol = first.get(symbols[j]);
changed |= followOfSymbol.addAll(firstOfNextSymbol);
if (!firstOfNextSymbol.contains("")) {
break;
}
j++;
}
if (j == symbols.length) {
changed |= followOfSymbol.addAll(follow.get(nonterminal));
}
}
}
}
}
} while (changed);
return follow;
}
public boolean isNonterminal(String symbol) {
return symbol.matches("[A-Z].*");
}
public boolean isTerminal(String symbol) {
return !isNonterminal(symbol);
}
public String eliminateLeftRecursion() {
List<String> nonterminals = new ArrayList<>(productions.keySet());
StringBuilder output = new StringBuilder();
for (int i = 0; i < nonterminals.size(); i++) {
String nonterminal = nonterminals.get(i);
output.append(nonterminal).append(" -> ");
List<String> productionsList = productions.get(nonterminal);
List<String> alpha = new ArrayList<>();
List<String> beta = new ArrayList<>();
for (String production : productionsList) {
String[] symbols = production.split("\\s+");
if (symbols[0].equals(nonterminal)) {
alpha.add(production.substring(nonterminal.length() + 3));
} else {
beta.add(production);
}
}
if (alpha.isEmpty()) {
output.append(String.join(" | ", beta)).append("\n");
continue;
}
String newNonterminal = nonterminal + "'";
output.append(String.join(" | ", beta)).append(" ").append(newNonterminal).append("\n");
List<String> newProductions = new ArrayList<>();
for (String b : beta) {
newProductions.add(b + " " + newNonterminal);
}
newProductions.add("");
List<String> newAlphaProductions = new ArrayList<>();
for (String a : alpha) {
newAlphaProductions.add(a.substring(1) + " " + newNonterminal);
}
newAlphaProductions.add("");
productions.put(nonterminal, new ArrayList<>(newProductions));
productions.put(newNonterminal, new ArrayList<>(newAlphaProductions));
nonterminals.add(i + 1, newNonterminal);
}
return output.toString();
}
public String factorize() {
List<String> nonterminals = new ArrayList<>(productions.keySet());
StringBuilder output = new StringBuilder();
for (int i = 0; i < nonterminals.size(); i++) {
String nonterminal = nonterminals.get(i);
List<String> productionsList = productions.get(nonterminal);
Map<String, List<String>> groups = new HashMap<>();
for (String production : productionsList) {
String symbol = production.split("\\s+")[0];
if (!groups.containsKey(symbol)) {
groups.put(symbol, new ArrayList<>());
}
groups.get(symbol).add(production);
}
List<String> newProductions = new ArrayList<>();
for (String symbol : groups.keySet()) {
List<String> group = groups.get(symbol);
if (group.size() > 1) {
String newNonterminal = nonterminal + "'";
output.append(newNonterminal).append(" -> ").append(symbol).append(" ").append(newNonterminal).append("\n");
productions.put(newNonterminal, new ArrayList<>(group));
newProductions.add(symbol + " " + newNonterminal);
nonterminals.add(i + 1, newNonterminal);
} else {
newProductions.addAll(group);
}
}
productions.put(nonterminal, newProductions);
}
return output.toString();
}
}
```
最后,我们实现LL(1)解析器算法,使用一个解析器类来实现此算法。代码如下:
```java
import java.util.*;
public class Parser {
private String[][] parsingTable;
private Map<String, List<String>> productions;
public Parser(Map<String, Set<String>> first, Map<String, Set<String>> follow, CFG cfg) {
Set<String> terminals = new HashSet<>();
Set<String> nonterminals = new HashSet<>(cfg.productions.keySet());
productions = cfg.productions;
for (String nonterminal : nonterminals) {
terminals.addAll(first.get(nonterminal));
terminals.addAll(follow.get(nonterminal));
}
terminals.remove("");
parsingTable = new String[nonterminals.size() + 1][terminals.size() + 1];
for (int i = 0; i < parsingTable.length; i++) {
for (int j = 0; j < parsingTable[0].length; j++) {
parsingTable[i][j] = "";
}
}
for (String nonterminal : nonterminals) {
int i = getIndex(nonterminal, nonterminals);
for (String production : productions.get(nonterminal)) {
Set<String> firstOfProduction = getFirstOfProduction(production, first);
for (String symbol : firstOfProduction) {
if (!symbol.equals("")) {
int j = getIndex(symbol, terminals);
parsingTable[i][j] = production;
}
}
if (firstOfProduction.contains("")) {
for (String symbol : follow.get(nonterminal)) {
int j = getIndex(symbol, terminals);
parsingTable[i][j] = production;
}
}
}
}
}
public boolean parse(String input) {
Stack<String> stack = new Stack<>();
stack.push("$");
stack.push("S");
String[] tokens = input.split("\\s+");
int i = 0;
while (!stack.empty()) {
String top = stack.pop();
if (isTerminal(top)) {
if (!top.equals(tokens[i])) {
return false;
}
i++;
} else if (isNonterminal(top)) {
int row = getIndex(top, productions.keySet());
int col = getIndex(tokens[i], parsingTable[0]);
String production = parsingTable[row][col];
if (production.equals("")) {
return false;
}
String[] symbols = production.split("\\s+");
for (int j = symbols.length - 1; j >= 0; j--) {
stack.push(symbols[j]);
}
}
}
return true;
}
public Set<String> getFirstOfProduction(String production, Map<String, Set<String>> first) {
String[] symbols = production.split("\\s+");
Set<String> firstOfProduction = new HashSet<>();
int i = 0;
while (i < symbols.length) {
String symbol = symbols[i];
if (isTerminal(symbol)) {
firstOfProduction.add(symbol);
break;
} else {
Set<String> firstOfSymbol = first.get(symbol);
firstOfProduction.addAll(firstOfSymbol);
if (!firstOfSymbol.contains("")) {
break;
}
}
i++;
}
if (i == symbols.length) {
firstOfProduction.add("");
}
return firstOfProduction;
}
public boolean isNonterminal(String symbol) {
return symbol.matches("[A-Z].*");
}
public boolean isTerminal(String symbol) {
return !isNonterminal(symbol);
}
public int getIndex(String symbol, Set<String> set) {
int i = 0;
for (String s : set) {
if (s.equals(symbol)) {
return i;
}
i++;
}
return -1;
}
public int getIndex(String symbol, String[] array) {
int i = 0;
for (String s : array) {
if (s.equals(symbol)) {
return i;
}
i++;
}
return -1;
}
}
```
最后,我们将CFG类和解析器类与GUI类集成,以便用户可以输入要解析的句子,并且输出可以显示在屏幕上。代码如下:
```java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) {
CFG_GUI gui = new CFG_GUI();
gui.addSubmitListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String input = gui.getInput();
CFG cfg = new CFG(input);
String output = "";
output += "Original Grammar:\n" + input + "\n\n";
output += "Eliminated Left Recursion:\n" + cfg.eliminateLeftRecursion() + "\n";
output += "Factored Grammar:\n" + cfg.factorize() + "\n";
Map<String, Set<String>> first = cfg.getFirst();
output += "FIRST Sets:\n";
for (String nonterminal : first.keySet()) {
output += nonterminal + ": " + first.get(nonterminal) + "\n";
}
output += "\n";
Map<String, Set<String>> follow = cfg.getFollow(first);
output += "FOLLOW Sets:\n";
for (String nonterminal : follow.keySet()) {
output += nonterminal + ": " + follow.get(nonterminal) + "\n";
}
output += "\n";
Parser parser = new Parser(first, follow, cfg);
output += "Parsing Table:\n";
output += String.format("%-6s", "");
Set<String> terminals = parser.getIndex("", first).isEmpty() ? first.get("S") : first.get("");
for (String terminal : terminals) {
output += String.format("%-25s", terminal);
}
output += "\n";
for (String nonterminal : cfg.productions.keySet()) {
output += String.format("%-6s", nonterminal);
for (String terminal : terminals) {
String production = parser.parsingTable[parser.getIndex(nonterminal, cfg.productions.keySet())][parser.getIndex(terminal, parser.parsingTable[0])];
if (!production.equals("")) {
output += String.format("%-25s", nonterminal + " -> " + production);
} else {
output += String.format("%-25s", "");
}
}
output += "\n";
}
output += "\n";
boolean success = parser.parse(gui.getInput());
output += "Parsing Result: " + (success ? "Accepted" : "Rejected");
gui.setOutput(output);
}
});
}
}
```
阅读全文