275 lines
9.4 KiB
Java
275 lines
9.4 KiB
Java
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);
|
|
}
|
|
}
|