diff --git a/src/main/java/Main.java b/src/main/java/Main.java index bc82379..8188324 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -9,6 +9,9 @@ import parser.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; import semantic.SemanticAnalyzer; +import ast.ClassNode; +import ast.ProgramNode; +import bytecode.ByteCodeGenerator; import java.io.IOException; import java.nio.file.Paths; diff --git a/src/main/java/ast/ExpressionNode.java b/src/main/java/ast/ExpressionNode.java new file mode 100644 index 0000000..891d87c --- /dev/null +++ b/src/main/java/ast/ExpressionNode.java @@ -0,0 +1,4 @@ +package ast; + +public class ExpressionNode { +} diff --git a/src/main/java/ast/FieldNode.java b/src/main/java/ast/FieldNode.java index 3bf6d2b..0f17f69 100644 --- a/src/main/java/ast/FieldNode.java +++ b/src/main/java/ast/FieldNode.java @@ -1,10 +1,10 @@ package ast; -public class FieldNode { - String type; +public class FieldNode extends MemberNode { + TypeNode type; String name; - public FieldNode(String type, String name){ + public FieldNode(TypeNode type, String name){ this.type = type; this.name = name; } diff --git a/src/main/java/ast/MethodNode.java b/src/main/java/ast/MethodNode.java index b9a8ab4..1db789c 100644 --- a/src/main/java/ast/MethodNode.java +++ b/src/main/java/ast/MethodNode.java @@ -1,11 +1,17 @@ package ast; +import java.util.ArrayList; +import java.util.List; + public class MethodNode extends MemberNode{ - public String visibility; + public TypeNode visibility; public String name; - public MethodNode(String visibility, String name){ + public ParameterListNode parameters; + + public MethodNode(TypeNode visibility, String name, ParameterListNode parameters){ this.visibility = visibility; this.name = name; + this.parameters = parameters; } } diff --git a/src/main/java/ast/ParameterListNode.java b/src/main/java/ast/ParameterListNode.java new file mode 100644 index 0000000..6096b69 --- /dev/null +++ b/src/main/java/ast/ParameterListNode.java @@ -0,0 +1,12 @@ +package ast; + +import java.util.ArrayList; +import java.util.List; + +public class ParameterListNode { + List parameters = new ArrayList<>(); + + public ParameterListNode(){ + parameters + } +} diff --git a/src/main/java/ast/ParameterNode.java b/src/main/java/ast/ParameterNode.java new file mode 100644 index 0000000..fc2d84a --- /dev/null +++ b/src/main/java/ast/ParameterNode.java @@ -0,0 +1,11 @@ +package ast; + +public class ParameterNode extends ASTNode { + public TypeNode type; + public String identifier; + + public ParameterNode(TypeNode type, String identifier) { + this.type = type; + this.identifier = identifier; + } +} \ No newline at end of file diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index d22af33..1fed1c0 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -1,12 +1,9 @@ -package ast; +public class ParameterNode extends ASTNode { + public TypeNode type; + public String identifier; -import java.util.ArrayList; -import java.util.List; - -public class ProgramNode extends ASTNode { - public List classes = new ArrayList<>(); - - public void addClass(ClassNode classNode) { - classes.add(classNode); + public ParameterNode(TypeNode type, String identifier) { + this.type = type; + this.identifier = identifier; } -} +} \ No newline at end of file diff --git a/src/main/java/ast/StatementNode.java b/src/main/java/ast/StatementNode.java new file mode 100644 index 0000000..059a96a --- /dev/null +++ b/src/main/java/ast/StatementNode.java @@ -0,0 +1,7 @@ +package ast; + +import ast.ASTNode; + +public abstract class StatementNode extends ASTNode { +} + diff --git a/src/main/java/ast/TypeNode.java b/src/main/java/ast/TypeNode.java index 1f657df..51a3dc7 100644 --- a/src/main/java/ast/TypeNode.java +++ b/src/main/java/ast/TypeNode.java @@ -1,5 +1,9 @@ package ast; -public class TypeNode { - String type; +public class TypeNode extends ASTNode { + public String typeName; + + public TypeNode(String typeName) { + this.typeName = typeName; + } } diff --git a/src/main/java/ast/VariableDeclarationStatementNode.java b/src/main/java/ast/VariableDeclarationStatementNode.java new file mode 100644 index 0000000..6222942 --- /dev/null +++ b/src/main/java/ast/VariableDeclarationStatementNode.java @@ -0,0 +1,13 @@ +package ast; + +public class VariableDeclarationStatementNode extends StatementNode { + public TypeNode type; + public String identifier; + public ExpressionNode expression; // Nullable for cases without initialization + + public VariableDeclarationStatementNode(TypeNode type, String identifier, ExpressionNode expression) { + this.type = type; + this.identifier = identifier; + this.expression = expression; + } +} \ No newline at end of file diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java new file mode 100644 index 0000000..619068a --- /dev/null +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -0,0 +1,39 @@ +package bytecode; + +import ast.ClassNode; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; + +import java.io.FileOutputStream; +import java.io.IOException; + +public class ClassCodeGen { + public void generateClassCode(ClassNode classNode) { + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, classNode.name, null, + "java/lang/Object", null); + + FieldCodeGen fieldCodeGen = new FieldCodeGen(); + fieldCodeGen.generateFieldCode(classWriter); + + MethodCodeGen methodCodeGen = new MethodCodeGen(); + methodCodeGen.generateMethodCode(classWriter); + + classWriter.visitEnd(); + printIntoClassFile(classWriter.toByteArray(), classNode.name); + + classWriter.visitEnd(); + } + + private void printIntoClassFile(byte[] byteCode, String name) { + String filePath = "./classFileOutput/" + name + ".class"; + + try { + FileOutputStream fileOutputStream = new FileOutputStream(filePath); + fileOutputStream.write(byteCode); + fileOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/parser/ASTBuilder.java b/src/main/java/parser/ASTBuilder.java index df2d1b3..f659299 100644 --- a/src/main/java/parser/ASTBuilder.java +++ b/src/main/java/parser/ASTBuilder.java @@ -4,6 +4,9 @@ import ast.*; import parser.generated.SimpleJavaBaseVisitor; import parser.generated.SimpleJavaParser; +import java.util.ArrayList; +import java.util.List; + public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitProgram(SimpleJavaParser.ProgramContext ctx) { @@ -25,4 +28,65 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { return classNode; } + @Override + public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { + TypeNode type = (TypeNode) visit(ctx.type()); + String identifier = ctx.IDENTIFIER().getText(); + return new FieldNode(type, identifier); + } + + @Override + public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) { + TypeNode returnType = (TypeNode) visit(ctx.type()); + String methodName = ctx.IDENTIFIER().getText(); + ParameterListNode = (ParameterListNode) visit(ctx.parameterList()); + List parameters = new ArrayList<>(); + for (SimpleJavaParser.ParameterContext parameter : ctx.parameterList()) { + parameters.add(parameter); + } + MethodNode method = new MethodNode(returnType, methodName); + + for (SimpleJavaParser.ParameterContext paramCtx : ctx.parameterList().parameter()) { + method.parameters.add((ParameterNode) visit(paramCtx)); + } + + for (SimpleJavaParser.StatementContext stmtCtx : ctx.statement()) { + method.statements.add((StatementNode) visit(stmtCtx)); + } + + return method; + } + @Override + public ASTNode visitType(SimpleJavaParser.TypeContext ctx) { + return new TypeNode(ctx.getText()); + } + + @Override + public ASTNode visitStatement(SimpleJavaParser.StatementContext ctx) { + if (ctx.variableDeclarationStatement() != null) { + return visitVariableDeclarationStatement(ctx.variableDeclarationStatement()); + } else if (ctx.assignmentStatement() != null) { + return visitAssignmentStatement(ctx.assignmentStatement()); + } + + return null; + } + + @Override + public ASTNode visitParameterList(SimpleJavaParser.ParameterListContext ctx) { + List parameters = new ArrayList<>(); + for (SimpleJavaParser.ParameterContext paramCtx : ctx.parameter()) { + parameters.add((ParameterNode) visitParameter(paramCtx)); + } + return new ParameterListNode(parameters); // Assuming you want to keep a dedicated node for the list + } + + @Override + public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) { + TypeNode type = (TypeNode) visit(ctx.type()); // Assuming visitType returns a TypeNode + String identifier = ctx.IDENTIFIER().getText(); + return new ParameterNode(type, identifier); + } + + } diff --git a/src/main/test/java/MainTest.java b/src/main/test/java/MainTest.java index c956827..46ad4ee 100644 --- a/src/main/test/java/MainTest.java +++ b/src/main/test/java/MainTest.java @@ -1,4 +1,19 @@ +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; import org.junit.jupiter.api.Test; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import parser.ASTBuilder; +import parser.generated.SimpleJavaLexer; +import parser.generated.SimpleJavaParser; +import ast.ClassNode; +import ast.ProgramNode; +import bytecode.ByteCodeGenerator; + +import java.io.IOException; +import java.nio.file.Paths; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -7,10 +22,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; */ public class MainTest { @Test - void testAdd() { - //Calculator calculator = new Calculator(); - //int result = calculator.add(2, 3); - //assertEquals(5, result, "2 + 3 should equal 5"); + void testEmptyClass() { + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/main/java/Example.java")); + Main.parsefile(codeCharStream); + } catch (IOException e) { + System.err.println("Error reading the file: " + e.getMessage()); + } } }