Initialize Template

This commit is contained in:
JanUlrich 2024-03-13 13:25:49 +01:00
commit 2b90f84c1e
32 changed files with 582 additions and 0 deletions

92
pom.xml Normal file
View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.dhbw.horb</groupId>
<artifactId>decaf</artifactId>
<version>1.0-SNAPSHOT</version>
<name>decaf</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.11.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin> <!-- ANTLR parser generation -->
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.11.1</version>
<configuration>
<visitor>true</visitor>
</configuration>
<executions>
<execution>
<id>antlr</id>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,55 @@
grammar Decaf;
program : (var | func)*;
var : type id ';';
type : INT | BOOL | VOID ;
func : 'def' type id '(' params? ')' block;
params : param (',' param)*;
param : type id;
block : '{' var* stmt* '}';
stmt : loc '=' expr ';' #Assign
| funcCall ';' #FunctionCall
| 'if' '(' expr ')' block ('else' block)? #If
| 'while' '(' expr ')' block #While
| 'return' expr ';' #Return
| 'return' ';' #ReturnVoid
| 'break' ';' #Break
| 'continue' ';' #Continue
;
expr : expr binaryOp expr #BinaryOperation
| literal #Constant
| '(' expr ')' #Expression
| funcCall #FunCallExpression
| loc #Location
;
binaryOp : ADD | SUB | MUL;
loc : id ;
funcCall : id '(' args? ')';
args : expr (',' expr)*;
literal : number | boolean;
boolean : 'true' | 'false' ;
number : Number;
id : IDENTIFIER;
SUB : '-';
ADD : '+';
MUL : '*';
INT : 'int';
BOOL : 'bool';
VOID : 'void';
IDENTIFIER : [a-zA-Z]+;
Number : [0-9]+;
WS : [ \t\r\n] -> skip;

View File

@ -0,0 +1,43 @@
package de.dhbw.horb;
import de.dhbw.horb.ast.*;
import java.util.ArrayList;
import java.util.List;
public class ASTGenerator {
public static Program generateAST(DecafParser.ProgramContext parseTree){
List<Variable> variables = new ArrayList<>();
for(DecafParser.VarContext varCtx : parseTree.var()){
variables.add(generateVariable(varCtx));
}
List<Function> funcs = new ArrayList<>();
for(DecafParser.FuncContext fctx : parseTree.func()){
funcs.add(generateFunc(fctx));
}
return new Program(variables, funcs);
}
public static Variable generateVariable(DecafParser.VarContext ctx) {
return new Variable(ctx.id().getText(), getType(ctx.type()));
}
public static Variable generateVariable(DecafParser.ParamContext ctx) {
return new Variable(ctx.id().getText(), getType(ctx.type()));
}
public static Function generateFunc(DecafParser.FuncContext ctx) {
throw new RuntimeException("TODO");
}
public static Type getType(DecafParser.TypeContext ctx){
if(ctx.INT() != null)
return Type.INT;
if(ctx.BOOL() != null)
return Type.BOOL;
if(ctx.VOID() != null)
return Type.VOID;
throw new RuntimeException();
}
}

View File

@ -0,0 +1,28 @@
package de.dhbw.horb;
import de.dhbw.horb.ast.*;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Decaf language Compiler
*/
public class Compiler
{
public static Program generateAST(String fromSource){
CharStream input = CharStreams.fromString(fromSource);
DecafLexer lexer = new DecafLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DecafParser parser = new DecafParser(tokens);
DecafParser.ProgramContext tree = parser.program(); //Parsen
return ASTGenerator.generateAST(tree);
}
}

View File

@ -0,0 +1,55 @@
package de.dhbw.horb;
import de.dhbw.horb.ast.*;
public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
@Override
public Expression visitBinaryOperation(DecafParser.BinaryOperationContext ctx) {
return generateBinary(ctx);
}
@Override
public Expression visitFunCallExpression(DecafParser.FunCallExpressionContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Expression visitConstant(DecafParser.ConstantContext ctx) {
return generateConstant(ctx.literal());
}
@Override
public Expression visitExpression(DecafParser.ExpressionContext ctx) {
//ParseTree for ( expr )
//Just pass it down to the inner expr:
return this.visit(ctx.expr());
}
@Override
public Expression visitLocation(DecafParser.LocationContext ctx) {
return generateLocation(ctx.loc());
}
public static Expression generateConstant(DecafParser.LiteralContext ctx){
if(ctx.number() != null)
return new IntConstant(Integer.valueOf(ctx.number().getText()));
if(ctx.boolean_() != null)
return new BoolConstant(Boolean.valueOf(ctx.boolean_().getText()));
throw new RuntimeException();
}
public static Operator generateOperator(DecafParser.BinaryOpContext ctx){
if(ctx.ADD() != null)return Operator.ADD;
if(ctx.SUB() != null)return Operator.SUB;
if(ctx.MUL() != null)return Operator.MUL;
throw new RuntimeException();
}
public static Binary generateBinary(DecafParser.BinaryOperationContext ctx){
ExpressionGenerator eGen = new ExpressionGenerator();
return new Binary(eGen.visit(ctx.expr().get(0)) // left side
, generateOperator(ctx.binaryOp()) //operator
, eGen.visit(ctx.expr().get(1))); //right side
}
public static Location generateLocation(DecafParser.LocContext loc) {
return new Location(loc.id().getText());
}
}

View File

