用java实现语法分析器(要求有界面),并实现预测分析法,不能使用JavaFX,并完成以下要求:处理文法中可能存在的左递归和公共左因子问题;对文法中的每个非终结符自动生成并打印输出:① FIRST集;② FOLLOW集;判断处理后的文法是否为LL(1)文法,如果是, 自动生成并打印输出其预测分析表;5) 模拟分析过程。如输入一个句子,如果该句子合法则输出与句子 对应的语法树;能够输出分析过程中每一步符号 栈的变化情况。如果该句子非法则进行相应的报错处理直接给出代码
时间: 2024-03-13 09:45:55 浏览: 106
以下是一个简单的Java语法分析器的实现,实现了预测分析法,处理了文法中可能存在的左递归和公共左因子问题,并对文法中的每个非终结符自动生成并打印输出:FIRST集、FOLLOW集,并判断处理后的文法是否为LL(1)文法,如果是,自动生成并打印输出其预测分析表,并能够输出分析过程中每一步符号栈的变化情况。如果该句子非法则进行相应的报错处理。
请注意,这只是一个简单的示例代码,您需要进一步完善和优化它以适应您的具体需求。
```java
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class SyntaxAnalyzer extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JTextArea textArea;
private JButton openButton;
private JButton parseButton;
private JFileChooser fileChooser;
private Map<String, List<String>> grammar;
private Map<String, Set<String>> firstSets;
private Map<String, Set<String>> followSets;
private Map<String, Map<String, String>> predictionTable;
private List<String> nonterminals;
private List<String> terminals;
public SyntaxAnalyzer() {
super("Syntax Analyzer");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
JPanel buttonPanel = new JPanel();
openButton = new JButton("Open");
openButton.addActionListener(this);
buttonPanel.add(openButton);
parseButton = new JButton("Parse");
parseButton.addActionListener(this);
buttonPanel.add(parseButton);
add(buttonPanel, BorderLayout.NORTH);
textArea = new JTextArea();
JScrollPane jScrollPane = new JScrollPane(textArea);
add(jScrollPane, BorderLayout.CENTER);
fileChooser = new JFileChooser(".");
}
public static void main(String[] args) {
SyntaxAnalyzer analyzer = new SyntaxAnalyzer();
analyzer.setVisible(true);
}
private void readGrammar(String filename) throws Exception {
grammar = new HashMap<String, List<String>>();
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line = null;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(" -> ");
String lhs = parts[0].trim();
String[] rhss = parts[1].split("\\|");
List<String> rhsList = new ArrayList<String>();
for (String rhs : rhss) {
rhsList.add(rhs.trim());
}
grammar.put(lhs, rhsList);
}
reader.close();
}
private void eliminateLeftRecursion() {
nonterminals = new ArrayList<String>(grammar.keySet());
for (int i = 0; i < nonterminals.size(); i++) {
String A = nonterminals.get(i);
for (int j = 0; j < i; j++) {
String B = nonterminals.get(j);
List<String> AProductions = grammar.get(A);
List<String> BProductions = grammar.get(B);
List<String> newAProductions = new ArrayList<String>();
List<String> newBProductions = new ArrayList<String>();
for (String production : AProductions) {
if (production.startsWith(B)) {
for (String bProduction : BProductions) {
newAProductions.add(bProduction + production.substring(1));
}
} else {
newAProductions.add(production);
}
}
grammar.put(A, newAProductions);
}
List<String> AProductions = grammar.get(A);
boolean leftRecursive = false;
for (String production : AProductions) {
if (production.startsWith(A)) {
leftRecursive = true;
break;
}
}
if (leftRecursive) {
List<String> newAProductions = new ArrayList<String>();
List<String> newAProductions = new ArrayList<String>();
for (String production : AProductions) {
if (production.startsWith(A)) {
newAProductions.add(production.substring(1) + A + "'");
} else {
newAProductions.add(production + A + "'");
}
}
newAProductions.add("epsilon");
grammar.put(A, newAProductions);
grammar.put(A + "'", newAProductions);
}
}
}
private void eliminateCommonLeftFactor() {
nonterminals = new ArrayList<String>(grammar.keySet());
for (int i = 0; i < nonterminals.size(); i++) {
String A = nonterminals.get(i);
List<String> AProductions = grammar.get(A);
for (int j = 0; j < AProductions.size(); j++) {
String aProduction = AProductions.get(j);
for (int k = j + 1; k < AProductions.size(); k++) {
String bProduction = AProductions.get(k);
int l = 0;
while (l < aProduction.length() && l < bProduction.length()
&& aProduction.charAt(l) == bProduction.charAt(l)) {
l++;
}
if (l > 0) {
String C = A + "_" + l;
String newAProduction = aProduction.substring(0, l) + C;
String newBProduction = bProduction.substring(0, l) + C;
List<String> CProductions = new ArrayList<String>();
CProductions.add(aProduction.substring(l));
CProductions.add(bProduction.substring(l));
grammar.put(C, CProductions);
AProductions.set(j, newAProduction);
AProductions.set(k, newBProduction);
}
}
}
grammar.put(A, AProductions);
}
}
private void computeFirstSets() {
firstSets = new HashMap<String, Set<String>>();
nonterminals = new ArrayList<String>(grammar.keySet());
terminals = new ArrayList<String>();
for (List<String> productions : grammar.values()) {
for (String production : productions) {
for (int i = 0; i < production.length(); i++) {
char symbol = production.charAt(i);
if (symbol >= 'A' && symbol <= 'Z') {
break;
} else if (i == production.length() - 1) {
terminals.add("" + symbol);
}
}
}
}
for (String terminal : terminals) {
Set<String> firstSet = new HashSet<String>();
firstSet.add(terminal);
firstSets.put(terminal, firstSet);
}
for (String nonterminal : nonterminals) {
firstSets.put(nonterminal, new HashSet<String>());
}
boolean changed = true;
while (changed) {
changed = false;
for (String nonterminal : nonterminals) {
List<String> productions = grammar.get(nonterminal);
for (String production : productions) {
boolean allNullable = true;
for (int i = 0; i < production.length(); i++) {
char symbol = production.charAt(i);
if (symbol >= 'A' && symbol <= 'Z') {
Set<String> symbolFirstSet = firstSets.get("" + symbol);
if (!symbolFirstSet.contains("epsilon")) {
allNullable = false;
firstSets.get(nonterminal).addAll(symbolFirstSet);
break;
} else {
symbolFirstSet.remove("epsilon");
firstSets.get(nonterminal).addAll(symbolFirstSet);
}
} else {
firstSets.get(nonterminal).add("" + symbol);
allNullable = false;
break;
}
}
if (allNullable) {
firstSets.get(nonterminal).add("epsilon");
}
}
Set<String> oldFirstSet = new HashSet<String>(firstSets.get(nonterminal));
for (String first : oldFirstSet) {
if (first.equals("epsilon")) {
continue;
}
for (int i = 0; i < productions.size(); i++) {
String production = productions.get(i);
if (first.equals("" + production.charAt(0))) {
firstSets.get(nonterminal).addAll(firstSets.get("" + production.charAt(0)));
if (i == productions.size() - 1 && oldFirstSet.contains("epsilon")) {
firstSets.get(nonterminal).add("epsilon");
}
}
}
}
if (!oldFirstSet.equals(firstSets.get(nonterminal))) {
changed = true;
}
}
}
}
private void computeFollowSets() {
followSets = new HashMap<String, Set<String>>();
nonterminals = new ArrayList<String>(grammar.keySet());
terminals.add("$");
for (String nonterminal : nonterminals) {
followSets.put(nonterminal, new HashSet<String>());
}
followSets.get(nonterminals.get(0)).add("$");
boolean changed = true;
while (changed) {
changed = false;
for (String nonterminal : nonterminals) {
List<String> productions = grammar.get(nonterminal);
for (String production : productions) {
for (int i = 0; i < production.length(); i++) {
char symbol = production.charAt(i);
if (symbol >= 'A' && symbol <= 'Z') {
boolean allNullable = true;
for (int j = i + 1; j < production.length(); j++) {
char nextSymbol = production.charAt(j);
if (nextSymbol >= 'A' && nextSymbol <= 'Z') {
followSets.get("" + symbol).addAll(firstSets.get("" + nextSymbol));
if (!firstSets.get("" + nextSymbol).contains("epsilon")) {
allNullable = false;
break;
}
} else {
followSets.get("" + symbol).add("" + nextSymbol);
allNullable = false;
break;
}
}
if (allNullable) {
followSets.get("" + symbol).addAll(followSets.get(nonterminal));
}
}
}
}
}
for (String nonterminal : nonterminals) {
Set<String> oldFollowSet = new HashSet<String>(followSets.get(nonterminal));
for (String production : grammar.get(nonterminal)) {
for (int i = production.length() - 1; i >= 0; i--) {
char symbol = production.charAt(i);
if (symbol >= 'A' && symbol <= 'Z') {
if (i == production.length() - 1) {
followSets.get("" + symbol).addAll(followSets.get(nonterminal));
}
boolean allNullable = true;
for (int j = i + 1; j < production.length(); j++) {
char nextSymbol = production.charAt(j);
if (nextSymbol >= 'A' && nextSymbol <= 'Z') {
followSets.get("" + symbol).addAll(firstSets.get("" + nextSymbol));
if (!firstSets.get("" + nextSymbol).contains("epsilon")) {
allNullable = false;
break;
}
} else {
followSets.get("" + symbol).add("" + nextSymbol);
allNullable = false;
break;
}
}
if (allNullable) {
followSets.get("" + symbol).addAll(followSets.get(nonterminal));
}
}
}
}
if (!oldFollowSet.equals(followSets.get(nonterminal))) {
changed = true;
}
}
}
}
private void buildPredictionTable() {
predictionTable = new HashMap<String, Map<String, String>>();
nonterminals = new ArrayList<String>(grammar.keySet());
terminals = new ArrayList<String>();
for (List<String> productions : grammar.values()) {
for (String production : productions) {
for (int i = 0; i < production.length(); i++) {
char symbol = production.charAt(i);
if (symbol >= 'A' && symbol <= 'Z') {
break;
} else if (i == production.length() - 1) {
terminals.add("" + symbol);
}
}
}
}
terminals.add("$");
for (String nonterminal : nonterminals) {
Map<String, String> row = new HashMap<String, String>();
for (String terminal : terminals) {
row.put(terminal, "");
}
predictionTable.put(nonterminal, row);
}
for (String nonterminal : nonterminals) {
List<String> productions = grammar.get(nonterminal);
for (String production : productions) {
Set<String> firstSet = computeFirstSet(production);
for (String terminal : firstSet) {
if (!terminal.equals("epsilon")) {
predictionTable.get(nonterminal).put(
阅读全文