使用Java实现下面功能 创建一个 GUI 界面,让用户输入语法 G。您可以使用 Java Swing 来创建用户界面。 创建一个 CFG 类,用于处理输入语法 G 的左递归和公共左因子分解。在该类中,您可以添加方法来计算每个非终端符号的 FIRST 和 FOLLOW 集。 实现 LL(1) 解析器算法。您可以使用一个解析器类来实现此算法。该算法需要 LL(1) 解析表来预测下一个输入标记是哪个。可以使用一个二维数组来表示解析表。每个单元格都对应一个非终结符和一个终结符。解析表中的每个元素包含一个产生式,该产生式来标识生成哪个非终极符号的语法树。 将 CFG 类和解析器类与 GUI 类集成,以便用户可以输入要解析的句子,并且输出可以显示在屏幕上。您可以将 CFG 类和解析器类作为 GUI 类的成员变量,并在 GUI 类中添加按钮和文本框,以便用户可以输入要解析的句子并将输出显示在屏幕上。
时间: 2024-03-10 11:45:33 浏览: 133
使用Java GUI实现用户登陆界面
这是一个比较复杂的任务,需要多个类的协调配合,下面提供一个基本的框架供参考:
1. 首先是GUI界面的实现,可以使用Java Swing来实现:
```java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI implements ActionListener {
private JFrame frame;
private JPanel panel;
private JLabel label;
private JTextField textField;
private JTextArea textArea;
private JButton button;
public GUI() {
frame = new JFrame("LL(1) Parser");
panel = new JPanel(new GridLayout(3, 1));
label = new JLabel("Enter CFG:");
textField = new JTextField();
textArea = new JTextArea();
button = new JButton("Parse");
button.addActionListener(this);
panel.add(label);
panel.add(textField);
panel.add(button);
frame.add(panel, BorderLayout.NORTH);
frame.add(textArea, BorderLayout.CENTER);
frame.setSize(600, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@Override
public void actionPerformed(ActionEvent e) {
String cfg = textField.getText();
CFG grammar = new CFG(cfg);
Parser parser = new Parser(grammar);
String result = parser.parse();
textArea.setText(result);
}
}
```
2. 接下来是CFG类的实现,用于处理输入语法G的左递归和公共左因子分解,以及计算FIRST和FOLLOW集:
```java
import java.util.*;
public class CFG {
private Map<String, List<String>> rules;
private Set<String> terminals;
private Set<String> nonTerminals;
private Map<String, Set<String>> firstSets;
private Map<String, Set<String>> followSets;
public CFG(String input) {
rules = new HashMap<>();
terminals = new HashSet<>();
nonTerminals = new HashSet<>();
firstSets = new HashMap<>();
followSets = new HashMap<>();
parse(input);
eliminateLeftRecursion();
factorize();
calculateFirstSets();
calculateFollowSets();
}
private void parse(String input) {
String[] lines = input.split("\n");
for (String line : lines) {
String[] parts = line.split("->");
String lhs = parts[0].trim();
String[] rhss = parts[1].split("\\|");
List<String> rhsList = new ArrayList<>();
for (String rhs : rhss) {
rhsList.add(rhs.trim());
for (int i = 0; i < rhs.length(); i++) {
char c = rhs.charAt(i);
if (Character.isLowerCase(c)) {
terminals.add(String.valueOf(c));
}
}
}
rules.put(lhs, rhsList);
nonTerminals.add(lhs);
}
}
private void eliminateLeftRecursion() {
List<String> nonTerminalList = new ArrayList<>(nonTerminals);
for (int i = 0; i < nonTerminalList.size(); i++) {
String A = nonTerminalList.get(i);
for (int j = 0; j < i; j++) {
String B = nonTerminalList.get(j);
List<String> newRules = new ArrayList<>();
List<String> oldRules = rules.get(A);
for (String rule : oldRules) {
if (rule.startsWith(B)) {
for (String newRule : rules.get(B)) {
String newRHS = newRule + rule.substring(B.length());
newRules.add(newRHS);
}
} else {
newRules.add(rule);
}
}
if (!newRules.isEmpty()) {
rules.put(A, newRules);
}
}
List<String> newRules = new ArrayList<>();
List<String> oldRules = rules.get(A);
for (String rule : oldRules) {
if (rule.startsWith(A)) {
String newNT = A + "'";
String newRule1 = rule.substring(1) + newNT;
String newRule2 = "ε";
newRules.add(newRule1);
newRules.add(newRule2);
nonTerminals.add(newNT);
} else {
String newRule = rule + A + "'";
newRules.add(newRule);
}
}
if (!newRules.isEmpty()) {
rules.put(A, newRules);
}
}
}
private void factorize() {
List<String> nonTerminalList = new ArrayList<>(nonTerminals);
for (int i = 0; i < nonTerminalList.size(); i++) {
String A = nonTerminalList.get(i);
List<String> oldRules = rules.get(A);
List<String> newRules = new ArrayList<>();
for (char c = 'a'; c <= 'z'; c++) {
List<String> alphaRules = new ArrayList<>();
for (String rule : oldRules) {
if (rule.startsWith(String.valueOf(c))) {
alphaRules.add(rule.substring(1));
}
}
if (!alphaRules.isEmpty()) {
String newNT = A + c;
nonTerminals.add(newNT);
List<String> betaRules = new ArrayList<>();
for (String rule : oldRules) {
if (!rule.startsWith(String.valueOf(c))) {
betaRules.add(rule + newNT);
}
}
newRules.addAll(betaRules);
List<String> newAlphaRules = new ArrayList<>();
for (String alphaRule : alphaRules) {
if (alphaRule.isEmpty()) {
newAlphaRules.add("ε");
} else {
newAlphaRules.add(alphaRule + newNT);
}
}
newRules.add(newNT + "->" + String.join("|", newAlphaRules));
}
}
if (!newRules.isEmpty()) {
rules.put(A, newRules);
}
}
}
private Set<String> first(String symbol) {
Set<String> firstSet = new HashSet<>();
if (terminals.contains(symbol)) {
firstSet.add(symbol);
} else if (nonTerminals.contains(symbol)) {
for (String rule : rules.get(symbol)) {
String[] parts = rule.split("");
boolean allNullable = true;
for (String part : parts) {
Set<String> firstPart = first(part);
firstSet.addAll(firstPart);
if (!firstPart.contains("ε")) {
allNullable = false;
break;
}
}
if (allNullable) {
firstSet.add("ε");
}
}
}
return firstSet;
}
private void calculateFirstSets() {
for (String symbol : terminals) {
firstSets.put(symbol, Collections.singleton(symbol));
}
for (String symbol : nonTerminals) {
firstSets.put(symbol, new HashSet<>());
}
boolean changed = true;
while (changed) {
changed = false;
for (String symbol : nonTerminals) {
Set<String> oldFirstSet = firstSets.get(symbol);
Set<String> newFirstSet = new HashSet<>(oldFirstSet);
for (String rule : rules.get(symbol)) {
String[] parts = rule.split("");
boolean allNullable = true;
for (String part : parts) {
Set<String> firstPart = firstSets.get(part);
newFirstSet.addAll(firstPart);
if (!firstPart.contains("ε")) {
allNullable = false;
break;
}
}
if (allNullable) {
newFirstSet.add("ε");
}
}
if (!newFirstSet.equals(oldFirstSet)) {
firstSets.put(symbol, newFirstSet);
changed = true;
}
}
}
}
private void calculateFollowSets() {
for (String symbol : nonTerminals) {
followSets.put(symbol, new HashSet<>());
}
followSets.get("S").add("$");
boolean changed = true;
while (changed) {
changed = false;
for (String A : nonTerminals) {
for (String B : nonTerminals) {
for (String rule : rules.get(B)) {
String[] parts = rule.split("");
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (part.equals(A)) {
Set<String> followA = followSets.get(A);
Set<String> followB = followSets.get(B);
Set<String> firstRest = first(String.join("", Arrays.copyOfRange(parts, i + 1, parts.length)));
if (i == parts.length - 1 || firstRest.contains("ε")) {
followA.addAll(followB);
}
followA.addAll(firstRest);
if (!followA.equals(followSets.get(A))) {
followSets.put(A, followA);
changed = true;
}
}
}
}
}
}
}
}
public Set<String> getFirstSet(String symbol) {
return firstSets.get(symbol);
}
public Set<String> getFollowSet(String symbol) {
return followSets.get(symbol);
}
public Map<String, List<String>> getRules() {
return rules;
}
}
```
3. 最后是LL(1)解析器的实现:
```java
import java.util.*;
public class Parser {
private CFG grammar;
private Map<String, Map<String, String>> parsingTable;
public Parser(CFG grammar) {
this.grammar = grammar;
calculateParsingTable();
}
private void calculateParsingTable() {
Set<String> terminals = grammar.terminals;
Set<String> nonTerminals = grammar.nonTerminals;
parsingTable = new HashMap<>();
for (String A : nonTerminals) {
Map<String, String> row = new HashMap<>();
for (String a : terminals) {
row.put(a, "");
}
row.put("$", "");
parsingTable.put(A, row);
}
for (String A : nonTerminals) {
for (String rule : grammar.getRules().get(A)) {
Set<String> firstSet = grammar.getFirstSet(rule.split("")[0]);
for (String a : firstSet) {
if (!a.equals("ε")) {
parsingTable.get(A).put(a, rule);
}
}
if (firstSet.contains("ε")) {
Set<String> followSet = grammar.getFollowSet(A);
for (String b : followSet) {
parsingTable.get(A).put(b, rule);
}
}
}
}
}
public String parse() {
Stack<String> stack = new Stack<>();
stack.push("$");
stack.push("S");
String input = "$" + GUI.textField.getText() + "$";
String output = "";
int i = 0;
while (!stack.isEmpty()) {
String X = stack.pop();
String a = String.valueOf(input.charAt(i));
if (grammar.terminals.contains(X)) {
if (X.equals(a)) {
i++;
} else {
output = "Syntax error!";
break;
}
} else if (grammar.nonTerminals.contains(X)) {
String rule = parsingTable.get(X).get(a);
if (!rule.isEmpty()) {
String[] parts = rule.split("");
for (int j = parts.length - 1; j >= 0; j--) {
if (!parts[j].equals("ε")) {
stack.push(parts[j]);
}
}
} else {
output = "Syntax error!";
break;
}
}
}
if (i == input.length() - 1 && output.isEmpty()) {
output = "Accepted!";
} else if (output.isEmpty()) {
output = "Syntax error!";
}
return output;
}
}
```
4. 最终的主函数:
```java
public class Main {
public static void main(String[] args) {
GUI gui = new GUI();
}
}
```
以上代码实现了一个简单的LL(1)解析器,可以通过GUI界面输入CFG并进行解析。
阅读全文