用java语言实现语法分析器,要求有界面,并实现预测分析法
时间: 2024-03-17 13:41:17 浏览: 81
好的,我可以给你提供一个Java语言实现的语法分析器,实现预测分析法,并且有简单的界面。这个示例程序使用了JavaFX框架来构建GUI界面。
为了简化实现,我将使用一个简单的算术表达式文法作为例子,文法如下:
```
E -> E + T | E - T | T
T -> T * F | T / F | F
F -> ( E ) | NUM
```
其中,E、T和F都是非终结符,+、-、*、/、(、)和NUM是终结符。这个文法表示了基本的四则运算表达式。
下面是Java代码的实现。在这个示例程序中,我将使用递归下降算法来实现预测分析法,将预测分析表作为一个二维数组来表示。
```java
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class SyntaxAnalyzer extends Application {
private static final String[][] PREDICT_TABLE = {
{"E+T", "", "", "E+T", "E+T", "", ""},
{"", "E-T", "", "", "", "", "EPSILON"},
{"T", "", "", "T", "T", "", ""},
{"", "", "T*F", "", "", "T/F", "EPSILON"},
{"F", "", "", "(E)", "", "", "NUM"}
};
private TextField inputField;
private Label resultLabel;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Syntax Analyzer");
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(5);
grid.setHgap(5);
Label inputLabel = new Label("Input:");
GridPane.setConstraints(inputLabel, 0, 0);
grid.getChildren().add(inputLabel);
inputField = new TextField();
GridPane.setConstraints(inputField, 1, 0);
grid.getChildren().add(inputField);
Button analyzeButton = new Button("Analyze");
GridPane.setConstraints(analyzeButton, 2, 0);
grid.getChildren().add(analyzeButton);
Label resultTitleLabel = new Label("Result:");
GridPane.setConstraints(resultTitleLabel, 0, 1);
grid.getChildren().add(resultTitleLabel);
resultLabel = new Label();
GridPane.setConstraints(resultLabel, 1, 1);
grid.getChildren().add(resultLabel);
analyzeButton.setOnAction(event -> analyze());
Scene scene = new Scene(grid, 400, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
private void analyze() {
String input = inputField.getText();
if (input == null || input.isEmpty()) {
resultLabel.setText("Please input an expression.");
return;
}
int index = 0;
char lookahead = input.charAt(index);
try {
E(lookahead, index);
resultLabel.setText("The expression is valid.");
} catch (SyntaxException e) {
resultLabel.setText("Syntax error: " + e.getMessage());
}
}
private void E(char lookahead, int index) throws SyntaxException {
T(lookahead, index);
String action = PREDICT_TABLE[0][getTokenIndex(lookahead)];
switch (action) {
case "E+T":
match('+', lookahead, index);
T(nextChar(), index + 1);
E(lookahead, index);
break;
case "E-T":
match('-', lookahead, index);
T(nextChar(), index + 1);
E(lookahead, index);
break;
case "":
break;
default:
throw new SyntaxException("Invalid input: " + lookahead);
}
}
private void T(char lookahead, int index) throws SyntaxException {
F(lookahead, index);
String action = PREDICT_TABLE[2][getTokenIndex(lookahead)];
switch (action) {
case "T*F":
match('*', lookahead, index);
F(nextChar(), index + 1);
T(lookahead, index);
break;
case "T/F":
match('/', lookahead, index);
F(nextChar(), index + 1);
T(lookahead, index);
break;
case "":
break;
default:
throw new SyntaxException("Invalid input: " + lookahead);
}
}
private void F(char lookahead, int index) throws SyntaxException {
String action = PREDICT_TABLE[4][getTokenIndex(lookahead)];
switch (action) {
case "(E)":
match('(', lookahead, index);
E(nextChar(), index + 1);
match(')', nextChar(), index + 2);
break;
case "NUM":
matchDigit(lookahead, index);
break;
default:
throw new SyntaxException("Invalid input: " + lookahead);
}
}
private void match(char expected, char actual, int index) throws SyntaxException {
if (actual == expected) {
if (index < inputField.getText().length() - 1) {
nextChar();
}
} else {
throw new SyntaxException("Expected " + expected + " but found " + actual);
}
}
private void matchDigit(char lookahead, int index) throws SyntaxException {
if (!Character.isDigit(lookahead)) {
throw new SyntaxException("Expected a digit but found " + lookahead);
}
while (index < inputField.getText().length() - 1) {
lookahead = nextChar();
if (!Character.isDigit(lookahead)) {
break;
}
}
}
private char nextChar() {
int index = inputField.getCaretPosition();
inputField.positionCaret(index + 1);
return inputField.getText().charAt(index + 1);
}
private int getTokenIndex(char token) {
switch (token) {
case '+':
return 0;
case '-':
return 1;
case '*':
return 2;
case '/':
return 3;
case '(':
return 4;
case ')':
return 5;
case ' ':
return 6;
default:
return 7;
}
}
private static class SyntaxException extends Exception {
public SyntaxException(String message) {
super(message);
}
}
}
```
这个程序的界面包含一个文本框和一个按钮,用户在文本框中输入一个算术表达式,然后单击按钮进行语法分析。如果表达式符合文法,程序会显示“表达式有效”的消息,否则会显示语法错误的消息。
在程序实现中,我将文法的预测分析表表示为一个二维数组,其中每个元素是一个字符串,表示要采取的产生式。我使用递归下降算法来实现预测分析法,每个非终结符对应一个方法,根据预测分析表中的产生式来推导输入符号串。
在方法中,我使用了一个 `match()` 方法来检查当前输入符号是否和预期符号匹配。如果匹配成功,我会将输入指针向前移动一个位置;否则,我会抛出一个 `SyntaxException` 异常。
此外,我还实现了一个 `getTokenIndex()` 方法,用于将终结符映射为预测分析表的索引。这个方法可以根据需要进行更改,以处理不同的文法。
运行这个程序时,你需要确保你已经安装了JavaFX库,并将它添加到了你的项目依赖中。在IntelliJ IDEA中,你可以通过添加以下行来添加JavaFX依赖项:
```xml
<dependencies>
...
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>16</version>
</dependency>
</dependencies>
```
这个示例程序只是一个简单的实现,如果你要处理更复杂的文法,你可能需要采用其他的语法分析算法,如LR分析或LL分析。
阅读全文