@ -0,0 +1,44 @@
package de.dhbw.horb;
import de.dhbw.horb.ast.*;
import java.util.ArrayList;
import java.util.List;
public class StatementGenerator extends DecafBaseVisitor<Statement> {
@Override
public Statement visitAssign(DecafParser.AssignContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Statement visitIf(DecafParser.IfContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Statement visitWhile(DecafParser.WhileContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Statement visitReturn(DecafParser.ReturnContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Statement visitReturnVoid(DecafParser.ReturnVoidContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Statement visitBreak(DecafParser.BreakContext ctx) {
throw new RuntimeException("TODO");
}
@Override
public Statement visitContinue(DecafParser.ContinueContext ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,4 @@
package de.dhbw.horb.ast;
public class ASTVisitor<T> {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Assignment(Location loc, Expression value) implements Statement {
}

View File

@ -0,0 +1,8 @@
package de.dhbw.horb.ast;
import de.dhbw.horb.ExpressionGenerator;
import java.util.List;
public record Binary(Expression left, Operator op, Expression right) implements Expression{
}

View File

@ -0,0 +1,7 @@
package de.dhbw.horb.ast;
import java.util.ArrayList;
import java.util.List;
public record Block(List<Variable> vars, List<Statement> stmts) implements Node {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record BoolConstant(Boolean value) implements Expression {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Break() implements Statement {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Continue() implements Statement {
}

View File

@ -0,0 +1,4 @@
package de.dhbw.horb.ast;
public sealed interface Expression extends Node permits Binary, IntConstant, BoolConstant, Location, FunctionCall {
}

View File

@ -0,0 +1,7 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Function(Type type, String name, List<Variable> params,
Block block) implements Node {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record FunctionCall(String name, List<Expression> args) implements Expression {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record IfElse(Expression cond, Block ifBlock, Block elseBlock) implements Statement {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record IntConstant(Integer value) implements Expression {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Location(String name) implements Expression {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public interface Node {
}

View File

@ -0,0 +1,7 @@
package de.dhbw.horb.ast;
public enum Operator {
ADD,
SUB,
MUL
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Program(List<Variable> variables, List<Function> methods) implements Node {
}

View File

@ -0,0 +1,7 @@
package de.dhbw.horb.ast;
import java.util.ArrayList;
import java.util.List;
public record Return(Expression ret) implements Statement {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record ReturnVoid() implements Statement {
}

View File

@ -0,0 +1,4 @@
package de.dhbw.horb.ast;
public sealed interface Statement extends Node permits Assignment, VoidFunctionCall, IfElse, While, Return, ReturnVoid, Break, Continue {
}

View File

@ -0,0 +1,7 @@
package de.dhbw.horb.ast;
public enum Type {
INT,
BOOL,
VOID
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record Variable(String name, Type type) implements Node{
}

View File

@ -0,0 +1,4 @@
package de.dhbw.horb.ast;
public record VoidFunctionCall(FunctionCall expr) implements Statement {
}

View File

@ -0,0 +1,6 @@
package de.dhbw.horb.ast;
import java.util.List;
public record While(Expression cond, Block block) implements Statement {
}

View File

@ -0,0 +1,32 @@
package de.dhbw.horb;
import static org.junit.Assert.assertTrue;
import de.dhbw.horb.ast.Program;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class CompilerTest
{
/**
* Rigorous Test :-)
*/
@Test
public void generateASTTest()
{
String inputString = "def int add(int x, int y)\n" +
"{\n" +
"return x + y;\n" +
"}\n" +
"def int main()\n" +
"{\n" +
"int a;\n" +
"a = 3;\n" +
"return add(a, 2);\n" +
"}";
Program ast = Compiler.generateAST(inputString);
assertTrue( ast.methods().size() == 2 );
}
}

View File

@ -0,0 +1,64 @@
package de.dhbw.horb;
import de.dhbw.horb.ast.*;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
/**
* Unit test for AST Generation of Expressions.
*/
public class ExpressionGeneratorTest
{
@Test
public void binaryTest()
{
Expression binary = generateExpression("x + 3");
assertTrue(binary instanceof Binary);
assertTrue( ((Binary) binary).left() instanceof Location);
assertTrue( ((Binary) binary).right() instanceof IntConstant);
}
@Test
public void locationTest()
{
Expression location = generateExpression("x");
assertTrue(location instanceof Location);
assertTrue(((Location) location).name().equals("x"));
}
@Test
public void methodCallTest()
{
Expression mCall = generateExpression("m(x,y)");
assertTrue(mCall instanceof FunctionCall);
assertTrue(((FunctionCall) mCall).name().equals("m"));
assertTrue(((FunctionCall) mCall).args().size() == 2);
}
@Test
public void intConstantTest()
{
Expression intCons = generateExpression("3");
assertTrue(intCons instanceof IntConstant);
assertTrue(((IntConstant) intCons).value() == 3);
}
@Test
public void boolConstantTest()
{
Expression boolCons = generateExpression("true");
assertTrue(boolCons instanceof BoolConstant);
assertTrue(((BoolConstant) boolCons).value() == true);
}
private Expression generateExpression(String from){
String inputString = from;
CharStream input = CharStreams.fromString(inputString);
DecafLexer lexer = new DecafLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DecafParser parser = new DecafParser(tokens);
return new ExpressionGenerator().visit(parser.expr());
}
}

View File

@ -0,0 +1,32 @@
package de.dhbw.horb;
import de.dhbw.horb.ast.*;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
/**
* Unit test for AST Generation of Expressions.
*/
public class StatementGeneratorTest
{
@Test
public void whileTest()
{
Statement whileStmt = generateStatement("while(true){}");
assertTrue(whileStmt instanceof While);
assertTrue( ((While) whileStmt).block().stmts().size() == 0);
}
private Statement generateStatement(String from){
String inputString = from;
CharStream input = CharStreams.fromString(inputString);
DecafLexer lexer = new DecafLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DecafParser parser = new DecafParser(tokens);
return new StatementGenerator().visit(parser.stmt());
}
}