From 0732712e61105d8c51bc399d0062f1988db89dec Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:42:56 +0200 Subject: [PATCH] Make, Main: Raupenpiler startup --- src/main/java/Main.java | 50 +++++++++++++------ src/main/java/bytecode/ByteCodeGenerator.java | 8 ++- src/main/java/bytecode/ClassCodeGen.java | 17 ++++--- .../java/bytecode/visitor/ClassVisitor.java | 5 +- src/test/Makefile | 10 +++- src/test/java/FailureTest.java | 2 +- src/test/java/MainTest.java | 2 +- src/test/java/TestCompilerOutput.java | 6 +-- src/test/java/parser/ParserTest.java | 4 ++ 9 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 src/test/java/parser/ParserTest.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 6f6517f..7174d66 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -13,23 +13,41 @@ import java.io.IOException; import java.nio.file.Paths; import java.util.List; +/** + * Start Raupenpiler with the following commands: + *
cd .\src\test\
+ *
make clean compile-raupenpiler
+ */
public class Main {
public static void main(String[] args) throws Exception {
if (args.length > 0) {
- System.out.println("Main file has args: " + args[0]);
- } else {
+ // args[0] is the input file path
+ // args[1] is the output directory path
+ String inputFilePath = args[0];
+ String outputDirectoryPath = args[1];
+ System.out.println("Compiling file: " + inputFilePath);
try {
- CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java"));
- parseFile(codeCharStream);
+ CharStream inputCharStream = CharStreams.fromPath(Paths.get(inputFilePath));
+ compileFile(inputCharStream, outputDirectoryPath);
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}
}
+ /* !!! Else Branch ist nicht zur Verwendung vorgesehen, alles über make starten !!!
+ else {
+ try {
+ CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java"));
+ compileFile(codeCharStream);
+ } catch (IOException e) {
+ System.err.println("Error reading the file: " + e.getMessage());
+ }
+ }
+ */
}
- static void parseFile(CharStream codeCharStream) {
+ static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
/* ------------------------- Scanner -> tokens ------------------------- */
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
+ SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
// Printing the tokens
@@ -51,20 +69,20 @@ public class Main {
ParseTree parseTree = parser.program(); // parse the input
// Printing the parse tree
- System.out.println("-------------------- Parser -> Parsetree --------------------");
- System.out.println(parseTree.toStringTree(parser));
- printTree(parseTree, parser, 0);
- System.out.println();
+ System.out.println("-------------------- Parser -> Parsetree --------------------");
+ System.out.println(parseTree.toStringTree(parser));
+ printTree(parseTree, parser, 0);
+ System.out.println();
/*------------------------- AST builder -> AST -------------------------*/
ASTBuilder astBuilder = new ASTBuilder();
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
// Printing the AST
- System.out.println("-------------------- AST builder -> AST --------------------");
- // System.out.println("AST: " + ast.toString());
- printAST(abstractSyntaxTree, 0);
- System.out.println();
+ System.out.println("-------------------- AST builder -> AST --------------------");
+ // System.out.println("AST: " + ast.toString());
+ printAST(abstractSyntaxTree, 0);
+ System.out.println();
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree);
@@ -75,11 +93,12 @@ public class Main {
System.out.println();
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
- ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
+ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath);
byteCodeGenerator.visit(typedAst);
System.out.println("Bytecode generated");
}
+ /* ------------------------- Printing methods ------------------------- */
/**
* This method is used to print the parse tree in a structured format.
@@ -114,6 +133,7 @@ public class Main {
}
}
+ // TODO: Fix this method
public static void printAST(ASTNode node, int indent) {
if (node == null) {
System.out.println("null");
diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java
index 5494255..99cf5c1 100644
--- a/src/main/java/bytecode/ByteCodeGenerator.java
+++ b/src/main/java/bytecode/ByteCodeGenerator.java
@@ -6,10 +6,16 @@ import bytecode.visitor.ProgramVisitor;
public class ByteCodeGenerator implements ProgramVisitor {
+ private final String outputDirectoryPath;
+
+ public ByteCodeGenerator(String outputDirectoryPath) {
+ this.outputDirectoryPath = outputDirectoryPath;
+ }
+
@Override
public void visit(ProgramNode programNode) {
for (ClassNode classDeclarationNode : programNode.classes) {
- ClassCodeGen classCodeGen = new ClassCodeGen();
+ ClassCodeGen classCodeGen = new ClassCodeGen(outputDirectoryPath);
classDeclarationNode.accept(classCodeGen);
}
}
diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java
index d91b17b..d8cdaaa 100644
--- a/src/main/java/bytecode/ClassCodeGen.java
+++ b/src/main/java/bytecode/ClassCodeGen.java
@@ -6,7 +6,9 @@ import ast.member.MemberNode;
import ast.member.MethodNode;
import ast.type.BaseTypeNode;
import bytecode.visitor.ClassVisitor;
+
import java.io.File;
+
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
@@ -17,8 +19,10 @@ import java.io.IOException;
public class ClassCodeGen implements ClassVisitor {
private Mapper mapper;
private ClassWriter classWriter;
+ private final String outputDirectoryPath;
- public ClassCodeGen() {
+ public ClassCodeGen(String outputDirectoryPath) {
+ this.outputDirectoryPath = outputDirectoryPath;
mapper = new Mapper();
}
@@ -45,20 +49,21 @@ public class ClassCodeGen implements ClassVisitor {
@Override
public void visit(FieldNode fieldNode) {
- if(fieldNode.type instanceof BaseTypeNode baseTypeNode){
- classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null );
+ if (fieldNode.type instanceof BaseTypeNode baseTypeNode) {
+ classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null);
}
classWriter.visitEnd();
}
private void printIntoClassFile(byte[] byteCode, String name) {
- String directoryPath = "src/main/resources/output";
- File directory = new File(directoryPath);
+ // String outputDirectoryPath = "src/main/resources/output";
+ System.out.println("Output directory path: " + outputDirectoryPath);
+ File directory = new File(outputDirectoryPath);
if (!directory.exists()) {
directory.mkdirs();
}
- String filePath = directoryPath + "/" + name + ".class";
+ String filePath = outputDirectoryPath + "/" + name + ".class";
try {
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write(byteCode);
diff --git a/src/main/java/bytecode/visitor/ClassVisitor.java b/src/main/java/bytecode/visitor/ClassVisitor.java
index 98ef25c..725b075 100644
--- a/src/main/java/bytecode/visitor/ClassVisitor.java
+++ b/src/main/java/bytecode/visitor/ClassVisitor.java
@@ -5,6 +5,7 @@ import ast.member.FieldNode;
import org.objectweb.asm.ClassWriter;
public interface ClassVisitor {
- void visit(ClassNode classNode);
- void visit(FieldNode fieldNode);
+ void visit(ClassNode classNode);
+
+ void visit(FieldNode fieldNode);
}
diff --git a/src/test/Makefile b/src/test/Makefile
index e14b5d4..1329f1d 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -9,8 +9,16 @@ compile-javac:
compile-raupenpiler:
cd ../.. ; mvn -DskipTests package
- cd ../.. ; mvn exec:java -Dexec.mainClass="Main" # -Dexec.args="arg0 arg1 arg2"
+ cd ../.. ; mvn exec:java -Dexec.mainClass="Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' "
+test: test-javac test-raupenpiler
+
+test-javac:
+ compile-javac
+ java -cp .\resources\output\javac CompilerInput
+
+test-raupenpiler:
+ java -cp .\resources\output\raupenpiler CompilerInput
clean:
rm -f ./resources/output/javac/*.class
diff --git a/src/test/java/FailureTest.java b/src/test/java/FailureTest.java
index 366ce56..028c5d1 100644
--- a/src/test/java/FailureTest.java
+++ b/src/test/java/FailureTest.java
@@ -63,7 +63,7 @@ public class FailureTest {
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java"));
- Main.parseFile(codeCharStream);
+ Main.compileFile(codeCharStream, "src/main/test/resources/output");
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}
diff --git a/src/test/java/MainTest.java b/src/test/java/MainTest.java
index a8c3a93..eec63b0 100644
--- a/src/test/java/MainTest.java
+++ b/src/test/java/MainTest.java
@@ -16,7 +16,7 @@ public class MainTest {
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.java"));
- Main.parseFile(codeCharStream);
+ Main.compileFile(codeCharStream, "src/main/test/resources/output");
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}
diff --git a/src/test/java/TestCompilerOutput.java b/src/test/java/TestCompilerOutput.java
index 567ebde..6a7c031 100644
--- a/src/test/java/TestCompilerOutput.java
+++ b/src/test/java/TestCompilerOutput.java
@@ -1,10 +1,10 @@
/**
* This class is used to test the output of the compiler.
*
- *
Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbstkompilierte CompilerInput.java Datei sein.
- *
Hinweis: Diese muss man also vom Ordner classFileOutput in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)
Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbst kompilierte CompilerInput.class Datei sein.
+ *
Hinweis: Diese muss man also vom Ordner main/resources/output
in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)
Die selbstkompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. + *
Die selbst kompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. *
Diese TestCompilerOutput.java Datei wird dann in \src\test\java>
mit javac .\TestCompilerOutput.java
kompiliert und mit java TestCompilerOutput
ausgeführt.
* Wenn unser Compiler funktioniert, sollten keine Errors kommen (sondern nur die Ausgaben, die wir in der CompilerInput.java Datei gemacht haben,
* oder Methoden, die wir hier aufrufen).