From e7ab233f1e3b4c288477404bcf59749395a86f70 Mon Sep 17 00:00:00 2001 From: MaarxS Date: Fri, 22 Mar 2024 17:17:41 +0100 Subject: [PATCH] finish StatmentGenerator --- .../de/dhbw/horb/ExpressionGenerator.java | 3 +- .../java/de/dhbw/horb/StatementGenerator.java | 47 +++++++++++++++---- .../java/de/dhbw/horb/ast/FunctionCall.java | 2 +- src/main/java/de/dhbw/horb/ast/Statement.java | 2 +- .../de/dhbw/horb/StatementGeneratorTest.java | 28 +++++++++++ 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/dhbw/horb/ExpressionGenerator.java b/src/main/java/de/dhbw/horb/ExpressionGenerator.java index 63f7730..2ffca20 100644 --- a/src/main/java/de/dhbw/horb/ExpressionGenerator.java +++ b/src/main/java/de/dhbw/horb/ExpressionGenerator.java @@ -2,6 +2,7 @@ package de.dhbw.horb; import de.dhbw.horb.ast.*; +import java.util.Collections; import java.util.List; public class ExpressionGenerator extends DecafBaseVisitor { @@ -34,7 +35,7 @@ public class ExpressionGenerator extends DecafBaseVisitor { public static FunctionCall generateFunctionCall(DecafParser.FuncCallContext ctx) { String name = ctx.id().getText(); - List expressions = ctx.args().expr(); + List expressions = ctx.args() == null ? Collections.emptyList() : ctx.args().expr(); List args = expressions.stream() .map(exp -> new ExpressionGenerator().visit(exp)).toList(); return new FunctionCall(name, args); diff --git a/src/main/java/de/dhbw/horb/StatementGenerator.java b/src/main/java/de/dhbw/horb/StatementGenerator.java index 77efb6b..3533e16 100644 --- a/src/main/java/de/dhbw/horb/StatementGenerator.java +++ b/src/main/java/de/dhbw/horb/StatementGenerator.java @@ -2,43 +2,74 @@ package de.dhbw.horb; import de.dhbw.horb.ast.*; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class StatementGenerator extends DecafBaseVisitor { @Override public Statement visitAssign(DecafParser.AssignContext ctx) { - throw new RuntimeException("TODO"); + Location loc = ExpressionGenerator.generateLocation(ctx.loc()); + Expression exp = ctx.expr().accept(new ExpressionGenerator()); + return new Assignment(loc, exp); + } + + @Override + public Statement visitFunctionCall(DecafParser.FunctionCallContext ctx) { + return ExpressionGenerator.generateFunctionCall(ctx.funcCall()); } @Override public Statement visitIf(DecafParser.IfContext ctx) { - throw new RuntimeException("TODO"); + Expression exp = ctx.accept(new ExpressionGenerator()); + Block ifBlock = generateBlock(ctx.block(0)); + Block elseBlock = ctx.block().size() > 1 ? + generateBlock(ctx.block(1)) : + new Block(Collections.emptyList(), Collections.emptyList()); + return new IfElse(exp, ifBlock, elseBlock); } @Override public Statement visitWhile(DecafParser.WhileContext ctx) { - throw new RuntimeException("TODO"); + return new While(ctx.expr().accept(new ExpressionGenerator()), generateBlock(ctx.block())); } @Override public Statement visitReturn(DecafParser.ReturnContext ctx) { - throw new RuntimeException("TODO"); + return new Return(ctx.expr().accept(new ExpressionGenerator())); } @Override public Statement visitReturnVoid(DecafParser.ReturnVoidContext ctx) { - throw new RuntimeException("TODO"); + return new ReturnVoid(); } @Override public Statement visitBreak(DecafParser.BreakContext ctx) { - throw new RuntimeException("TODO"); + return new Break(); } @Override public Statement visitContinue(DecafParser.ContinueContext ctx) { - throw new RuntimeException("TODO"); + return new Continue(); } + public Block generateBlock(DecafParser.BlockContext ctx) { + List vars = ctx.var().stream().map(StatementGenerator::generateVariable).toList(); + List stmt = ctx.stmt().stream().map(this::visit).toList(); + return new Block(vars, stmt); + } + + public static Variable generateVariable(DecafParser.VarContext ctx) { + Type type; + if (ctx.type().INT() != null) { + type = Type.INT; + } else if (ctx.type().BOOL() != null) { + type = Type.BOOL; + } else if (ctx.type().VOID() != null) { + type = Type.VOID; + } else { + throw new RuntimeException("Unknown Type"); + } + return new Variable(ctx.id().getText(), type); + } } diff --git a/src/main/java/de/dhbw/horb/ast/FunctionCall.java b/src/main/java/de/dhbw/horb/ast/FunctionCall.java index 85150f5..ffa6edd 100644 --- a/src/main/java/de/dhbw/horb/ast/FunctionCall.java +++ b/src/main/java/de/dhbw/horb/ast/FunctionCall.java @@ -2,5 +2,5 @@ package de.dhbw.horb.ast; import java.util.List; -public record FunctionCall(String name, List args) implements Expression { +public record FunctionCall(String name, List args) implements Expression, Statement { } diff --git a/src/main/java/de/dhbw/horb/ast/Statement.java b/src/main/java/de/dhbw/horb/ast/Statement.java index 11bbbdb..617ee56 100644 --- a/src/main/java/de/dhbw/horb/ast/Statement.java +++ b/src/main/java/de/dhbw/horb/ast/Statement.java @@ -1,4 +1,4 @@ package de.dhbw.horb.ast; -public sealed interface Statement extends Node permits Assignment, VoidFunctionCall, IfElse, While, Return, ReturnVoid, Break, Continue { +public sealed interface Statement extends Node permits Assignment, Break, Continue, FunctionCall, IfElse, Return, ReturnVoid, VoidFunctionCall, While { } diff --git a/src/test/java/de/dhbw/horb/StatementGeneratorTest.java b/src/test/java/de/dhbw/horb/StatementGeneratorTest.java index 4229bf1..dd97fed 100644 --- a/src/test/java/de/dhbw/horb/StatementGeneratorTest.java +++ b/src/test/java/de/dhbw/horb/StatementGeneratorTest.java @@ -7,12 +7,40 @@ import org.antlr.v4.runtime.CommonTokenStream; import org.junit.Test; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; /** * Unit test for AST Generation of Expressions. */ public class StatementGeneratorTest { + @Test + public void ifTest() { + Statement stmt = generateStatement("if (true) { break; }"); + assertTrue(stmt instanceof IfElse); + IfElse ifElse = (IfElse) stmt; + assertEquals(0, (ifElse.elseBlock().stmts().size())); + assertTrue(ifElse.ifBlock().stmts().get(0) instanceof Break); + } + + @Test + public void ifElseTest() { + Statement stmt = generateStatement("if (true) { int x; } else { return; }"); + assertTrue(stmt instanceof IfElse); + IfElse ifElse = (IfElse) stmt; + assertEquals("x", ifElse.ifBlock().vars().get(0).name()); + assertTrue(ifElse.elseBlock().stmts().get(0) instanceof ReturnVoid); + } + + @Test + public void methodCall() { + Statement stmt = generateStatement("foo();"); + assertTrue(stmt instanceof FunctionCall); + FunctionCall functionCall = (FunctionCall) stmt; + assertEquals(0, functionCall.args().size()); + assertEquals("foo", functionCall.name()); + } + @Test public void whileTest() {