Files
MY_COMPILER/frontend/ast/block/Stmt.java
2025-12-12 20:14:00 +08:00

275 lines
9.7 KiB
Java
Executable File

package frontend.ast.block;
import error.Errors;
import java.util.ArrayList;
import error.Error;
import error.ErrorType;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import frontend.ast.exp.Exp;
import frontend.ast.exp.Cond;
import frontend.ast.exp.LVal;
public class Stmt extends Node {
private boolean getint;
public Stmt(TokenStream ts) {
super(SyntaxType.STMT, ts);
getint = false;
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.LBRACE) {
Block block = new Block(this.ts);
block.parse(errors);
addChild(block);
} else if (getCurrToken().getType() == TokenType.IFTK) {
handleIf(errors);
} else if (getCurrToken().getType() == TokenType.FORTK) {
handleFor(errors);
} else if (getCurrToken().getType() == TokenType.BREAKTK) {
TokenNode breakkk = new TokenNode(this.ts);
addChild(breakkk);
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
} else if (getCurrToken().getType() == TokenType.CONTINUETK) {
TokenNode continuekk = new TokenNode(this.ts);
addChild(continuekk);
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
} else if (getCurrToken().getType() == TokenType.RETURNTK) {
handleReturn(errors);
} else if (getCurrToken().getType() == TokenType.PRINTFTK) {
handlePrintf(errors);
} else {
handleAssign(errors);
}
}
public void handleIf(Errors errors) {
TokenNode ifkk = new TokenNode(this.ts);
addChild(ifkk);
TokenNode lparent = new TokenNode(this.ts);
addChild(lparent);
Cond cond = new Cond(this.ts);
cond.parse(errors);
addChild(cond);
if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
}
Stmt stmt = new Stmt(this.ts);
stmt.parse(errors);
addChild(stmt);
if (getCurrToken().getType() == TokenType.ELSETK) {
TokenNode elsekk = new TokenNode(this.ts);
addChild(elsekk);
Stmt elseStmt = new Stmt(this.ts);
elseStmt.parse(errors);
addChild(elseStmt);
}
}
public void handleFor(Errors errors) {
TokenNode forkk = new TokenNode(this.ts);
addChild(forkk);
TokenNode lparent = new TokenNode(this.ts);
addChild(lparent);
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
ForStmt fst = new ForStmt(this.ts);
fst.parse(errors);
addChild(fst);
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
}
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
Cond cond = new Cond(this.ts);
cond.parse(errors);
addChild(cond);
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
}
if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
} else {
ForStmt fst = new ForStmt(this.ts);
fst.parse(errors);
addChild(fst);
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
}
Stmt stmt = new Stmt(this.ts);
stmt.parse(errors);
addChild(stmt);
}
public void handleReturn(Errors errors) {
TokenNode returnkk = new TokenNode(this.ts);
addChild(returnkk);
if (currentIsExp()) {
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
}
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
public void handlePrintf(Errors errors) {
TokenNode printfkk = new TokenNode(this.ts);
addChild(printfkk);
addChild(new TokenNode(this.ts)); // lparent
addChild(new TokenNode(this.ts)); // strconst
while (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(this.ts)); // comma
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
}
if (getCurrToken().getType() != TokenType.RPARENT) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} else {
addChild(new TokenNode(this.ts)); // rparent
}
if (getCurrToken().getType() != TokenType.SEMICN) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} else {
addChild(new TokenNode(this.ts)); // semicolon
}
}
public void handleAssign(Errors errors) {
if (getCurrToken().getType() == TokenType.IDENFR) {
if (this.ts.peek(1).getType() == TokenType.ASSIGN) {
LVal lval = new LVal(this.ts);
lval.parse(errors);
addChild(lval);
addChild(new TokenNode(this.ts)); // assign
if (getCurrToken().getValue().equals("getint")) {
getint = true;
}
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
} else if (this.ts.peek(1).getType() == TokenType.LBRACK) {
int start = this.ts.getCurrentIndex();
LVal lval = new LVal(this.ts);
lval.parse(errors);
if (getCurrToken().getType() == TokenType.ASSIGN) {
addChild(lval);
addChild(new TokenNode(this.ts)); // assign
if (getCurrToken().getValue().equals("getint")) {
getint = true;
}
handleExpInAssign(errors);
} else {
this.ts.resetIndex(start);
// parse exp ;
handleExpInAssign(errors);
}
} else {
handleExpInAssign(errors);
}
} else {
if (currentIsExp()) {
handleExpInAssign(errors);
} else {
if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
}
}
public void handleExpInAssign(Errors errors) {
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
public boolean currentIsExp() {
TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
}
public boolean isGetint() {
return getint;
}
public ArrayList<Exp> getExpList() {
ArrayList<Exp> expList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Exp) {
expList.add((Exp) getChild(i));
}
}
return expList;
}
public Cond getCond() { //just for fortype stmt
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Cond) {
return (Cond) getChild(i);
}
}
return null;
}
public ForStmt getinitStmt() {
if (getChild(2) instanceof ForStmt) {
return (ForStmt) getChild(2);
}
return null;
}
public ForStmt getStepStmt() {
if (getChild(getChildren().size() - 3) instanceof ForStmt) {
return (ForStmt) getChild(getChildren().size() - 3);
}
return null;
}
public Stmt getBodyStmt() {
return (Stmt) getChild(getChildren().size() - 1);
}
}