Skip to content
2 changes: 1 addition & 1 deletion src/main/java/com/InterpreterMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ public static void main(String[] args) throws Exception {
outStream.flush();
}

}
}
82 changes: 82 additions & 0 deletions src/main/java/com/compiler/ASTForLoopStmtNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.compiler;

import com.compiler.ast.ASTExprNode;
import com.compiler.ast.ASTStmtNode;
import com.compiler.instr.InstrCondJump;
import com.compiler.instr.InstrJump;

import java.io.OutputStreamWriter;

public class ASTForLoopStmtNode extends ASTStmtNode {
private ASTStmtNode m_initStmt;
private ASTExprNode m_predicate;
private ASTStmtNode m_updateStmt;
private ASTStmtNode m_body;

public ASTForLoopStmtNode(ASTStmtNode initStmt, ASTExprNode predicate, ASTStmtNode updateStmt, ASTStmtNode body) {
m_initStmt = initStmt;
m_predicate = predicate;
m_updateStmt = updateStmt;
m_body = body;
}

@Override
public void execute(OutputStreamWriter out) {
m_initStmt.execute(out);
while (m_predicate.eval() != 0) {
m_body.execute(out);
m_updateStmt.execute(out);
}
}

@Override
public void codegen(CompileEnvIntf env) {
InstrBlock initBlock = env.createBlock("for_init");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sieht gut aus
der for_init block und der for_update block sind nicht notwendig, der Content kann auch in den Vorgängerblock geschrieben werden (kann man aber auch so lassen, wenn es euch besser gefällt)

InstrBlock predicateBlock = env.createBlock("for_predicate");
InstrBlock bodyBlock = env.createBlock("for_body");
InstrBlock updateBlock = env.createBlock("for_update");
InstrBlock exitBlock = env.createBlock("for_exit");

env.addInstr(new InstrJump(initBlock));
env.setCurrentBlock(initBlock);
m_initStmt.codegen(env);
env.addInstr(new InstrJump(predicateBlock));

env.setCurrentBlock(predicateBlock);
InstrIntf predicateInstr = m_predicate.codegen(env);
env.addInstr(predicateInstr);
env.addInstr(new InstrCondJump(predicateInstr, bodyBlock, exitBlock));

env.setCurrentBlock(bodyBlock);
m_body.codegen(env);
env.addInstr(new InstrJump(updateBlock));

env.setCurrentBlock(updateBlock);
m_updateStmt.codegen(env);
env.addInstr(new InstrJump(predicateBlock));

env.setCurrentBlock(exitBlock);

}

@Override
public void print(OutputStreamWriter outStream, String indent) throws Exception {
outStream.write(indent + "FOR:\n" );

outStream.write(indent + "\t" + "initStmt: \n");
m_initStmt.print(outStream, indent + "\t\t");
outStream.write("\n");

outStream.write(indent + "\t" + "predicate: \n");
m_predicate.print(outStream, indent + "\t\t");
outStream.write("\n");

outStream.write(indent + "\t" + "updateStmt: \n");
m_updateStmt.print(outStream, indent + "\t\t");
outStream.write("\n");

outStream.write(indent + "\t" + "body: \n");
m_body.print(outStream, indent + "\t\t");
outStream.write("\n");
}
}
29 changes: 26 additions & 3 deletions src/main/java/com/compiler/StmtParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ public ASTStmtNode parseStmt() throws Exception {
if (type == TokenIntf.Type.DO) {
return parseDoWhileLoopStmt();
}


if (type == TokenIntf.Type.FOR) {
return parseForLoopStmt();
}

if (type == TokenIntf.Type.EXECUTE) {
return parseExecuteNTimesStmt();
}
Expand Down Expand Up @@ -166,6 +170,25 @@ private List<String> parseParameterList() throws Exception {
}
}

private ASTStmtNode parseForLoopStmt() throws Exception {
// forStmt: FOR LPAREN stmt questionMarkExpr SEMICOLON stmt RPAREN blockStmt SEMICOLON
m_lexer.expect(TokenIntf.Type.FOR);
m_lexer.expect(TokenIntf.Type.LPAREN);

ASTStmtNode initStmt = parseStmt();

ASTExprNode predicate = this.m_exprParser.getQuestionMarkExpr();
m_lexer.expect(TokenIntf.Type.SEMICOLON);

ASTStmtNode updateStmt = parseStmt();

m_lexer.expect(TokenIntf.Type.RPAREN);
ASTStmtNode body = parseBlockStmt();
m_lexer.expect(TokenIntf.Type.SEMICOLON);

return new ASTForLoopStmtNode(initStmt, predicate, updateStmt, body);
}

public ASTStmtNode parsePrintStmt() throws Exception {
m_lexer.expect(Type.PRINT);
ASTPrintStmtNode astPrintStmtNode = new ASTPrintStmtNode(m_exprParser.getQuestionMarkExpr());
Expand Down Expand Up @@ -331,7 +354,7 @@ private ASTStmtNode parseBreakNode() throws Exception {
m_lexer.expect(Type.BREAK);
return new ASTBreakStmtNode();
}

ASTStmtNode parseExecuteNTimesStmt() throws Exception {
// EXECUTE integer|identifier TIMES LBRACE stmtList RBRACE SEMICOLON
m_lexer.expect(Type.EXECUTE);
Expand Down Expand Up @@ -389,4 +412,4 @@ private ASTCaseNode parseCaseStmt() throws Exception {
ASTStmtListNode stmtList = parseStmtlist();
return new ASTCaseNode(value, stmtList);
}
}
}
1 change: 0 additions & 1 deletion src/test/java/com/compiler/ConstFoldUnaryExprTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public void testNotZero() throws Exception {

""";
testInterpreter(input, expected);

}

}
57 changes: 57 additions & 0 deletions src/test/java/com/compiler/TestForLoop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.compiler;

import org.junit.Test;

public class TestForLoop extends InterpreterTestBase {

@Test
public void testForLoop1() throws Exception {
String code = """
{
DECLARE index;
DECLARE sum;
index = 0;
sum = 0;
FOR(index = 10; index; index = index - 1;) {
sum = sum + index;
};
PRINT sum;
}
""";
testInterpreter(code, "55\n");
}

@Test
public void testForLoop2() throws Exception {
String code = """
{
DECLARE index;
DECLARE sum;
index = 64;
sum = 0;
FOR(index = index * 2; index; index = index / 2;) {
sum = sum + index;
};
PRINT sum;
}
""";
testInterpreter(code, "255\n");
}

@Test
public void testForLoop3() throws Exception {
String code = """
{
DECLARE index;
DECLARE sum;
index = 10 - 20;
sum = 0;
FOR(PRINT index; index; index = index + 2;) {
sum = sum + index;
};
PRINT sum;
}
""";
testInterpreter(code, "-10\n-30\n");
}
}