使用Java语言编写PL/0编译程序的语法分析程序
时间: 2023-11-25 18:07:20 浏览: 78
精选_毕业设计_基于Java实现的PL/0文法分析器-词法分析、语法分析、语义分析_完整源码
以下是使用Java语言编写的PL/0编译程序的语法分析程序:
```java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Parser {
private Lexer lexer;
private Token currentToken;
private Stack<Integer> jumpStack;
private int codePointer;
private List<Instruction> instructions;
public Parser(Lexer lexer) {
this.lexer = lexer;
this.currentToken = lexer.getNextToken();
this.jumpStack = new Stack<>();
this.codePointer = 0;
this.instructions = new ArrayList<>();
}
public List<Instruction> parse() {
program();
return instructions;
}
private void program() {
block();
match(TokenType.PERIOD);
}
private void block() {
if (currentToken.getType() == TokenType.CONST) {
constDeclaration();
}
if (currentToken.getType() == TokenType.VAR) {
varDeclaration();
}
while (currentToken.getType() == TokenType.PROCEDURE) {
procedureDeclaration();
}
statement();
}
private void constDeclaration() {
match(TokenType.CONST);
do {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
match(TokenType.EQUAL);
int value = Integer.parseInt(currentToken.getValue());
match(TokenType.NUMBER);
instructions.add(new Instruction(Operation.LIT, value));
instructions.add(new Instruction(Operation.STO, SymbolTable.addSymbol(name)));
} while (currentToken.getType() == TokenType.COMMA);
match(TokenType.SEMICOLON);
}
private void varDeclaration() {
match(TokenType.VAR);
do {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
instructions.add(new Instruction(Operation.INT, SymbolTable.addSymbol(name)));
} while (currentToken.getType() == TokenType.COMMA);
match(TokenType.SEMICOLON);
}
private void procedureDeclaration() {
match(TokenType.PROCEDURE);
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
match(TokenType.SEMICOLON);
int procedurePointer = codePointer;
instructions.add(null);
block();
instructions.add(new Instruction(Operation.RET, 0));
instructions.set(procedurePointer, new Instruction(Operation.JMP, codePointer));
SymbolTable.addSymbol(name, procedurePointer);
match(TokenType.SEMICOLON);
}
private void statement() {
if (currentToken.getType() == TokenType.IDENTIFIER) {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
if (currentToken.getType() == TokenType.ASSIGN) {
match(TokenType.ASSIGN);
expression();
instructions.add(new Instruction(Operation.STO, SymbolTable.getSymbol(name)));
} else {
callStatement(name);
}
} else if (currentToken.getType() == TokenType.BEGIN) {
match(TokenType.BEGIN);
statement();
while (currentToken.getType() == TokenType.SEMICOLON) {
match(TokenType.SEMICOLON);
statement();
}
match(TokenType.END);
} else if (currentToken.getType() == TokenType.IF) {
match(TokenType.IF);
condition();
match(TokenType.THEN);
int falseJumpPointer = instructions.size();
instructions.add(null);
statement();
if (currentToken.getType() == TokenType.ELSE) {
match(TokenType.ELSE);
int endJumpPointer = instructions.size();
instructions.add(null);
instructions.set(falseJumpPointer, new Instruction(Operation.JPF, codePointer));
statement();
instructions.set(endJumpPointer, new Instruction(Operation.JMP, codePointer));
} else {
instructions.set(falseJumpPointer, new Instruction(Operation.JPF, codePointer));
}
} else if (currentToken.getType() == TokenType.WHILE) {
match(TokenType.WHILE);
int loopStartPointer = codePointer;
condition();
match(TokenType.DO);
int falseJumpPointer = instructions.size();
instructions.add(null);
statement();
instructions.add(new Instruction(Operation.JMP, loopStartPointer));
instructions.set(falseJumpPointer, new Instruction(Operation.JPF, codePointer));
} else if (currentToken.getType() == TokenType.CALL) {
match(TokenType.CALL);
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
callStatement(name);
} else if (currentToken.getType() == TokenType.READ) {
match(TokenType.READ);
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
instructions.add(new Instruction(Operation.RED, SymbolTable.getSymbol(name)));
} else if (currentToken.getType() == TokenType.WRITE) {
match(TokenType.WRITE);
expression();
instructions.add(new Instruction(Operation.WRT, 0));
}
}
private void expression() {
TokenType operator = currentToken.getType();
if (operator == TokenType.PLUS || operator == TokenType.MINUS) {
match(operator);
}
term();
while (currentToken.getType() == TokenType.PLUS || currentToken.getType() == TokenType.MINUS) {
operator = currentToken.getType();
match(operator);
term();
if (operator == TokenType.PLUS) {
instructions.add(new Instruction(Operation.ADD, 0));
} else {
instructions.add(new Instruction(Operation.SUB, 0));
}
}
}
private void term() {
factor();
while (currentToken.getType() == TokenType.TIMES || currentToken.getType() == TokenType.DIVIDE) {
TokenType operator = currentToken.getType();
match(operator);
factor();
if (operator == TokenType.TIMES) {
instructions.add(new Instruction(Operation.MUL, 0));
} else {
instructions.add(new Instruction(Operation.DIV, 0));
}
}
}
private void factor() {
if (currentToken.getType() == TokenType.NUMBER) {
int value = Integer.parseInt(currentToken.getValue());
match(TokenType.NUMBER);
instructions.add(new Instruction(Operation.LIT, value));
} else if (currentToken.getType() == TokenType.IDENTIFIER) {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
instructions.add(new Instruction(Operation.LOD, SymbolTable.getSymbol(name)));
} else if (currentToken.getType() == TokenType.LPAREN) {
match(TokenType.LPAREN);
expression();
match(TokenType.RPAREN);
} else {
throw new RuntimeException("Invalid factor: " + currentToken.getValue());
}
}
private void condition() {
if (currentToken.getType() == TokenType.ODD) {
match(TokenType.ODD);
expression();
instructions.add(new Instruction(Operation.ODD, 0));
} else {
expression();
TokenType operator = currentToken.getType();
relationalOperator();
expression();
if (operator == TokenType.EQUAL) {
instructions.add(new Instruction(Operation.EQL, 0));
} else if (operator == TokenType.NOT_EQUAL) {
instructions.add(new Instruction(Operation.NEQ, 0));
} else if (operator == TokenType.LESS_THAN) {
instructions.add(new Instruction(Operation.LES, 0));
} else if (operator == TokenType.LESS_THAN_OR_EQUAL) {
instructions.add(new Instruction(Operation.LEQ, 0));
} else if (operator == TokenType.GREATER_THAN) {
instructions.add(new Instruction(Operation.GTR, 0));
} else if (operator == TokenType.GREATER_THAN_OR_EQUAL) {
instructions.add(new Instruction(Operation.GEQ, 0));
}
}
}
private void relationalOperator() {
TokenType operator = currentToken.getType();
if (operator == TokenType.EQUAL || operator == TokenType.NOT_EQUAL ||
operator == TokenType.LESS_THAN || operator == TokenType.LESS_THAN_OR_EQUAL ||
operator == TokenType.GREATER_THAN || operator == TokenType.GREATER_THAN_OR_EQUAL) {
match(operator);
} else {
throw new RuntimeException("Invalid relational operator: " + currentToken.getValue());
}
}
private void callStatement(String name) {
instructions.add(new Instruction(Operation.CAL, SymbolTable.getSymbol(name)));
}
private void match(TokenType expectedType) {
if (currentToken.getType() == expectedType) {
currentToken = lexer.getNextToken();
} else {
throw new RuntimeException("Invalid token: " + currentToken.getValue() +
". Expected " + expectedType.toString());
}
}
}
```
此程序使用递归下降方法进行语法分析,并将生成的指令保存在一个列表中。其中包括各种声明(常量、变量和过程)、语句(赋值、条件、循环、调用、读入和输出)和表达式(加减乘除和关系运算)。在处理过程中,还要维护符号表和跳转指令的位置。
阅读全文