From b173d776209987bf791eef8f7afce9e4739b4da9 Mon Sep 17 00:00:00 2001 From: i22007 Date: Wed, 8 May 2024 13:06:27 +0200 Subject: [PATCH 1/4] Fixed change errors --- src/main/java/Main.java | 8 ++-- src/main/java/bytecode/ByteCodeGenerator.java | 7 ++-- src/main/java/bytecode/ClassCodeGen.java | 39 +++++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 src/main/java/bytecode/ClassCodeGen.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index ab4a4fe..309d16f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,11 +1,11 @@ +import ast.ClassNode; +import ast.ProgramNode; import bytecode.ByteCodeGenerator; 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.ClassDeclarationNode; -import parser.ProgramNode; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; @@ -37,8 +37,8 @@ public class Main { // Optionally print or process the AST System.out.println("Parsed " + ast.classes.size() + " classes with identifiers/names:"); - for (ClassDeclarationNode classNode : ast.classes) { - System.out.println(classNode.identifier); + for (ClassNode classNode : ast.classes) { + System.out.println(classNode.name); } ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index b00f429..60c8d46 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -3,6 +3,7 @@ package bytecode; import java.io.FileOutputStream; import java.io.IOException; +import ast.ClassNode; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import ast.ProgramNode; @@ -10,9 +11,9 @@ import ast.ProgramNode; public class ByteCodeGenerator { public void generateByteCode(ProgramNode ast) { - for (ClassDeclarationNode classDeclarationNode : ast.classes) { + for (ClassNode classNode : ast.classes) { ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, classDeclarationNode.identifier, null, + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, classNode.name, null, "java/lang/Object", null); FieldCodeGen fieldCodeGen = new FieldCodeGen(); @@ -22,7 +23,7 @@ public class ByteCodeGenerator { methodCodeGen.generateMethodCode(classWriter); classWriter.visitEnd(); - printIntoClassFile(classWriter.toByteArray(), classDeclarationNode.identifier); + printIntoClassFile(classWriter.toByteArray(), classNode.name); classWriter.visitEnd(); } 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(); + } + } +} From ce2ea07f9686513fd6ece4ae8378e21f034bf72c Mon Sep 17 00:00:00 2001 From: i22007 Date: Wed, 8 May 2024 13:10:29 +0200 Subject: [PATCH 2/4] Move code generation --- src/main/java/bytecode/ByteCodeGenerator.java | 33 ++----------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index 60c8d46..f8a5570 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -1,43 +1,14 @@ package bytecode; -import java.io.FileOutputStream; -import java.io.IOException; - import ast.ClassNode; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; import ast.ProgramNode; public class ByteCodeGenerator { public void generateByteCode(ProgramNode ast) { for (ClassNode classNode : ast.classes) { - 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(); + ClassCodeGen classCodeGen = new ClassCodeGen(); + classCodeGen.generateClassCode(classNode); } } } From d014cb28c74a662b3ffa26d7574ea9b0dcb80240 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 8 May 2024 13:10:45 +0200 Subject: [PATCH 3/4] Structure and Fixes --- src/main/java/Main.java | 10 +++---- src/main/java/bytecode/ByteCodeGenerator.java | 7 ++--- src/main/test/java/MainTest.java | 27 ++++++++++++++++--- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index ab4a4fe..10322be 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,13 +1,13 @@ -import bytecode.ByteCodeGenerator; 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.ClassDeclarationNode; -import parser.ProgramNode; 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; @@ -37,8 +37,8 @@ public class Main { // Optionally print or process the AST System.out.println("Parsed " + ast.classes.size() + " classes with identifiers/names:"); - for (ClassDeclarationNode classNode : ast.classes) { - System.out.println(classNode.identifier); + for (ClassNode classNode : ast.classes) { + System.out.println(classNode.name); } ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index b00f429..4890004 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -3,6 +3,7 @@ package bytecode; import java.io.FileOutputStream; import java.io.IOException; +import ast.ClassNode; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import ast.ProgramNode; @@ -10,9 +11,9 @@ import ast.ProgramNode; public class ByteCodeGenerator { public void generateByteCode(ProgramNode ast) { - for (ClassDeclarationNode classDeclarationNode : ast.classes) { + for (ClassNode classDeclarationNode : ast.classes) { ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, classDeclarationNode.identifier, null, + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, classDeclarationNode.name, null, "java/lang/Object", null); FieldCodeGen fieldCodeGen = new FieldCodeGen(); @@ -22,7 +23,7 @@ public class ByteCodeGenerator { methodCodeGen.generateMethodCode(classWriter); classWriter.visitEnd(); - printIntoClassFile(classWriter.toByteArray(), classDeclarationNode.identifier); + printIntoClassFile(classWriter.toByteArray(), classDeclarationNode.name); classWriter.visitEnd(); } 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()); + } } } From 20052e619db647b55cc1ffc1040661b48f11170c Mon Sep 17 00:00:00 2001 From: Purplumbi Date: Wed, 8 May 2024 13:27:40 +0200 Subject: [PATCH 4/4] Antlr + Visitors --- src/main/java/ast/ExpressionNode.java | 4 ++ src/main/java/ast/FieldNode.java | 6 +- src/main/java/ast/MethodNode.java | 10 +++- src/main/java/ast/ParameterListNode.java | 12 ++++ src/main/java/ast/ParameterNode.java | 11 ++++ src/main/java/ast/ProgramNode.java | 17 +++--- src/main/java/ast/StatementNode.java | 7 +++ src/main/java/ast/TypeNode.java | 8 ++- .../ast/VariableDeclarationStatementNode.java | 13 +++++ src/main/java/parser/ASTBuilder.java | 56 +++++++++++++++++++ 10 files changed, 127 insertions(+), 17 deletions(-) create mode 100644 src/main/java/ast/ExpressionNode.java create mode 100644 src/main/java/ast/ParameterListNode.java create mode 100644 src/main/java/ast/ParameterNode.java create mode 100644 src/main/java/ast/StatementNode.java create mode 100644 src/main/java/ast/VariableDeclarationStatementNode.java 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/parser/ASTBuilder.java b/src/main/java/parser/ASTBuilder.java index fe0bdeb..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) { @@ -32,5 +35,58 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { 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); + } + }