static HashMap<String, ArrayList<String>> follow = new HashMap<>();
时间: 2024-05-31 12:15:08 浏览: 146
这是一个静态变量,在Java中,静态变量属于类而不是对象,可以通过类名直接访问。该变量名为follow,类型为HashMap<String, ArrayList<String>>,即键为字符串类型,值为字符串类型的ArrayList。这个HashMap用于存储每个字符串对应的一个字符串列表,可以用来表示关注某个用户的所有粉丝或者关注某个用户所关注的所有人。
相关问题
假如你是一个高级程序员,请用Java编写具体代码实现下面功能 创建一个 GUI 界面,让用户输入语法 G。您可以使用 Java Swing 来创建用户界面。 创建一个 CFG 类,用于处理输入语法 G 的左递归和公共左因子分解。在该类中,您可以添加方法来计算每个非终端符号的 FIRST 和 FOLLOW 集。 实现 LL(1) 解析器算法。您可以使用一个解析器类来实现此算法。该算法需要 LL(1) 解析表来预测下一个输入标记是哪个。可以使用一个二维数组来表示解析表。每个单元格都对应一个非终结符和一个终结符。解析表中的每个元素包含一个产生式,该产生式来标识生成哪个非终极符号的语法树。 将 CFG 类和解析器类与 GUI 类集成,以便用户可以输入要解析的句子,并且输出可以显示在屏幕上。您可以将 CFG 类和解析器类作为 GUI 类的成员变量,并在 GUI 类中添加按钮和文本框,以便用户可以输入要解析的句子并将打印出来的FIRST、FOLLOW集和预测分析表输出显示在屏幕上。
好的,以下是我给出的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);
}
});
}
}
```
写一个Java实现LL(1)文法,文法和字符串控制台输入,需要输出预测分析表(以表格的形式)和LL(1)分析表(步骤 | 分析栈 | 判定串 | 使用规则)E->TH H->+TH H->@ T->FJ J->*FJ J->@ F->(E) F->a end
以下是一个完整的Java程序,实现了您提供的LL(1)文法,并在控制台上输入文法和字符串后,输出预测分析表和LL(1)分析表。
```java
import java.util.*;
public class LL1Parser {
static class Grammar {
String nonTerminal;
List<String> productions = new ArrayList<>();
public Grammar(String nonTerminal, List<String> productions) {
this.nonTerminal = nonTerminal;
this.productions.addAll(productions);
}
}
private static Map<String, Set<String>> firstSet = new HashMap<>();
private static Map<String, Set<String>> followSet = new HashMap<>();
private static Map<String, Map<String, String>> predictiveParsingTable = new HashMap<>();
private static Set<String> terminals = new HashSet<>();
private static int step = 1;
private static boolean isSpecialSymbol(char symbol) {
return symbol == '(' || symbol == ')' || symbol == '+' || symbol == '*';
}
private static void computeFirst(List<Grammar> grammars) {
for (Grammar g : grammars) {
if (!firstSet.containsKey(g.nonTerminal)) {
firstSet.put(g.nonTerminal, new HashSet<>());
}
for (String production : g.productions) {
addFirst(g.nonTerminal, production, grammars);
}
}
}
private static void addFirst(String nonTerminal, String production, List<Grammar> grammars) {
if (production.isEmpty() || production.equals("@")) {
firstSet.get(nonTerminal).add("@");
return;
}
char firstSymbol = production.charAt(0);
if (Character.isLowerCase(firstSymbol) || isSpecialSymbol(firstSymbol)) {
firstSet.get(nonTerminal).add(Character.toString(firstSymbol));
terminals.add(Character.toString(firstSymbol));
} else {
for (Grammar g : grammars) {
if (g.nonTerminal.equals(Character.toString(firstSymbol))) {
for (String p : g.productions) {
if (p.equals("@") && !firstSet.get(nonTerminal).contains("@")) {
firstSet.get(nonTerminal).add("@");
} else {
addFirst(nonTerminal, p, grammars);
}
}
}
}
}
}
private static void computeFollow(List<Grammar> grammars, String startSymbol) {
for (Grammar g : grammars) {
followSet.put(g.nonTerminal, new HashSet<>());
}
followSet.get(startSymbol).add("$");
boolean changed;
do {
changed = false;
for (Grammar g : grammars) {
for (String production : g.productions) {
for (int i = 0; i < production.length(); i++) {
char symbol = production.charAt(i);
if (Character.isUpperCase(symbol)) {
Set<String> followOfSymbol = followSet.get(Character.toString(symbol));
if (i == production.length() - 1) {
followOfSymbol.addAll(followSet.get(g.nonTerminal));
} else {
String nextSymbol = Character.toString(production.charAt(i + 1));
if (Character.isLowerCase(nextSymbol.charAt(0)) || isSpecialSymbol(nextSymbol.charAt(0))) {
followOfSymbol.add(nextSymbol);
} else {
Set<String> firstOfNext = firstSet.get(nextSymbol);
if (firstOfNext.contains("@")) {
followOfSymbol.addAll(followSet.get(g.nonTerminal));
}
for (String f : firstOfNext) {
if (!f.equals("@")) {
followOfSymbol.add(f);
}
}
}
}
if (followOfSymbol.size() > followSet.get(Character.toString(symbol)).size()) {
followSet.get(Character.toString(symbol)).addAll(followOfSymbol);
changed = true;
}
}
}
}
}
} while (changed);
}
private static void buildPredictiveParsingTable(List<Grammar> grammars, String startSymbol) {
for (Grammar g : grammars) {
for (String production : g.productions) {
Set<String> first = new HashSet<>();
if (production.equals("@")) {
first.addAll(followSet.get(g.nonTerminal));
} else {
for (char c : production.toCharArray()) {
if (Character.isLowerCase(c) || isSpecialSymbol(c)) {
first.add(Character.toString(c));
break;
} else {
first.addAll(firstSet.get(Character.toString(c)));
if (!first.contains("@")) {
break;
}
first.remove("@");
}
}
if (first.isEmpty()) {
first.addAll(followSet.get(g.nonTerminal));
}
}
for (String a : first) {
if (!predictiveParsingTable.containsKey(g.nonTerminal)) {
predictiveParsingTable.put(g.nonTerminal, new HashMap<>());
}
predictiveParsingTable.get(g.nonTerminal).put(a, production);
}
}
}
}
private static boolean parse(String input, String startSymbol) {
Stack<String> stack = new Stack<>();
stack.push("$");
stack.push(startSymbol);
int i = 0;
System.out.println("步骤 | 分析栈 | 判定串 | 使用规则");
System.out.println("----+----------------+----------------+---------");
while (!stack.isEmpty()) {
String top = stack.peek();
if (top.equals("$") && i == input.length()) {
System.out.printf("%-4d| %-16s| %-16s| %s", step, "$" + stack, input.substring(i), "接受");
return true;
} else if (top.equals("$") || i == input.length()) {
System.out.printf("%-4d| %-16s| %-16s| %s", step, "$" + stack, input.substring(i), "错误");
return false;
}
if (Character.isLowerCase(top.charAt(0)) || isSpecialSymbol(top.charAt(0))) {
if (top.equals(Character.toString(input.charAt(i)))) {
stack.pop();
i++;
System.out.printf("%-4d| %-16s| %-16s| 匹配%s", step++, "$" + stack, input.substring(i), top);
} else {
System.out.printf("%-4d| %-16s| %-16s| 错误", step++, "$" + stack, input.substring(i));
return false;
}
} else {
String terminal = Character.toString(input.charAt(i));
if (predictiveParsingTable.get(top).containsKey(terminal)) {
String production = predictiveParsingTable.get(top).get(terminal);
System.out.printf("%-4d| %-16s| %-16s| %s -> %s", step++, "$" + stack, input.substring(i), top, production.replace("@", "ε"));
stack.pop();
if (!production.equals("@")) {
for (int j = production.length() - 1; j >= 0; j--) {
stack.push(Character.toString(production.charAt(j)));
}
}
} else {
System.out.printf("%-4d| %-16s| %-16s| 错误", step++, "$" + stack, input.substring(i));
return false;
}
}
}
return true;
}
private static void printPredictiveParsingTable() {
System.out.println("预测分析表:");
terminals.add("$");
System.out.print(" | ");
for (String terminal : terminals) {
System.out.printf("%-3s", terminal);
}
System.out.println();
System.out.print("---+");
for (int i = 0; i < terminals.size(); i++) {
System.out.print("---");
}
System.out.println();
for (String nonTerminal : predictiveParsingTable.keySet()) {
System.out.printf("%-3s| ", nonTerminal);
for (String terminal : terminals) {
if (predictiveParsingTable.get(nonTerminal).containsKey(terminal)) {
String production = predictiveParsingTable.get(nonTerminal).get(terminal);
if (!production.equals("@")) {
System.out.printf("%-3s", production);
} else {
System.out.print(" ε ");
}
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入文法规则(格式:E->TH|H->+TH|H->@|T->FJ|J->*FJ|J->@|F->(E)|F->a),输入'end'结束:");
List<Grammar> grammars = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.equalsIgnoreCase("end")) {
break;
}
String[] parts = line.split("->");
String nonTerminal = parts[0].trim();
String[] productions = parts[1].split("\\|");
for (int i = 0; i < productions.length; i++) {
productions[i] = productions[i].trim();
}
grammars.add(new Grammar(nonTerminal, Arrays.asList(productions)));
}
String startSymbol = "E";
computeFirst(grammars);
computeFollow(grammars, startSymbol);
buildPredictiveParsingTable(grammars, startSymbol);
printPredictiveParsingTable();
System.out.println("请输入待解析的字符串:");
String input = scanner.nextLine().trim();
if (parse(input, startSymbol)) {
System.out.println("字符串符合文法规则。");
} else {
System.out.println("字符串不符合文法规则。");
}
}
}
```
### 说明
1. **文法规则输入**:程序会提示用户输入文法规则,格式如 `E->TH|H->+TH|H->@|T->FJ|J->*FJ|J->@|F->(E)|F->a`,输入 `end` 结束。
2. **计算 FIRST 和 FOLLOW 集**:根据输入的文法规则,计算每个非终结符的 FIRST 和 FOLLOW 集。
3. **构建预测分析表**:根据 FIRST 和 FOLLOW 集构建预测分析表。
4. **打印预测分析表**:以表格形式输出预测分析表。
5. **解析字符串**:用户输入待解析的字符串,程序执行 LL(1) 分析并输出每一步的解析过程。
6. **判断字符串是否符合文法规则**:最后输出字符串是否符合文法规则。
希望这个程序能满足您的需求!如果有任何问题或需要进一步的帮助,请随时告诉我。
阅读全文