Running now possible with make or java.exe -jar in console
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Lucas 2024-06-19 16:32:46 +02:00
parent 8f742191bb
commit cfcb61d49e
11 changed files with 151 additions and 111 deletions

4
.gitignore vendored
View File

@ -76,4 +76,6 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
/target
/target
src/main/resources/logs/RaupenLog.log
src/main/resources/output/CompilerInput.class

22
pom.xml
View File

@ -45,6 +45,28 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version> <!-- Change the version as needed -->
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>main.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -1,102 +0,0 @@
import ast.ASTNode;
import ast.ProgramNode;
import parser.ASTBuilder;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
import semantic.SemanticAnalyzer;
import bytecode.ByteCodeGenerator;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import java.io.IOException;
import java.nio.file.Paths;
/**
* 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) {
// 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 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());
}
}
*/
}
/**
* This method is used to compile a file from a given CharStream and output the bytecode to a specified directory.
* It goes through the following steps:
* <p>1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream.
* <p>2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree.
* <p>3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST).
* <p>4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST.
* <p>5. Bytecode Generator: It uses the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory.
*
* @param inputCharStream The CharStream representing the input file to be compiled.
* @param outputDirectoryPath The path of the directory where the output bytecode should be written.
*/
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
// Initialize the logger
new RaupenLogger();
/* ------------------------- Scanner -> tokens ------------------------- */
// Use the SimpleJavaLexer to tokenize the input CharStream
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
tokenStream.fill();
// Log the tokens
RaupenLogger.logScanner(tokenStream);
/*------------------------- Parser -> Parsetree -------------------------*/
// Use the SimpleJavaParser to parse the tokens and generate a ParseTree
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program(); // parse the input
// Log the ParseTree
RaupenLogger.logParser(parseTree, parser);
/*------------------------- AST builder -> AST -------------------------*/
// Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST)
ASTBuilder astBuilder = new ASTBuilder();
ASTNode abstractSyntaxTree = astBuilder.visit(parseTree);
// Log the AST
RaupenLogger.logAST(abstractSyntaxTree);
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
// Use the SemanticAnalyzer to generate a typed AST
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
// Log the typed AST
RaupenLogger.logSemanticAnalyzer(typedAst);
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
// Use the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath);
assert typedAst != null;
byteCodeGenerator.visit((ProgramNode) typedAst);
// Log the bytecode generation
RaupenLogger.logBytecodeGenerator();
}
}

View File

@ -0,0 +1,108 @@
package main;
import ast.ASTNode;
import ast.ProgramNode;
import parser.ASTBuilder;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
import semantic.SemanticAnalyzer;
import bytecode.ByteCodeGenerator;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import java.io.IOException;
import java.nio.file.Paths;
/**
* Start Raupenpiler using make:
* <p> <code> cd .\src\test\ </code>
* <p> <code> make clean compile-raupenpiler </code>
* <p> Start Raupenpiler using jar:
* <p> <code> java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory' </code>
* <p> Example:
* <code> java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' </code>
*/
public class Main {
public static void main(String[] args) throws Exception {
if (args.length > 0) {
// 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 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, immer mit args 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());
}
}
*/
}
/**
* This method is used to compile a file from a given CharStream and output the bytecode to a specified directory.
* It goes through the following steps:
* <p>1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream.
* <p>2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree.
* <p>3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST).
* <p>4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST.
* <p>5. Bytecode Generator: It uses the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory.
*
* @param inputCharStream The CharStream representing the input file to be compiled.
* @param outputDirectoryPath The path of the directory where the output bytecode should be written.
*/
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
// Initialize the logger
new RaupenLogger();
/* ------------------------- Scanner -> tokens ------------------------- */
// Use the SimpleJavaLexer to tokenize the input CharStream
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
tokenStream.fill();
// Log the tokens
RaupenLogger.logScanner(tokenStream);
/*------------------------- Parser -> Parsetree -------------------------*/
// Use the SimpleJavaParser to parse the tokens and generate a ParseTree
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program(); // parse the input
// Log the ParseTree
RaupenLogger.logParser(parseTree, parser);
/*------------------------- AST builder -> AST -------------------------*/
// Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST)
ASTBuilder astBuilder = new ASTBuilder();
ASTNode abstractSyntaxTree = astBuilder.visit(parseTree);
// Log the AST
RaupenLogger.logAST(abstractSyntaxTree);
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
// Use the SemanticAnalyzer to generate a typed AST
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
// Log the typed AST
RaupenLogger.logSemanticAnalyzer(typedAst);
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
// Use the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath);
assert typedAst != null;
byteCodeGenerator.visit((ProgramNode) typedAst);
// Log the bytecode generation
RaupenLogger.logBytecodeGenerator();
}
}

View File

@ -1,3 +1,5 @@
package main;
import ast.ASTNode;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Parser;

View File

@ -8,8 +8,8 @@ compile-javac:
javac -d .\resources\output\javac .\resources\input\CompilerInput.java
compile-raupenpiler:
cd ../.. ; mvn -DskipTests package
cd ../.. ; mvn exec:java -Dexec.mainClass="Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' "
cd ../.. ; mvn -DskipTests install
cd ../.. ; mvn exec:java -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' "
test: test-javac test-raupenpiler

View File

@ -78,8 +78,8 @@ Compiled Classfile
wenn beides erfolgreich
- Ergebnis vom eigenen Compiler mithilfe von TestCompilerOutput ausführen
- (Ergebnis von javac mithilfe von TestCompilerOutput ausführen)
- Ergebnis vom eigenen Compiler mithilfe von main.TestCompilerOutput ausführen
- (Ergebnis von javac mithilfe von main.TestCompilerOutput ausführen)
### Andis Tipps:
@ -89,4 +89,4 @@ wenn beides erfolgreich
- mvn package
- javac tester // tester compilen
- java tester // tester ausführen
- -> tester ist in unserem Fall TestCompilerOutput.java
- -> tester ist in unserem Fall main.TestCompilerOutput.java

View File

@ -1,3 +1,5 @@
package main;
public class EmptyClassExample {
private class Inner {
}

View File

@ -1,3 +1,5 @@
package main;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -62,7 +64,7 @@ public class FailureTest {
void typedASTTest() throws IOException {
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java"));
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/main/EmptyClassExample.java"));
Main.compileFile(codeCharStream, "src/main/test/resources/output");
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());

View File

@ -1,3 +1,5 @@
package main;
import org.junit.jupiter.api.Test;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;

View File

@ -1,11 +1,13 @@
package main;
/**
* This class is used to test the output of the compiler.
*
* <p>Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbst kompilierte CompilerInput.class Datei sein.
* <p>Im gleichen Ordner wie diese Datei (main.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 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.
* <p>Diese main.TestCompilerOutput.java Datei wird dann in <code> \src\test\java> </code> mit <code>javac .\main.TestCompilerOutput.java</code> kompiliert und mit <code>java main.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>
*