diff --git a/Source/Decaf.g4 b/Source/Decaf.g4 index 2dde8dd..2af8297 100644 --- a/Source/Decaf.g4 +++ b/Source/Decaf.g4 @@ -3,11 +3,11 @@ grammar Decaf; program: classdecl+; //class identifier{...} -classdecl: AccessModifierPublic? 'class' Identifier OpenCurlyBracket (constuctorDecl|fieldDecl|methodDecl)* ClosedCurlyBracket; -constuctorDecl: AccessModifierPublic? Identifier OpenRoundBracket parameterList? ClosedRoundBracket block; //Maybe not needed +classdecl: AccessModifierPublic? 'class' Identifier OpenCurlyBracket (constuctorDecl|fieldDecl|methodDecl)*(MainMethodDecl block)? ClosedCurlyBracket; +constuctorDecl: AccessModifierPublic? Identifier OpenRoundBracket parameterList? ClosedRoundBracket block; //Method without //Method and FieldVar -methodDecl: MainMethodDecl block | AccessModifierPublic? (type | Void) Identifier OpenRoundBracket parameterList? ClosedRoundBracket block; +methodDecl: AccessModifierPublic? (type | Void) Identifier OpenRoundBracket parameterList? ClosedRoundBracket block; fieldDecl: AccessModifierPublic? type Identifier Semicolon; //Parameters @@ -17,16 +17,20 @@ parameter: type Identifier; //property, object.a, 3+1, a = 3 expression: subExpression | binaryExpr; //subExpression to dissolve left-recusion -subExpression: This | Identifier | instVar | value | stmtExpr | notExpr | OpenRoundBracket expression ClosedRoundBracket; -notExpr: Not expression; +subExpression: This | assignableExpr | stmtExpr | OpenRoundBracket subExpression ClosedRoundBracket; assignableExpr: Identifier | instVar; -instVar: This Dot Identifier | (This Dot)? (Identifier Dot)+ Identifier; +instVar: subReceiver? receivingMethod* Identifier; //.trim().toLength().toLowerCase().count ... methodCall: receiver? receivingMethod* Identifier OpenRoundBracket argumentList ClosedRoundBracket; -argumentList: expression? | expression (Comma expression)*?; +argumentList: expression? | expression (Comma expression)+; -binaryExpr: calcExpr | nonCalcExpr; +subReceiver: ((This | newDecl | Identifier) Dot); +receiver: ((This | instVar | newDecl | Identifier) Dot); +receivingMethod: Identifier OpenRoundBracket argumentList ClosedRoundBracket Dot; + + +binaryExpr: calcExpr | nonCalcExpr| value | Not binaryExpr; calcExpr: calcExpr LineOperator dotExpr | dotExpr; dotExpr: dotExpr DotOperator dotSubExpr | dotSubExpr; @@ -44,14 +48,14 @@ statement: returnStmt Semicolon | localVarDecl Semicolon | block | whileStmt | i returnStmt: Return (expression)?; localVarDecl: type Identifier (Assign expression)?; block: OpenCurlyBracket statement* ClosedCurlyBracket; -whileStmt: While OpenRoundBracket expression ClosedRoundBracket block; +whileStmt: While OpenRoundBracket expression ClosedRoundBracket statement; ifElseStmt: ifStmt elseStmt?; ifStmt: If OpenRoundBracket expression ClosedRoundBracket statement; elseStmt: Else statement; assign: assignableExpr Assign expression; newDecl: New Identifier OpenRoundBracket argumentList ClosedRoundBracket; -receiver: ((This | instVar | newDecl | Identifier) Dot); -receivingMethod: Identifier OpenRoundBracket argumentList ClosedRoundBracket Dot; + + type: Int | Boolean | Char | Identifier; value: IntValue | BooleanValue | CharValue | NullValue; @@ -59,11 +63,7 @@ value: IntValue | BooleanValue | CharValue | NullValue; AccessModifierPublic : 'public' ; MainMethodDecl : 'public static void main(String[] args)'; -//Types -Void : 'void'; -Int : 'int'; -Boolean : 'bool'; -Char : 'char'; + //Operators DotOperator : Multipilkation | Division | Modulo; @@ -102,7 +102,6 @@ This : 'this'; While : 'while'; If : 'if'; Else : 'else'; -For : 'for'; Return : 'return'; New : 'new'; @@ -112,6 +111,12 @@ fragment Numeric: [0-9]; fragment ValidIdentSymbols : Alpabetic|Numeric|'$'|'_'; Identifier: Alpabetic ValidIdentSymbols*; +//Types +Void : 'void'; +Int : 'int'; +Boolean : 'bool'; +Char : 'char'; + //Values IntValue : ('+'|'-')*[0-9]+; CharValue: '\''~[\r\n]?'\''; diff --git a/Source/abstractSyntaxTree/Class/FieldDecl.java b/Source/abstractSyntaxTree/Class/FieldDecl.java index 98e2225..e0a4675 100644 --- a/Source/abstractSyntaxTree/Class/FieldDecl.java +++ b/Source/abstractSyntaxTree/Class/FieldDecl.java @@ -4,6 +4,7 @@ import TypeCheck.AbstractType; import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Program; +import org.objectweb.asm.ClassWriter; import java.util.ArrayList; import java.util.HashMap; @@ -32,4 +33,9 @@ public class FieldDecl extends AbstractType implements IClass{ //write field table } + + @Override + public void codeGen(ClassWriter cw) { + + } } diff --git a/Source/abstractSyntaxTree/Class/IClass.java b/Source/abstractSyntaxTree/Class/IClass.java index 85803f2..6af7dec 100644 --- a/Source/abstractSyntaxTree/Class/IClass.java +++ b/Source/abstractSyntaxTree/Class/IClass.java @@ -1,9 +1,15 @@ package abstractSyntaxTree.Class; import TypeCheck.TypeCheckResult; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.TypeReference; import java.util.List; public interface IClass { // visit method for code generation + + TypeCheckResult typeCheck() throws Exception; + void codeGen(ClassWriter cw) throws Exception; + } diff --git a/Source/abstractSyntaxTree/Class/MethodDecl.java b/Source/abstractSyntaxTree/Class/MethodDecl.java index ec150be..d1d5c93 100644 --- a/Source/abstractSyntaxTree/Class/MethodDecl.java +++ b/Source/abstractSyntaxTree/Class/MethodDecl.java @@ -1,6 +1,8 @@ package abstractSyntaxTree.Class; import TypeCheck.TypeCheckResult; +import abstractSyntaxTree.Program; +import org.objectweb.asm.ClassWriter; import java.util.HashMap; import java.util.List; @@ -23,4 +25,5 @@ public class MethodDecl implements IClass { // jede methode als block statement aufrufen return null; } + } diff --git a/Source/abstractSyntaxTree/Datatype/RefType.java b/Source/abstractSyntaxTree/Class/RefType.java similarity index 88% rename from Source/abstractSyntaxTree/Datatype/RefType.java rename to Source/abstractSyntaxTree/Class/RefType.java index 11438ee..291f29c 100644 --- a/Source/abstractSyntaxTree/Datatype/RefType.java +++ b/Source/abstractSyntaxTree/Class/RefType.java @@ -1,17 +1,19 @@ -package abstractSyntaxTree.Datatype; +package abstractSyntaxTree.Class; import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.MethodDecl; +import abstractSyntaxTree.Datatype.IDatatype; import abstractSyntaxTree.Program; import jdk.jshell.spi.ExecutionControl; +import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import java.util.HashMap; import java.util.List; -public class RefType extends AbstractType implements IDatatype { +public class RefType extends AbstractType implements IClass { public String name; public List fieldDecls; @@ -51,7 +53,7 @@ public class RefType extends AbstractType implements IDatatype { // Method for code generation which iterates over all the field declarations // and method declarations and calls their CodeGen methods @Override - public void codeGen(MethodVisitor mv) throws Exception { + public void codeGen(ClassWriter cw) throws Exception { throw new ExecutionControl.NotImplementedException("CodeGen not implemented for RefType"); } diff --git a/Source/abstractSyntaxTree/Expression/InstVarExpression.java b/Source/abstractSyntaxTree/Expression/InstVarExpression.java index 7b45d3a..f7d58e3 100644 --- a/Source/abstractSyntaxTree/Expression/InstVarExpression.java +++ b/Source/abstractSyntaxTree/Expression/InstVarExpression.java @@ -1,7 +1,7 @@ package abstractSyntaxTree.Expression; import TypeCheck.TypeCheckResult; -import abstractSyntaxTree.Datatype.RefType; +import abstractSyntaxTree.Class.RefType; import jdk.jshell.spi.ExecutionControl; import org.objectweb.asm.MethodVisitor; diff --git a/Source/abstractSyntaxTree/Program.java b/Source/abstractSyntaxTree/Program.java index 415a256..634e05e 100644 --- a/Source/abstractSyntaxTree/Program.java +++ b/Source/abstractSyntaxTree/Program.java @@ -5,8 +5,17 @@ import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.MethodDecl; import abstractSyntaxTree.Datatype.RefType; import org.objectweb.asm.MethodVisitor; +import abstractSyntaxTree.Class.RefType; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; import java.util.*; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; public class Program { public List classes; @@ -37,8 +46,36 @@ public class Program { } public void codeGen() throws Exception{ - for(RefType oneClass : classes){ - //oneClass.codeGen(); + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream("output.jar"))) { + for (RefType oneClass : classes) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null); + + oneClass.codeGen(cw); + + cw.visitEnd(); + byte[] bytecode = cw.toByteArray(); + + // Write the bytecode to a .class file in the .jar file + JarEntry entry = new JarEntry(oneClass.name + ".class"); + jos.putNextEntry(entry); + jos.write(bytecode); + jos.closeEntry(); + } + } catch (IOException e) { + e.printStackTrace(); } + + /* + for(RefType oneClass : classes){ + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC,oneClass.name, null, + "java/lang/Object", null); + oneClass.codeGen(cw); + + cw.visitEnd(); + byte[] bytecode = cw.toByteArray(); + } + */ } } diff --git a/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java b/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java index 659ea6b..7eb133c 100644 --- a/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java +++ b/Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java @@ -3,7 +3,7 @@ package abstractSyntaxTree.StatementExpression; import TypeCheck.AbstractType; import TypeCheck.TypeCheckResult; import abstractSyntaxTree.Class.MethodDecl; -import abstractSyntaxTree.Datatype.RefType; +import abstractSyntaxTree.Class.RefType; import abstractSyntaxTree.Expression.IExpression; import abstractSyntaxTree.Statement.IStatement; import org.objectweb.asm.MethodVisitor; @@ -42,15 +42,12 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr return result; } + //Errors occur due to the change in parameter in the RefType class @Override - public void codeGen(MethodVisitor mv) throws Exception { - - } - public void CodeGen(MethodVisitor mv) throws Exception { //Generate Bytecode for the receiver if(classThatHasTheMethodIfNotThis != null){ - classThatHasTheMethodIfNotThis.codeGen(mv); + classThatHasTheMethodIfNotThis.codeGen(); } else { mv.visitVarInsn(Opcodes.ALOAD, 0); }