使用java语言编写PL/0编译程序的语法分析程序。
时间: 2023-11-25 19:08:16 浏览: 84
java编写的PL/0词法分析器
3星 · 编辑精心推荐
以下是使用Java语言编写PL/0编译程序的语法分析程序的示例代码:
```java
import java.util.ArrayList;
import java.util.List;
public class Parser {
private Lexer lexer;
private Token currentToken;
public Parser(Lexer lexer) {
this.lexer = lexer;
this.currentToken = lexer.getNextToken();
}
public void parse() {
program();
}
private void program() {
block();
if (currentToken.getType() != TokenType.PERIOD) {
throw new RuntimeException("Syntax error: period expected but " + currentToken.getValue() + " found");
}
}
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);
SymbolTable.getInstance().addConstant(name, value);
} while (currentToken.getType() == TokenType.COMMA);
match(TokenType.SEMICOLON);
}
private void varDeclaration() {
match(TokenType.VAR);
do {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
SymbolTable.getInstance().addVariable(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);
BlockNode blockNode = new BlockNode();
blockNode.setParentNode(SymbolTable.getInstance().getCurrentScope());
SymbolTable.getInstance().enterScope(blockNode);
procedureParams();
match(TokenType.SEMICOLON);
block();
match(TokenType.SEMICOLON);
SymbolTable.getInstance().exitScope();
SymbolTable.getInstance().addProcedure(name, blockNode);
}
private void procedureParams() {
if (currentToken.getType() != TokenType.LEFT_PARENTHESIS) {
return;
}
match(TokenType.LEFT_PARENTHESIS);
List<String> params = new ArrayList<>();
if (currentToken.getType() == TokenType.IDENTIFIER) {
params.add(currentToken.getValue());
match(TokenType.IDENTIFIER);
while (currentToken.getType() == TokenType.COMMA) {
match(TokenType.COMMA);
params.add(currentToken.getValue());
match(TokenType.IDENTIFIER);
}
}
SymbolTable.getInstance().addProcedureParams(params);
match(TokenType.RIGHT_PARENTHESIS);
}
private void statement() {
if (currentToken.getType() == TokenType.IDENTIFIER) {
assignmentStatement();
} else if (currentToken.getType() == TokenType.CALL) {
callStatement();
} else if (currentToken.getType() == TokenType.BEGIN) {
compoundStatement();
} else if (currentToken.getType() == TokenType.IF) {
ifStatement();
} else if (currentToken.getType() == TokenType.WHILE) {
whileStatement();
}
}
private void assignmentStatement() {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
if (currentToken.getType() == TokenType.LEFT_BRACKET) {
match(TokenType.LEFT_BRACKET);
expression();
match(TokenType.RIGHT_BRACKET);
SymbolTable.getInstance().setArrayAssignment(true);
}
match(TokenType.ASSIGN);
expression();
SymbolTable.getInstance().addAssignment(name);
}
private void callStatement() {
match(TokenType.CALL);
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
List<String> params = new ArrayList<>();
if (currentToken.getType() == TokenType.LEFT_PARENTHESIS) {
match(TokenType.LEFT_PARENTHESIS);
if (currentToken.getType() == TokenType.IDENTIFIER) {
params.add(currentToken.getValue());
match(TokenType.IDENTIFIER);
while (currentToken.getType() == TokenType.COMMA) {
match(TokenType.COMMA);
params.add(currentToken.getValue());
match(TokenType.IDENTIFIER);
}
}
SymbolTable.getInstance().checkProcedureParams(name, params);
match(TokenType.RIGHT_PARENTHESIS);
}
SymbolTable.getInstance().addCall(name);
}
private void compoundStatement() {
match(TokenType.BEGIN);
statement();
while (currentToken.getType() == TokenType.SEMICOLON) {
match(TokenType.SEMICOLON);
statement();
}
match(TokenType.END);
}
private void ifStatement() {
match(TokenType.IF);
condition();
match(TokenType.THEN);
statement();
if (currentToken.getType() == TokenType.ELSE) {
match(TokenType.ELSE);
statement();
}
}
private void whileStatement() {
match(TokenType.WHILE);
condition();
match(TokenType.DO);
statement();
}
private void condition() {
if (currentToken.getType() == TokenType.ODD) {
match(TokenType.ODD);
expression();
} else {
expression();
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);
expression();
} else {
throw new RuntimeException("Syntax error: invalid operator " + currentToken.getValue());
}
}
}
private void expression() {
TokenType operator = null;
if (currentToken.getType() == TokenType.PLUS || currentToken.getType() == TokenType.MINUS) {
operator = currentToken.getType();
match(operator);
}
term();
if (operator != null && operator == TokenType.MINUS) {
SymbolTable.getInstance().negateLastNumber();
}
while (currentToken.getType() == TokenType.PLUS || currentToken.getType() == TokenType.MINUS) {
operator = currentToken.getType();
match(operator);
term();
SymbolTable.getInstance().addOperator(operator);
}
}
private void term() {
factor();
while (currentToken.getType() == TokenType.MULTIPLY || currentToken.getType() == TokenType.DIVIDE) {
TokenType operator = currentToken.getType();
match(operator);
factor();
SymbolTable.getInstance().addOperator(operator);
}
}
private void factor() {
if (currentToken.getType() == TokenType.NUMBER) {
int value = Integer.parseInt(currentToken.getValue());
match(TokenType.NUMBER);
SymbolTable.getInstance().addNumber(value);
} else if (currentToken.getType() == TokenType.IDENTIFIER) {
String name = currentToken.getValue();
match(TokenType.IDENTIFIER);
if (currentToken.getType() == TokenType.LEFT_BRACKET) {
match(TokenType.LEFT_BRACKET);
expression();
match(TokenType.RIGHT_BRACKET);
SymbolTable.getInstance().addArrayAccess(name);
} else {
SymbolTable.getInstance().addIdentifier(name);
}
} else if (currentToken.getType() == TokenType.LEFT_PARENTHESIS) {
match(TokenType.LEFT_PARENTHESIS);
expression();
match(TokenType.RIGHT_PARENTHESIS);
} else {
throw new RuntimeException("Syntax error: invalid factor " + currentToken.getValue());
}
}
private void match(TokenType expectedType) {
if (currentToken.getType() == expectedType) {
currentToken = lexer.getNextToken();
} else {
throw new RuntimeException("Syntax error: " + expectedType + " expected but " + currentToken.getValue() + " found");
}
}
}
```
这个示例代码包含了PL/0编译程序的语法分析器,它负责将词法分析器产生的标记序列转换为语法树。它使用递归下降语法分析方法,它对每个语法规则实现了一个相应的方法。每个方法都检查当前标记是否符合该语法规则,如果符合,则继续解析。如果不符合,则抛出一个运行时异常。在解析过程中,符号表也被更新,以便在后面的代码生成阶段使用。
阅读全文