Make, Main: Raupenpiler startup
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Lucas 2024-06-17 13:42:56 +02:00
parent b6cc925e02
commit 0732712e61
9 changed files with 74 additions and 30 deletions

View File

@ -13,23 +13,41 @@ import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
/**
* Start Raupenpiler with the following commands:
* <p> <code> cd .\src\test\ </code>
* <p> <code> make clean compile-raupenpiler </code>
*/
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");

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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());
}

View File

@ -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());
}

View File

@ -1,10 +1,10 @@
/**
* This class is used to test the output of the compiler.
*
* <p>Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbstkompilierte CompilerInput.java Datei sein.
* <br><strong>Hinweis:</strong> Diese muss man also vom Ordner classFileOutput in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)</p>
* <p>Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbst kompilierte CompilerInput.class Datei sein.
* <br><strong>Hinweis:</strong> Diese muss man also vom Ordner <code> main/resources/output </code> in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)</p>
*
* <p>Die selbstkompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden.
* <p>Die selbst kompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden.
* <p>Diese TestCompilerOutput.java Datei wird dann in <code> \src\test\java> </code> mit <code>javac .\TestCompilerOutput.java</code> kompiliert und mit <code>java TestCompilerOutput</code> 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).</p>

View File

@ -0,0 +1,4 @@
package parser;
public class ParserTest {
}