diff --git a/.gitignore b/.gitignore
index 8c5079b..cb648af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,3 +83,4 @@ src/test/resources/output/javac/CompilerInput$Test.class
src/test/resources/output/javac/CompilerInput.class
src/test/resources/output/raupenpiler/CompilerInput.class
src/test/resources/output/raupenpiler/CompilerInput$Test.class
+.idea/inspectionProfiles/Project_Default.xml
diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java
index 69de2bc..7568d24 100644
--- a/src/main/java/main/Main.java
+++ b/src/main/java/main/Main.java
@@ -20,13 +20,11 @@ import java.nio.file.Paths;
*
cd .\src\test\
*
make clean compile-raupenpiler
*
Start Raupenpiler using jar:
- *
java.exe -jar path_to_jar\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory'
+ *
java.exe -jar path_to_jar\JavaCompiler-1.0-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory'
*
Example (jar needs to be in the target directory, compile with make or mvn package first):
- * java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'src/main/resources/input/CompilerInput.java' 'src/main/resources/output'
+ * java.exe -jar .\target\JavaCompiler-1.0-jar-with-dependencies.jar 'src/main/resources/input/CompilerInput.java' 'src/main/resources/output'
*/
public class Main {
-
-
public static void main(String[] args) throws Exception {
if (args.length == 2) {
// args[0] is the input file path
diff --git a/src/main/java/main/RaupenLogger.java b/src/main/java/main/RaupenLogger.java
index 4ea499f..90bc7e2 100644
--- a/src/main/java/main/RaupenLogger.java
+++ b/src/main/java/main/RaupenLogger.java
@@ -16,18 +16,18 @@ import java.util.List;
import java.util.logging.*;
/**
- Beispiel für Logging-Arten:
-
logger.severe("Schwerwiegender Fehler");
-
logger.warning("Warnung");
-
logger.info("Information");
-
logger.config("Konfigurationshinweis");
-
logger.fine("Fein");
-
logger.finer("Feiner");
-
logger.finest("Am feinsten");
-
You may toggle the logging level of the console and file handlers by
- changing the level ALL/OFF/etc. in the constructor.
- consoleHandler.setLevel(Level.OFF);
- fileHandler.setLevel(Level.ALL);
+ * Beispiel für Logging-Arten:
+ *
logger.severe("Schwerwiegender Fehler");
+ *
logger.warning("Warnung");
+ *
logger.info("Information");
+ *
logger.config("Konfigurationshinweis");
+ *
logger.fine("Fein");
+ *
logger.finer("Feiner");
+ *
logger.finest("Am feinsten");
+ *
You may toggle the logging level of the console and file handlers by
+ * changing the level ALL/OFF/etc. in the constructor.
+ * consoleHandler.setLevel(Level.OFF);
+ * fileHandler.setLevel(Level.ALL);
*/
public class RaupenLogger {
@@ -172,9 +172,9 @@ public class RaupenLogger {
}
String indentString = " ".repeat(indent * 2);
logger.info(indentString + abstractSyntaxTree.getClass());
+ //for (ASTNode child : abstractSyntaxTree.getChildren()) {
+ // logAST(child, indent + 1);
+ // }
- // for (ASTNode child : node.) {
- // printAST(child, indent + 1);
- // }
}
}
diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java
index 39dd2f8..b6b40c4 100644
--- a/src/main/java/semantic/Scope.java
+++ b/src/main/java/semantic/Scope.java
@@ -1,7 +1,7 @@
package semantic;
import ast.type.type.*;
-import semantic.exeptions.AlreadyDeclearedException;
+import semantic.exceptions.AlreadyDeclaredException;
import java.util.HashMap;
import java.util.Stack;
@@ -16,7 +16,7 @@ public class Scope {
public void addLocalVar(String name, ITypeNode type) {
if (this.contains(name)) {
- throw new AlreadyDeclearedException("Variable " + name + " already exists in this scope");
+ throw new AlreadyDeclaredException("Variable " + name + " already exists in this scope");
}
localVars.peek().put(name, type);
}
diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java
index 4fc169a..d00b2e3 100644
--- a/src/main/java/semantic/SemanticAnalyzer.java
+++ b/src/main/java/semantic/SemanticAnalyzer.java
@@ -24,7 +24,7 @@ import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
import ast.statements.*;
import ast.type.type.*;
import semantic.context.Context;
-import semantic.exeptions.*;
+import semantic.exceptions.*;
import typechecker.TypeCheckResult;
public class SemanticAnalyzer implements SemanticVisitor {
@@ -116,7 +116,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
if (Objects.equals(otherMethod, methodNode))
break;
if (otherMethod.isSame(methodNode)) {
- errors.add(new AlreadyDeclearedException(
+ errors.add(new AlreadyDeclaredException(
"Method " + methodNode.getIdentifier() + " is already defined in class "
+ currentClass.identifier));
valid = false;
@@ -129,8 +129,8 @@ public class SemanticAnalyzer implements SemanticVisitor {
valid = valid && result.isValid();
try {
currentScope.addLocalVar(parameter.identifier, parameter.type);
- } catch (AlreadyDeclearedException e) {
- errors.add(new AlreadyDeclearedException(parameter.identifier));
+ } catch (AlreadyDeclaredException e) {
+ errors.add(new AlreadyDeclaredException(parameter.identifier));
}
}
@@ -164,7 +164,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(FieldNode toCheck) {
if (currentFields.get(toCheck.identifier) != null) {
- errors.add(new AlreadyDeclearedException("Already declared " + toCheck.identifier));
+ errors.add(new AlreadyDeclaredException("Already declared " + toCheck.identifier));
return new TypeCheckResult(false, null);
} else {
currentFields.put(toCheck.identifier, toCheck.type);
@@ -361,7 +361,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
} else if(currentFields.get(unary.identifier) != null) {
return new TypeCheckResult(valid, currentFields.get(unary.identifier));
} else {
- errors.add(new NotDeclearedException("Var is not Decleared"));
+ errors.add(new NotDeclaredException("Var is not Declared"));
}
return new TypeCheckResult(valid, null);
}
diff --git a/src/main/java/semantic/exceptions/AlreadyDeclaredException.java b/src/main/java/semantic/exceptions/AlreadyDeclaredException.java
new file mode 100644
index 0000000..c59e104
--- /dev/null
+++ b/src/main/java/semantic/exceptions/AlreadyDeclaredException.java
@@ -0,0 +1,9 @@
+package semantic.exceptions;
+
+public class AlreadyDeclaredException extends RuntimeException {
+
+ public AlreadyDeclaredException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/semantic/exeptions/AlreadyDefinedException.java b/src/main/java/semantic/exceptions/AlreadyDefinedException.java
similarity index 83%
rename from src/main/java/semantic/exeptions/AlreadyDefinedException.java
rename to src/main/java/semantic/exceptions/AlreadyDefinedException.java
index 441a5d9..0128bda 100644
--- a/src/main/java/semantic/exeptions/AlreadyDefinedException.java
+++ b/src/main/java/semantic/exceptions/AlreadyDefinedException.java
@@ -1,4 +1,4 @@
-package semantic.exeptions;
+package semantic.exceptions;
public class AlreadyDefinedException extends RuntimeException {
diff --git a/src/main/java/semantic/exeptions/MultipleReturnTypes.java b/src/main/java/semantic/exceptions/MultipleReturnTypes.java
similarity index 83%
rename from src/main/java/semantic/exeptions/MultipleReturnTypes.java
rename to src/main/java/semantic/exceptions/MultipleReturnTypes.java
index 59f92fa..3f74874 100644
--- a/src/main/java/semantic/exeptions/MultipleReturnTypes.java
+++ b/src/main/java/semantic/exceptions/MultipleReturnTypes.java
@@ -1,4 +1,4 @@
-package semantic.exeptions;
+package semantic.exceptions;
public class MultipleReturnTypes extends RuntimeException {
diff --git a/src/main/java/semantic/exceptions/NotDeclaredException.java b/src/main/java/semantic/exceptions/NotDeclaredException.java
new file mode 100644
index 0000000..307a55d
--- /dev/null
+++ b/src/main/java/semantic/exceptions/NotDeclaredException.java
@@ -0,0 +1,9 @@
+package semantic.exceptions;
+
+public class NotDeclaredException extends RuntimeException {
+
+ public NotDeclaredException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/semantic/exeptions/TypeMismatchException.java b/src/main/java/semantic/exceptions/TypeMismatchException.java
similarity index 83%
rename from src/main/java/semantic/exeptions/TypeMismatchException.java
rename to src/main/java/semantic/exceptions/TypeMismatchException.java
index 93fb62b..2a3fe07 100644
--- a/src/main/java/semantic/exeptions/TypeMismatchException.java
+++ b/src/main/java/semantic/exceptions/TypeMismatchException.java
@@ -1,4 +1,4 @@
-package semantic.exeptions;
+package semantic.exceptions;
public class TypeMismatchException extends RuntimeException {
diff --git a/src/main/java/semantic/exceptions/UnknownException.java b/src/main/java/semantic/exceptions/UnknownException.java
new file mode 100644
index 0000000..8869fdc
--- /dev/null
+++ b/src/main/java/semantic/exceptions/UnknownException.java
@@ -0,0 +1,9 @@
+package semantic.exceptions;
+
+public class UnknownException extends RuntimeException {
+
+ public UnknownException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/semantic/exeptions/AlreadyDeclearedException.java b/src/main/java/semantic/exeptions/AlreadyDeclearedException.java
deleted file mode 100644
index d00fd36..0000000
--- a/src/main/java/semantic/exeptions/AlreadyDeclearedException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package semantic.exeptions;
-
-public class AlreadyDeclearedException extends RuntimeException {
-
- public AlreadyDeclearedException(String message) {
- super(message);
- }
-
-}
diff --git a/src/main/java/semantic/exeptions/NotDeclearedException.java b/src/main/java/semantic/exeptions/NotDeclearedException.java
deleted file mode 100644
index aa223a0..0000000
--- a/src/main/java/semantic/exeptions/NotDeclearedException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package semantic.exeptions;
-
-public class NotDeclearedException extends RuntimeException {
-
- public NotDeclearedException(String message) {
- super(message);
- }
-
-}
diff --git a/src/test/Makefile b/src/test/Makefile
index e3e7d75..883b79c 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -10,20 +10,33 @@ compile-javac:
compile-raupenpiler:
cd ../.. ; mvn -DskipTests install
cd ../.. ; mvn exec:java -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' "
+ cp ../main/resources/output/CompilerInput.class .java/resources/output/raupenpiler
-test: test-javac test-raupenpiler
+test: compile-javac compile-raupenpiler test-javac test-raupenpiler
test-javac:
- #compile-javac
- #java -cp .\resources\output\javac CompilerInput
+ # gleich wie bei raupenpiler, kann ich ohne funktionierenden Compiler nicht testen
+
test-raupenpiler:
- #java -cp .\resources\output\raupenpiler CompilerInput
+ # move the compiled class to the test/main folder
+ mv ../main/resources/output/CompilerInput.class .java/main/
+ # compile the test class
+ javac .java/main.EndToEndTester.java
+ # run the test class
+ java .java/main.EndToEndTester
+
+
clean:
+ # clean output folders
+ rm -f ../main/resources/output/*.class
rm -f ./resources/output/javac/*.class
rm -f ./resources/output/raupenpiler/*.class
- rm -f ./java/*.class
- rm -f ../main/resources/output/*.class
+ # clean logs
rm -f ../main/resources/logs/*.log
+ # clean test/main folders from .class files for End-to-End tests
+ rm -f ./java/main/*.class
+ # clean javac output from featureTests
+ rm -f ./resources/input/featureTests/*.class
diff --git a/src/test/TestSpecs.md b/src/test/TestSpecs.md
index 0911765..da23e18 100644
--- a/src/test/TestSpecs.md
+++ b/src/test/TestSpecs.md
@@ -78,8 +78,8 @@ Compiled Classfile
wenn beides erfolgreich
-- Ergebnis vom eigenen Compiler mithilfe von main.TestCompilerOutput ausführen
-- (Ergebnis von javac mithilfe von main.TestCompilerOutput ausführen)
+- Ergebnis vom eigenen Compiler mithilfe von main.EndToEndTester ausführen
+- (Ergebnis von javac mithilfe von main.EndToEndTester ausführen)
### Andis Tipps:
@@ -89,4 +89,5 @@ wenn beides erfolgreich
- mvn package
- javac tester // tester compilen
- java tester // tester ausführen
-- -> tester ist in unserem Fall main.TestCompilerOutput.java
\ No newline at end of file
+- -> tester ist in unserem Fall main.EndToEndTester.java
+- -> Hab ich alles umgesetzt
\ No newline at end of file
diff --git a/src/test/java/main/EmptyClassExample.java b/src/test/java/main/EmptyClassExample.java
deleted file mode 100644
index e7715be..0000000
--- a/src/test/java/main/EmptyClassExample.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package main;
-
-public class EmptyClassExample {
- private class Inner {
- }
-} // -o für outout
\ No newline at end of file
diff --git a/src/test/java/main/TestCompilerOutput.java b/src/test/java/main/EndToEndTester.java
similarity index 82%
rename from src/test/java/main/TestCompilerOutput.java
rename to src/test/java/main/EndToEndTester.java
index 6a30e14..233a9c3 100644
--- a/src/test/java/main/TestCompilerOutput.java
+++ b/src/test/java/main/EndToEndTester.java
@@ -3,18 +3,18 @@ package main;
/**
* This class is used to test the output of the compiler.
*
- *
Im gleichen Ordner wie diese Datei (main.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)
+ * Im gleichen Ordner wie diese Datei (EndToEndTester.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/main) rein kopieren. (bis es eine bessere Lösung gibt -> bin grad in der Make dran das alles hier automatisch zu machen)
*
* Die selbst kompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden.
- *
Diese main.TestCompilerOutput.java Datei wird dann in \src\test\java>
mit javac .\main.TestCompilerOutput.java
kompiliert und mit java main.TestCompilerOutput
ausgeführt.
+ *
Diese EndToEndTester.java Datei wird dann in \src\test\java>
mit javac .\main.EndToEndTester.java
kompiliert und mit java main.EndToEndTester
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).
*
* PROBLEM: Hier kommen Errors, was eigentlich heißt, dass der Compiler nicht funktioniert, der Test sollte eigentlich passen.
*
DENN: Wenn ich statt unserem CompilerInput.class die CompilerInput.class von javac verwende (aus src/test/resources/output/javac
), dann funktioniert es.
*/
-public class TestCompilerOutput {
+public class EndToEndTester {
public static void main(String[] args) {
try {
// Try to load the class named "CompilerInput"
diff --git a/src/test/java/main/FailureTest.java b/src/test/java/main/FailureTest.java
index 5a2e1c8..60c504b 100644
--- a/src/test/java/main/FailureTest.java
+++ b/src/test/java/main/FailureTest.java
@@ -3,71 +3,45 @@ package main;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.CharStreams;
import org.junit.jupiter.api.Test;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
-import java.io.IOException;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.List;
public class FailureTest {
- private static final List TEST_FILES = Arrays.asList(
- "src/main/test/resources/input/failureTests/TestClass1.java",
- "src/main/test/resources/input/failureTests/TestClass2.java",
- "src/main/test/resources/input/failureTests/TestClass3.java",
- "src/main/test/resources/input/failureTests/TestClass4.java",
- "src/main/test/resources/input/failureTests/TestClass5.java",
- "src/main/test/resources/input/failureTests/TestClass6.java",
- "src/main/test/resources/input/failureTests/TestClass7.java",
- "src/main/test/resources/input/failureTests/TestClass8.java",
- "src/main/test/resources/input/failureTests/TestClass9.java",
- "src/main/test/resources/input/failureTests/TestClass10.java",
- "src/main/test/resources/input/failureTests/TestClass11.java"
- );
-
/**
* This test method checks if invalid Java files fail to compile as expected.
* It uses the JavaCompiler from the ToolProvider to compile the files.
* The test passes if all the files fail to compile.
*/
@Test
- public void invalidJavaFilesTest() {
+ public void areTestFilesActuallyFailTest() {
// Get the system Java compiler
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-
+ JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
// Assert that the compiler is available
- assertNotNull(compiler, "Java Compiler is not available");
+ assertNotNull(javac, "Java Compiler is not available");
- // Iterate over the test files
- for (String fileName : TEST_FILES) {
- // Create a File object for the current file
- File file = new File(fileName);
+ String directoryPath = "src/test/resources/input/failureTests";
+ File folder = new File(directoryPath);
- // Try to compile the file and get the result
- // The run method returns 0 if the compilation was successful, and non-zero otherwise
- int result = compiler.run(null, null, null, file.getPath());
+ if (folder.isDirectory()) {
+ File[] files = folder.listFiles((dir, name) -> name.endsWith(".java"));
- // Assert that the compilation failed (i.e., the result is non-zero)
- assertTrue(result != 0, "Expected compilation failure for " + fileName);
- }
- }
+ if (files != null) {
+ for (File file : files) {
+ // Try to compile the file and get the result
+ // The run method returns 0 if the compilation was successful, and non-zero otherwise
+ int result = javac.run(null, null, null, file.getPath());
- // schmeißt John Fehler, wenn namen doppelt sind?
- // Input: ParseTree mit genanntem Fehler
- // Output: Fehlermeldung
- @Test
- void typedASTTest() throws IOException {
- CharStream codeCharStream = null;
- try {
- 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());
+ // Assert that the compilation failed (i.e., the result is non-zero)
+ assertTrue(result != 0, "Expected compilation failure for " + file.getName());
+ }
+ } else {
+ System.out.println("No files found in the directory.");
+ }
+ } else {
+ System.out.println("The provided path is not a directory.");
}
}
}
diff --git a/src/test/java/main/FeatureTest.java b/src/test/java/main/FeatureTest.java
new file mode 100644
index 0000000..a3e30de
--- /dev/null
+++ b/src/test/java/main/FeatureTest.java
@@ -0,0 +1,46 @@
+package main;
+
+import org.junit.jupiter.api.Test;
+
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+import java.io.File;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class FeatureTest {
+ /**
+ * This test method checks if valid Java files compile successfully.
+ * It uses the JavaCompiler from the ToolProvider to compile the files.
+ * The test passes if all the files compile without errors.
+ */
+ @Test
+ public void areTestFilesActuallyValid() {
+ // Get the system Java compiler
+ JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
+ // Assert that the compiler is available
+ assertNotNull(javac, "Java Compiler is not available");
+
+ String directoryPath = "src/test/resources/input/featureTests";
+ File folder = new File(directoryPath);
+
+ if (folder.isDirectory()) {
+ File[] files = folder.listFiles((dir, name) -> name.endsWith(".java"));
+
+ if (files != null) {
+ for (File file : files) {
+ // Try to compile the file and get the result
+ // The run method returns 0 if the compilation was successful, and non-zero otherwise
+ int result = javac.run(null, null, null, file.getPath());
+
+ // Assert that the compilation succeeded (i.e., the result is zero)
+ assertEquals(0, result, "Expected compilation success for " + file.getName());
+ }
+ } else {
+ System.out.println("No files found in the directory.");
+ }
+ } else {
+ System.out.println("The provided path is not a directory.");
+ }
+ }
+}
diff --git a/src/test/java/main/MainTest.java b/src/test/java/main/MainTest.java
index 363fa35..24389bc 100644
--- a/src/test/java/main/MainTest.java
+++ b/src/test/java/main/MainTest.java
@@ -7,14 +7,14 @@ import org.antlr.v4.runtime.CharStreams;
import java.io.IOException;
import java.nio.file.Paths;
-import static org.junit.jupiter.api.Assertions.assertEquals;
/**
- * run: mvn test
+ * run every test: mvn test
+ * Nutzen dieser Klasse: Eigentlich nicht vorhanden, in der Main gibts nichts zu testen
*/
public class MainTest {
@Test
- void testEmptyClass() {
+ void test() {
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.java"));
diff --git a/src/test/java/parser/AstBuilderTest.java b/src/test/java/parser/AstBuilderTest.java
new file mode 100644
index 0000000..b5bec24
--- /dev/null
+++ b/src/test/java/parser/AstBuilderTest.java
@@ -0,0 +1,103 @@
+package parser;
+
+import ast.ClassNode;
+import ast.ProgramNode;
+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 org.junit.jupiter.api.Test;
+import parser.astBuilder.ASTBuilder;
+import parser.generated.SimpleJavaLexer;
+import parser.generated.SimpleJavaParser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AstBuilderTest {
+
+ @Test
+ public void astBuilderTest() {
+ // ---------------- Leere Klasse nachgebaut ----------------
+
+ ProgramNode expectedASTEmptyClass = new ProgramNode();
+
+ // public class Name {}
+ ClassNode nameClass = new ClassNode("public", "Name");
+
+ expectedASTEmptyClass.addClass(nameClass);
+
+
+ // ---------------- Leere Klasse erzeugt ----------------
+
+ // init
+ CharStream inputCharStream = CharStreams.fromString("public class Name {}");
+ SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
+ CommonTokenStream tokenStream = new CommonTokenStream(lexer);
+ tokenStream.fill();
+
+ /* Parser -> Parsetree */
+ SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
+ ParseTree parseTreeEmptyClass = parser.program(); // parse the input
+
+ /* AST builder -> AST */
+ ASTBuilder astBuilder = new ASTBuilder();
+ ProgramNode actualASTEmptyClass = (ProgramNode) new ASTBuilder().visit(parseTreeEmptyClass);
+
+
+ // ---------------- Vergleichen ----------------
+
+ String expectedASTasString = expectedASTEmptyClass.toString();
+ String actualASTasString = new ASTBuilder().visit(parseTreeEmptyClass).toString();
+
+ // Wie vergleiche ich das?
+ assertEquals(expectedASTasString, actualASTasString);
+ assertEquals(expectedASTEmptyClass, actualASTEmptyClass);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // ---------------- Alter CompilerInput nachgebaut ----------------
+ // ProgramNode startNode = new ProgramNode();
+ // public class CompilerInput {}
+ // ClassNode compilerInputClass = new ClassNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), "CompilerInput");
+ // public int a;
+ // compilerInputClass.addMember(new FieldNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), new BaseTypeNode(EnumTypeNode.INT), "a"));
+ // public static int testMethod(char x) { return 0; }
+ /* compilerInputClass.addMember(
+ new MethodNode(
+ new AccessTypeNode(EnumAccessTypeNode.PUBLIC),
+ new BaseTypeNode(EnumTypeNode.INT),
+ "testMethod",
+ new ParameterListNode(List.of(new ParameterNode(new BaseTypeNode(EnumTypeNode.CHAR), "x"))),
+ List.of(new ReturnStatementNode(new LiteralNode(0)))
+ ));
+
+ ClassNode testClass = new ClassNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), "Test");
+ testClass.addMember(
+ new MethodNode(
+ new AccessTypeNode(EnumAccessTypeNode.PUBLIC),
+ new BaseTypeNode(EnumTypeNode.INT),
+ "testMethod",
+ new ParameterListNode(List.of(new ParameterNode(new BaseTypeNode(EnumTypeNode.CHAR), "x"), new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "a"))),
+ List.of(new ReturnStatementNode(new LiteralNode(0)))
+ )
+ );
+
+ */
+
+ //compilerInputClass.addClass(testClass);
+
+ // startNode.addClass(compilerInputClass);
+ // startNode.addClass(testClass);
+}
diff --git a/src/test/java/parser/ParserTest.java b/src/test/java/parser/ParserTest.java
index 4c39828..c567b4b 100644
--- a/src/test/java/parser/ParserTest.java
+++ b/src/test/java/parser/ParserTest.java
@@ -4,7 +4,6 @@ import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import parser.astBuilder.ASTBuilder;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
@@ -13,41 +12,13 @@ import static org.junit.jupiter.api.Assertions.*;
import java.util.*;
public class ParserTest {
+ /*
@BeforeEach
public void init() { // noch nicht benötigt
String inputFilePath = "src/main/resources/input/CompilerInput.java";
String outputDirectoryPath = "src/main/resources/output";
}
-
- /**
- * This test method is used to test the scanner functionality of the SimpleJavaLexer.
- * It creates a CharStream from a string representing a simple Java class declaration,
- * and uses the SimpleJavaLexer to tokenize this input.
- * It then compares the actual tokens and their types produced by the lexer to the expected tokens and their types.
*/
- @Test
- public void scannerTest() {
- // Create a CharStream from a string representing a simple Java class declaration
- CharStream inputCharStream = CharStreams.fromString("public class Name {}");
-
- // Use the SimpleJavaLexer to tokenize the input
- SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
- tokenStream.fill();
-
- // Prepare the expected results
- List actualTokens = tokenStream.getTokens();
- List expectedTokens = Arrays.asList("public", "class", "Name", "{", "}", "");
- List expectedTokenTypes = Arrays.asList(null, null, "IDENTIFIER", null, null, "EOF");
-
- // Compare the actual tokens and their types to the expected tokens and their types
- assertEquals(expectedTokens.size(), actualTokens.size());
- for (int i = 0; i < expectedTokens.size(); i++) {
- assertEquals(expectedTokens.get(i), actualTokens.get(i).getText());
- assertEquals(expectedTokenTypes.get(i), SimpleJavaLexer.VOCABULARY.getSymbolicName(actualTokens.get(i).getType()));
- }
- }
-
@Test
public void parserTest() {
@@ -63,38 +34,20 @@ public class ParserTest {
ParseTree parseTree = parser.program(); // parse the input
//Variante 1 (geht)
+ String expectedParseTreeAsString = "(program (classDeclaration public class Name { }))";
String actualParseTreeAsString = parseTree.toStringTree(parser);
- String expectedParseTreeAsString = "(program (classDeclaration (accessType public) class Name { }))";
- assertEquals(actualParseTreeAsString, expectedParseTreeAsString);
+ assertEquals(expectedParseTreeAsString, actualParseTreeAsString);
- //Variante 2 (geht nicht)
+ // Variante 2 (geht nicht)
// - Sollte es gehen und es liegt am Parser? (keine Ahnung) -> Bitte Fehler (actual und expected) durchlesen
- Map actualTreeStructure = buildTreeStructure(parseTree, parser);
+ // ist die Methode parseStringToTree() korrekt? -> (glaub nicht)
Map expectedTreeStructure = parseStringToTree(expectedParseTreeAsString);
+ Map actualTreeStructure = buildTreeStructure(parseTree, parser);
- assertEquals(actualTreeStructure, expectedTreeStructure);
-
-
+ // assertEquals(expectedTreeStructure, actualTreeStructure);
}
- @Test
- public void astBuilderTest() {
- // TODO: Implement this test method
-
-
-
-
- /* AST builder -> AST */
- ASTBuilder astBuilder = new ASTBuilder();
- // ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- //String actualASTasString = new ASTBuilder().visit(parseTree).toString();
-
- // ProgramNode actualAST = new ASTBuilder().visit(parseTree);
- // ProgramNode expectedAST = new ProgramNode();
- // expectedAST.add(new ProgramNode.ClassNode("Name", new ProgramNode()));
- }
// Helpers Variante 2.1
@@ -146,7 +99,7 @@ public class ParserTest {
for (char ch : input.toCharArray()) {
if (ch == '(') {
if (depth == 0) {
- if (currentToken.length() > 0) {
+ if (!currentToken.isEmpty()) {
node.put("node", currentToken.toString().trim());
currentToken.setLength(0);
}
@@ -163,7 +116,7 @@ public class ParserTest {
currentToken.append(ch);
}
} else if (Character.isWhitespace(ch) && depth == 0) {
- if (currentToken.length() > 0) {
+ if (!currentToken.isEmpty()) {
node.put("node", currentToken.toString().trim());
currentToken.setLength(0);
}
@@ -172,7 +125,7 @@ public class ParserTest {
}
}
- if (currentToken.length() > 0) {
+ if (!currentToken.isEmpty()) {
node.put("node", currentToken.toString().trim());
}
diff --git a/src/test/java/parser/ScannerTest.java b/src/test/java/parser/ScannerTest.java
new file mode 100644
index 0000000..ba31a81
--- /dev/null
+++ b/src/test/java/parser/ScannerTest.java
@@ -0,0 +1,45 @@
+package parser;
+
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.Token;
+import org.junit.jupiter.api.Test;
+import parser.generated.SimpleJavaLexer;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ScannerTest {
+
+ /**
+ * This test method is used to test the scanner functionality of the SimpleJavaLexer.
+ * It creates a CharStream from a string representing a simple Java class declaration,
+ * and uses the SimpleJavaLexer to tokenize this input.
+ * It then compares the actual tokens and their types produced by the lexer to the expected tokens and their types.
+ */
+ @Test
+ public void scannerTest() {
+ // Create a CharStream from a string representing a simple Java class declaration
+ CharStream inputCharStream = CharStreams.fromString("public class Name {}");
+
+ // Use the SimpleJavaLexer to tokenize the input
+ SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
+ CommonTokenStream tokenStream = new CommonTokenStream(lexer);
+ tokenStream.fill();
+
+ // Prepare the expected results
+ List expectedTokens = Arrays.asList("public", "class", "Name", "{", "}", "");
+ List expectedTokenTypes = Arrays.asList("AccessModifier", "Class", "Identifier", "OpenCurlyBracket", "ClosedCurlyBracket", "EOF");
+ List actualTokens = tokenStream.getTokens();
+
+ // Compare the actual tokens and their types to the expected tokens and their types
+ assertEquals(expectedTokens.size(), actualTokens.size());
+ for (int i = 0; i < expectedTokens.size(); i++) {
+ assertEquals(expectedTokens.get(i), actualTokens.get(i).getText());
+ assertEquals(expectedTokenTypes.get(i), SimpleJavaLexer.VOCABULARY.getSymbolicName(actualTokens.get(i).getType()));
+ }
+ }
+}
diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java
deleted file mode 100644
index 3189802..0000000
--- a/src/test/java/semantic/EndToTAST.java
+++ /dev/null
@@ -1,282 +0,0 @@
-package semantic;
-
-import ast.ASTNode;
-import ast.ProgramNode;
-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 org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import parser.astBuilder.ASTBuilder;
-import parser.generated.SimpleJavaLexer;
-import parser.generated.SimpleJavaParser;
-import semantic.exeptions.AlreadyDeclearedException;
-import semantic.exeptions.MultipleReturnTypes;
-import semantic.exeptions.NotDeclearedException;
-import semantic.exeptions.TypeMismatchException;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-public class EndToTAST {
-
- @BeforeEach
- public void setup(){
- SemanticAnalyzer.clearAnalyzer();
- }
-
- @Test
- public void CorrectTest(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectTest.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program(); // parse the input
-
- /* ------------------------- AST builder -> AST ------------------------- */
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
-
- assertEquals(SemanticAnalyzer.errors.size(), 0);
- assertNotNull(tast);
-
- }
-
- @Test
- public void notDecleared() {
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/NotDecleared.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program(); // parse the input
-
- /* ------------------------- AST builder -> AST ------------------------- */
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(NotDeclearedException.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void typeMismatch(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void parameterAlreadyDecleared(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void fieldAlreadyDecleared(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void typeMismatchRefType(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchRefType.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void correctRetType(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectRetType.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertTrue(SemanticAnalyzer.errors.isEmpty());
-
- }
-
- @Test
- public void retTypeMismatch(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/retTypeMismatch.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void multipleRetType(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/MultipleRetTypes.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
- assertInstanceOf(MultipleReturnTypes.class, SemanticAnalyzer.errors.getFirst());
-
- }
-
- @Test
- public void wrongTypeInIfClause(){
-
- CharStream codeCharStream = null;
- try {
- codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/WrongIfClause.java"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
- CommonTokenStream tokenStream = new CommonTokenStream(lexer);
-
- SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
- ParseTree parseTree = parser.program();
-
- ASTBuilder astBuilder = new ASTBuilder();
- ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
-
- ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
-
- assertFalse(SemanticAnalyzer.errors.isEmpty());
-
- }
-
-}
diff --git a/src/test/java/semantic/EndToTypedAstTest.java b/src/test/java/semantic/EndToTypedAstTest.java
new file mode 100644
index 0000000..9bf5485
--- /dev/null
+++ b/src/test/java/semantic/EndToTypedAstTest.java
@@ -0,0 +1,218 @@
+package semantic;
+
+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 ast.ASTNode;
+import ast.ProgramNode;
+
+import parser.astBuilder.ASTBuilder;
+import parser.generated.SimpleJavaLexer;
+import parser.generated.SimpleJavaParser;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class EndToTypedAstTest {
+ private static final Map> exceptionMap = new HashMap<>();
+
+ @Test
+ public void exceptionsTest() {
+ String directoryPath = "src/test/resources/input/typedAstExceptionsTests";
+ File folder = new File(directoryPath);
+
+ try {
+ loadCustomExceptions();
+ System.out.println("Custom exceptions loaded successfully.");
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to load custom exceptions", e);
+
+ }
+
+ if (folder.isDirectory()) {
+ File[] files = folder.listFiles((_, name) -> name.endsWith(".java"));
+ if (files != null) {
+ for (File file : files) {
+ String expectedException = extractExpectedException(file);
+
+ SemanticAnalyzer.clearAnalyzer();
+ CharStream codeCharStream;
+ try {
+ codeCharStream = CharStreams.fromPath(Paths.get(file.getPath()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
+ CommonTokenStream tokenStream = new CommonTokenStream(lexer);
+
+ SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
+ ParseTree parseTree = parser.program();
+
+ ASTBuilder astBuilder = new ASTBuilder();
+ ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
+
+ ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
+
+ if (expectedException != null) {
+ System.out.println("Testing the file: " + file.getName());
+ assertFalse(SemanticAnalyzer.errors.isEmpty(), "Expected an exception, but none was found.");
+ assertInstanceOf(getExceptionClass(expectedException), SemanticAnalyzer.errors.getFirst());
+ } else {
+ System.out.println("No expected exception specified.");
+ // If no expected exception is specified, you might want to add a different check
+ // e.g., assertTrue(SemanticAnalyzer.errors.isEmpty(), "No exceptions expected, but some were found.");
+ }
+ }
+ } else {
+ System.out.println("No files found in the directory.");
+ }
+ } else {
+ System.out.println("The provided path is not a directory.");
+ }
+ }
+
+ @Test
+ public void featureTest(){
+ String directoryPath = "src/test/resources/input/typedAstFeaturesTests";
+ File folder = new File(directoryPath);
+ if (folder.isDirectory()) {
+ File[] files = folder.listFiles((_, name) -> name.endsWith(".java"));
+ if (files != null) {
+ for (File file : files) {
+ SemanticAnalyzer.clearAnalyzer();
+ CharStream codeCharStream;
+ try {
+ codeCharStream = CharStreams.fromPath(Paths.get(file.getPath()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
+ CommonTokenStream tokenStream = new CommonTokenStream(lexer);
+
+ SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
+ ParseTree parseTree = parser.program();
+
+ ASTBuilder astBuilder = new ASTBuilder();
+ ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
+
+ ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
+
+ System.out.println("Testing the file: " + file.getName());
+ assertTrue(SemanticAnalyzer.errors.isEmpty());
+ assertNotNull(typedAst);
+ }
+ } else {
+ System.out.println("No files found in the directory.");
+ }
+ } else {
+ System.out.println("The provided path is not a directory.");
+ }
+ }
+
+
+
+
+ // ------------------ Helpers ------------------
+ /**
+ * This method is used to extract the expected exception from a given file.
+ * It reads the file line by line and uses a regular expression to match the expected exception annotation.
+ * The expected exception annotation should be in the format: "// @expected: ExceptionName".
+ * If the expected exception annotation is found, it returns the name of the expected exception.
+ * If the expected exception annotation is not found, it returns null.
+ *
+ * @param file The file from which the expected exception is to be extracted.
+ * @return The name of the expected exception, or null if the expected exception annotation is not found.
+ */
+ private String extractExpectedException(File file) {
+ String annotationPattern = "//\\s*@expected:\\s*(\\S+)";
+ Pattern pattern = Pattern.compile(annotationPattern);
+ try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.find()) {
+ return matcher.group(1);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * This method is used to retrieve the Class object associated with a given exception name.
+ * It first prints the original exception name, then appends the package name to the exception name and prints it.
+ * It then retrieves the Class object from the exceptionMap using the fully qualified exception name.
+ * If the Class object is not found in the exceptionMap, it throws a RuntimeException.
+ *
+ * @param exceptionName The name of the exception for which the Class object is to be retrieved.
+ * @return The Class object associated with the given exception name.
+ * @throws RuntimeException If the Class object for the given exception name is not found in the exceptionMap.
+ */
+private Class> getExceptionClass(String exceptionName) {
+ System.out.println(exceptionName);
+ exceptionName = "semantic.exceptions." + exceptionName;
+ System.out.println(exceptionName);
+ Class> exceptionClass = exceptionMap.get(exceptionName);
+ if (exceptionClass == null) {
+ throw new RuntimeException("Exception class not found: " + exceptionName);
+ }
+ return exceptionClass;
+}
+
+ /**
+ * This method is used to load custom exceptions from a specified package.
+ * It first constructs the directory path from the package name and checks if the directory exists.
+ * If the directory does not exist, it throws an IllegalArgumentException.
+ * It then creates a URLClassLoader to load the classes from the directory.
+ * It iterates over all the files in the directory, and for each file, it constructs the class name and loads the class.
+ * If the loaded class is a subtype of Throwable, it adds the class to the exceptionMap.
+ *
+ * @throws Exception If any error occurs during class loading.
+ */
+ private static void loadCustomExceptions() throws Exception {
+ final String packName = "semantic.exceptions";
+ final String dirForMyClasses = "src/main/java/%s".formatted(packName.replace(".", "/"));
+ File folder = new File(dirForMyClasses);
+ if (!folder.isDirectory()) {
+ throw new IllegalArgumentException("The provided path is not a directory.");
+ }
+
+ URL[] urls = {folder.toURI().toURL()};
+ URLClassLoader classLoader;
+ try {
+ classLoader = new URLClassLoader(urls);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create class loader", e);
+ }
+
+ for (File file : Objects.requireNonNull(folder.listFiles())) {
+ String className = packName + "." + file.getName().replaceAll("\\.(?:class|java)$", "");
+ System.out.printf("Loading custom exception: %s (=> %s)", file.getName(), className);
+ Class> cls = classLoader.loadClass(className);
+
+ if (Throwable.class.isAssignableFrom(cls)) { // Check if the class is a subtype of Throwable
+ exceptionMap.put(className, cls);
+ System.out.println("Loaded custom exception: " + className);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java
index 7b8ad6a..a4039ac 100644
--- a/src/test/java/semantic/SemanticTest.java
+++ b/src/test/java/semantic/SemanticTest.java
@@ -1,18 +1,5 @@
package semantic;
-import ast.*;
-import ast.members.FieldNode;
-import ast.members.MemberNode;
-import ast.members.MethodNode;
-import ast.parameters.ParameterNode;
-
-import org.junit.jupiter.api.Test;
-import semantic.exeptions.AlreadyDeclearedException;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
public class SemanticTest {
@@ -35,7 +22,7 @@ public class SemanticTest {
// ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//
// assertEquals(1, SemanticAnalyzer.errors.size());
-// assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
+// assertInstanceOf(AlreadyDeclaredException.class, SemanticAnalyzer.errors.getFirst());
// assertNull(typedAst);
// }
//
diff --git a/src/test/resources/input/AllFeaturesClassExample.java b/src/test/resources/input/AllFeaturesClassExample.java
index 69ab631..1a8493d 100644
--- a/src/test/resources/input/AllFeaturesClassExample.java
+++ b/src/test/resources/input/AllFeaturesClassExample.java
@@ -1,5 +1,3 @@
-package resources;
-
public class AllFeaturesClassExample {
int a;
boolean b;
diff --git a/src/test/resources/input/CombinedExample.java b/src/test/resources/input/CombinedExample.java
index e3dae84..e7e000c 100644
--- a/src/test/resources/input/CombinedExample.java
+++ b/src/test/resources/input/CombinedExample.java
@@ -1,5 +1,3 @@
-package resources;
-
public class CombinedExample {
int number;
boolean flag;
diff --git a/src/test/resources/input/MoreFeaturesClassExample.java b/src/test/resources/input/MoreFeaturesClassExample.java
index c58b5a2..4f6fbf3 100644
--- a/src/test/resources/input/MoreFeaturesClassExample.java
+++ b/src/test/resources/input/MoreFeaturesClassExample.java
@@ -1,5 +1,3 @@
-package resources;
-
public class MoreFeaturesClassExample {
int hallo;
private class Inner {
diff --git a/src/test/resources/input/featureTests/BooleanOperations.java b/src/test/resources/input/featureTests/BooleanOperations.java
index 17d4a15..5a1af93 100644
--- a/src/test/resources/input/featureTests/BooleanOperations.java
+++ b/src/test/resources/input/featureTests/BooleanOperations.java
@@ -1,5 +1,3 @@
-package resources.featureTests;
-
public class BooleanOperations {
boolean flag;
diff --git a/src/test/resources/input/featureTests/CharManipulation.java b/src/test/resources/input/featureTests/CharManipulation.java
index 7b70ad2..c46c169 100644
--- a/src/test/resources/input/featureTests/CharManipulation.java
+++ b/src/test/resources/input/featureTests/CharManipulation.java
@@ -1,5 +1,3 @@
-package resources.featureTests;
-
public class CharManipulation {
char letter;
diff --git a/src/test/resources/input/featureTests/ConditionalStatements.java b/src/test/resources/input/featureTests/ConditionalStatements.java
index 8b26079..73cabda 100644
--- a/src/test/resources/input/featureTests/ConditionalStatements.java
+++ b/src/test/resources/input/featureTests/ConditionalStatements.java
@@ -1,5 +1,3 @@
-package resources.featureTests;
-
public class ConditionalStatements {
int number;
diff --git a/src/test/resources/input/featureTests/EmptyClassExample.java b/src/test/resources/input/featureTests/EmptyClassExample.java
new file mode 100644
index 0000000..f30a941
--- /dev/null
+++ b/src/test/resources/input/featureTests/EmptyClassExample.java
@@ -0,0 +1,2 @@
+public class EmptyClassExample {
+}
\ No newline at end of file
diff --git a/src/test/resources/input/featureTests/LoopExamples.java b/src/test/resources/input/featureTests/LoopExamples.java
index 2eb2927..ce323a5 100644
--- a/src/test/resources/input/featureTests/LoopExamples.java
+++ b/src/test/resources/input/featureTests/LoopExamples.java
@@ -1,5 +1,3 @@
-package resources.featureTests;
-
public class LoopExamples {
public static void main(String[] args) {
// For loop example
diff --git a/src/test/resources/input/featureTests/MethodOverloading.java b/src/test/resources/input/featureTests/MethodOverloading.java
index 3ca1d13..16c9f09 100644
--- a/src/test/resources/input/featureTests/MethodOverloading.java
+++ b/src/test/resources/input/featureTests/MethodOverloading.java
@@ -1,5 +1,3 @@
-package resources.featureTests;
-
public class MethodOverloading {
public int add(int a, int b) {
return a + b;
diff --git a/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java b/src/test/resources/input/typedAstExceptionsTests/FieldAlreadyDeclared.java
similarity index 73%
rename from src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java
rename to src/test/resources/input/typedAstExceptionsTests/FieldAlreadyDeclared.java
index 535a592..9b268e4 100644
--- a/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java
+++ b/src/test/resources/input/typedAstExceptionsTests/FieldAlreadyDeclared.java
@@ -1,3 +1,4 @@
+// @expected: AlreadyDeclaredException
public class Example {
public int a;
diff --git a/src/test/resources/semantic/endToTAST/MultipleRetTypes.java b/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java
similarity index 77%
rename from src/test/resources/semantic/endToTAST/MultipleRetTypes.java
rename to src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java
index a5680ed..f368e60 100644
--- a/src/test/resources/semantic/endToTAST/MultipleRetTypes.java
+++ b/src/test/resources/input/typedAstExceptionsTests/MultipleReturnTypes.java
@@ -1,3 +1,4 @@
+// @expected: MultipleReturnTypes
public class Example {
public static int testMethod(int x, char c){
diff --git a/src/test/resources/semantic/endToTAST/NotDecleared.java b/src/test/resources/input/typedAstExceptionsTests/NotDeclared.java
similarity index 74%
rename from src/test/resources/semantic/endToTAST/NotDecleared.java
rename to src/test/resources/input/typedAstExceptionsTests/NotDeclared.java
index 4aba5f8..948fe91 100644
--- a/src/test/resources/semantic/endToTAST/NotDecleared.java
+++ b/src/test/resources/input/typedAstExceptionsTests/NotDeclared.java
@@ -1,3 +1,4 @@
+// @expected: NotDeclaredException
public class Test {
public static int testMethod(int x){
int a = b;
diff --git a/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java b/src/test/resources/input/typedAstExceptionsTests/ParameterAlreadyDeclared.java
similarity index 66%
rename from src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java
rename to src/test/resources/input/typedAstExceptionsTests/ParameterAlreadyDeclared.java
index d2b3425..25854c1 100644
--- a/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java
+++ b/src/test/resources/input/typedAstExceptionsTests/ParameterAlreadyDeclared.java
@@ -1,3 +1,4 @@
+// @expected: AlreadyDeclaredException
public class Example {
public static int testMethod(char a, int a){
diff --git a/src/test/resources/semantic/endToTAST/retTypeMismatch.java b/src/test/resources/input/typedAstExceptionsTests/ReturnTypeMismatch.java
similarity index 72%
rename from src/test/resources/semantic/endToTAST/retTypeMismatch.java
rename to src/test/resources/input/typedAstExceptionsTests/ReturnTypeMismatch.java
index d3a2674..6a7f3cc 100644
--- a/src/test/resources/semantic/endToTAST/retTypeMismatch.java
+++ b/src/test/resources/input/typedAstExceptionsTests/ReturnTypeMismatch.java
@@ -1,3 +1,4 @@
+// @expected: TypeMismatchException
public class Example {
public static int testMethod(char x){
diff --git a/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchIntBool.java
similarity index 74%
rename from src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java
rename to src/test/resources/input/typedAstExceptionsTests/TypeMismatchIntBool.java
index 9b609b6..ec304a2 100644
--- a/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java
+++ b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchIntBool.java
@@ -1,3 +1,4 @@
+// @expected: TypeMismatchException
public class Test {
public boolean b;
diff --git a/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchRefType.java
similarity index 85%
rename from src/test/resources/semantic/endToTAST/TypeMismatchRefType.java
rename to src/test/resources/input/typedAstExceptionsTests/TypeMismatchRefType.java
index a7b8cc9..870b222 100644
--- a/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java
+++ b/src/test/resources/input/typedAstExceptionsTests/TypeMismatchRefType.java
@@ -1,3 +1,4 @@
+// @expected: TypeMismatchException
public class Test {
public static int testMethod(ExampleA exampleA, ExampleB exampleB){
diff --git a/src/test/resources/semantic/endToTAST/WrongIfClause.java b/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java
similarity index 67%
rename from src/test/resources/semantic/endToTAST/WrongIfClause.java
rename to src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java
index f73f052..e1b7c27 100644
--- a/src/test/resources/semantic/endToTAST/WrongIfClause.java
+++ b/src/test/resources/input/typedAstExceptionsTests/WrongIfClause.java
@@ -1,3 +1,4 @@
+// @expected: TypeMismatchException
public class Example {
public static void testMethod(int x){
diff --git a/src/test/resources/semantic/endToTAST/CorrectRetType.java b/src/test/resources/input/typedAstFeaturesTests/CorrectReturnType.java
similarity index 100%
rename from src/test/resources/semantic/endToTAST/CorrectRetType.java
rename to src/test/resources/input/typedAstFeaturesTests/CorrectReturnType.java
diff --git a/src/test/resources/semantic/endToTAST/CorrectTest.java b/src/test/resources/input/typedAstFeaturesTests/CorrectTest.java
similarity index 100%
rename from src/test/resources/semantic/endToTAST/CorrectTest.java
rename to src/test/resources/input/typedAstFeaturesTests/CorrectTest.java
diff --git a/src/test/resources/semantic/correctRefType.json b/src/test/resources/trees/correctRefType.json
similarity index 100%
rename from src/test/resources/semantic/correctRefType.json
rename to src/test/resources/trees/correctRefType.json
diff --git a/src/test/resources/semantic/refTypeMismatch.json b/src/test/resources/trees/refTypeMismatch.json
similarity index 100%
rename from src/test/resources/semantic/refTypeMismatch.json
rename to src/test/resources/trees/refTypeMismatch.json
diff --git a/src/test/resources/semantic/test.json b/src/test/resources/trees/test.json
similarity index 100%
rename from src/test/resources/semantic/test.json
rename to src/test/resources/trees/test.json