运用Java代码和dfaRecognize函数实现E' → E → E + T → E + F → E + id → id * id + id的完整分析过程
时间: 2024-01-24 14:03:49 浏览: 66
首先,我们需要定义文法的产生式规则:
```
E' -> E
E -> E + T | T
T -> T * F | F
F -> ( E ) | id
```
其中,`E'` 是起始符号,`id` 表示标识符,`+` 和 `*` 分别表示加法和乘法操作符。
接下来,我们需要实现一个词法分析器,将输入的字符串分解成一个个单独的词素。在这个文法中,我们只需要考虑两种词素:标识符和操作符(+ 和 *)。
```java
public class Lexer {
private String input;
private int position;
public Lexer(String input) {
this.input = input;
this.position = 0;
}
public Token getNextToken() {
if (position >= input.length()) {
return new Token(TokenType.EOF, null);
}
char currentChar = input.charAt(position);
if (Character.isDigit(currentChar)) {
return new Token(TokenType.INTEGER, getInteger());
} else if (Character.isLetter(currentChar)) {
return new Token(TokenType.ID, getIdentifier());
} else if (currentChar == '+') {
position++;
return new Token(TokenType.PLUS, "+");
} else if (currentChar == '*') {
position++;
return new Token(TokenType.MULTIPLY, "*");
} else if (currentChar == '(') {
position++;
return new Token(TokenType.LPAREN, "(");
} else if (currentChar == ')') {
position++;
return new Token(TokenType.RPAREN, ")");
} else {
throw new RuntimeException("Invalid character: " + currentChar);
}
}
private String getIdentifier() {
StringBuilder sb = new StringBuilder();
char currentChar = input.charAt(position);
while (Character.isLetterOrDigit(currentChar)) {
sb.append(currentChar);
position++;
if (position >= input.length()) {
break;
}
currentChar = input.charAt(position);
}
return sb.toString();
}
private int getInteger() {
StringBuilder sb = new StringBuilder();
char currentChar = input.charAt(position);
while (Character.isDigit(currentChar)) {
sb.append(currentChar);
position++;
if (position >= input.length()) {
break;
}
currentChar = input.charAt(position);
}
return Integer.parseInt(sb.toString());
}
}
```
接下来,我们需要实现语法分析器。首先,定义一个 `Node` 类,用于表示语法树上的节点。
```java
public abstract class Node {
public abstract String toString();
}
```
然后,定义四个具体的节点类型:`BinOpNode` 表示二元操作符节点,`UnaryOpNode` 表示一元操作符节点,`NumNode` 表示数字节点,`VarNode` 表示变量节点。
```java
public class BinOpNode extends Node {
private Node left;
private Token operator;
private Node right;
public BinOpNode(Node left, Token operator, Node right) {
this.left = left;
this.operator = operator;
this.right = right;
}
public Node getLeft() {
return left;
}
public Token getOperator() {
return operator;
}
public Node getRight() {
return right;
}
@Override
public String toString() {
return "(" + left.toString() + " " + operator.getValue() + " " + right.toString() + ")";
}
}
public class UnaryOpNode extends Node {
private Token operator;
private Node expr;
public UnaryOpNode(Token operator, Node expr) {
this.operator = operator;
this.expr = expr;
}
public Token getOperator() {
return operator;
}
public Node getExpr() {
return expr;
}
@Override
public String toString() {
return operator.getValue() + expr.toString();
}
}
public class NumNode extends Node {
private Token token;
public NumNode(Token token) {
this.token = token;
}
public int getValue() {
return (int) token.getValue();
}
@Override
public String toString() {
return token.getValue().toString();
}
}
public class VarNode extends Node {
private Token token;
public VarNode(Token token) {
this.token = token;
}
public String getName() {
return (String) token.getValue();
}
@Override
public String toString() {
return token.getValue().toString();
}
}
```
接下来,我们需要实现语法分析器的核心函数 `parse`。该函数接受一个 `Lexer` 对象作为参数,返回一棵语法树。
```java
public class Parser {
private Lexer lexer;
private Token currentToken;
public Parser(Lexer lexer) {
this.lexer = lexer;
this.currentToken = lexer.getNextToken();
}
private void eat(TokenType type) {
if (currentToken.getType() == type) {
currentToken = lexer.getNextToken();
} else {
throw new RuntimeException("Invalid syntax");
}
}
private Node factor() {
Token token = currentToken;
if (token.getType() == TokenType.INTEGER) {
eat(TokenType.INTEGER);
return new NumNode(token);
} else if (token.getType() == TokenType.ID) {
eat(TokenType.ID);
return new VarNode(token);
} else if (token.getType() == TokenType.LPAREN) {
eat(TokenType.LPAREN);
Node node = expr();
eat(TokenType.RPAREN);
return node;
} else {
throw new RuntimeException("Invalid syntax");
}
}
private Node term() {
Node node = factor();
while (currentToken.getType() == TokenType.MULTIPLY) {
Token token = currentToken;
eat(TokenType.MULTIPLY);
node = new BinOpNode(node, token, factor());
}
return node;
}
private Node expr() {
Node node = term();
while (currentToken.getType() == TokenType.PLUS) {
Token token = currentToken;
eat(TokenType.PLUS);
node = new BinOpNode(node, token, term());
}
return node;
}
public Node parse() {
return expr();
}
}
```
最后,我们可以通过以下代码进行完整分析过程的演示:
```java
public class Main {
public static void main(String[] args) {
String input = "id * id + id";
Lexer lexer = new Lexer(input);
Parser parser = new Parser(lexer);
Node node = parser.parse();
System.out.println(node.toString());
}
}
```
输出结果为:
```
((id * id) + id)
```
这说明我们成功地将输入的字符串转换成了一棵语法树,其中乘法优先级高于加法。
阅读全文