用java语言实现语法分析器,要求有界面,并实现预测分析法,不能使用JavaFX
时间: 2024-03-17 13:42:17 浏览: 78
好的,我可以提供一个使用Swing实现预测分析法的语法分析器的示例代码。这个语法分析器可以分析一个简单的四则运算表达式,并将其转化为抽象语法树。这个语法分析器的界面使用Swing实现,可以让用户输入一个四则运算表达式,然后单击“分析”按钮进行语法分析,最后将分析结果显示在界面上。
下面是这个语法分析器的示例代码:
```java
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class SyntaxAnalyzer extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JTextField inputField;
private JTextArea outputArea;
private JButton analyzeButton;
public SyntaxAnalyzer() {
super("Syntax Analyzer");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 400);
inputField = new JTextField();
outputArea = new JTextArea();
analyzeButton = new JButton("Analyze");
analyzeButton.addActionListener(this);
JPanel inputPanel = new JPanel();
inputPanel.add(inputField);
inputPanel.add(analyzeButton);
JScrollPane outputScrollPane = new JScrollPane(outputArea);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(inputPanel, BorderLayout.NORTH);
getContentPane().add(outputScrollPane, BorderLayout.CENTER);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == analyzeButton) {
String input = inputField.getText();
List<Token> tokens = getTokens(input);
Node root = analyze(tokens);
outputArea.setText(root.toString());
}
}
private List<Token> getTokens(String input) {
List<Token> tokens = new ArrayList<Token>();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isDigit(c)) {
int j = i + 1;
while (j < input.length() && Character.isDigit(input.charAt(j))) {
j++;
}
tokens.add(new Token(Type.NUMBER, input.substring(i, j)));
i = j - 1;
} else if (c == '+') {
tokens.add(new Token(Type.PLUS, "+"));
} else if (c == '-') {
tokens.add(new Token(Type.MINUS, "-"));
} else if (c == '*') {
tokens.add(new Token(Type.TIMES, "*"));
} else if (c == '/') {
tokens.add(new Token(Type.DIVIDE, "/"));
} else if (c == '(') {
tokens.add(new Token(Type.LEFT_PAREN, "("));
} else if (c == ')') {
tokens.add(new Token(Type.RIGHT_PAREN, ")"));
}
}
return tokens;
}
private Node analyze(List<Token> tokens) {
Stack<Node> nodeStack = new Stack<Node>();
Stack<Token> tokenStack = new Stack<Token>();
tokenStack.push(new Token(Type.END, "$"));
tokenStack.push(new Token(Type.START, "E"));
int i = 0;
while (i < tokens.size()) {
Token token = tokens.get(i);
Token topToken = tokenStack.peek();
if (topToken.getType() == Type.END) {
break;
} else if (topToken.getType() == Type.TERMINAL) {
if (topToken.getValue().equals(token.getValue())) {
i++;
tokenStack.pop();
} else {
throw new RuntimeException("Syntax error: " + token);
}
} else {
Production production = getProduction(topToken.getValue(), token.getValue());
if (production == null) {
throw new RuntimeException("Syntax error: " + token);
}
tokenStack.pop();
if (!production.getRhs().get(0).getValue().equals("$")) {
for (int j = production.getRhs().size() - 1; j >= 0; j--) {
tokenStack.push(production.getRhs().get(j));
}
}
List<Node> nodes = new ArrayList<Node>();
for (int j = 0; j < production.getRhs().size(); j++) {
nodes.add(nodeStack.pop());
}
Node node = new Node(production.getLhs(), nodes);
nodeStack.push(node);
}
}
return nodeStack.pop();
}
private Production getProduction(String nonTerminal, String terminal) {
if (nonTerminal.equals("E")) {
if (terminal.equals("(") || Character.isDigit(terminal.charAt(0))) {
return new Production("E", "T", "E'");
}
} else if (nonTerminal.equals("E'")) {
if (terminal.equals("+")) {
return new Production("E'", "+", "T", "E'");
} else if (terminal.equals("-")) {
return new Production("E'", "-", "T", "E'");
} else if (terminal.equals(")") || terminal.equals("$")) {
return new Production("E'", "$");
}
} else if (nonTerminal.equals("T")) {
if (terminal.equals("(") || Character.isDigit(terminal.charAt(0))) {
return new Production("T", "F", "T'");
}
} else if (nonTerminal.equals("T'")) {
if (terminal.equals("*")) {
return new Production("T'", "*", "F", "T'");
} else if (terminal.equals("/")) {
return new Production("T'", "/", "F", "T'");
} else if (terminal.equals("+") || terminal.equals("-") || terminal.equals(")") || terminal.equals("$")) {
return new Production("T'", "$");
}
} else if (nonTerminal.equals("F")) {
if (Character.isDigit(terminal.charAt(0))) {
return new Production("F", "NUMBER");
} else if (terminal.equals("(")) {
return new Production("F", "(", "E", ")");
}
}
return null;
}
public static void main(String[] args) {
SyntaxAnalyzer analyzer = new SyntaxAnalyzer();
analyzer.setVisible(true);
}
}
class Token {
private Type type;
private String value;
public Token(Type type, String value) {
this.type = type;
this.value = value;
}
public Type getType() {
return type;
}
public String getValue() {
return value;
}
public String toString() {
return "(" + type + ", " + value + ")";
}
}
enum Type {
START, END, NON_TERMINAL, TERMINAL, NUMBER, PLUS, MINUS, TIMES, DIVIDE, LEFT_PAREN, RIGHT_PAREN
}
class Production {
private String lhs;
private List<Token> rhs;
public Production(String lhs, String... rhs) {
this.lhs = lhs;
this.rhs = new ArrayList<Token>();
for (String symbol : rhs) {
if (Character.isUpperCase(symbol.charAt(0))) {
this.rhs.add(new Token(Type.NON_TERMINAL, symbol));
} else if (Character.isLowerCase(symbol.charAt(0))) {
this.rhs.add(new Token(Type.TERMINAL, symbol));
} else if (Character.isDigit(symbol.charAt(0))) {
this.rhs.add(new Token(Type.NUMBER, symbol));
} else if (symbol.equals("+")) {
this.rhs.add(new Token(Type.PLUS, symbol));
} else if (symbol.equals("-")) {
this.rhs.add(new Token(Type.MINUS, symbol));
} else if (symbol.equals("*")) {
this.rhs.add(new Token(Type.TIMES, symbol));
} else if (symbol.equals("/")) {
this.rhs.add(new Token(Type.DIVIDE, symbol));
} else if (symbol.equals("(")) {
this.rhs.add(new Token(Type.LEFT_PAREN, symbol));
} else if (symbol.equals(")")) {
this.rhs.add(new Token(Type.RIGHT_PAREN, symbol));
}
}
}
public String getLhs() {
return lhs;
}
public List<Token> getRhs() {
return rhs;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(lhs).append(" -> ");
for (Token token : rhs) {
sb.append(token.getValue()).append(" ");
}
return sb.toString();
}
}
class Node {
private String value;
private List<Node> children;
public Node(String value, List<Node> children) {
this.value = value;
this.children = children;
}
public Node(String value) {
this.value = value;
this.children = new ArrayList<Node>();
}
public String getValue() {
return value;
}
public List<Node> getChildren() {
return children;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(value);
if (!children.isEmpty()) {
sb.append("(");
for (int i = 0; i < children.size(); i++) {
sb.append(children.get(i));
if (i < children.size() - 1) {
sb.append(", ");
}
}
sb.append(")");
}
return sb.toString();
}
}
```
在这个示例代码中,Token表示一个词法单元,它包含一个类型和一个值。Type表示Token的类型,可以是非终结符、终结符、数字、加号、减号、乘号、除号、左括号、右括号、开始符号和结束符号。Production表示一个产生式,它包含一个左部非终结符和一个右部符号串。Node表示一个语法树节点,它包含一个值和一个子节点列表。
在语法分析器的界面中,用户可以输入一个四则运算表达式,然后单击“分析”按钮进行语法分析。程序会将输入的表达式分解为词法单元,然后使用预测分析法进行语法分析,并将分析结果显示在界面上。
需要注意的是,这个示例代码只是一个简单的语法分析器,并没有考虑到很多实际问题,例如错误处理、优先级、结合性等。如果需要实现一个更完善的语法分析器,需要进一步修改和扩展这个示例代码。
阅读全文