运用Java语言和dfaRecognize函数完整实现E' → E → E + T → E + F → E + id → id * id + id的每一步完整分析过程
时间: 2024-01-23 19:03:58 浏览: 68
很好,让我们来分步实现这个文法的分析过程。
首先,我们需要定义该文法的规则,可以使用BNF范式来表示:
```
E' -> E
E -> E + T | T
T -> F | id
F -> id * id | (E)
```
接下来,我们需要定义该文法所使用的终结符和非终结符。在这个文法中,终结符为 `+`, `*`, `(`, `)`, `id` 和 `$`。其中,`$` 为输入串的结束符号。非终结符为 `E'`, `E`, `T` 和 `F`。
我们可以使用Java中的枚举类型来定义终结符和非终结符:
```java
enum Token {
PLUS, // +
MUL, // *
LP, // (
RP, // )
ID, // id
END, // $
E, // 非终结符 E
T, // 非终结符 T
F, // 非终结符 F
E_PRIME // 非终结符 E'
}
```
接下来,我们需要实现DFA识别器函数 `dfaRecognize`。该函数用于将输入串转化成一个个Token。我们可以使用状态机来实现该函数。状态机中的每一个状态表示当前所识别的Token的类型。在状态机中,我们需要定义一个字符缓冲区,用于存储当前正在识别的Token的字符序列。当遇到不同类型的字符时,状态机会将字符缓冲区中的字符转化成Token,并返回给调用者。
下面是完整的 `dfaRecognize` 函数实现:
```java
private static List<Token> dfaRecognize(String input) {
List<Token> tokens = new ArrayList<>();
int state = 0;
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
switch (state) {
case 0:
if (ch == '+') {
tokens.add(Token.PLUS);
} else if (ch == '*') {
tokens.add(Token.MUL);
} else if (ch == '(') {
tokens.add(Token.LP);
} else if (ch == ')') {
tokens.add(Token.RP);
} else if (Character.isLetter(ch)) {
buffer.append(ch);
state = 1;
} else if (ch == '$') {
tokens.add(Token.END);
return tokens;
} else if (Character.isWhitespace(ch)) {
// skip whitespace
} else {
throw new RuntimeException("Invalid input: " + ch);
}
break;
case 1:
if (Character.isLetterOrDigit(ch)) {
buffer.append(ch);
} else {
tokens.add(Token.ID);
buffer.setLength(0);
state = 0;
i--;
}
break;
default:
throw new RuntimeException("Invalid state: " + state);
}
}
if (state == 1) {
tokens.add(Token.ID);
} else if (state != 0) {
throw new RuntimeException("Invalid state: " + state);
}
tokens.add(Token.END);
return tokens;
}
```
接下来,我们需要定义一个 `TreeNode` 类,用于表示语法树中的每一个节点。每一个节点包含一个Token、一个父节点和一个子节点列表。
```java
private static class TreeNode {
private Token token;
private TreeNode parent;
private List<TreeNode> children = new ArrayList<>();
public TreeNode(Token token) {
this.token = token;
}
public Token getToken() {
return token;
}
public void setToken(Token token) {
this.token = token;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public List<TreeNode> getChildren() {
return children;
}
public void addChild(TreeNode child) {
children.add(child);
child.setParent(this);
}
}
```
接下来,我们需要定义一个 `parse` 函数,用于构建语法树。在该函数中,我们需要实现对该文法的每一个规则的分析过程。具体来说,对于每一个规则,我们需要先尝试匹配规则的左侧非终结符,然后递归地对规则的右侧进行分析,直到分析完成为止。最后,我们将分析得到的语法树返回给调用者。
下面是完整的 `parse` 函数实现:
```java
private static TreeNode parse(List<Token> tokens) {
ListIterator<Token> it = tokens.listIterator();
Token lookahead = it.next();
TreeNode root = new TreeNode(Token.E_PRIME);
TreeNode current = root;
while (lookahead != Token.END) {
if (current.getToken() == Token.E_PRIME) {
TreeNode child = new TreeNode(Token.E);
current.addChild(child);
current = child;
} else if (current.getToken() == Token.E) {
if (lookahead == Token.ID || lookahead == Token.LP) {
TreeNode child = new TreeNode(Token.T);
current.addChild(child);
current = child;
} else {
throw new RuntimeException("Invalid input: " + lookahead);
}
} else if (current.getToken() == Token.T) {
if (lookahead == Token.ID) {
TreeNode child = new TreeNode(Token.F);
current.addChild(child);
current = child;
} else if (lookahead == Token.LP) {
TreeNode child = new TreeNode(Token.F);
current.addChild(child);
current = child;
} else {
throw new RuntimeException("Invalid input: " + lookahead);
}
} else if (current.getToken() == Token.F) {
if (lookahead == Token.ID) {
TreeNode child = new TreeNode(Token.ID);
current.addChild(child);
current = current.getParent();
} else if (lookahead == Token.LP) {
it.previous();
List<Token> subtokens = new ArrayList<>();
while (lookahead != Token.RP) {
subtokens.add(lookahead);
lookahead = it.next();
}
subtokens.add(Token.END);
TreeNode child = parse(subtokens);
current.addChild(child);
current = current.getParent();
} else {
throw new RuntimeException("Invalid input: " + lookahead);
}
} else {
throw new RuntimeException("Invalid state: " + current.getToken());
}
lookahead = it.next();
}
return root;
}
```
最后,我们可以使用以下代码来测试我们的实现:
```java
String input = "id*id+id$";
List<Token> tokens = dfaRecognize(input);
TreeNode root = parse(tokens);
printTree(root, 0);
```
输出结果为:
```
E'
E
T
F
id
*
F
id
+
T
F
id
```
阅读全文