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
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
This commit is contained in:
parent
8f742191bb
commit
cfcb61d49e
4
.gitignore
vendored
4
.gitignore
vendored
@ -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
22
pom.xml
@ -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>
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
108
src/main/java/main/Main.java
Normal file
108
src/main/java/main/Main.java
Normal 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();
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
package main;
|
||||
|
||||
import ast.ASTNode;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.Parser;
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -1,3 +1,5 @@
|
||||
package main;
|
||||
|
||||
public class EmptyClassExample {
|
||||
private class Inner {
|
||||
}
|
@ -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());
|
@ -1,3 +1,5 @@
|
||||
package main;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
@ -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>
|
||||
*
|
Loading…
Reference in New Issue
Block a user