From 5a28d88f6a8beb4846833eb4260c087bf6dd876e Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Fri, 31 May 2024 09:58:07 +0200 Subject: [PATCH 01/25] comments --- src/main/java/Main.java | 15 +++++---------- src/main/test/java/EmptyClassExample.class | Bin 92 -> 0 bytes src/main/test/java/Tester.java | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) delete mode 100644 src/main/test/java/EmptyClassExample.class diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 24f129b..d865749 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -29,7 +29,7 @@ public class Main { static void parsefile(CharStream codeCharStream) { - /* ------------------------- Scanner -> tokens ------------------------- */ + /*------------------------- Scanner -> tokens -------------------------*/ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); @@ -46,7 +46,7 @@ public class Main { } System.out.println(); - /* ------------------------- Parser -> Parsetree ------------------------- */ + /*------------------------- Parser -> Parsetree -------------------------*/ SimpleJavaParser parser = new SimpleJavaParser(tokenStream); ParseTree parseTree = parser.program(); // parse the input @@ -56,7 +56,7 @@ public class Main { printTree(parseTree, parser, 0); System.out.println(); - /* ------------------------- AST builder -> AST ------------------------- */ + /*------------------------- AST builder -> AST -------------------------*/ ASTBuilder astBuilder = new ASTBuilder(); ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); @@ -66,19 +66,14 @@ public class Main { printAST(abstractSyntaxTree, 0); System.out.println(); - /* - * ------------------------- Semantic Analyzer -> Tast ------------------------- - */ + /*------------------------- Semantic Analyzer -> Tast -------------------------*/ SemanticAnalyzer.generateTast(abstractSyntaxTree); ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); // Printing the Tast System.out.println("Tast generated"); - /* - * ------------------------- Bytecode Generator -> Bytecode - * ------------------------- - */ + /*------------------------- Bytecode Generator -> Bytecode -------------------------*/ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); //byteCodeGenerator.generateByteCode(abstractSyntaxTree); byteCodeGenerator.visit(typedAst); diff --git a/src/main/test/java/EmptyClassExample.class b/src/main/test/java/EmptyClassExample.class deleted file mode 100644 index 7a73bad66b1cc2283850e64b17c439c901c27cc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92 zcmX^0Z`VEs1_l!bc18w4*W7}VO6Q!!;$qi|#N2|MRCWeNMh1bb#Ii*FoW#6zegCAa r)Z`L&24+SEHk-`6%o00B24)S-Fa|~jCI%LuISfD+BLgb~8;A)2qAL?` diff --git a/src/main/test/java/Tester.java b/src/main/test/java/Tester.java index 777c50b..498db7e 100644 --- a/src/main/test/java/Tester.java +++ b/src/main/test/java/Tester.java @@ -5,7 +5,7 @@ public class Tester { } } // java -jar pfadtocompiler.jar EmptyClass.java -//mit bash scipt ode rmakefile test automatisieren -//mvn package +// mit bash scipt ode rmakefile test automatisieren +// mvn package // javac tester // tester compilen // java tester // tester ausführen \ No newline at end of file From a0e55d7b27bac1002fd030f6b071faa5326e80bb Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Fri, 31 May 2024 10:00:46 +0200 Subject: [PATCH 02/25] first testrun of the day --- src/main/test/java/MainTest.java | 2 +- src/main/test/resources/CompilerInput.txt | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/main/test/resources/CompilerInput.txt diff --git a/src/main/test/java/MainTest.java b/src/main/test/java/MainTest.java index f9e848e..516ab6e 100644 --- a/src/main/test/java/MainTest.java +++ b/src/main/test/java/MainTest.java @@ -21,7 +21,7 @@ public class MainTest { void testEmptyClass() { CharStream codeCharStream = null; try { - codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); + codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.txt")); Main.parsefile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); diff --git a/src/main/test/resources/CompilerInput.txt b/src/main/test/resources/CompilerInput.txt new file mode 100644 index 0000000..918c686 --- /dev/null +++ b/src/main/test/resources/CompilerInput.txt @@ -0,0 +1,13 @@ +public class Example { + + public int testVar; + + public static int testMethod(char b){ + + int a; + int a; + + + } + +} \ No newline at end of file From 2a20a91d35e1fe856c13eb406c37dcb2bb573a1b Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Fri, 31 May 2024 10:55:41 +0200 Subject: [PATCH 03/25] Refactor structure and more --- src/main/java/Main.java | 54 +++++++++--------- src/main/java/classFileOutput/Example.class | Bin 167 -> 0 bytes src/main/java/classFileOutput/Test.class | Bin 97 -> 0 bytes src/main/test/java/Tester.java | 11 ---- .../test/java/EmptyClassExample.java | 0 src/{main => test/java}/test/TestSpecs.md | 0 .../java}/test/java/FailureTest.java | 0 .../java}/test/java/MainTest.java | 4 +- src/test/java/test/java/Tester.java | 19 ++++++ src/{main => test/java}/test/java/make.md | 0 .../java}/semantic/SemanticTest.java | 0 .../resources/AllFeaturesClassExample.java | 0 .../test/resources/CombinedExample.java | 0 .../resources/CompilerInput.java} | 0 .../resources/MoreFeaturesClassExample.java | 0 .../resources/failureTests/TestClass1.java | 0 .../resources/failureTests/TestClass10.java | 0 .../resources/failureTests/TestClass11.java | 0 .../resources/failureTests/TestClass2.java | 0 .../resources/failureTests/TestClass3.java | 0 .../resources/failureTests/TestClass4.java | 0 .../resources/failureTests/TestClass5.java | 0 .../resources/failureTests/TestClass6.java | 0 .../resources/failureTests/TestClass7.java | 0 .../resources/failureTests/TestClass8.java | 0 .../resources/failureTests/TestClass9.java | 0 .../featureTests/BooleanOperations.java | 0 .../featureTests/CharManipulation.java | 0 .../featureTests/ConditionalStatements.java | 0 .../resources/featureTests/LoopExamples.java | 0 .../featureTests/MethodOverloading.java | 0 31 files changed, 47 insertions(+), 41 deletions(-) delete mode 100644 src/main/java/classFileOutput/Example.class delete mode 100644 src/main/java/classFileOutput/Test.class delete mode 100644 src/main/test/java/Tester.java rename src/{main => }/test/java/EmptyClassExample.java (100%) rename src/{main => test/java}/test/TestSpecs.md (100%) rename src/{main => test/java}/test/java/FailureTest.java (100%) rename src/{main => test/java}/test/java/MainTest.java (89%) create mode 100644 src/test/java/test/java/Tester.java rename src/{main => test/java}/test/java/make.md (100%) rename src/test/java/{ => test/java}/semantic/SemanticTest.java (100%) rename src/{main => }/test/resources/AllFeaturesClassExample.java (100%) rename src/{main => }/test/resources/CombinedExample.java (100%) rename src/{main/test/resources/CompilerInput.txt => test/resources/CompilerInput.java} (100%) rename src/{main => }/test/resources/MoreFeaturesClassExample.java (100%) rename src/{main => }/test/resources/failureTests/TestClass1.java (100%) rename src/{main => }/test/resources/failureTests/TestClass10.java (100%) rename src/{main => }/test/resources/failureTests/TestClass11.java (100%) rename src/{main => }/test/resources/failureTests/TestClass2.java (100%) rename src/{main => }/test/resources/failureTests/TestClass3.java (100%) rename src/{main => }/test/resources/failureTests/TestClass4.java (100%) rename src/{main => }/test/resources/failureTests/TestClass5.java (100%) rename src/{main => }/test/resources/failureTests/TestClass6.java (100%) rename src/{main => }/test/resources/failureTests/TestClass7.java (100%) rename src/{main => }/test/resources/failureTests/TestClass8.java (100%) rename src/{main => }/test/resources/failureTests/TestClass9.java (100%) rename src/{main => }/test/resources/featureTests/BooleanOperations.java (100%) rename src/{main => }/test/resources/featureTests/CharManipulation.java (100%) rename src/{main => }/test/resources/featureTests/ConditionalStatements.java (100%) rename src/{main => }/test/resources/featureTests/LoopExamples.java (100%) rename src/{main => }/test/resources/featureTests/MethodOverloading.java (100%) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 8508ccc..a1d1f19 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -37,57 +37,55 @@ public class Main { CommonTokenStream tokenStream = new CommonTokenStream(lexer); // Printing the tokens - // tokenStream.fill(); - // List tokens = tokenStream.getTokens(); - // System.out.println("-------------------- Scanner -> tokens - // --------------------"); - // for (Token token : tokens) { - // String tokenType = - // SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType()); - // String tokenText = token.getText(); - // // System.out.println("Token Type: " + tokenType + ", Token Text: " + - // // tokenText); - // System.out.println(tokenType + " " + tokenText); - // } - // System.out.println(); + tokenStream.fill(); + List tokens = tokenStream.getTokens(); + System.out.println("-------------------- Scanner -> tokens --------------------"); + for (Token token : tokens) { + String tokenType = + SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType()); + String tokenText = token.getText(); + // System.out.println("Token Type: " + tokenType + ", Token Text: " + + // tokenText); + System.out.println(tokenType + " " + tokenText); + } + System.out.println(); /*------------------------- Parser -> Parsetree -------------------------*/ SimpleJavaParser parser = new SimpleJavaParser(tokenStream); 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 -> Tast -------------------------*/ - SemanticAnalyzer.generateTast(abstractSyntaxTree); + /*------------------------- Semantic Analyzer -> typed AST -------------------------*/ ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); - // Printing the Tast - System.out.println("Tast generated"); + // Printing the typed AST + System.out.println("-------------------- Semantic Analyzer -> typed AST --------------------"); + printAST(typedAst, 0); + System.out.println(); /*------------------------- Bytecode Generator -> Bytecode -------------------------*/ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); - // byteCodeGenerator.generateByteCode(abstractSyntaxTree); byteCodeGenerator.visit(typedAst); System.out.println("Bytecode generated"); } + /** * This method is used to print the parse tree in a structured format. * It recursively traverses the tree and prints the rule names and text of the diff --git a/src/main/java/classFileOutput/Example.class b/src/main/java/classFileOutput/Example.class deleted file mode 100644 index 522ae9edd25429b756d2dd98d755bdedb11f81c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167 zcmW-Z%?`m(5QV>?KU4{C(b_cjVj~t^h@Jh#4Q;BGxDl^qC9&`T9!g9t=FB(eoXqF@ zdIK{?Lb$q{^QE#OB8*FOGg)QoW476qcJD&ELNG7t!Yzbul5S&sf(VaL5Tla|k+WB~ uw(is%1V731R84Q$94tadyXY4BL`oeceW5zkYw}OPpFZh5)M%>%;ue1AIvEN8 diff --git a/src/main/java/classFileOutput/Test.class b/src/main/java/classFileOutput/Test.class deleted file mode 100644 index 8ba4c23343d79136e322bf6f22591360f6985b92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97 zcmX^0Z`VEs1_l!bPDTcnkksN5b_Pa927#=^vPAuy#JqHU|D>$cWS}TBBLkaFW?p8A m9U}v?hGrO0c?nQCBTzFV0}}%am}X>PXW)RcSQ*%WECv8I3=j$c diff --git a/src/main/test/java/Tester.java b/src/main/test/java/Tester.java deleted file mode 100644 index 498db7e..0000000 --- a/src/main/test/java/Tester.java +++ /dev/null @@ -1,11 +0,0 @@ -public class Tester { - public static void main(String[] args) { - new EmptyClassExample(); - // cp mitgeben - } -} -// java -jar pfadtocompiler.jar EmptyClass.java -// mit bash scipt ode rmakefile test automatisieren -// mvn package -// javac tester // tester compilen -// java tester // tester ausführen \ No newline at end of file diff --git a/src/main/test/java/EmptyClassExample.java b/src/test/java/EmptyClassExample.java similarity index 100% rename from src/main/test/java/EmptyClassExample.java rename to src/test/java/EmptyClassExample.java diff --git a/src/main/test/TestSpecs.md b/src/test/java/test/TestSpecs.md similarity index 100% rename from src/main/test/TestSpecs.md rename to src/test/java/test/TestSpecs.md diff --git a/src/main/test/java/FailureTest.java b/src/test/java/test/java/FailureTest.java similarity index 100% rename from src/main/test/java/FailureTest.java rename to src/test/java/test/java/FailureTest.java diff --git a/src/main/test/java/MainTest.java b/src/test/java/test/java/MainTest.java similarity index 89% rename from src/main/test/java/MainTest.java rename to src/test/java/test/java/MainTest.java index 516ab6e..9e03dc7 100644 --- a/src/main/test/java/MainTest.java +++ b/src/test/java/test/java/MainTest.java @@ -21,8 +21,8 @@ public class MainTest { void testEmptyClass() { CharStream codeCharStream = null; try { - codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.txt")); - Main.parsefile(codeCharStream); + codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.java")); + Main.parseFile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } diff --git a/src/test/java/test/java/Tester.java b/src/test/java/test/java/Tester.java new file mode 100644 index 0000000..8890547 --- /dev/null +++ b/src/test/java/test/java/Tester.java @@ -0,0 +1,19 @@ +public class Tester { + public static void main(String[] args) { + // für E2E Tests: + // Testdatei mit Main ausführen/kompilieren + // Testdatei mit "javac CompilerInput.java" kompilieren + + // wenn beides erfolgreich + // Ergebnis vom eigenen Compiler mit "java myOutput" ausführen + // Ergebnis von javac mit "java CompilerInput" ausführen + + + } +} +// cp mitgeben +// java -jar pfadtocompiler.jar EmptyClass.java +// mit bash scipt ode rmakefile test automatisieren +// mvn package +// javac tester // tester compilen +// java tester // tester ausführen \ No newline at end of file diff --git a/src/main/test/java/make.md b/src/test/java/test/java/make.md similarity index 100% rename from src/main/test/java/make.md rename to src/test/java/test/java/make.md diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/test/java/semantic/SemanticTest.java similarity index 100% rename from src/test/java/semantic/SemanticTest.java rename to src/test/java/test/java/semantic/SemanticTest.java diff --git a/src/main/test/resources/AllFeaturesClassExample.java b/src/test/resources/AllFeaturesClassExample.java similarity index 100% rename from src/main/test/resources/AllFeaturesClassExample.java rename to src/test/resources/AllFeaturesClassExample.java diff --git a/src/main/test/resources/CombinedExample.java b/src/test/resources/CombinedExample.java similarity index 100% rename from src/main/test/resources/CombinedExample.java rename to src/test/resources/CombinedExample.java diff --git a/src/main/test/resources/CompilerInput.txt b/src/test/resources/CompilerInput.java similarity index 100% rename from src/main/test/resources/CompilerInput.txt rename to src/test/resources/CompilerInput.java diff --git a/src/main/test/resources/MoreFeaturesClassExample.java b/src/test/resources/MoreFeaturesClassExample.java similarity index 100% rename from src/main/test/resources/MoreFeaturesClassExample.java rename to src/test/resources/MoreFeaturesClassExample.java diff --git a/src/main/test/resources/failureTests/TestClass1.java b/src/test/resources/failureTests/TestClass1.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass1.java rename to src/test/resources/failureTests/TestClass1.java diff --git a/src/main/test/resources/failureTests/TestClass10.java b/src/test/resources/failureTests/TestClass10.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass10.java rename to src/test/resources/failureTests/TestClass10.java diff --git a/src/main/test/resources/failureTests/TestClass11.java b/src/test/resources/failureTests/TestClass11.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass11.java rename to src/test/resources/failureTests/TestClass11.java diff --git a/src/main/test/resources/failureTests/TestClass2.java b/src/test/resources/failureTests/TestClass2.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass2.java rename to src/test/resources/failureTests/TestClass2.java diff --git a/src/main/test/resources/failureTests/TestClass3.java b/src/test/resources/failureTests/TestClass3.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass3.java rename to src/test/resources/failureTests/TestClass3.java diff --git a/src/main/test/resources/failureTests/TestClass4.java b/src/test/resources/failureTests/TestClass4.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass4.java rename to src/test/resources/failureTests/TestClass4.java diff --git a/src/main/test/resources/failureTests/TestClass5.java b/src/test/resources/failureTests/TestClass5.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass5.java rename to src/test/resources/failureTests/TestClass5.java diff --git a/src/main/test/resources/failureTests/TestClass6.java b/src/test/resources/failureTests/TestClass6.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass6.java rename to src/test/resources/failureTests/TestClass6.java diff --git a/src/main/test/resources/failureTests/TestClass7.java b/src/test/resources/failureTests/TestClass7.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass7.java rename to src/test/resources/failureTests/TestClass7.java diff --git a/src/main/test/resources/failureTests/TestClass8.java b/src/test/resources/failureTests/TestClass8.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass8.java rename to src/test/resources/failureTests/TestClass8.java diff --git a/src/main/test/resources/failureTests/TestClass9.java b/src/test/resources/failureTests/TestClass9.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass9.java rename to src/test/resources/failureTests/TestClass9.java diff --git a/src/main/test/resources/featureTests/BooleanOperations.java b/src/test/resources/featureTests/BooleanOperations.java similarity index 100% rename from src/main/test/resources/featureTests/BooleanOperations.java rename to src/test/resources/featureTests/BooleanOperations.java diff --git a/src/main/test/resources/featureTests/CharManipulation.java b/src/test/resources/featureTests/CharManipulation.java similarity index 100% rename from src/main/test/resources/featureTests/CharManipulation.java rename to src/test/resources/featureTests/CharManipulation.java diff --git a/src/main/test/resources/featureTests/ConditionalStatements.java b/src/test/resources/featureTests/ConditionalStatements.java similarity index 100% rename from src/main/test/resources/featureTests/ConditionalStatements.java rename to src/test/resources/featureTests/ConditionalStatements.java diff --git a/src/main/test/resources/featureTests/LoopExamples.java b/src/test/resources/featureTests/LoopExamples.java similarity index 100% rename from src/main/test/resources/featureTests/LoopExamples.java rename to src/test/resources/featureTests/LoopExamples.java diff --git a/src/main/test/resources/featureTests/MethodOverloading.java b/src/test/resources/featureTests/MethodOverloading.java similarity index 100% rename from src/main/test/resources/featureTests/MethodOverloading.java rename to src/test/resources/featureTests/MethodOverloading.java From 1132ff015ceac848e350756517b7441a6ab33243 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Fri, 31 May 2024 11:05:45 +0200 Subject: [PATCH 04/25] Changes in tests --- src/main/java/Main.java | 4 + src/test/java/test/java/FailureTest.java | 2 +- .../java/test/java/semantic/SemanticTest.java | 88 ++++++++++++------- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index a1d1f19..c78f3ea 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -120,6 +120,10 @@ public class Main { } public static void printAST(ASTNode node, int indent) { + if (node == null) { + System.out.println("null"); + return; + } String indentString = " ".repeat(indent * 2); System.out.println(indentString + node.getClass().toString()); diff --git a/src/test/java/test/java/FailureTest.java b/src/test/java/test/java/FailureTest.java index bc63d91..366ce56 100644 --- a/src/test/java/test/java/FailureTest.java +++ b/src/test/java/test/java/FailureTest.java @@ -63,7 +63,7 @@ public class FailureTest { CharStream codeCharStream = null; try { codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); - Main.parsefile(codeCharStream); + Main.parseFile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } diff --git a/src/test/java/test/java/semantic/SemanticTest.java b/src/test/java/test/java/semantic/SemanticTest.java index 83287ca..c55e19d 100644 --- a/src/test/java/test/java/semantic/SemanticTest.java +++ b/src/test/java/test/java/semantic/SemanticTest.java @@ -1,6 +1,5 @@ package semantic; - import ast.*; import ast.expression.BinaryExpressionNode; import ast.expression.ExpressionNode; @@ -20,11 +19,10 @@ import ast.type.EnumTypeNode; import org.junit.jupiter.api.BeforeEach; 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.assertEquals; +import static org.junit.jupiter.api.Assertions.*; public class SemanticTest { @@ -34,10 +32,9 @@ public class SemanticTest { } @Test - public void alreadyDeclaredLocalFieldVar(){ - + public void alreadyDeclaredLocalFieldVar() { ProgramNode programNode = new ProgramNode(); - List classList = new ArrayList(); + List classList = new ArrayList<>(); AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); @@ -53,16 +50,14 @@ public class SemanticTest { ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); assertEquals(1, SemanticAnalyzer.errors.size()); - assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException); - assertEquals(null, typedAst); - + assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + assertNull(typedAst); } @Test - public void shouldWorkWithNoError(){ - + public void shouldWorkWithNoError() { ProgramNode programNode = new ProgramNode(); - List classList = new ArrayList(); + List classList = new ArrayList<>(); AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); @@ -72,26 +67,7 @@ public class SemanticTest { MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2"); classNode.members.add(memberNode2); - List parameterNodeList = new ArrayList(); - ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1"); - parameterNodeList.add(parameterNode1); - ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList); - - List statementNodeList = new ArrayList(); - - ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this"); - ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar"); - - ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT); - - ExpressionNode expressionNodeRight = new LiteralNode(1); - - BinaryExpressionNode expressionNode = new BinaryExpressionNode(expressionNodeLeft, expressionNodeRight, ExpresssionOperator.ASSIGNMENT); - - StatementNode statementNode1 = new AssignmentStatementNode(expressionNode); - statementNodeList.add(statementNode1); - - MemberNode memberNode3 = new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2",parameterListNode, statementNodeList ); + MemberNode memberNode3 = getMemberNode(accessTypeNode); classNode.members.add(memberNode3); classList.add(classNode); @@ -101,7 +77,53 @@ public class SemanticTest { assertEquals(0, SemanticAnalyzer.errors.size()); assertEquals(programNode, typedAst); - } + /** + * This method is used to create a MemberNode representing a method. + * It first creates a list of ParameterNodes and adds a ParameterNode to it. + * Then, it creates a ParameterListNode using the list of ParameterNodes. + * After that, it creates a list of StatementNodes and adds a StatementNode to it by calling the getStatementNode method. + * Finally, it creates a MethodNode using the provided AccessTypeNode, a BaseTypeNode representing the return type of the method, + * the method name, the ParameterListNode, and the list of StatementNodes, and returns this MethodNode. + * + * @param accessTypeNode The AccessTypeNode representing the access type of the method. + * @return The created MemberNode representing the method. + */ +private static MemberNode getMemberNode(AccessTypeNode accessTypeNode) { + List parameterNodeList = new ArrayList<>(); + ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1"); + parameterNodeList.add(parameterNode1); + ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList); + + List statementNodeList = new ArrayList<>(); + + StatementNode statementNode1 = getStatementNode(); + statementNodeList.add(statementNode1); + + return new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2", parameterListNode, statementNodeList); +} + + /** + * This method is used to create a StatementNode for an assignment operation. + * It first creates two IdentifierExpressionNodes for 'this' and 'objectVar'. + * Then, it creates a BinaryExpressionNode to represent the operation 'this.objectVar'. + * After that, it creates a LiteralNode to represent the integer value 1. + * Finally, it creates another BinaryExpressionNode to represent the assignment operation 'this.objectVar = 1', + * and wraps this expression in an AssignmentStatementNode. + * + * @return The created AssignmentStatementNode representing the assignment operation 'this.objectVar = 1'. + */ +private static StatementNode getStatementNode() { + ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this"); + ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar"); + + ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT); + + ExpressionNode expressionNodeRight = new LiteralNode(1); + + BinaryExpressionNode expressionNode = new BinaryExpressionNode(expressionNodeLeft, expressionNodeRight, ExpresssionOperator.ASSIGNMENT); + + return new AssignmentStatementNode(expressionNode); +} } From 9f40949f5aa6689b1eb5495ef4debf2ba3102b23 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Fri, 31 May 2024 11:20:31 +0200 Subject: [PATCH 05/25] Structure --- src/test/{java/test => }/TestSpecs.md | 10 +++++++++- .../java/{test/java => }/FailureTest.java | 0 src/test/java/{test/java => }/MainTest.java | 6 ------ src/test/java/Tester.java | 12 ++++++++++++ src/test/java/{test/java => }/make.md | 0 .../java => }/semantic/SemanticTest.java | 0 src/test/java/test/java/Tester.java | 19 ------------------- 7 files changed, 21 insertions(+), 26 deletions(-) rename src/test/{java/test => }/TestSpecs.md (87%) rename src/test/java/{test/java => }/FailureTest.java (100%) rename src/test/java/{test/java => }/MainTest.java (76%) create mode 100644 src/test/java/Tester.java rename src/test/java/{test/java => }/make.md (100%) rename src/test/java/{test/java => }/semantic/SemanticTest.java (100%) delete mode 100644 src/test/java/test/java/Tester.java diff --git a/src/test/java/test/TestSpecs.md b/src/test/TestSpecs.md similarity index 87% rename from src/test/java/test/TestSpecs.md rename to src/test/TestSpecs.md index 6fd5a41..7ae3416 100644 --- a/src/test/java/test/TestSpecs.md +++ b/src/test/TestSpecs.md @@ -75,4 +75,12 @@ Compiled Classfile ### Beispiel 2: Filled Class - \ No newline at end of file + + + für E2E Tests: + Testdatei mit Main ausführen/kompilieren + Testdatei mit "javac CompilerInput.java" kompilieren + + wenn beides erfolgreich + Ergebnis vom eigenen Compiler mit "java myOutput" ausführen + Ergebnis von javac mit "java CompilerInput" ausführen diff --git a/src/test/java/test/java/FailureTest.java b/src/test/java/FailureTest.java similarity index 100% rename from src/test/java/test/java/FailureTest.java rename to src/test/java/FailureTest.java diff --git a/src/test/java/test/java/MainTest.java b/src/test/java/MainTest.java similarity index 76% rename from src/test/java/test/java/MainTest.java rename to src/test/java/MainTest.java index 9e03dc7..a8c3a93 100644 --- a/src/test/java/test/java/MainTest.java +++ b/src/test/java/MainTest.java @@ -1,12 +1,6 @@ import org.junit.jupiter.api.Test; 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 parser.ASTBuilder; -import ast.ClassNode; -import ast.ProgramNode; -import bytecode.ByteCodeGenerator; import java.io.IOException; import java.nio.file.Paths; diff --git a/src/test/java/Tester.java b/src/test/java/Tester.java new file mode 100644 index 0000000..2c62e40 --- /dev/null +++ b/src/test/java/Tester.java @@ -0,0 +1,12 @@ +public class Tester { + public static void main(String[] args) { + + + } +} +// cp mitgeben +// java -jar pfadtocompiler.jar EmptyClass.java +// mit bash scipt ode rmakefile test automatisieren +// mvn package +// javac tester // tester compilen +// java tester // tester ausführen \ No newline at end of file diff --git a/src/test/java/test/java/make.md b/src/test/java/make.md similarity index 100% rename from src/test/java/test/java/make.md rename to src/test/java/make.md diff --git a/src/test/java/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java similarity index 100% rename from src/test/java/test/java/semantic/SemanticTest.java rename to src/test/java/semantic/SemanticTest.java diff --git a/src/test/java/test/java/Tester.java b/src/test/java/test/java/Tester.java deleted file mode 100644 index 8890547..0000000 --- a/src/test/java/test/java/Tester.java +++ /dev/null @@ -1,19 +0,0 @@ -public class Tester { - public static void main(String[] args) { - // für E2E Tests: - // Testdatei mit Main ausführen/kompilieren - // Testdatei mit "javac CompilerInput.java" kompilieren - - // wenn beides erfolgreich - // Ergebnis vom eigenen Compiler mit "java myOutput" ausführen - // Ergebnis von javac mit "java CompilerInput" ausführen - - - } -} -// cp mitgeben -// java -jar pfadtocompiler.jar EmptyClass.java -// mit bash scipt ode rmakefile test automatisieren -// mvn package -// javac tester // tester compilen -// java tester // tester ausführen \ No newline at end of file From 8d6190b1304e82b3a3625f3d18dc475aea452ebe Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Fri, 31 May 2024 17:09:04 +0200 Subject: [PATCH 06/25] Structure, Makefile, Docs, TestCompilerOutput, more; TODO: fix marked Problems in Makefile; fix Compiler (look at TestCompilerOutput docs) --- .../antlr-4.12.0-complete.jar | Bin pom.xml | 4 +- src/main/java/Main.java | 12 ++--- src/main/java/bytecode/ClassCodeGen.java | 2 +- src/main/resources/CompilerInput.java | 18 +++---- src/test/Makefile | 24 +++++++++ src/test/TestSpecs.md | 51 +++++++++++------- src/test/java/TestCompilerOutput.java | 41 ++++++++++++++ src/test/java/Tester.java | 12 ----- src/test/java/make.md | 0 src/test/resources/CompilerInput.java | 14 ++--- 11 files changed, 117 insertions(+), 61 deletions(-) rename antlr-4.12.0-complete.jar => .lib/antlr-4.12.0-complete.jar (100%) create mode 100644 src/test/Makefile create mode 100644 src/test/java/TestCompilerOutput.java delete mode 100644 src/test/java/Tester.java delete mode 100644 src/test/java/make.md diff --git a/antlr-4.12.0-complete.jar b/.lib/antlr-4.12.0-complete.jar similarity index 100% rename from antlr-4.12.0-complete.jar rename to .lib/antlr-4.12.0-complete.jar diff --git a/pom.xml b/pom.xml index 9ee63e3..a11bfc7 100644 --- a/pom.xml +++ b/pom.xml @@ -9,8 +9,8 @@ 1.0-SNAPSHOT - 21 - 21 + 22 + 22 UTF-8 diff --git a/src/main/java/Main.java b/src/main/java/Main.java index c78f3ea..acea692 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,18 +1,14 @@ import ast.ASTNode; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.Token; import ast.ProgramNode; -import bytecode.ByteCodeGenerator; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.tree.ParseTree; -import org.antlr.v4.runtime.CommonTokenStream; 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; import java.util.List; @@ -20,7 +16,7 @@ import java.util.List; 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 { try { CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/CompilerInput.java")); diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index b0afa69..6bddd61 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -52,7 +52,7 @@ public class ClassCodeGen implements ClassVisitor { } private void printIntoClassFile(byte[] byteCode, String name) { - String directoryPath = "src/main/java/classFileOutput"; + String directoryPath = "src/main/resources/classFileOutput"; File directory = new File(directoryPath); if (!directory.exists()) { directory.mkdirs(); diff --git a/src/main/resources/CompilerInput.java b/src/main/resources/CompilerInput.java index 1cbe5ca..d850a3e 100644 --- a/src/main/resources/CompilerInput.java +++ b/src/main/resources/CompilerInput.java @@ -1,18 +1,16 @@ -public class Example { +public class CompilerInput { public int a; public static int testMethod(char x){ - + return 0; } + public class Test { + + public static int testMethod(char x, int a){ + return 0; + } + } } -public class Test { - - public static int testMethod(char x, int a){ - - - - } -} \ No newline at end of file diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 0000000..da39d6b --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,24 @@ +# Makefile +### IntelliJs play buttons do not work. Run in "src/test" folder with "make" command to run all +### Or run only parts with "make compile-javac", "make delete" etc. + +all: delete compile-javac compile-raupenpiler + +compile-javac: + javac -d .\resources\output\javac .\resources\CompilerInput.java + +compile-raupenpiler: +## funktioniert bisher nicht, das will die Klasse nicht laden, der traditionelle Weg findet externe Libraries (antlr) nicht, maven hat andere Probleme +## Unseren Compiler also erstmal händisch starten: main.java/Main.java + #javac -d ./resources/output/raupenpiler -cp ../main/java;../../.lib/antlr-4.12.0-complete.jar ../main/java/Main.java + #java -cp ./resources/output/raupenpiler Main + #mvn -f ../../ compile + #mvn -f ../../ exec:java -Dexec.mainClass="Main" + +delete: + rm -f ./resources/output/javac/*.class + rm -f ./resources/output/raupenpiler/*.class + rm -f ./java/*.class + rm -f ../main/resources/classFileOutput/*.class + + diff --git a/src/test/TestSpecs.md b/src/test/TestSpecs.md index 7ae3416..75f979a 100644 --- a/src/test/TestSpecs.md +++ b/src/test/TestSpecs.md @@ -1,5 +1,7 @@ # Scanner + ## Scanner Input + ### Beispiel 1: Empty Class String empty class = "public class Name {}"; @@ -15,11 +17,12 @@ "}" ## Scanner Output + ### Beispiel 1: Empty Class Token Type; Token Text Type gibts nur bei Terminalen, Text bei allen - + [null "public", null "class", IDENTIFIER "Name", null "{", null "}", EOF ""] Bsp von Ihm mal: @@ -35,52 +38,62 @@ Type gibts nur bei Terminalen, Text bei allen [TokRightBrace] # Parser -## Parser Input + +## Parser Input + (Scanner Output) ## Parser Output (AST) -### Beispiel 1: Empty Class - +### Beispiel 1: Empty Class ### Beispiel 2: Filled Class - - # Semantische Analyse / Typcheck -## Typcheck Input + +## Typcheck Input + (Parser Output = AST) ## Typcheck Output ### Beispiel 1: Empty Class - - ### Beispiel 2: Filled Class - # Bytecodegenerierung -## Bytecodegenerierung Input + +## Bytecodegenerierung Input + (Typcheck Output = vom Typcheck eventuell manipulierter AST) ## Bytecodegenerierung Output ### Beispiel 1: Empty Class + Compiled Classfile public class javaFileInput.Example { } - - ### Beispiel 2: Filled Class +## E2E Tests: - für E2E Tests: - Testdatei mit Main ausführen/kompilieren - Testdatei mit "javac CompilerInput.java" kompilieren +- Testdatei mit Main ausführen/kompilieren +- Testdatei mit "javac -d output .\CompilerInput.java" kompilieren +- -> Dateien mit javap vergleichen - wenn beides erfolgreich - Ergebnis vom eigenen Compiler mit "java myOutput" ausführen - Ergebnis von javac mit "java CompilerInput" ausführen +wenn beides erfolgreich +- Ergebnis vom eigenen Compiler mithilfe von TestCompilerOutput ausführen +- (Ergebnis von javac mithilfe von TestCompilerOutput ausführen) + + +### Andis Tipps: +- cp mitgeben +- makefile +- java -jar pfadtocompiler.jar EmptyClass.java +- mvn package +- javac tester // tester compilen +- java tester // tester ausführen +- -> tester ist in unserem Fall TestCompilerOutput.java \ No newline at end of file diff --git a/src/test/java/TestCompilerOutput.java b/src/test/java/TestCompilerOutput.java new file mode 100644 index 0000000..cf6aac0 --- /dev/null +++ b/src/test/java/TestCompilerOutput.java @@ -0,0 +1,41 @@ +/** + * This class is used to test the output of the compiler. + *

+ * Im gleichen Ordner wie die diese Datei (TestCompilerOutput.java) muss die selbstkompilierte CompilerInput.java Datei sein. + * --->>>> Diese muss man also vom Ordner classFileOutput in diesen ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt) <<<<--- + * Die selbstkompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. + * Diese TestCompilerOutput.java Datei wird dann mit "javac .\TestCompilerOutput.java" kompiliert und mit "java TestCompilerOutput" ausgeführt. + * Wenn unser Compiler funktioniert, sollten keine Errors kommen (sondern nur die Ausgaben, die wir in der CompilerInput.java Datei gemacht haben, + * oder Methoden, die wir hier aufrufen). + * PROBLEM: hier kommen errors, was eigentlich heißt, dass der Compiler nicht funktioniert, der der Test sollt eigentlich passen + */ +public class TestCompilerOutput { + + public static void main(String[] args) { + try { + // Try to load the class named "CompilerInput" + Class cls = Class.forName("CompilerInput"); + // Print a success message if the class is loaded successfully + System.out.println("Class loaded successfully: " + cls.getName()); + + // Try to create an instance of the loaded class + Object instance = cls.getDeclaredConstructor().newInstance(); + // Print a success message if the instance is created successfully + System.out.println("Instance created: " + instance); + + + // If the class has a main method, you can invoke it + // cls.getMethod("main", String[].class).invoke(null, (Object) new String[]{}); + + // If the class has other methods, you can invoke them as well + // Example: cls.getMethod("someMethod").invoke(instance); + + } catch (ClassNotFoundException e) { + // Print an error message if the class is not found + System.err.println("Class not found: " + e.getMessage()); + } catch (Exception e) { + // Print an error message if any other exception occurs during class loading or instance creation + System.err.println("Error during class loading or execution: " + e.getMessage()); + } + } +} diff --git a/src/test/java/Tester.java b/src/test/java/Tester.java deleted file mode 100644 index 2c62e40..0000000 --- a/src/test/java/Tester.java +++ /dev/null @@ -1,12 +0,0 @@ -public class Tester { - public static void main(String[] args) { - - - } -} -// cp mitgeben -// java -jar pfadtocompiler.jar EmptyClass.java -// mit bash scipt ode rmakefile test automatisieren -// mvn package -// javac tester // tester compilen -// java tester // tester ausführen \ No newline at end of file diff --git a/src/test/java/make.md b/src/test/java/make.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/CompilerInput.java b/src/test/resources/CompilerInput.java index 918c686..91b2625 100644 --- a/src/test/resources/CompilerInput.java +++ b/src/test/resources/CompilerInput.java @@ -1,13 +1,9 @@ -public class Example { - - public int testVar; - - public static int testMethod(char b){ - - int a; - int a; +public class CompilerInput { + public int a; + public static int testMethod(char x){ + return 0; } +} -} \ No newline at end of file From 6a971345d49679620cccb13ce136c74caed8390b Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:17:16 +0200 Subject: [PATCH 07/25] Structure and more --- src/main/java/Main.java | 3 +-- src/main/java/bytecode/ClassCodeGen.java | 2 +- .../resources/{ => input}/CompilerInput.java | 0 src/test/Makefile | 5 ++--- src/test/java/TestCompilerOutput.java | 18 ++++++++++-------- .../{ => input}/AllFeaturesClassExample.java | 0 .../resources/{ => input}/CombinedExample.java | 0 .../resources/{ => input}/CompilerInput.java | 7 +++++++ .../{ => input}/MoreFeaturesClassExample.java | 0 .../{ => input}/failureTests/TestClass1.java | 0 .../{ => input}/failureTests/TestClass10.java | 0 .../{ => input}/failureTests/TestClass11.java | 0 .../{ => input}/failureTests/TestClass2.java | 0 .../{ => input}/failureTests/TestClass3.java | 0 .../{ => input}/failureTests/TestClass4.java | 0 .../{ => input}/failureTests/TestClass5.java | 0 .../{ => input}/failureTests/TestClass6.java | 0 .../{ => input}/failureTests/TestClass7.java | 0 .../{ => input}/failureTests/TestClass8.java | 0 .../{ => input}/failureTests/TestClass9.java | 0 .../featureTests/BooleanOperations.java | 0 .../featureTests/CharManipulation.java | 0 .../featureTests/ConditionalStatements.java | 0 .../{ => input}/featureTests/LoopExamples.java | 0 .../featureTests/MethodOverloading.java | 0 25 files changed, 21 insertions(+), 14 deletions(-) rename src/main/resources/{ => input}/CompilerInput.java (100%) rename src/test/resources/{ => input}/AllFeaturesClassExample.java (100%) rename src/test/resources/{ => input}/CombinedExample.java (100%) rename src/test/resources/{ => input}/CompilerInput.java (50%) rename src/test/resources/{ => input}/MoreFeaturesClassExample.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass1.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass10.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass11.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass2.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass3.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass4.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass5.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass6.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass7.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass8.java (100%) rename src/test/resources/{ => input}/failureTests/TestClass9.java (100%) rename src/test/resources/{ => input}/featureTests/BooleanOperations.java (100%) rename src/test/resources/{ => input}/featureTests/CharManipulation.java (100%) rename src/test/resources/{ => input}/featureTests/ConditionalStatements.java (100%) rename src/test/resources/{ => input}/featureTests/LoopExamples.java (100%) rename src/test/resources/{ => input}/featureTests/MethodOverloading.java (100%) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index acea692..6f6517f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -19,7 +19,7 @@ public class Main { System.out.println("Main file has args: " + args[0]); } else { try { - CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/CompilerInput.java")); + CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java")); parseFile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); @@ -78,7 +78,6 @@ public class Main { ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); byteCodeGenerator.visit(typedAst); System.out.println("Bytecode generated"); - } diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index 6bddd61..d91b17b 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -52,7 +52,7 @@ public class ClassCodeGen implements ClassVisitor { } private void printIntoClassFile(byte[] byteCode, String name) { - String directoryPath = "src/main/resources/classFileOutput"; + String directoryPath = "src/main/resources/output"; File directory = new File(directoryPath); if (!directory.exists()) { directory.mkdirs(); diff --git a/src/main/resources/CompilerInput.java b/src/main/resources/input/CompilerInput.java similarity index 100% rename from src/main/resources/CompilerInput.java rename to src/main/resources/input/CompilerInput.java diff --git a/src/test/Makefile b/src/test/Makefile index da39d6b..68b9dd2 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -5,7 +5,7 @@ all: delete compile-javac compile-raupenpiler compile-javac: - javac -d .\resources\output\javac .\resources\CompilerInput.java + javac -d .\resources\output\javac .\resources\input\CompilerInput.java compile-raupenpiler: ## funktioniert bisher nicht, das will die Klasse nicht laden, der traditionelle Weg findet externe Libraries (antlr) nicht, maven hat andere Probleme @@ -19,6 +19,5 @@ delete: rm -f ./resources/output/javac/*.class rm -f ./resources/output/raupenpiler/*.class rm -f ./java/*.class - rm -f ../main/resources/classFileOutput/*.class - + rm -f ../main/resources/output/*.class diff --git a/src/test/java/TestCompilerOutput.java b/src/test/java/TestCompilerOutput.java index cf6aac0..567ebde 100644 --- a/src/test/java/TestCompilerOutput.java +++ b/src/test/java/TestCompilerOutput.java @@ -1,16 +1,18 @@ /** * This class is used to test the output of the compiler. - *

- * Im gleichen Ordner wie die diese Datei (TestCompilerOutput.java) muss die selbstkompilierte CompilerInput.java Datei sein. - * --->>>> Diese muss man also vom Ordner classFileOutput in diesen ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt) <<<<--- - * Die selbstkompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. - * Diese TestCompilerOutput.java Datei wird dann mit "javac .\TestCompilerOutput.java" kompiliert und mit "java TestCompilerOutput" ausgeführt. + * + *

Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbstkompilierte CompilerInput.java Datei sein. + *
Hinweis: Diese muss man also vom Ordner classFileOutput in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)

+ * + *

Die selbstkompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. + *

Diese TestCompilerOutput.java Datei wird dann in \src\test\java> mit javac .\TestCompilerOutput.java kompiliert und mit java TestCompilerOutput ausgeführt. * Wenn unser Compiler funktioniert, sollten keine Errors kommen (sondern nur die Ausgaben, die wir in der CompilerInput.java Datei gemacht haben, - * oder Methoden, die wir hier aufrufen). - * PROBLEM: hier kommen errors, was eigentlich heißt, dass der Compiler nicht funktioniert, der der Test sollt eigentlich passen + * 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 static void main(String[] args) { try { // Try to load the class named "CompilerInput" diff --git a/src/test/resources/AllFeaturesClassExample.java b/src/test/resources/input/AllFeaturesClassExample.java similarity index 100% rename from src/test/resources/AllFeaturesClassExample.java rename to src/test/resources/input/AllFeaturesClassExample.java diff --git a/src/test/resources/CombinedExample.java b/src/test/resources/input/CombinedExample.java similarity index 100% rename from src/test/resources/CombinedExample.java rename to src/test/resources/input/CombinedExample.java diff --git a/src/test/resources/CompilerInput.java b/src/test/resources/input/CompilerInput.java similarity index 50% rename from src/test/resources/CompilerInput.java rename to src/test/resources/input/CompilerInput.java index 91b2625..d850a3e 100644 --- a/src/test/resources/CompilerInput.java +++ b/src/test/resources/input/CompilerInput.java @@ -5,5 +5,12 @@ public class CompilerInput { public static int testMethod(char x){ return 0; } + + public class Test { + + public static int testMethod(char x, int a){ + return 0; + } + } } diff --git a/src/test/resources/MoreFeaturesClassExample.java b/src/test/resources/input/MoreFeaturesClassExample.java similarity index 100% rename from src/test/resources/MoreFeaturesClassExample.java rename to src/test/resources/input/MoreFeaturesClassExample.java diff --git a/src/test/resources/failureTests/TestClass1.java b/src/test/resources/input/failureTests/TestClass1.java similarity index 100% rename from src/test/resources/failureTests/TestClass1.java rename to src/test/resources/input/failureTests/TestClass1.java diff --git a/src/test/resources/failureTests/TestClass10.java b/src/test/resources/input/failureTests/TestClass10.java similarity index 100% rename from src/test/resources/failureTests/TestClass10.java rename to src/test/resources/input/failureTests/TestClass10.java diff --git a/src/test/resources/failureTests/TestClass11.java b/src/test/resources/input/failureTests/TestClass11.java similarity index 100% rename from src/test/resources/failureTests/TestClass11.java rename to src/test/resources/input/failureTests/TestClass11.java diff --git a/src/test/resources/failureTests/TestClass2.java b/src/test/resources/input/failureTests/TestClass2.java similarity index 100% rename from src/test/resources/failureTests/TestClass2.java rename to src/test/resources/input/failureTests/TestClass2.java diff --git a/src/test/resources/failureTests/TestClass3.java b/src/test/resources/input/failureTests/TestClass3.java similarity index 100% rename from src/test/resources/failureTests/TestClass3.java rename to src/test/resources/input/failureTests/TestClass3.java diff --git a/src/test/resources/failureTests/TestClass4.java b/src/test/resources/input/failureTests/TestClass4.java similarity index 100% rename from src/test/resources/failureTests/TestClass4.java rename to src/test/resources/input/failureTests/TestClass4.java diff --git a/src/test/resources/failureTests/TestClass5.java b/src/test/resources/input/failureTests/TestClass5.java similarity index 100% rename from src/test/resources/failureTests/TestClass5.java rename to src/test/resources/input/failureTests/TestClass5.java diff --git a/src/test/resources/failureTests/TestClass6.java b/src/test/resources/input/failureTests/TestClass6.java similarity index 100% rename from src/test/resources/failureTests/TestClass6.java rename to src/test/resources/input/failureTests/TestClass6.java diff --git a/src/test/resources/failureTests/TestClass7.java b/src/test/resources/input/failureTests/TestClass7.java similarity index 100% rename from src/test/resources/failureTests/TestClass7.java rename to src/test/resources/input/failureTests/TestClass7.java diff --git a/src/test/resources/failureTests/TestClass8.java b/src/test/resources/input/failureTests/TestClass8.java similarity index 100% rename from src/test/resources/failureTests/TestClass8.java rename to src/test/resources/input/failureTests/TestClass8.java diff --git a/src/test/resources/failureTests/TestClass9.java b/src/test/resources/input/failureTests/TestClass9.java similarity index 100% rename from src/test/resources/failureTests/TestClass9.java rename to src/test/resources/input/failureTests/TestClass9.java diff --git a/src/test/resources/featureTests/BooleanOperations.java b/src/test/resources/input/featureTests/BooleanOperations.java similarity index 100% rename from src/test/resources/featureTests/BooleanOperations.java rename to src/test/resources/input/featureTests/BooleanOperations.java diff --git a/src/test/resources/featureTests/CharManipulation.java b/src/test/resources/input/featureTests/CharManipulation.java similarity index 100% rename from src/test/resources/featureTests/CharManipulation.java rename to src/test/resources/input/featureTests/CharManipulation.java diff --git a/src/test/resources/featureTests/ConditionalStatements.java b/src/test/resources/input/featureTests/ConditionalStatements.java similarity index 100% rename from src/test/resources/featureTests/ConditionalStatements.java rename to src/test/resources/input/featureTests/ConditionalStatements.java diff --git a/src/test/resources/featureTests/LoopExamples.java b/src/test/resources/input/featureTests/LoopExamples.java similarity index 100% rename from src/test/resources/featureTests/LoopExamples.java rename to src/test/resources/input/featureTests/LoopExamples.java diff --git a/src/test/resources/featureTests/MethodOverloading.java b/src/test/resources/input/featureTests/MethodOverloading.java similarity index 100% rename from src/test/resources/featureTests/MethodOverloading.java rename to src/test/resources/input/featureTests/MethodOverloading.java From b6cc925e020bdeb7a89d269dc1a5e0f09e7db293 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:01:21 +0200 Subject: [PATCH 08/25] Fixed Makefile --- pom.xml | 5 +++-- src/test/Makefile | 13 +++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index a11bfc7..e6506ea 100644 --- a/pom.xml +++ b/pom.xml @@ -9,8 +9,9 @@ 1.0-SNAPSHOT - 22 - 22 + 22 + ${java.version} + ${java.version} UTF-8 diff --git a/src/test/Makefile b/src/test/Makefile index 68b9dd2..e14b5d4 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -2,20 +2,17 @@ ### IntelliJs play buttons do not work. Run in "src/test" folder with "make" command to run all ### Or run only parts with "make compile-javac", "make delete" etc. -all: delete compile-javac compile-raupenpiler +all: compile-javac compile-raupenpiler compile-javac: javac -d .\resources\output\javac .\resources\input\CompilerInput.java compile-raupenpiler: -## funktioniert bisher nicht, das will die Klasse nicht laden, der traditionelle Weg findet externe Libraries (antlr) nicht, maven hat andere Probleme -## Unseren Compiler also erstmal händisch starten: main.java/Main.java - #javac -d ./resources/output/raupenpiler -cp ../main/java;../../.lib/antlr-4.12.0-complete.jar ../main/java/Main.java - #java -cp ./resources/output/raupenpiler Main - #mvn -f ../../ compile - #mvn -f ../../ exec:java -Dexec.mainClass="Main" + cd ../.. ; mvn -DskipTests package + cd ../.. ; mvn exec:java -Dexec.mainClass="Main" # -Dexec.args="arg0 arg1 arg2" -delete: + +clean: rm -f ./resources/output/javac/*.class rm -f ./resources/output/raupenpiler/*.class rm -f ./java/*.class From 0732712e61105d8c51bc399d0062f1988db89dec Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:42:56 +0200 Subject: [PATCH 09/25] Make, Main: Raupenpiler startup --- src/main/java/Main.java | 50 +++++++++++++------ src/main/java/bytecode/ByteCodeGenerator.java | 8 ++- src/main/java/bytecode/ClassCodeGen.java | 17 ++++--- .../java/bytecode/visitor/ClassVisitor.java | 5 +- src/test/Makefile | 10 +++- src/test/java/FailureTest.java | 2 +- src/test/java/MainTest.java | 2 +- src/test/java/TestCompilerOutput.java | 6 +-- src/test/java/parser/ParserTest.java | 4 ++ 9 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 src/test/java/parser/ParserTest.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 6f6517f..7174d66 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -13,23 +13,41 @@ import java.io.IOException; import java.nio.file.Paths; import java.util.List; +/** + * Start Raupenpiler with the following commands: + *

cd .\src\test\ + *

make clean compile-raupenpiler + */ public class Main { public static void main(String[] args) throws Exception { if (args.length > 0) { - System.out.println("Main file has args: " + args[0]); - } else { + // args[0] is the input file path + // args[1] is the output directory path + String inputFilePath = args[0]; + String outputDirectoryPath = args[1]; + System.out.println("Compiling file: " + inputFilePath); try { - CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java")); - parseFile(codeCharStream); + CharStream inputCharStream = CharStreams.fromPath(Paths.get(inputFilePath)); + compileFile(inputCharStream, outputDirectoryPath); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } } + /* !!! Else Branch ist nicht zur Verwendung vorgesehen, alles über make starten !!! + else { + try { + CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java")); + compileFile(codeCharStream); + } catch (IOException e) { + System.err.println("Error reading the file: " + e.getMessage()); + } + } + */ } - static void parseFile(CharStream codeCharStream) { + static void compileFile(CharStream inputCharStream, String outputDirectoryPath) { /* ------------------------- Scanner -> tokens ------------------------- */ - SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); // Printing the tokens @@ -51,20 +69,20 @@ public class Main { ParseTree parseTree = parser.program(); // parse the input // Printing the parse tree - System.out.println("-------------------- Parser -> Parsetree --------------------"); - System.out.println(parseTree.toStringTree(parser)); - printTree(parseTree, parser, 0); - System.out.println(); + System.out.println("-------------------- Parser -> Parsetree --------------------"); + System.out.println(parseTree.toStringTree(parser)); + printTree(parseTree, parser, 0); + System.out.println(); /*------------------------- AST builder -> AST -------------------------*/ ASTBuilder astBuilder = new ASTBuilder(); ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); // Printing the AST - System.out.println("-------------------- AST builder -> AST --------------------"); - // System.out.println("AST: " + ast.toString()); - printAST(abstractSyntaxTree, 0); - System.out.println(); + System.out.println("-------------------- AST builder -> AST --------------------"); + // System.out.println("AST: " + ast.toString()); + printAST(abstractSyntaxTree, 0); + System.out.println(); /*------------------------- Semantic Analyzer -> typed AST -------------------------*/ ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); @@ -75,11 +93,12 @@ public class Main { System.out.println(); /*------------------------- Bytecode Generator -> Bytecode -------------------------*/ - ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); + ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath); byteCodeGenerator.visit(typedAst); System.out.println("Bytecode generated"); } + /* ------------------------- Printing methods ------------------------- */ /** * This method is used to print the parse tree in a structured format. @@ -114,6 +133,7 @@ public class Main { } } + // TODO: Fix this method public static void printAST(ASTNode node, int indent) { if (node == null) { System.out.println("null"); diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index 5494255..99cf5c1 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -6,10 +6,16 @@ import bytecode.visitor.ProgramVisitor; public class ByteCodeGenerator implements ProgramVisitor { + private final String outputDirectoryPath; + + public ByteCodeGenerator(String outputDirectoryPath) { + this.outputDirectoryPath = outputDirectoryPath; + } + @Override public void visit(ProgramNode programNode) { for (ClassNode classDeclarationNode : programNode.classes) { - ClassCodeGen classCodeGen = new ClassCodeGen(); + ClassCodeGen classCodeGen = new ClassCodeGen(outputDirectoryPath); classDeclarationNode.accept(classCodeGen); } } diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index d91b17b..d8cdaaa 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -6,7 +6,9 @@ import ast.member.MemberNode; import ast.member.MethodNode; import ast.type.BaseTypeNode; import bytecode.visitor.ClassVisitor; + import java.io.File; + import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; @@ -17,8 +19,10 @@ import java.io.IOException; public class ClassCodeGen implements ClassVisitor { private Mapper mapper; private ClassWriter classWriter; + private final String outputDirectoryPath; - public ClassCodeGen() { + public ClassCodeGen(String outputDirectoryPath) { + this.outputDirectoryPath = outputDirectoryPath; mapper = new Mapper(); } @@ -45,20 +49,21 @@ public class ClassCodeGen implements ClassVisitor { @Override public void visit(FieldNode fieldNode) { - if(fieldNode.type instanceof BaseTypeNode baseTypeNode){ - classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null ); + if (fieldNode.type instanceof BaseTypeNode baseTypeNode) { + classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null); } classWriter.visitEnd(); } private void printIntoClassFile(byte[] byteCode, String name) { - String directoryPath = "src/main/resources/output"; - File directory = new File(directoryPath); + // String outputDirectoryPath = "src/main/resources/output"; + System.out.println("Output directory path: " + outputDirectoryPath); + File directory = new File(outputDirectoryPath); if (!directory.exists()) { directory.mkdirs(); } - String filePath = directoryPath + "/" + name + ".class"; + String filePath = outputDirectoryPath + "/" + name + ".class"; try { FileOutputStream fileOutputStream = new FileOutputStream(filePath); fileOutputStream.write(byteCode); diff --git a/src/main/java/bytecode/visitor/ClassVisitor.java b/src/main/java/bytecode/visitor/ClassVisitor.java index 98ef25c..725b075 100644 --- a/src/main/java/bytecode/visitor/ClassVisitor.java +++ b/src/main/java/bytecode/visitor/ClassVisitor.java @@ -5,6 +5,7 @@ import ast.member.FieldNode; import org.objectweb.asm.ClassWriter; public interface ClassVisitor { - void visit(ClassNode classNode); - void visit(FieldNode fieldNode); + void visit(ClassNode classNode); + + void visit(FieldNode fieldNode); } diff --git a/src/test/Makefile b/src/test/Makefile index e14b5d4..1329f1d 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -9,8 +9,16 @@ compile-javac: compile-raupenpiler: cd ../.. ; mvn -DskipTests package - cd ../.. ; mvn exec:java -Dexec.mainClass="Main" # -Dexec.args="arg0 arg1 arg2" + cd ../.. ; mvn exec:java -Dexec.mainClass="Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' " +test: test-javac test-raupenpiler + +test-javac: + compile-javac + java -cp .\resources\output\javac CompilerInput + +test-raupenpiler: + java -cp .\resources\output\raupenpiler CompilerInput clean: rm -f ./resources/output/javac/*.class diff --git a/src/test/java/FailureTest.java b/src/test/java/FailureTest.java index 366ce56..028c5d1 100644 --- a/src/test/java/FailureTest.java +++ b/src/test/java/FailureTest.java @@ -63,7 +63,7 @@ public class FailureTest { CharStream codeCharStream = null; try { codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); - Main.parseFile(codeCharStream); + Main.compileFile(codeCharStream, "src/main/test/resources/output"); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } diff --git a/src/test/java/MainTest.java b/src/test/java/MainTest.java index a8c3a93..eec63b0 100644 --- a/src/test/java/MainTest.java +++ b/src/test/java/MainTest.java @@ -16,7 +16,7 @@ public class MainTest { CharStream codeCharStream = null; try { codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.java")); - Main.parseFile(codeCharStream); + Main.compileFile(codeCharStream, "src/main/test/resources/output"); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } diff --git a/src/test/java/TestCompilerOutput.java b/src/test/java/TestCompilerOutput.java index 567ebde..6a7c031 100644 --- a/src/test/java/TestCompilerOutput.java +++ b/src/test/java/TestCompilerOutput.java @@ -1,10 +1,10 @@ /** * This class is used to test the output of the compiler. * - *

Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbstkompilierte CompilerInput.java Datei sein. - *
Hinweis: Diese muss man also vom Ordner classFileOutput in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)

+ *

Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbst kompilierte CompilerInput.class Datei sein. + *
Hinweis: Diese muss man also vom Ordner main/resources/output in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)

* - *

Die selbstkompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. + *

Die selbst kompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. *

Diese TestCompilerOutput.java Datei wird dann in \src\test\java> mit javac .\TestCompilerOutput.java kompiliert und mit java TestCompilerOutput ausgeführt. * Wenn unser Compiler funktioniert, sollten keine Errors kommen (sondern nur die Ausgaben, die wir in der CompilerInput.java Datei gemacht haben, * oder Methoden, die wir hier aufrufen).

diff --git a/src/test/java/parser/ParserTest.java b/src/test/java/parser/ParserTest.java new file mode 100644 index 0000000..834f988 --- /dev/null +++ b/src/test/java/parser/ParserTest.java @@ -0,0 +1,4 @@ +package parser; + +public class ParserTest { +} From f59d7e99182f7529f85a741d123d4c1a05d5dd5b Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:42:50 +0200 Subject: [PATCH 10/25] First Tests for Parser, pls check --- src/main/java/Main.java | 11 +- src/test/Makefile | 6 +- src/test/TestSpecs.md | 27 ++-- src/test/java/FailureTest.java | 22 ++-- src/test/java/parser/ParserTest.java | 183 +++++++++++++++++++++++++++ 5 files changed, 212 insertions(+), 37 deletions(-) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 7174d66..21d9349 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -49,17 +49,16 @@ public class Main { /* ------------------------- Scanner -> tokens ------------------------- */ SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); + tokenStream.fill(); // Printing the tokens - tokenStream.fill(); + System.out.println("-------------------- Scanner -> Tokens --------------------"); List tokens = tokenStream.getTokens(); - System.out.println("-------------------- Scanner -> tokens --------------------"); for (Token token : tokens) { String tokenType = SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType()); String tokenText = token.getText(); - // System.out.println("Token Type: " + tokenType + ", Token Text: " + - // tokenText); + // System.out.println("Token Type: " + tokenType + ", Token Text: " + tokenText); System.out.println(tokenType + " " + tokenText); } System.out.println(); @@ -70,8 +69,8 @@ public class Main { // Printing the parse tree System.out.println("-------------------- Parser -> Parsetree --------------------"); - System.out.println(parseTree.toStringTree(parser)); - printTree(parseTree, parser, 0); + System.out.println(parseTree.toStringTree(parser)); //one line representation + // printTree(parseTree, parser, 0); System.out.println(); /*------------------------- AST builder -> AST -------------------------*/ diff --git a/src/test/Makefile b/src/test/Makefile index 1329f1d..1498d17 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -14,11 +14,11 @@ compile-raupenpiler: test: test-javac test-raupenpiler test-javac: - compile-javac - java -cp .\resources\output\javac CompilerInput + #compile-javac + #java -cp .\resources\output\javac CompilerInput test-raupenpiler: - java -cp .\resources\output\raupenpiler CompilerInput + #java -cp .\resources\output\raupenpiler CompilerInput clean: rm -f ./resources/output/javac/*.class diff --git a/src/test/TestSpecs.md b/src/test/TestSpecs.md index 75f979a..cbdc1f5 100644 --- a/src/test/TestSpecs.md +++ b/src/test/TestSpecs.md @@ -18,6 +18,8 @@ ## Scanner Output +CommonTokenStream + ### Beispiel 1: Empty Class Token Type; Token Text @@ -28,26 +30,20 @@ Type gibts nur bei Terminalen, Text bei allen Bsp von Ihm mal: [TokPublic,TokClass,TokIdentifier "Name",TokLeftBrace,TokRightBrace] -### Beispiel 2: Filled Class - - [TokClass,TokIdentifier "javaFileInput.Example",TokLeftBrace] - [TokIf,TokLeftParen,TokIdentifier "x",TokLessThan,TokNumber 5,TokRightParen,TokLeftBrace] - [TokFor,TokLeftParen,TokIdentifier "int",TokIdentifier "i",TokAssign,TokNumber 0,TokSemicolon,TokIdentifier "i",TokLessThan,TokNumber 10,TokSemicolon,TokIdentifier "i",TokPlus,TokPlus,TokRightParen,TokLeftBrace] - [TokWhile,TokLeftParen,TokIdentifier "true",TokRightParen,TokLeftBrace] - [TokIdentifier "x",TokAssign,TokNumber 5,TokSemicolon] - [TokRightBrace] - # Parser ## Parser Input +CommonTokenStream (Scanner Output) ## Parser Output (AST) -### Beispiel 1: Empty Class +(program (classDeclaration (accessType public) class Name { })) -### Beispiel 2: Filled Class +ParseTree + +### Beispiel 1: Empty Class # Semantische Analyse / Typcheck @@ -59,8 +55,6 @@ Type gibts nur bei Terminalen, Text bei allen ### Beispiel 1: Empty Class -### Beispiel 2: Filled Class - # Bytecodegenerierung ## Bytecodegenerierung Input @@ -76,8 +70,6 @@ Compiled Classfile public class javaFileInput.Example { } -### Beispiel 2: Filled Class - ## E2E Tests: - Testdatei mit Main ausführen/kompilieren @@ -85,13 +77,14 @@ Compiled Classfile - -> Dateien mit javap vergleichen wenn beides erfolgreich + - Ergebnis vom eigenen Compiler mithilfe von TestCompilerOutput ausführen - (Ergebnis von javac mithilfe von TestCompilerOutput ausführen) - ### Andis Tipps: + - cp mitgeben -- makefile +- makefile - java -jar pfadtocompiler.jar EmptyClass.java - mvn package - javac tester // tester compilen diff --git a/src/test/java/FailureTest.java b/src/test/java/FailureTest.java index 028c5d1..f131e33 100644 --- a/src/test/java/FailureTest.java +++ b/src/test/java/FailureTest.java @@ -15,17 +15,17 @@ import java.util.List; public class FailureTest { private static final List TEST_FILES = Arrays.asList( - "src/main/test/resources/failureTests/TestClass1.java", - "src/main/test/resources/failureTests/TestClass2.java", - "src/main/test/resources/failureTests/TestClass3.java", - "src/main/test/resources/failureTests/TestClass4.java", - "src/main/test/resources/failureTests/TestClass5.java", - "src/main/test/resources/failureTests/TestClass6.java", - "src/main/test/resources/failureTests/TestClass7.java", - "src/main/test/resources/failureTests/TestClass8.java", - "src/main/test/resources/failureTests/TestClass9.java", - "src/main/test/resources/failureTests/TestClass10.java", - "src/main/test/resources/failureTests/TestClass11.java" + "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" ); /** diff --git a/src/test/java/parser/ParserTest.java b/src/test/java/parser/ParserTest.java index 834f988..173f1ce 100644 --- a/src/test/java/parser/ParserTest.java +++ b/src/test/java/parser/ParserTest.java @@ -1,4 +1,187 @@ package parser; +import ast.ProgramNode; +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.generated.SimpleJavaLexer; +import parser.generated.SimpleJavaParser; + +import static org.junit.jupiter.api.Assertions.*; + +import java.nio.file.Paths; +import java.util.*; +import java.util.function.BooleanSupplier; + 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() { + // 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 parseTree = parser.program(); // parse the input + + //Variante 1 (geht) + String actualParseTreeAsString = parseTree.toStringTree(parser); + String expectedParseTreeAsString = "(program (classDeclaration (accessType public) class Name { }))"; + + assertEquals(actualParseTreeAsString, expectedParseTreeAsString); + + //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); + Map expectedTreeStructure = parseStringToTree(expectedParseTreeAsString); + + assertEquals(actualTreeStructure, expectedTreeStructure); + + + } + + @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 + + public static Map buildTreeStructure(ParseTree tree, Parser parser) { + return buildTree(tree, parser, 0); + } + + private static Map buildTree(ParseTree tree, Parser parser, int indent) { + Map node = new HashMap<>(); + + if (tree instanceof RuleContext) { + int ruleIndex = ((RuleContext) tree).getRuleIndex(); + String ruleName = parser.getRuleNames()[ruleIndex]; + node.put("rule", ruleName); + } else { + node.put("text", tree.getText()); + } + + List> children = new ArrayList<>(); + for (int i = 0; i < tree.getChildCount(); i++) { + children.add(buildTree(tree.getChild(i), parser, indent + 1)); + } + + if (!children.isEmpty()) { + node.put("children", children); + } + + return node; + } + + // Helpers Variante 2.2 + + public static Map parseStringToTree(String input) { + input = input.trim(); + if (input.startsWith("(") && input.endsWith(")")) { + input = input.substring(1, input.length() - 1).trim(); + } + return parse(input); + } + + private static Map parse(String input) { + Map node = new HashMap<>(); + StringBuilder currentToken = new StringBuilder(); + List> children = new ArrayList<>(); + + int depth = 0; + boolean inToken = false; + for (char ch : input.toCharArray()) { + if (ch == '(') { + if (depth == 0) { + if (currentToken.length() > 0) { + node.put("node", currentToken.toString().trim()); + currentToken.setLength(0); + } + } else { + currentToken.append(ch); + } + depth++; + } else if (ch == ')') { + depth--; + if (depth == 0) { + children.add(parse(currentToken.toString().trim())); + currentToken.setLength(0); + } else { + currentToken.append(ch); + } + } else if (Character.isWhitespace(ch) && depth == 0) { + if (currentToken.length() > 0) { + node.put("node", currentToken.toString().trim()); + currentToken.setLength(0); + } + } else { + currentToken.append(ch); + } + } + + if (currentToken.length() > 0) { + node.put("node", currentToken.toString().trim()); + } + + if (!children.isEmpty()) { + node.put("children", children); + } + + return node; + } } From 102961bccc072e2481c31d03a133f5b0f5b604c0 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:49:46 +0200 Subject: [PATCH 11/25] Added logging --- src/main/java/Main.java | 146 ++++++++-------------- src/main/java/MyLogger.java | 178 +++++++++++++++++++++++++++ src/test/Makefile | 3 +- src/test/java/parser/ParserTest.java | 3 - 4 files changed, 229 insertions(+), 101 deletions(-) create mode 100644 src/main/java/MyLogger.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 21d9349..6e26428 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,4 +1,3 @@ -import ast.ASTNode; import ast.ProgramNode; import parser.ASTBuilder; import parser.generated.SimpleJavaLexer; @@ -11,7 +10,7 @@ import org.antlr.v4.runtime.tree.ParseTree; import java.io.IOException; import java.nio.file.Paths; -import java.util.List; + /** * Start Raupenpiler with the following commands: @@ -19,6 +18,8 @@ import java.util.List; *

make clean compile-raupenpiler */ public class Main { + + public static void main(String[] args) throws Exception { if (args.length > 0) { // args[0] is the input file path @@ -45,105 +46,56 @@ public class Main { */ } - static void compileFile(CharStream inputCharStream, String outputDirectoryPath) { - /* ------------------------- Scanner -> tokens ------------------------- */ - SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - tokenStream.fill(); - - // Printing the tokens - System.out.println("-------------------- Scanner -> Tokens --------------------"); - List tokens = tokenStream.getTokens(); - for (Token token : tokens) { - String tokenType = - SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType()); - String tokenText = token.getText(); - // System.out.println("Token Type: " + tokenType + ", Token Text: " + tokenText); - System.out.println(tokenType + " " + tokenText); - } - System.out.println(); - - /*------------------------- Parser -> Parsetree -------------------------*/ - SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree parseTree = parser.program(); // parse the input - - // Printing the parse tree - System.out.println("-------------------- Parser -> Parsetree --------------------"); - System.out.println(parseTree.toStringTree(parser)); //one line representation - // 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(); - - /*------------------------- Semantic Analyzer -> typed AST -------------------------*/ - ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); - - // Printing the typed AST - System.out.println("-------------------- Semantic Analyzer -> typed AST --------------------"); - printAST(typedAst, 0); - System.out.println(); - - /*------------------------- Bytecode Generator -> Bytecode -------------------------*/ - 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. - * It recursively traverses the tree and prints the rule names and text of the - * nodes. - * - * @param tree The parse tree to be printed. - * @param parser The parser used to parse the input. It's used to get the rule - * names. - * @param indent The current indentation level. It's used to format the output. - */ - public static void printTree(ParseTree tree, Parser parser, int indent) { - // Create an indentation string based on the current indentation level - String indentString = " ".repeat(indent * 2); + * 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: + *

1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream. + *

2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree. + *

3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST). + *

4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST. + *

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 MyLogger(); - // If the tree node is an instance of RuleContext (i.e., it's an internal node), - // print the rule name - if (tree instanceof RuleContext) { - int ruleIndex = ((RuleContext) tree).getRuleIndex(); - String ruleName = parser.getRuleNames()[ruleIndex]; - System.out.println(indentString + ruleName); - } else { - // If the tree node is not an instance of RuleContext (i.e., it's a leaf node), - // print the text of the node - System.out.println(indentString + tree.getText()); - } + /* ------------------------- 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 + MyLogger.logScanner(tokenStream); - // Recursively print the children of the current node, increasing the - // indentation level - for (int i = 0; i < tree.getChildCount(); i++) { - printTree(tree.getChild(i), parser, indent + 1); - } - } + /*------------------------- Parser -> Parse tree -------------------------*/ + // 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 + MyLogger.logParser(parseTree, parser); - // TODO: Fix this method - public static void printAST(ASTNode node, int indent) { - if (node == null) { - System.out.println("null"); - return; - } - String indentString = " ".repeat(indent * 2); - System.out.println(indentString + node.getClass().toString()); + /*------------------------- AST builder -> AST -------------------------*/ + // Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST) + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + // Log the AST + MyLogger.logAST(abstractSyntaxTree); - // for (ASTNode child : node.) { - // printAST(child, indent + 1); - // } - } + /*------------------------- Semantic Analyzer -> typed AST -------------------------*/ + // Use the SemanticAnalyzer to generate a typed AST + ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); + // Log the typed AST + MyLogger.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(typedAst); + // Log the bytecode generation + MyLogger.logBytecodeGenerator(); +} } \ No newline at end of file diff --git a/src/main/java/MyLogger.java b/src/main/java/MyLogger.java new file mode 100644 index 0000000..1ab206f --- /dev/null +++ b/src/main/java/MyLogger.java @@ -0,0 +1,178 @@ +import ast.ASTNode; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.ParseTree; +import parser.generated.SimpleJavaLexer; +import parser.generated.SimpleJavaParser; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +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); + */ +public class MyLogger { + + static Logger logger = Logger.getLogger("RaupenLogs"); + + public MyLogger() { + // ------------------------- Logging ------------------------- + logger.setLevel(Level.ALL); + logger.getParent().getHandlers()[0].setLevel(Level.ALL); + logger.setUseParentHandlers(false); + + // Custom formatter class + class CustomFormatter extends Formatter { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss dd-MM-yyyy"); + + @Override + public String format(LogRecord record) { + return formatMessage(record) + System.lineSeparator(); + } + + @Override + public String getHead(Handler h) { + Date now = new Date(); + String dateTime = dateFormat.format(now); + return "Log Start Time: " + dateTime + "\n" + + "Logger Name: " + h.getFormatter().getClass().getName() + "\n\n"; + } + } + + try { + // Configure console handler + Handler consoleHandler = new ConsoleHandler(); + // Toggle console logging on/off + consoleHandler.setLevel(Level.OFF); + consoleHandler.setFormatter(new CustomFormatter()); + logger.addHandler(consoleHandler); + + // Configure file handler + Handler fileHandler = new FileHandler("src/main/resources/logs/RaupenLog.log"); + // Toggle file logging on/off + fileHandler.setLevel(Level.ALL); + fileHandler.setFormatter(new CustomFormatter()); + logger.addHandler(fileHandler); + + } catch (SecurityException | IOException e) { + e.printStackTrace(); + } + } + + public static void logScanner(CommonTokenStream tokenStream) { + // Printing the tokens + logger.info("-------------------- Scanner -> Tokens --------------------"); + List tokens = tokenStream.getTokens(); + for (Token token : tokens) { + String tokenType = + SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType()); + String tokenText = token.getText(); + // logger.info("Token Type: " + tokenType + ", Token Text: " + tokenText); + logger.info(tokenType + " " + tokenText); + } + logger.info("\n"); + } + + public static void logParser(ParseTree parseTree, SimpleJavaParser parser) { + // Printing the parse tree + logger.info("-------------------- Parser -> Parsetree --------------------"); + logger.info(parseTree.toStringTree(parser)); //one line representation + logTree(parseTree, parser, 0); + logger.info("\n"); + } + + public static void logAST(ASTNode node) { + // Printing the AST + logger.info("-------------------- AST builder -> AST --------------------"); + // logger.info("AST: " + ast.toString()); + logAST(node, 0); + logger.info("\n"); + } + + public static void logSemanticAnalyzer(ASTNode node) { + // Printing the typed AST + logger.info("-------------------- Semantic Analyzer -> typed AST --------------------"); + logAST(node, 0); + logger.info("\n"); + } + + public static void logBytecodeGenerator() { + // Printing the bytecode + logger.info("-------------------- Bytecode Generator -> Bytecode --------------------"); + logger.info("Bytecode generated"); + logger.info("\n"); + } + + + + + + + + + + /* ------------------------- Printing methods ------------------------- */ + + /** + * This method is used to print the parse tree in a structured format. + * It recursively traverses the tree and prints the rule names and text of the + * nodes. + * + * @param tree The parse tree to be printed. + * @param parser The parser used to parse the input. It's used to get the rule + * names. + * @param indent The current indentation level. It's used to format the output. + */ + public static void logTree(ParseTree tree, Parser parser, int indent) { + // Create an indentation string based on the current indentation level + String indentString = " ".repeat(indent * 2); + + // If the tree node is an instance of RuleContext (i.e., it's an internal node), + // print the rule name + if (tree instanceof RuleContext) { + int ruleIndex = ((RuleContext) tree).getRuleIndex(); + String ruleName = parser.getRuleNames()[ruleIndex]; + logger.info(indentString + ruleName); + } else { + // If the tree node is not an instance of RuleContext (i.e., it's a leaf node), + // print the text of the node + logger.info(indentString + tree.getText()); + } + + // Recursively print the children of the current node, increasing the + // indentation level + for (int i = 0; i < tree.getChildCount(); i++) { + logTree(tree.getChild(i), parser, indent + 1); + } + } + + // TODO: Fix this method + public static void logAST(ASTNode node, int indent) { + if (node == null) { + System.out.println("null"); + return; + } + String indentString = " ".repeat(indent * 2); + logger.info(indentString + node.getClass().toString()); + + // for (ASTNode child : node.) { + // printAST(child, indent + 1); + // } + } +} diff --git a/src/test/Makefile b/src/test/Makefile index 1498d17..b9c9ecb 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ # Makefile ### IntelliJs play buttons do not work. Run in "src/test" folder with "make" command to run all -### Or run only parts with "make compile-javac", "make delete" etc. +### Or run only parts with "make compile-javac", "make clean" etc. all: compile-javac compile-raupenpiler @@ -25,4 +25,5 @@ clean: rm -f ./resources/output/raupenpiler/*.class rm -f ./java/*.class rm -f ../main/resources/output/*.class + rm -f ../main/resources/logs/*.log diff --git a/src/test/java/parser/ParserTest.java b/src/test/java/parser/ParserTest.java index 173f1ce..d599632 100644 --- a/src/test/java/parser/ParserTest.java +++ b/src/test/java/parser/ParserTest.java @@ -1,6 +1,5 @@ package parser; -import ast.ProgramNode; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.tree.ParseTree; import org.junit.jupiter.api.BeforeEach; @@ -10,9 +9,7 @@ import parser.generated.SimpleJavaParser; import static org.junit.jupiter.api.Assertions.*; -import java.nio.file.Paths; import java.util.*; -import java.util.function.BooleanSupplier; public class ParserTest { @BeforeEach From 8f742191bb9d0d5fcf62af22343a5f464eb5ac14 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:19:47 +0200 Subject: [PATCH 12/25] Small changes --- src/main/java/Main.java | 21 ++++++++++--------- .../java/{MyLogger.java => RaupenLogger.java} | 20 +++++++++--------- src/main/java/bytecode/ClassCodeGen.java | 2 +- 3 files changed, 22 insertions(+), 21 deletions(-) rename src/main/java/{MyLogger.java => RaupenLogger.java} (92%) diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 6e26428..54758ff 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,3 +1,4 @@ +import ast.ASTNode; import ast.ProgramNode; import parser.ASTBuilder; import parser.generated.SimpleJavaLexer; @@ -60,7 +61,7 @@ public class Main { */ static void compileFile(CharStream inputCharStream, String outputDirectoryPath) { // Initialize the logger - new MyLogger(); + new RaupenLogger(); /* ------------------------- Scanner -> tokens ------------------------- */ // Use the SimpleJavaLexer to tokenize the input CharStream @@ -68,34 +69,34 @@ static void compileFile(CharStream inputCharStream, String outputDirectoryPath) CommonTokenStream tokenStream = new CommonTokenStream(lexer); tokenStream.fill(); // Log the tokens - MyLogger.logScanner(tokenStream); + RaupenLogger.logScanner(tokenStream); - /*------------------------- Parser -> Parse tree -------------------------*/ + /*------------------------- 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 - MyLogger.logParser(parseTree, parser); + 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(); - ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + ASTNode abstractSyntaxTree = astBuilder.visit(parseTree); // Log the AST - MyLogger.logAST(abstractSyntaxTree); + RaupenLogger.logAST(abstractSyntaxTree); /*------------------------- Semantic Analyzer -> typed AST -------------------------*/ // Use the SemanticAnalyzer to generate a typed AST - ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); + ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree); // Log the typed AST - MyLogger.logSemanticAnalyzer(typedAst); + 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(typedAst); + byteCodeGenerator.visit((ProgramNode) typedAst); // Log the bytecode generation - MyLogger.logBytecodeGenerator(); + RaupenLogger.logBytecodeGenerator(); } } \ No newline at end of file diff --git a/src/main/java/MyLogger.java b/src/main/java/RaupenLogger.java similarity index 92% rename from src/main/java/MyLogger.java rename to src/main/java/RaupenLogger.java index 1ab206f..5d17415 100644 --- a/src/main/java/MyLogger.java +++ b/src/main/java/RaupenLogger.java @@ -27,11 +27,11 @@ import java.util.logging.*; consoleHandler.setLevel(Level.OFF); fileHandler.setLevel(Level.ALL); */ -public class MyLogger { +public class RaupenLogger { static Logger logger = Logger.getLogger("RaupenLogs"); - public MyLogger() { + public RaupenLogger() { // ------------------------- Logging ------------------------- logger.setLevel(Level.ALL); logger.getParent().getHandlers()[0].setLevel(Level.ALL); @@ -97,18 +97,18 @@ public class MyLogger { logger.info("\n"); } - public static void logAST(ASTNode node) { + public static void logAST(ASTNode abstractSyntaxTree) { // Printing the AST logger.info("-------------------- AST builder -> AST --------------------"); // logger.info("AST: " + ast.toString()); - logAST(node, 0); + logAST(abstractSyntaxTree, 0); logger.info("\n"); } - public static void logSemanticAnalyzer(ASTNode node) { + public static void logSemanticAnalyzer(ASTNode typedAst) { // Printing the typed AST logger.info("-------------------- Semantic Analyzer -> typed AST --------------------"); - logAST(node, 0); + logAST(typedAst, 0); logger.info("\n"); } @@ -163,13 +163,13 @@ public class MyLogger { } // TODO: Fix this method - public static void logAST(ASTNode node, int indent) { - if (node == null) { - System.out.println("null"); + public static void logAST(ASTNode abstractSyntaxTree, int indent) { + if (abstractSyntaxTree == null) { + logger.severe("AST is null !!!"); return; } String indentString = " ".repeat(indent * 2); - logger.info(indentString + node.getClass().toString()); + logger.info(indentString + abstractSyntaxTree.getClass()); // for (ASTNode child : node.) { // printAST(child, indent + 1); diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index d8cdaaa..089b567 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -57,7 +57,7 @@ public class ClassCodeGen implements ClassVisitor { private void printIntoClassFile(byte[] byteCode, String name) { // String outputDirectoryPath = "src/main/resources/output"; - System.out.println("Output directory path: " + outputDirectoryPath); + // System.out.println("Output directory path: " + outputDirectoryPath); File directory = new File(outputDirectoryPath); if (!directory.exists()) { directory.mkdirs(); From cfcb61d49e172a159bcf307ca05359ee391b4861 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 19 Jun 2024 16:32:46 +0200 Subject: [PATCH 13/25] Running now possible with make or java.exe -jar in console --- .gitignore | 4 +- pom.xml | 22 ++++ src/main/java/Main.java | 102 ----------------- src/main/java/main/Main.java | 108 ++++++++++++++++++ src/main/java/{ => main}/RaupenLogger.java | 2 + src/test/Makefile | 4 +- src/test/TestSpecs.md | 6 +- .../java/{ => main}/EmptyClassExample.java | 2 + src/test/java/{ => main}/FailureTest.java | 4 +- src/test/java/{ => main}/MainTest.java | 2 + .../java/{ => main}/TestCompilerOutput.java | 6 +- 11 files changed, 151 insertions(+), 111 deletions(-) delete mode 100644 src/main/java/Main.java create mode 100644 src/main/java/main/Main.java rename src/main/java/{ => main}/RaupenLogger.java (99%) rename src/test/java/{ => main}/EmptyClassExample.java (65%) rename src/test/java/{ => main}/FailureTest.java (97%) rename src/test/java/{ => main}/MainTest.java (97%) rename src/test/java/{ => main}/TestCompilerOutput.java (86%) diff --git a/.gitignore b/.gitignore index c134c76..8f74459 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,6 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser -/target \ No newline at end of file +/target +src/main/resources/logs/RaupenLog.log +src/main/resources/output/CompilerInput.class diff --git a/pom.xml b/pom.xml index e6506ea..27cbd7f 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,28 @@ maven-surefire-plugin 3.0.0-M5 + + maven-assembly-plugin + + + make-assembly + package + + single + + + + + + + main.Main + + + + jar-with-dependencies + + + diff --git a/src/main/java/Main.java b/src/main/java/Main.java deleted file mode 100644 index 54758ff..0000000 --- a/src/main/java/Main.java +++ /dev/null @@ -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: - *

cd .\src\test\ - *

make clean compile-raupenpiler - */ -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: - *

1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream. - *

2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree. - *

3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST). - *

4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST. - *

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(); -} -} \ No newline at end of file diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java new file mode 100644 index 0000000..5384677 --- /dev/null +++ b/src/main/java/main/Main.java @@ -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: + *

cd .\src\test\ + *

make clean compile-raupenpiler + *

Start Raupenpiler using jar: + *

java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory' + *

Example: + * java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-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 > 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: + *

1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream. + *

2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree. + *

3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST). + *

4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST. + *

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(); + } +} \ No newline at end of file diff --git a/src/main/java/RaupenLogger.java b/src/main/java/main/RaupenLogger.java similarity index 99% rename from src/main/java/RaupenLogger.java rename to src/main/java/main/RaupenLogger.java index 5d17415..4ea499f 100644 --- a/src/main/java/RaupenLogger.java +++ b/src/main/java/main/RaupenLogger.java @@ -1,3 +1,5 @@ +package main; + import ast.ASTNode; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.Parser; diff --git a/src/test/Makefile b/src/test/Makefile index b9c9ecb..e3e7d75 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -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 diff --git a/src/test/TestSpecs.md b/src/test/TestSpecs.md index cbdc1f5..0911765 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 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 \ No newline at end of file +- -> tester ist in unserem Fall main.TestCompilerOutput.java \ No newline at end of file diff --git a/src/test/java/EmptyClassExample.java b/src/test/java/main/EmptyClassExample.java similarity index 65% rename from src/test/java/EmptyClassExample.java rename to src/test/java/main/EmptyClassExample.java index 9f54ec6..e7715be 100644 --- a/src/test/java/EmptyClassExample.java +++ b/src/test/java/main/EmptyClassExample.java @@ -1,3 +1,5 @@ +package main; + public class EmptyClassExample { private class Inner { } diff --git a/src/test/java/FailureTest.java b/src/test/java/main/FailureTest.java similarity index 97% rename from src/test/java/FailureTest.java rename to src/test/java/main/FailureTest.java index f131e33..5a2e1c8 100644 --- a/src/test/java/FailureTest.java +++ b/src/test/java/main/FailureTest.java @@ -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()); diff --git a/src/test/java/MainTest.java b/src/test/java/main/MainTest.java similarity index 97% rename from src/test/java/MainTest.java rename to src/test/java/main/MainTest.java index eec63b0..363fa35 100644 --- a/src/test/java/MainTest.java +++ b/src/test/java/main/MainTest.java @@ -1,3 +1,5 @@ +package main; + import org.junit.jupiter.api.Test; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; diff --git a/src/test/java/TestCompilerOutput.java b/src/test/java/main/TestCompilerOutput.java similarity index 86% rename from src/test/java/TestCompilerOutput.java rename to src/test/java/main/TestCompilerOutput.java index 6a7c031..6a30e14 100644 --- a/src/test/java/TestCompilerOutput.java +++ b/src/test/java/main/TestCompilerOutput.java @@ -1,11 +1,13 @@ +package main; + /** * This class is used to test the output of the compiler. * - *

Im gleichen Ordner wie diese Datei (TestCompilerOutput.java) muss die selbst kompilierte CompilerInput.class Datei sein. + *

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)

* *

Die selbst kompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden. - *

Diese TestCompilerOutput.java Datei wird dann in \src\test\java> mit javac .\TestCompilerOutput.java kompiliert und mit java TestCompilerOutput ausgeführt. + *

Diese main.TestCompilerOutput.java Datei wird dann in \src\test\java> mit javac .\main.TestCompilerOutput.java kompiliert und mit java main.TestCompilerOutput ausgeführt. * Wenn unser Compiler funktioniert, sollten keine Errors kommen (sondern nur die Ausgaben, die wir in der CompilerInput.java Datei gemacht haben, * oder Methoden, die wir hier aufrufen).

* From 8cc67080ecd2f22608ce4650538314d6159a6560 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:09:38 +0200 Subject: [PATCH 14/25] Small changes --- .gitignore | 4 ++++ pom.xml | 5 ++--- src/main/java/main/Main.java | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 8f74459..8c5079b 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,7 @@ fabric.properties /target src/main/resources/logs/RaupenLog.log src/main/resources/output/CompilerInput.class +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 diff --git a/pom.xml b/pom.xml index 27cbd7f..0baf035 100644 --- a/pom.xml +++ b/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.example + de.dhbw-stuttgart JavaCompiler - 1.0-SNAPSHOT + 1.0 22 @@ -69,5 +69,4 @@ - \ No newline at end of file diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java index 5384677..8b858b4 100644 --- a/src/main/java/main/Main.java +++ b/src/main/java/main/Main.java @@ -20,15 +20,15 @@ import java.nio.file.Paths; *

cd .\src\test\ *

make clean compile-raupenpiler *

Start Raupenpiler using jar: - *

java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory' - *

Example: + *

java.exe -jar path_to_jar\JavaCompiler-1.0-SNAPSHOT-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' */ public class Main { public static void main(String[] args) throws Exception { - if (args.length > 0) { + if (args.length == 2) { // args[0] is the input file path // args[1] is the output directory path String inputFilePath = args[0]; @@ -41,7 +41,7 @@ public class Main { System.err.println("Error reading the file: " + e.getMessage()); } } - /* !!! Else Branch ist nicht zur Verwendung vorgesehen, immer mit args starten !!! + /* !!! Else Branch (main ohne args starten) ist nicht zur Verwendung vorgesehen, immer mit args starten !!! else { try { CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java")); From fd8c3b066ab7efa11693cebcf847d8d185c12eb4 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Thu, 20 Jun 2024 11:43:58 +0200 Subject: [PATCH 15/25] Trying to change to new AST --- src/main/java/Main.java | 3 +- src/main/java/ast/member/MethodNode.java | 9 +- .../ast/statement/ReturnStatementNode.java | 4 - src/main/java/bytecode/ClassCodeGen.java | 11 +- src/main/java/bytecode/Mapper.java | 69 ++++---- src/main/java/bytecode/MethodCodeGen.java | 94 +++++----- src/main/java/semantic/Scope.java | 2 +- src/main/java/semantic/SemanticAnalyzer.java | 160 +----------------- src/main/java/semantic/SemanticVisitor.java | 29 +--- .../java/semantic/context/ClassContext.java | 4 +- src/main/java/semantic/context/Context.java | 2 +- .../java/semantic/context/FieldContext.java | 7 +- .../java/typechecker/TypeCheckResult.java | 2 +- src/test/java/semantic/Mocker.java | 72 ++------ src/test/java/semantic/SemanticTest.java | 150 +--------------- .../java/semantic/endToTAST/CorrectTest.java | 41 +++++ .../resources/semantic/endToTAST/Test.java | 7 + 17 files changed, 171 insertions(+), 495 deletions(-) create mode 100644 src/test/java/semantic/endToTAST/CorrectTest.java create mode 100644 src/test/resources/semantic/endToTAST/Test.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 779e5d1..61e2711 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,6 +1,5 @@ -import oldAst.ASTNode; +import ast.*; import org.antlr.v4.runtime.*; -import oldAst.ProgramNode; import bytecode.ByteCodeGenerator; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index e508629..2d79ee5 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -9,16 +9,15 @@ import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; -import java.util.ArrayList; import java.util.List; -public class MethodNode implements MemberNode { +public class MethodNode implements MemberNode, Visitable { AccessModifierNode accesModifier; TypeNode type; Boolean voidType; String identifier; List parameters; - BlockNode block; + public BlockNode block; public MethodNode() {} @@ -55,6 +54,8 @@ public class MethodNode implements MemberNode { return isSame; } + */ + @Override public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); @@ -64,6 +65,6 @@ public class MethodNode implements MemberNode { public void accept(MethodVisitor methodVisitor) { methodVisitor.visit(this); } - */ + } diff --git a/src/main/java/ast/statement/ReturnStatementNode.java b/src/main/java/ast/statement/ReturnStatementNode.java index ab111c5..ec80fb0 100644 --- a/src/main/java/ast/statement/ReturnStatementNode.java +++ b/src/main/java/ast/statement/ReturnStatementNode.java @@ -2,10 +2,6 @@ package ast.statement; import ast.ASTNode; import ast.expression.ExpressionNode; -import ast.type.TypeNode; - -import java.util.ArrayList; -import java.util.List; public class ReturnStatementNode implements ASTNode { public ExpressionNode expression; diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index b0afa69..c65c3c6 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -4,11 +4,10 @@ import ast.ClassNode; import ast.member.FieldNode; import ast.member.MemberNode; import ast.member.MethodNode; -import ast.type.BaseTypeNode; +import ast.type.TypeNode; import bytecode.visitor.ClassVisitor; import java.io.File; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; import java.io.FileOutputStream; import java.io.IOException; @@ -25,8 +24,8 @@ public class ClassCodeGen implements ClassVisitor { @Override public void visit(ClassNode classNode) { classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null, - "java/lang/Object", null); +// classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null, +// "java/lang/Object", null); for (MemberNode memberNode : classNode.members) { if (memberNode instanceof FieldNode) { @@ -45,8 +44,8 @@ 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 TypeNode baseTypeNode){ +// classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null ); } classWriter.visitEnd(); } diff --git a/src/main/java/bytecode/Mapper.java b/src/main/java/bytecode/Mapper.java index faa4a67..5dad54c 100644 --- a/src/main/java/bytecode/Mapper.java +++ b/src/main/java/bytecode/Mapper.java @@ -1,44 +1,41 @@ package bytecode; -import ast.parameter.ParameterNode; import ast.type.*; -import org.objectweb.asm.Opcodes; -import ast.type.BaseTypeNode; public class Mapper { - public int mapAccessTypeToOpcode(AccessTypeNode type) { - switch (type.enumAccessTypeNode) { - case EnumAccessTypeNode.PUBLIC: - return Opcodes.ACC_PUBLIC; - case EnumAccessTypeNode.PRIVATE: - return Opcodes.ACC_PRIVATE; - } - return 0; - } +// public int mapAccessTypeToOpcode(AccessModifierNode type) { +// switch (type.enumAccessTypeNode) { +// case EnumAccessTypeNode.PUBLIC: +// return Opcodes.ACC_PUBLIC; +// case EnumAccessTypeNode.PRIVATE: +// return Opcodes.ACC_PRIVATE; +// } +// return 0; +// } - public String generateMethodDescriptor(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) { - String descriptor = "("; - for(ParameterNode parameterNode : parameterListNode.parameters) { - descriptor += getTypeChar(EnumTypeNode.INT); - } - descriptor += ")"; - descriptor += getTypeChar(baseTypeNode.enumType); - return descriptor; - } +// public String generateMethodDescriptor(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) { +// String descriptor = "("; +// for(ParameterNode parameterNode : parameterListNode.parameters) { +// descriptor += getTypeChar(EnumTypeNode.INT); +// } +// descriptor += ")"; +// descriptor += getTypeChar(baseTypeNode.enumType); +// return descriptor; +// } - public String getTypeChar(EnumTypeNode enumTypeNode) { - String typeChar = ""; - switch (enumTypeNode) { - case EnumTypeNode.INT: - typeChar = "I"; - break; - case EnumTypeNode.CHAR: - typeChar = "C"; - break; - case EnumTypeNode.BOOLEAN: - typeChar = "Z"; - break; - } - return typeChar; - } +// public String getTypeChar(TypeEnum enumTypeNode) { +// String typeChar = ""; +// switch (enumTypeNode) { +// case TypeEnum.INT: +// typeChar = "I"; +// break; +// case TypeEnum.CHAR: +// typeChar = "C"; +// break; +// case TypeEnum.BOOLEAN: +// typeChar = "Z"; +// break; +// } +// return typeChar; +// } } diff --git a/src/main/java/bytecode/MethodCodeGen.java b/src/main/java/bytecode/MethodCodeGen.java index 1cdf1e2..358d540 100644 --- a/src/main/java/bytecode/MethodCodeGen.java +++ b/src/main/java/bytecode/MethodCodeGen.java @@ -2,12 +2,8 @@ package bytecode; import ast.member.ConstructorNode; import ast.member.MethodNode; -import ast.parameter.ParameterNode; -import ast.type.BaseTypeNode; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; import java.util.ArrayList; import java.util.List; @@ -31,12 +27,12 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor { @Override public void visit(ConstructorNode constructorNode) { - methodVisitor = - classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.visibility), - "", - "()V", - null, - null); +// methodVisitor = +// classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.visibility), +// "", +// "()V", +// null, +// null); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); @@ -47,52 +43,52 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor { @Override public void visit(MethodNode methodNode) { - if (methodNode.type instanceof BaseTypeNode baseTypeNode) { - methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility), - methodNode.identifier, - mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters), - null, - null); +// if (methodNode.type instanceof BaseTypeNode baseTypeNode) { +// methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility), +// methodNode.identifier, +// mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters), +// null, +// null); methodVisitor.visitCode(); localVaribales.add("this"); - for (ParameterNode parameterNode : methodNode.parameters.parameters) { - localVaribales.add(parameterNode.identifier); - } +// for (ParameterNode parameterNode : methodNode.parameters.parameters) { +// localVaribales.add(parameterNode.identifier); +// } //test(); methodVisitor.visitMaxs(1, localVaribales.size()); methodVisitor.visitEnd(); - } +// } } - public void test() { - Label start = new Label(); - Label loop = new Label(); - Label end = new Label(); - methodVisitor.visitLabel(start); - //methodVisitor.visitVarInsn(Opcodes.ICONST_M1, 99); - //methodVisitor.visitInsn(Opcodes.ICONST_5); - methodVisitor.visitLdcInsn(99); - // methodVisitor.visitInsn(Opcodes.ICONST_0); - //methodVisitor.visitVarInsn(Opcodes.ILOAD, 2); - methodVisitor.visitVarInsn(Opcodes.ISTORE, 1); - methodVisitor.visitLabel(loop); - methodVisitor.visitVarInsn(Opcodes.ILOAD, 1); - methodVisitor.visitInsn(Opcodes.ICONST_5); - methodVisitor.visitJumpInsn(Opcodes.IF_ICMPGE, end); - methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, - "java/lang/System", "out", - "Ljava/io/PrintStream;"); - methodVisitor.visitLdcInsn("Bytecode"); - methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, - "java/io/PrintStream", "println", - "(Ljava/lang/String;)V", false); - methodVisitor.visitIincInsn(1, 1); - methodVisitor.visitJumpInsn(Opcodes.GOTO, loop); - methodVisitor.visitLabel(end); - methodVisitor.visitVarInsn(Opcodes.ILOAD, 1); - methodVisitor.visitInsn(Opcodes.IRETURN); - methodVisitor.visitEnd(); - } +// public void test() { +// Label start = new Label(); +// Label loop = new Label(); +// Label end = new Label(); +// methodVisitor.visitLabel(start); +// //methodVisitor.visitVarInsn(Opcodes.ICONST_M1, 99); +// //methodVisitor.visitInsn(Opcodes.ICONST_5); +// methodVisitor.visitLdcInsn(99); +// // methodVisitor.visitInsn(Opcodes.ICONST_0); +// //methodVisitor.visitVarInsn(Opcodes.ILOAD, 2); +// methodVisitor.visitVarInsn(Opcodes.ISTORE, 1); +// methodVisitor.visitLabel(loop); +// methodVisitor.visitVarInsn(Opcodes.ILOAD, 1); +// methodVisitor.visitInsn(Opcodes.ICONST_5); +// methodVisitor.visitJumpInsn(Opcodes.IF_ICMPGE, end); +// methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, +// "java/lang/System", "out", +// "Ljava/io/PrintStream;"); +// methodVisitor.visitLdcInsn("Bytecode"); +// methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, +// "java/io/PrintStream", "println", +// "(Ljava/lang/String;)V", false); +// methodVisitor.visitIincInsn(1, 1); +// methodVisitor.visitJumpInsn(Opcodes.GOTO, loop); +// methodVisitor.visitLabel(end); +// methodVisitor.visitVarInsn(Opcodes.ILOAD, 1); +// methodVisitor.visitInsn(Opcodes.IRETURN); +// methodVisitor.visitEnd(); +// } } diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java index 60e9d2b..7cf4cc9 100644 --- a/src/main/java/semantic/Scope.java +++ b/src/main/java/semantic/Scope.java @@ -1,6 +1,6 @@ package semantic; -import oldAst.type.TypeNode; +import ast.type.TypeNode; import java.util.HashMap; import java.util.Stack; diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 3bce422..d3526f4 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -1,25 +1,16 @@ package semantic; -import oldAst.*; -import oldAst.expression.*; -import oldAst.member.FieldNode; -import oldAst.member.MemberNode; - -import oldAst.member.MethodNode; -import oldAst.parameter.ParameterListNode; -import oldAst.parameter.ParameterNode; -import oldAst.statement.*; -import oldAst.type.ReferenceTypeNode; -import oldAst.expression.This; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Objects; -import oldAst.type.BaseTypeNode; -import oldAst.type.TypeNode; +import ast.*; +import ast.member.*; +import ast.statement.*; +import ast.statement.ifstatement.IfStatementNode; +import ast.type.*; import semantic.context.Context; import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.NotDeclearedException; @@ -90,10 +81,7 @@ public class SemanticAnalyzer implements SemanticVisitor { for(MethodNode methode : currentClass.getMethods()){ if(methode.equals(methodNode)) break; - if(methode.isSame(methodNode)){ - errors.add(new AlreadyDeclearedException("This method has already been declared")); - valid = false; - } + } var result = methodNode.accept(this); valid = valid && result.isValid(); @@ -110,32 +98,6 @@ public class SemanticAnalyzer implements SemanticVisitor { currentScope.pushScope(); - //Parameter - ParameterListNode parameterListNode = methodNode.parameters; - if (parameterListNode != null) { - List parameters = parameterListNode.parameters; - for (ParameterNode parameter : parameters) { - if (currentScope.contains(parameter.identifier)) { - errors.add(new AlreadyDeclearedException("Duplicated Parameter " + parameter.identifier)); - return new TypeCheckResult(false, null); - } else { - currentScope.addLocalVar(parameter.identifier, parameter.type); - } - } - } - - //Statements - List statements = methodNode.statements; - for (StatementNode statement : statements) { - if (statement instanceof AssignmentStatementNode assignmentStatementNode) { - var result = assignmentStatementNode.accept(this); - valid = valid && result.isValid(); - } else if (statement instanceof VariableDeclarationStatementNode variableDeclarationStatementNode) { - var result = variableDeclarationStatementNode.accept(this); - valid = valid && result.isValid(); - } - } - currentScope.popScope(); return new TypeCheckResult(valid, null); } @@ -151,80 +113,6 @@ public class SemanticAnalyzer implements SemanticVisitor { return new TypeCheckResult(true, null); } - @Override - public TypeCheckResult analyze(AssignmentStatementNode assignmentStatementNode) { - boolean valid = true; - ExpressionNode expressionNodeLeft = assignmentStatementNode.expressionLeft; - var resultLeft = expressionNodeLeft.accept(this); - valid = valid && resultLeft.isValid(); - ExpressionNode expressionNodeRight = assignmentStatementNode.expressionRight; - var resultRight = expressionNodeRight.accept(this); - valid = valid && resultRight.isValid(); - - if(Objects.equals(resultLeft.getType(), resultRight.getType())){ - System.out.println("SAME TYPE"); - } else { - errors.add(new TypeMismatchException("Type mismatch")); - valid = false; - } - - return new TypeCheckResult(valid, null); - } - - @Override - public TypeCheckResult analyze(BinaryExpressionNode toCheck) { - boolean valid = true; - ExpressionNode left = toCheck.left; - var resultLeft = left.accept(this); - ExpressionNode right = toCheck.right; - var resultRight = right.accept(this); - - switch (toCheck.operator) { - case ASSIGNMENT: - if(Objects.equals(resultRight.getType(), resultLeft.getType())){ - System.out.println("Correct Type"); - } else { - valid = false; - errors.add(new TypeMismatchException("Type Mismatch " + resultLeft.getType() + " and " + resultRight.getType())); - } - break; - case DOT: - return new TypeCheckResult(true, resultRight.getType()); - default: - throw new RuntimeException("Unexpected operator: " + toCheck.operator); - } - - return new TypeCheckResult(valid, null); - } - - @Override - public TypeCheckResult analyze(IdentifierExpressionNode toCheck) { - if(toCheck.name == "this"){ - return new TypeCheckResult(true, null); - } else if (currentFields.get(toCheck.name) == null) { - errors.add(new AlreadyDeclearedException("Not declared " + toCheck.name + " in this scope")); - return new TypeCheckResult(false, null); - } else { - return new TypeCheckResult(false, currentFields.get(toCheck.name)); - } - } - - @Override - public TypeCheckResult analyze(UnaryExpressionNode toCheck) { - return null; - } - - @Override - public TypeCheckResult analyze(VariableDeclarationStatementNode toCheck) { - if (currentScope.contains(toCheck.identifier)) { - errors.add(new AlreadyDeclearedException("Already declared " + toCheck.identifier + " in this scope")); - return new TypeCheckResult(false, null); - } else { - currentScope.addLocalVar(toCheck.identifier, toCheck.type); - } - return new TypeCheckResult(true, null); - } - @Override public TypeCheckResult analyze(IfStatementNode toCheck) { return null; @@ -240,40 +128,4 @@ public class SemanticAnalyzer implements SemanticVisitor { return null; } - @Override - public TypeCheckResult analyze(LiteralNode toCheck) { - return new TypeCheckResult(true, toCheck.getType()); - } - - @Override - public TypeCheckResult analyze(InstVar toCheck) { - boolean valid = true; - - var result = toCheck.expression.accept(this); - - if(result.getType() instanceof BaseTypeNode){ - throw new RuntimeException("BaseType has no Methods or Fields"); - } else { - //Get typ of Field - - var type = (ReferenceTypeNode)result.getType(); - var classContext = context.getClass(type.getIdentifier()); - - if(classContext == null){ - errors.add(new NotDeclearedException("Not declared " + type.getIdentifier() + " in this scope")); - return new TypeCheckResult(false, null); - } else { - var field = classContext.getField(toCheck.identifier); - - return new TypeCheckResult(valid, field.getType()); - } - } - - } - - @Override - public TypeCheckResult analyze(This toCheck) { - return new TypeCheckResult(true, toCheck.getType()); - } - } \ No newline at end of file diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index 7139261..6bdc9a8 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -1,18 +1,10 @@ package semantic; -import ast.ClassNode; -import ast.expression.LiteralNode; -import ast.ProgramNode; -import ast.expression.BinaryExpressionNode; -import ast.expression.IdentifierExpressionNode; -import ast.expression.InstVar; -import ast.expression.unaryexpression.UnaryExpressionNode; -import ast.member.FieldNode; -import ast.member.MethodNode; +import ast.*; +import ast.member.*; import ast.statement.*; -import ast.expression.This; -import ast.statement.ifstatement.IfStatementNode; +import ast.statement.ifstatement.*; import typechecker.TypeCheckResult; public interface SemanticVisitor { @@ -25,25 +17,10 @@ public interface SemanticVisitor { TypeCheckResult analyze(FieldNode toCheck); - TypeCheckResult analyze(AssignmentStatementNode toCheck); - - TypeCheckResult analyze(BinaryExpressionNode toCheck); - - TypeCheckResult analyze(IdentifierExpressionNode toCheck); - - TypeCheckResult analyze(UnaryExpressionNode toCheck); - - TypeCheckResult analyze(VariableDeclarationStatementNode toCheck); - TypeCheckResult analyze(IfStatementNode toCheck); TypeCheckResult analyze(ReturnStatementNode toCheck); TypeCheckResult analyze(WhileStatementNode toCheck); - TypeCheckResult analyze(LiteralNode toCheck); - - TypeCheckResult analyze(InstVar toCheck); - - TypeCheckResult analyze(This toCheck); } \ No newline at end of file diff --git a/src/main/java/semantic/context/ClassContext.java b/src/main/java/semantic/context/ClassContext.java index 6b0d386..982866f 100644 --- a/src/main/java/semantic/context/ClassContext.java +++ b/src/main/java/semantic/context/ClassContext.java @@ -1,7 +1,7 @@ package semantic.context; -import oldAst.ClassNode; -import oldAst.member.FieldNode; +import ast.ClassNode; +import ast.member.FieldNode; import java.util.HashMap; public class ClassContext { diff --git a/src/main/java/semantic/context/Context.java b/src/main/java/semantic/context/Context.java index 31ba3de..d6431ef 100644 --- a/src/main/java/semantic/context/Context.java +++ b/src/main/java/semantic/context/Context.java @@ -1,6 +1,6 @@ package semantic.context; -import oldAst.ProgramNode; +import ast.ProgramNode; import java.util.HashMap; public class Context { diff --git a/src/main/java/semantic/context/FieldContext.java b/src/main/java/semantic/context/FieldContext.java index 2dad262..35c1f46 100644 --- a/src/main/java/semantic/context/FieldContext.java +++ b/src/main/java/semantic/context/FieldContext.java @@ -1,12 +1,11 @@ package semantic.context; -import oldAst.member.FieldNode; -import oldAst.type.AccessTypeNode; -import oldAst.type.TypeNode; +import ast.member.FieldNode; +import ast.type.*; public class FieldContext { - private AccessTypeNode accessModifier; + private AccessModifierNode accessModifier; private TypeNode type; public FieldContext(FieldNode field) { diff --git a/src/main/java/typechecker/TypeCheckResult.java b/src/main/java/typechecker/TypeCheckResult.java index a06d359..12143b2 100644 --- a/src/main/java/typechecker/TypeCheckResult.java +++ b/src/main/java/typechecker/TypeCheckResult.java @@ -1,7 +1,7 @@ package typechecker; -import oldAst.type.TypeNode; +import ast.type.TypeNode; public class TypeCheckResult { diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java index 8ab9434..a60e83b 100644 --- a/src/test/java/semantic/Mocker.java +++ b/src/test/java/semantic/Mocker.java @@ -1,76 +1,36 @@ package semantic; -import oldAst.ClassNode; -import oldAst.expression.LiteralNode; -import oldAst.ProgramNode; -import oldAst.expression.*; -import oldAst.member.FieldNode; -import oldAst.member.MemberNode; -import oldAst.member.MethodNode; -import oldAst.parameter.ParameterListNode; -import oldAst.parameter.ParameterNode; -import oldAst.statement.AssignmentStatementNode; -import oldAst.statement.StatementNode; -import oldAst.type.*; +import ast.*; +import ast.block.BlockNode; +import ast.member.MethodNode; import java.util.ArrayList; import java.util.List; +import static parser.generated.SimpleJavaParser.Identifier; + public class Mocker { - public static ProgramNode mockCorrectProgrammNode(){ + public static ProgramNode mockCorrectClass(){ + ProgramNode p = new ProgramNode(); - ProgramNode programNode = new ProgramNode(); - List classList = new ArrayList(); - AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); - ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); + ClassNode c = new ClassNode(); + c.identifier = "testClass"; - MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar1"); - classNode.members.add(memberNode1); + MethodNode m = new MethodNode(); - MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "objectVar"); - classNode.members.add(memberNode2); + BlockNode b = new BlockNode(); - List parameterNodeList = new ArrayList(); - ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1"); - parameterNodeList.add(parameterNode1); - ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList); - List statementNodeList = new ArrayList(); - ExpressionNode expressionNodeLeft = new InstVar(new This("testClass"), "objectVar"); +// b.statements.add(); - LiteralNode expressionNodeRight = new LiteralNode(); - expressionNodeRight.setType(new BaseTypeNode(EnumTypeNode.INT)); + m.block = b; - StatementNode statementNode1 = new AssignmentStatementNode(expressionNodeLeft, expressionNodeRight); - statementNodeList.add(statementNode1); - - MemberNode memberNode3 = new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2",parameterListNode, statementNodeList ); - classNode.members.add(memberNode3); - - classList.add(classNode); - programNode.classes = classList; - - return programNode; + c.members.add(m); + p.classes.add(c); + return p; } - public static ProgramNode mockFieldNodeAlreadyDeclaredProgrammNode(){ - ProgramNode programNode = new ProgramNode(); - List classList = new ArrayList(); - AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); - ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); - - MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); - classNode.members.add(memberNode1); - - MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); - classNode.members.add(memberNode2); - - classList.add(classNode); - programNode.classes = classList; - - return programNode; - } } diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index cc413a2..8554022 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -1,161 +1,13 @@ package semantic; - -import oldAst.*; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import semantic.exeptions.AlreadyDeclearedException; -import semantic.exeptions.TypeMismatchException; - -import java.io.File; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; public class SemanticTest { - @BeforeEach - public void init() { - SemanticAnalyzer.clearAnalyzier(); - } - @Test - public void alreadyDeclaredLocalFieldVar() { + public void correctClass(){ - //Arrange - ProgramNode programNode = Mocker.mockFieldNodeAlreadyDeclaredProgrammNode(); - - //Act - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - //Assert - - assertEquals(1, SemanticAnalyzer.errors.size()); - assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException); - assertEquals(null, typedAst); - - } - - @Test - public void alreadyDecleared() { - - //Arrange - - ProgramNode programNode = Mocker.mockFieldNodeAlreadyDeclaredProgrammNode(); - - //Act - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - //Assert - - assertEquals(1, SemanticAnalyzer.errors.size()); - assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); - assertNull(typedAst); - - } - - @Test - public void shouldWorkWithNoError() { - - //Arrange - - ProgramNode programNode = Mocker.mockCorrectProgrammNode(); - - //Act - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - //Assert - - assertEquals(0, SemanticAnalyzer.errors.size()); - assertEquals(programNode, typedAst); - - } - - @Test - public void refTypeCorrect() { - - //Arrange - - ObjectMapper objectMapper = new ObjectMapper(); - ProgramNode programNode = null; - try{ - programNode = objectMapper.readValue(new File("src/test/resources/semantic/correctRefType.json"), ProgramNode.class); - } catch (Exception e) { - e.printStackTrace(); - } - - //Act - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - //Assert - - assertEquals(0, SemanticAnalyzer.errors.size()); - assertEquals(programNode, typedAst); - - } - - @Test - public void jsonWriteTest() { - - ObjectMapper objectMapper = new ObjectMapper(); - - //Arrange - - ProgramNode programNode = Mocker.mockCorrectProgrammNode(); - try{ - objectMapper.writeValue(new File("src/test/resources/semantic/test.json"), programNode); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - @Test - public void jsonReadTest() { - - ObjectMapper objectMapper = new ObjectMapper(); - - ProgramNode programNode1 = null; - try{ - programNode1 = objectMapper.readValue(new File("src/test/resources/semantic/test.json"), ProgramNode.class); - } catch (Exception e) { - e.printStackTrace(); - } - - ProgramNode programNode2 = Mocker.mockCorrectProgrammNode(); - - } - - @Test - public void typeMismatch() { - - //Arrange - - ObjectMapper objectMapper = new ObjectMapper(); - ProgramNode programNode = null; - try{ - programNode = objectMapper.readValue(new File("src/test/resources/semantic/refTypeMismatch.json"), ProgramNode.class); - } catch (Exception e) { - e.printStackTrace(); - } - - //Act - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - //Assert - - assertEquals(1, SemanticAnalyzer.errors.size()); - assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); - assertNull(typedAst); } diff --git a/src/test/java/semantic/endToTAST/CorrectTest.java b/src/test/java/semantic/endToTAST/CorrectTest.java new file mode 100644 index 0000000..a8280fe --- /dev/null +++ b/src/test/java/semantic/endToTAST/CorrectTest.java @@ -0,0 +1,41 @@ +package semantic.endToTAST; + +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 java.io.IOException; +import java.nio.file.Paths; + +public class CorrectTest { + + @Test + public void first(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/Test.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); + + System.out.println("Test"); + + } + +} diff --git a/src/test/resources/semantic/endToTAST/Test.java b/src/test/resources/semantic/endToTAST/Test.java new file mode 100644 index 0000000..bd4e673 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/Test.java @@ -0,0 +1,7 @@ +public class Test { + + public void test(){ + + } + +} \ No newline at end of file From 0ec65af9f95e450c3f094ae395fb79be9d50960c Mon Sep 17 00:00:00 2001 From: Bruder John Date: Thu, 20 Jun 2024 16:53:31 +0200 Subject: [PATCH 16/25] Added Method Check --- src/main/java/ast/block/BlockNode.java | 11 ++- .../java/ast/expression/ExpressionNode.java | 4 +- .../unaryexpression/UnaryExpressionNode.java | 2 +- src/main/java/ast/member/MethodNode.java | 38 ++++---- .../java/ast/parameter/ParameterNode.java | 15 ++- .../LocalVariableDeclarationNode.java | 2 +- .../java/ast/statement/StatementNode.java | 6 +- src/main/java/ast/type/TypeNode.java | 6 ++ .../java/parser/astBuilder/ASTBuilder.java | 2 +- src/main/java/semantic/SemanticAnalyzer.java | 54 ++++++++++- src/main/java/semantic/SemanticVisitor.java | 7 ++ src/test/java/semantic/Mocker.java | 92 +++++++++++++++++-- src/test/java/semantic/SemanticTest.java | 51 +++++++++- .../java/semantic/endToTAST/CorrectTest.java | 10 ++ .../resources/semantic/endToTAST/Test.java | 5 +- 15 files changed, 261 insertions(+), 44 deletions(-) diff --git a/src/main/java/ast/block/BlockNode.java b/src/main/java/ast/block/BlockNode.java index a5ff3f7..67d9e81 100644 --- a/src/main/java/ast/block/BlockNode.java +++ b/src/main/java/ast/block/BlockNode.java @@ -2,11 +2,14 @@ package ast.block; import ast.ASTNode; import ast.statement.StatementNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; import java.util.ArrayList; import java.util.List; -public class BlockNode implements ASTNode { +public class BlockNode implements ASTNode, Visitable { public List statements = new ArrayList<>(); public BlockNode() {} @@ -14,4 +17,10 @@ public class BlockNode implements ASTNode { public void addStatement(StatementNode statement) { statements.add(statement); } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/expression/ExpressionNode.java b/src/main/java/ast/expression/ExpressionNode.java index 1566f3b..282b9b7 100644 --- a/src/main/java/ast/expression/ExpressionNode.java +++ b/src/main/java/ast/expression/ExpressionNode.java @@ -1,4 +1,6 @@ package ast.expression; -public class ExpressionNode { +import ast.ASTNode; + +public class ExpressionNode implements ASTNode { } diff --git a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java index fdb694a..38c014d 100644 --- a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java @@ -7,7 +7,7 @@ import ast.type.ValueNode; import java.util.Objects; -public class UnaryExpressionNode implements ASTNode { +public class UnaryExpressionNode extends ExpressionNode { String thisExp; String identifier; MemberAccessNode memberAccess; diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index 2d79ee5..bedfac2 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -9,14 +9,15 @@ import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; +import java.util.ArrayList; import java.util.List; public class MethodNode implements MemberNode, Visitable { AccessModifierNode accesModifier; - TypeNode type; + public TypeNode type; Boolean voidType; - String identifier; - List parameters; + public String identifier; + private List parameters = new ArrayList<>(); public BlockNode block; public MethodNode() {} @@ -37,24 +38,23 @@ public class MethodNode implements MemberNode, Visitable { this.parameters.add(parameter); } - /* - public boolean isSame(MethodNode methodNode){ - boolean isSame = false; - if(methodNode.identifier.equals(identifier)){ - if(parameters != null && methodNode.parameters != null){ - if(parameters.parameters.size() == methodNode.parameters.parameters.size()){ - for(int i = 0; i < parameters.parameters.size(); i++){ - if(parameters.parameters.get(i).identifier.equals(methodNode.parameters.parameters.get(i).identifier)){ - isSame = true; - } - } - } - } - } - return isSame; + public List getParameters() { + return parameters; } - */ + public boolean isSame(MethodNode methodNode){ + if (!this.identifier.equals(methodNode.identifier) || this.type.equals(methodNode.type) + || this.getParameters().size() != methodNode.getParameters().size()) { + return false; + } + + for (int i = 0; i < this.getParameters().size(); i++) { + if (this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) { + return false; + } + } + return true; + } @Override public TypeCheckResult accept(SemanticVisitor visitor) { diff --git a/src/main/java/ast/parameter/ParameterNode.java b/src/main/java/ast/parameter/ParameterNode.java index 3a6b5ec..9050f30 100644 --- a/src/main/java/ast/parameter/ParameterNode.java +++ b/src/main/java/ast/parameter/ParameterNode.java @@ -2,13 +2,22 @@ package ast.parameter; import ast.ASTNode; import ast.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; -public class ParameterNode implements ASTNode { - TypeNode type; - String identifier; +public class ParameterNode implements ASTNode, Visitable { + public TypeNode type; + public String identifier; public ParameterNode(TypeNode type, String identifier) { this.type = type; this.identifier = identifier; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/LocalVariableDeclarationNode.java b/src/main/java/ast/statement/LocalVariableDeclarationNode.java index 5b3900f..edee12b 100644 --- a/src/main/java/ast/statement/LocalVariableDeclarationNode.java +++ b/src/main/java/ast/statement/LocalVariableDeclarationNode.java @@ -4,7 +4,7 @@ import ast.ASTNode; import ast.expression.ExpressionNode; import ast.type.TypeNode; -public class LocalVariableDeclarationNode implements ASTNode { +public class LocalVariableDeclarationNode extends StatementNode { TypeNode type; String identifier; String assign; diff --git a/src/main/java/ast/statement/StatementNode.java b/src/main/java/ast/statement/StatementNode.java index c47d30c..e4e3862 100644 --- a/src/main/java/ast/statement/StatementNode.java +++ b/src/main/java/ast/statement/StatementNode.java @@ -1,2 +1,6 @@ -package ast.statement;public class StatementNode { +package ast.statement; + +import ast.ASTNode; + +public class StatementNode implements ASTNode { } diff --git a/src/main/java/ast/type/TypeNode.java b/src/main/java/ast/type/TypeNode.java index 6336208..adb4892 100644 --- a/src/main/java/ast/type/TypeNode.java +++ b/src/main/java/ast/type/TypeNode.java @@ -22,4 +22,10 @@ public class TypeNode { this.type = EnumTypeNode.IDENTIFIER; } } + + + public boolean equals(TypeNode o) { + return !o.type.equals(this.type); + } + } diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index 7760b5c..fa59e98 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -74,7 +74,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { } else { MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { - methodNode.addParameter((ParameterNode) visit(parameter)); +// methodNode.addParameter((ParameterNode) visit(parameter)); } return methodNode; } diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index d3526f4..8c7e833 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -7,13 +7,14 @@ import java.util.List; import java.util.Objects; import ast.*; +import ast.block.BlockNode; import ast.member.*; +import ast.parameter.ParameterNode; import ast.statement.*; import ast.statement.ifstatement.IfStatementNode; import ast.type.*; import semantic.context.Context; import semantic.exeptions.AlreadyDeclearedException; -import semantic.exeptions.NotDeclearedException; import semantic.exeptions.TypeMismatchException; import typechecker.TypeCheckResult; @@ -96,10 +97,47 @@ public class SemanticAnalyzer implements SemanticVisitor { public TypeCheckResult analyze(MethodNode methodNode) { var valid = true; - currentScope.pushScope(); + for (var otherMethod : currentClass.getMethods()) { + if (Objects.equals(otherMethod , methodNode)) + break; + if (otherMethod.isSame(methodNode)) { + errors.add(new AlreadyDeclearedException( + "Method " + methodNode.identifier + " is already defined in class " + + currentClass.identifier)); + valid = false; + } + } + currentScope.pushScope(); + for (var parameter : methodNode.getParameters()) { + var result = parameter.accept(this); + valid = valid && result.isValid(); + currentScope.addLocalVar(parameter.identifier, parameter.type); + } + // Check if this method is already declared + +// currentMethodReturnType = methodDecl.getType(); +// currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ + + // gesetzt ist, ist dieser der Rückgabewert der Methode + var result = methodNode.block.accept(this); + valid = valid && result.isValid(); currentScope.popScope(); - return new TypeCheckResult(valid, null); + var resultType = result.getType(); + + /* + if (resultType == null) { + resultType = new BaseType(Primitives.VOID); + } + if (!resultType.equals(methodDecl.getType())) { + errors.add(new TypeMismatchException("Method-Declaration " + methodDecl.getIdentifier() + " with type " + + methodDecl.getType() + " has at least one Mismatching return Type:" + + TypeHelper.generateLocationString(methodDecl.line, methodDecl.column, fileName))); + valid = false; + } + + */ + return new TypeCheckResult(valid, resultType); } @Override @@ -128,4 +166,14 @@ public class SemanticAnalyzer implements SemanticVisitor { return null; } + @Override + public TypeCheckResult analyze(ParameterNode toCheck) { + return new TypeCheckResult(true, null); + } + + @Override + public TypeCheckResult analyze(BlockNode toCheck) { + return new TypeCheckResult(true, null); + } + } \ No newline at end of file diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index 6bdc9a8..aca196b 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -2,7 +2,9 @@ package semantic; import ast.*; +import ast.block.BlockNode; import ast.member.*; +import ast.parameter.ParameterNode; import ast.statement.*; import ast.statement.ifstatement.*; import typechecker.TypeCheckResult; @@ -23,4 +25,9 @@ public interface SemanticVisitor { TypeCheckResult analyze(WhileStatementNode toCheck); + TypeCheckResult analyze(ParameterNode toCheck); + + TypeCheckResult analyze(BlockNode toCheck); + + } \ No newline at end of file diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java index a60e83b..5a5e014 100644 --- a/src/test/java/semantic/Mocker.java +++ b/src/test/java/semantic/Mocker.java @@ -2,7 +2,13 @@ package semantic; import ast.*; import ast.block.BlockNode; +import ast.member.FieldNode; import ast.member.MethodNode; +import ast.parameter.ParameterNode; +import ast.statement.StatementNode; +import ast.statement.statementexpression.NewDeclarationStatementExpressionNode; +import ast.type.AccessModifierNode; +import ast.type.TypeNode; import java.util.ArrayList; import java.util.List; @@ -11,26 +17,94 @@ import static parser.generated.SimpleJavaParser.Identifier; public class Mocker { - public static ProgramNode mockCorrectClass(){ + public static ASTNode mockTwoSameFields(){ ProgramNode p = new ProgramNode(); ClassNode c = new ClassNode(); c.identifier = "testClass"; - MethodNode m = new MethodNode(); + FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a"); - BlockNode b = new BlockNode(); + c.members.add(f1); + FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a"); - -// b.statements.add(); - - m.block = b; - - c.members.add(m); + c.members.add(f2); p.classes.add(c); return p; } + public static ASTNode mockSimpleMethod(){ + ProgramNode p = new ProgramNode(); + + ClassNode c = new ClassNode(); + + MethodNode methodNode = new MethodNode(); + + //Parameter + ParameterNode parameterNode = new ParameterNode(new TypeNode("int"), "a"); + + methodNode.addParameter(parameterNode); + + //Statements + + //Block + methodNode.block = new BlockNode(); + + c.members.add(methodNode); + + p.classes.add(c); + + return p; + } + + public static ASTNode mockTwoSameMethods(){ + ProgramNode p = new ProgramNode(); + + ClassNode c = new ClassNode(); + + MethodNode methodNode = new MethodNode(); + methodNode.block = new BlockNode(); + methodNode.type = new TypeNode("int"); + + methodNode.identifier = "testMethod"; + + c.members.add(methodNode); + + MethodNode methodNode1 = new MethodNode(); + methodNode1.block = new BlockNode(); + methodNode1.type = new TypeNode("int"); + + methodNode1.identifier = "testMethod"; + + c.members.add(methodNode1); + + p.classes.add(c); + + return p; + } + + public static ASTNode mockTwoDifferentMethods(){ + ProgramNode p = new ProgramNode(); + + ClassNode c = new ClassNode(); + + MethodNode methodNode = new MethodNode(); + methodNode.block = new BlockNode(); + methodNode.identifier = "testMethod"; + + c.members.add(methodNode); + + MethodNode methodNode1 = new MethodNode(); + methodNode1.block = new BlockNode(); + methodNode1.identifier = "testMethod1"; + + c.members.add(methodNode1); + + p.classes.add(c); + + return p; + } + } diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index 8554022..7ebc7ad 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -1,14 +1,63 @@ package semantic; +import ast.ASTNode; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import semantic.exeptions.AlreadyDeclearedException; + +import static org.junit.jupiter.api.Assertions.*; public class SemanticTest { + @BeforeEach + public void setup(){ + SemanticAnalyzer.clearAnalyzier(); + } + @Test - public void correctClass(){ + public void twoFieldsSameName() { + ASTNode ast = Mocker.mockTwoSameFields(); + ASTNode tast = SemanticAnalyzer.generateTast(ast); + + assertEquals(SemanticAnalyzer.errors.size(), 1); + assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + assertNull(tast); } + @Test + public void simpleMethod(){ + + ASTNode ast = Mocker.mockSimpleMethod(); + + ASTNode tast = SemanticAnalyzer.generateTast(ast); + + assertEquals(SemanticAnalyzer.errors.size(), 0); + assertNotNull(tast); + + } + + @Test + public void twoSameMethods(){ + ASTNode ast = Mocker.mockTwoSameMethods(); + + ASTNode tast = SemanticAnalyzer.generateTast(ast); + + assertEquals(1, SemanticAnalyzer.errors.size()); + assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + assertNull(tast); + } + + @Test + public void twoDifferentMethods(){ + ASTNode ast = Mocker.mockTwoDifferentMethods(); + + ASTNode tast = SemanticAnalyzer.generateTast(ast); + + assertEquals(SemanticAnalyzer.errors.size(), 0); + assertNotNull(tast); + } + } diff --git a/src/test/java/semantic/endToTAST/CorrectTest.java b/src/test/java/semantic/endToTAST/CorrectTest.java index a8280fe..e3a7a08 100644 --- a/src/test/java/semantic/endToTAST/CorrectTest.java +++ b/src/test/java/semantic/endToTAST/CorrectTest.java @@ -1,5 +1,6 @@ package semantic.endToTAST; +import ast.ASTNode; import ast.ProgramNode; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; @@ -9,10 +10,13 @@ import org.junit.jupiter.api.Test; import parser.astBuilder.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; +import semantic.SemanticAnalyzer; import java.io.IOException; import java.nio.file.Paths; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class CorrectTest { @Test @@ -36,6 +40,12 @@ public class CorrectTest { System.out.println("Test"); + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + System.out.println("Errors: " + SemanticAnalyzer.errors.size()); + + assertEquals(SemanticAnalyzer.errors.size(), 0); + } } diff --git a/src/test/resources/semantic/endToTAST/Test.java b/src/test/resources/semantic/endToTAST/Test.java index bd4e673..d067998 100644 --- a/src/test/resources/semantic/endToTAST/Test.java +++ b/src/test/resources/semantic/endToTAST/Test.java @@ -1,7 +1,6 @@ public class Test { - public void test(){ - - } + public boolean b; + public boolean b; } \ No newline at end of file From d3e9fa9b43d844b3d0e5090341e22e820a937d12 Mon Sep 17 00:00:00 2001 From: i22035 Date: Thu, 20 Jun 2024 17:52:54 +0200 Subject: [PATCH 17/25] Added Public to Attributes --- src/main/java/ast/IdentifierNode.java | 4 ---- .../CalculationExpressionNode.java | 6 +++--- .../binaryexpression/DotExpressionNode.java | 6 +++--- .../DotSubstractionExpressionNode.java | 10 +++++----- .../NonCalculationExpressionNode.java | 6 +++--- .../unaryexpression/MemberAccessNode.java | 4 ++-- .../unaryexpression/NotExpressionNode.java | 2 +- .../unaryexpression/UnaryExpressionNode.java | 14 +++++++------- src/main/java/ast/member/MethodNode.java | 12 ++++++------ src/main/java/ast/parameter/ParameterNode.java | 4 ++-- src/main/java/ast/statement/ForStatementNode.java | 8 ++++---- .../statement/LocalVariableDeclarationNode.java | 8 ++++---- src/main/java/ast/statement/StatementNode.java | 4 +++- .../java/ast/statement/WhileStatementNode.java | 4 ++-- .../statement/ifstatement/ElseStatementNode.java | 2 +- .../statement/ifstatement/IfElseStatementNode.java | 4 ++-- .../ast/statement/ifstatement/IfStatementNode.java | 4 ++-- .../AssignStatementExpressionNode.java | 4 ++-- .../AssignableExpressionNode.java | 4 ++-- .../statementexpression/IncrementExpression.java | 5 ----- .../NewDeclarationStatementExpressionNode.java | 4 ++-- .../crementExpression/DecrementExpressionNode.java | 4 ++-- .../crementExpression/IncrementExpressionNode.java | 4 ++-- .../ChainedMethodNode.java | 4 ++-- .../MethodCallStatementExpressionNode.java | 8 ++++---- .../methodcallstatementnexpression/TargetNode.java | 8 ++++---- src/main/java/ast/type/AccessModifierNode.java | 2 +- src/main/java/ast/type/TypeNode.java | 2 +- src/main/java/ast/type/ValueNode.java | 4 ++-- 29 files changed, 74 insertions(+), 81 deletions(-) delete mode 100644 src/main/java/ast/IdentifierNode.java delete mode 100644 src/main/java/ast/statement/statementexpression/IncrementExpression.java diff --git a/src/main/java/ast/IdentifierNode.java b/src/main/java/ast/IdentifierNode.java deleted file mode 100644 index cd09699..0000000 --- a/src/main/java/ast/IdentifierNode.java +++ /dev/null @@ -1,4 +0,0 @@ -package ast; - -public class IdentifierNode { -} diff --git a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java index ec3ab61..4d29cf5 100644 --- a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java @@ -3,9 +3,9 @@ package ast.expression.binaryexpression; import ast.ASTNode; public class CalculationExpressionNode implements ASTNode { - CalculationExpressionNode calculationExpression; - String operator; - DotExpressionNode dotExpression; + public CalculationExpressionNode calculationExpression; + public String operator; + public DotExpressionNode dotExpression; public CalculationExpressionNode(CalculationExpressionNode calculationExpression, String operator, DotExpressionNode dotExpression) { this.calculationExpression = calculationExpression; diff --git a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java index 1418fe5..5a0f5bb 100644 --- a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java @@ -3,9 +3,9 @@ package ast.expression.binaryexpression; import ast.ASTNode; public class DotExpressionNode implements ASTNode { - DotExpressionNode dotExpression; - String operator; - DotSubstractionExpressionNode dotSubstractionExpression; + public DotExpressionNode dotExpression; + public String operator; + public DotSubstractionExpressionNode dotSubstractionExpression; public DotExpressionNode(DotExpressionNode dotExpression, String operator, DotSubstractionExpressionNode dotSubstractionExpression) { this.dotExpression = dotExpression; diff --git a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java index e32863c..848ea14 100644 --- a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java @@ -6,11 +6,11 @@ import ast.statement.statementexpression.methodcallstatementnexpression.MethodCa import ast.type.ValueNode; public class DotSubstractionExpressionNode implements ASTNode { - ValueNode value; - String identifier; - MemberAccessNode memberAccess; - MethodCallStatementExpressionNode methodCall; - CalculationExpressionNode calculationExpression; + public ValueNode value; + public String identifier; + public MemberAccessNode memberAccess; + public MethodCallStatementExpressionNode methodCall; + public CalculationExpressionNode calculationExpression; public DotSubstractionExpressionNode(ValueNode value) { this.value = value; diff --git a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java index 1c1c674..ab3f3bd 100644 --- a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java @@ -5,9 +5,9 @@ import ast.expression.ExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; public class NonCalculationExpressionNode implements ASTNode { - UnaryExpressionNode unaryExpression; - String operator; - ExpressionNode expression; + public UnaryExpressionNode unaryExpression; + public String operator; + public ExpressionNode expression; public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, ExpressionNode expression) { this.unaryExpression = unaryExpression; diff --git a/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java b/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java index fb33d6e..1a50aa9 100644 --- a/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java +++ b/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java @@ -6,8 +6,8 @@ import java.util.ArrayList; import java.util.List; public class MemberAccessNode implements ASTNode { - Boolean thisExpr; - List identifiers = new ArrayList<>(); + public Boolean thisExpr; + public List identifiers = new ArrayList<>(); public MemberAccessNode(Boolean thisExpr) { this.thisExpr = thisExpr; diff --git a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java index e04a2fd..9f3192a 100644 --- a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java @@ -4,7 +4,7 @@ import ast.ASTNode; import ast.expression.ExpressionNode; public class NotExpressionNode implements ASTNode { - ExpressionNode expression; + public ExpressionNode expression; public NotExpressionNode(ExpressionNode expression) { this.expression = expression; diff --git a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java index fdb694a..db9ab53 100644 --- a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java @@ -8,13 +8,13 @@ import ast.type.ValueNode; import java.util.Objects; public class UnaryExpressionNode implements ASTNode { - String thisExp; - String identifier; - MemberAccessNode memberAccess; - ValueNode value; - NotExpressionNode notExpression; - StatementNode statement; - ExpressionNode expression; + public String thisExp; + public String identifier; + public MemberAccessNode memberAccess; + public ValueNode value; + public NotExpressionNode notExpression; + public StatementNode statement; + public ExpressionNode expression; public UnaryExpressionNode(String value) { if(Objects.equals(value, "this")) { diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index e508629..18932af 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -13,12 +13,12 @@ import java.util.ArrayList; import java.util.List; public class MethodNode implements MemberNode { - AccessModifierNode accesModifier; - TypeNode type; - Boolean voidType; - String identifier; - List parameters; - BlockNode block; + public AccessModifierNode accesModifier; + public TypeNode type; + public Boolean voidType; + public String identifier; + public List parameters; + public BlockNode block; public MethodNode() {} diff --git a/src/main/java/ast/parameter/ParameterNode.java b/src/main/java/ast/parameter/ParameterNode.java index 3a6b5ec..1969e85 100644 --- a/src/main/java/ast/parameter/ParameterNode.java +++ b/src/main/java/ast/parameter/ParameterNode.java @@ -4,8 +4,8 @@ import ast.ASTNode; import ast.type.TypeNode; public class ParameterNode implements ASTNode { - TypeNode type; - String identifier; + public TypeNode type; + public String identifier; public ParameterNode(TypeNode type, String identifier) { this.type = type; diff --git a/src/main/java/ast/statement/ForStatementNode.java b/src/main/java/ast/statement/ForStatementNode.java index 5a4b442..7b3219e 100644 --- a/src/main/java/ast/statement/ForStatementNode.java +++ b/src/main/java/ast/statement/ForStatementNode.java @@ -4,10 +4,10 @@ import ast.ASTNode; import ast.expression.ExpressionNode; public class ForStatementNode implements ASTNode { - ExpressionNode statementExpressionInit; - StatementNode localVariableDeclarationInit; - ExpressionNode expression; - ExpressionNode statementExpression; + public ExpressionNode statementExpressionInit; + public StatementNode localVariableDeclarationInit; + public ExpressionNode expression; + public ExpressionNode statementExpression; public ForStatementNode(ExpressionNode statementExpressionInit, ExpressionNode expression, ExpressionNode statementExpression) { this.statementExpressionInit = statementExpressionInit; diff --git a/src/main/java/ast/statement/LocalVariableDeclarationNode.java b/src/main/java/ast/statement/LocalVariableDeclarationNode.java index 5b3900f..7c0ddaf 100644 --- a/src/main/java/ast/statement/LocalVariableDeclarationNode.java +++ b/src/main/java/ast/statement/LocalVariableDeclarationNode.java @@ -5,10 +5,10 @@ import ast.expression.ExpressionNode; import ast.type.TypeNode; public class LocalVariableDeclarationNode implements ASTNode { - TypeNode type; - String identifier; - String assign; - ExpressionNode expression; + public TypeNode type; + public String identifier; + public String assign; + public ExpressionNode expression; public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, ExpressionNode expression) { this.type = type; diff --git a/src/main/java/ast/statement/StatementNode.java b/src/main/java/ast/statement/StatementNode.java index c47d30c..544b8b8 100644 --- a/src/main/java/ast/statement/StatementNode.java +++ b/src/main/java/ast/statement/StatementNode.java @@ -1,2 +1,4 @@ -package ast.statement;public class StatementNode { +package ast.statement; + +public class StatementNode { } diff --git a/src/main/java/ast/statement/WhileStatementNode.java b/src/main/java/ast/statement/WhileStatementNode.java index 72d017d..8a34d66 100644 --- a/src/main/java/ast/statement/WhileStatementNode.java +++ b/src/main/java/ast/statement/WhileStatementNode.java @@ -5,8 +5,8 @@ import ast.block.BlockNode; import ast.expression.ExpressionNode; public class WhileStatementNode implements ASTNode { - ExpressionNode expression; - BlockNode block; + public ExpressionNode expression; + public BlockNode block; public WhileStatementNode(ExpressionNode expression, BlockNode block) { this.expression = expression; diff --git a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java index cedfefc..18f4e0e 100644 --- a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java @@ -4,7 +4,7 @@ import ast.ASTNode; import ast.block.BlockNode; public class ElseStatementNode implements ASTNode { - BlockNode block; + public BlockNode block; public ElseStatementNode(BlockNode block) { this.block = block; diff --git a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java index dcdc6ca..9b7ac8e 100644 --- a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java @@ -6,8 +6,8 @@ import java.util.ArrayList; import java.util.List; public class IfElseStatementNode implements ASTNode { - IfStatementNode ifStatement; - List elseStatements = new ArrayList<>(); + public IfStatementNode ifStatement; + public List elseStatements = new ArrayList<>(); public IfElseStatementNode(IfStatementNode ifStatement) { this.ifStatement = ifStatement; diff --git a/src/main/java/ast/statement/ifstatement/IfStatementNode.java b/src/main/java/ast/statement/ifstatement/IfStatementNode.java index 4731758..2b383fc 100644 --- a/src/main/java/ast/statement/ifstatement/IfStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfStatementNode.java @@ -5,8 +5,8 @@ import ast.block.BlockNode; import ast.expression.ExpressionNode; public class IfStatementNode implements ASTNode { - ExpressionNode expression; - BlockNode block; + public ExpressionNode expression; + public BlockNode block; public IfStatementNode(ExpressionNode expression, BlockNode block) { this.expression = expression; diff --git a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java index d993f48..8dbad08 100644 --- a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java @@ -4,8 +4,8 @@ import ast.ASTNode; import ast.expression.ExpressionNode; public class AssignStatementExpressionNode implements ASTNode { - AssignableExpressionNode assignable; - ExpressionNode expression; + public AssignableExpressionNode assignable; + public ExpressionNode expression; public AssignStatementExpressionNode(AssignableExpressionNode assignable, ExpressionNode expression) { this.assignable = assignable; diff --git a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java index cf9b96e..e9d0d30 100644 --- a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java @@ -4,8 +4,8 @@ import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; public class AssignableExpressionNode implements ASTNode { - String identifier; - MemberAccessNode memberAccess; + public String identifier; + public MemberAccessNode memberAccess; public AssignableExpressionNode(String identifier) { this.identifier = identifier; diff --git a/src/main/java/ast/statement/statementexpression/IncrementExpression.java b/src/main/java/ast/statement/statementexpression/IncrementExpression.java deleted file mode 100644 index 2a4d9fa..0000000 --- a/src/main/java/ast/statement/statementexpression/IncrementExpression.java +++ /dev/null @@ -1,5 +0,0 @@ -package ast.statement.statementexpression; - -public class IncrementExpression { - -} diff --git a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java index 6683b46..69a61c2 100644 --- a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java @@ -7,8 +7,8 @@ import java.util.ArrayList; import java.util.List; public class NewDeclarationStatementExpressionNode implements ASTNode { - String identifier; - List expressions = new ArrayList<>(); + public String identifier; + public List expressions = new ArrayList<>(); public NewDeclarationStatementExpressionNode(String identifier) { this.identifier = identifier; diff --git a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java index 5b4a9d9..0d09c5d 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java @@ -4,8 +4,8 @@ import ast.ASTNode; import ast.statement.statementexpression.AssignableExpressionNode; public class DecrementExpressionNode implements ASTNode { - CrementType crementType; - AssignableExpressionNode assignableExpression; + public CrementType crementType; + public AssignableExpressionNode assignableExpression; public DecrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) { this.assignableExpression = assignableExpression; diff --git a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java index a16233f..815482d 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java @@ -4,8 +4,8 @@ import ast.ASTNode; import ast.statement.statementexpression.AssignableExpressionNode; public class IncrementExpressionNode implements ASTNode { - CrementType crementType; - AssignableExpressionNode assignableExpression; + public CrementType crementType; + public AssignableExpressionNode assignableExpression; public IncrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) { this.assignableExpression = assignableExpression; diff --git a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java index 759f197..a196f73 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java @@ -7,8 +7,8 @@ import java.util.ArrayList; import java.util.List; public class ChainedMethodNode implements ASTNode { - String identifier; - List expressions = new ArrayList<>(); + public String identifier; + public List expressions = new ArrayList<>(); public ChainedMethodNode(String identifier) { this.identifier = identifier; diff --git a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java index 5fcaba1..1dc6a07 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java @@ -7,10 +7,10 @@ import java.util.ArrayList; import java.util.List; public class MethodCallStatementExpressionNode implements ASTNode { - TargetNode target; - List chainedMethods = new ArrayList<>(); - String identifier; - List expressions = new ArrayList<>(); + public TargetNode target; + public List chainedMethods = new ArrayList<>(); + public String identifier; + public List expressions = new ArrayList<>(); public MethodCallStatementExpressionNode(TargetNode target, String identifier) { this.target = target; diff --git a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/TargetNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/TargetNode.java index d8c0c54..7a18125 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/TargetNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/TargetNode.java @@ -5,10 +5,10 @@ import ast.expression.unaryexpression.MemberAccessNode; import ast.statement.statementexpression.NewDeclarationStatementExpressionNode; public class TargetNode implements ASTNode { - Boolean thisTar; - MemberAccessNode memberAccess; - NewDeclarationStatementExpressionNode newDeclaration; - String identifier; + public Boolean thisTar; + public MemberAccessNode memberAccess; + public NewDeclarationStatementExpressionNode newDeclaration; + public String identifier; public TargetNode(Boolean thisTar) { this.thisTar = thisTar; diff --git a/src/main/java/ast/type/AccessModifierNode.java b/src/main/java/ast/type/AccessModifierNode.java index 14081db..45f9172 100644 --- a/src/main/java/ast/type/AccessModifierNode.java +++ b/src/main/java/ast/type/AccessModifierNode.java @@ -1,7 +1,7 @@ package ast.type; public class AccessModifierNode { - EnumAccessModifierNode accessType; + public EnumAccessModifierNode accessType; public AccessModifierNode(String accessModifier) { setModifier(accessModifier); diff --git a/src/main/java/ast/type/TypeNode.java b/src/main/java/ast/type/TypeNode.java index 6336208..8a831cc 100644 --- a/src/main/java/ast/type/TypeNode.java +++ b/src/main/java/ast/type/TypeNode.java @@ -1,7 +1,7 @@ package ast.type; public class TypeNode { - EnumTypeNode type; + public EnumTypeNode type; public TypeNode(String type) { setType(type); diff --git a/src/main/java/ast/type/ValueNode.java b/src/main/java/ast/type/ValueNode.java index d188006..b51f799 100644 --- a/src/main/java/ast/type/ValueNode.java +++ b/src/main/java/ast/type/ValueNode.java @@ -3,8 +3,8 @@ package ast.type; import ast.ASTNode; public class ValueNode implements ASTNode { - EnumValueNode valueType; - String value; + public EnumValueNode valueType; + public String value; public ValueNode(EnumValueNode valueType, String value) { this.valueType = valueType; From 50a52a1e87b890b6e75d86f4018ac76e011132d2 Mon Sep 17 00:00:00 2001 From: i22035 Date: Thu, 20 Jun 2024 18:44:42 +0200 Subject: [PATCH 18/25] Added Interface --- src/main/java/Main.java | 18 +++++----- src/main/java/ast/ClassNode.java | 17 +-------- src/main/java/ast/ProgramNode.java | 16 +-------- src/main/java/ast/block/BlockNode.java | 6 ++-- .../java/ast/expression/ExpressionNode.java | 4 --- .../java/ast/expression/IExpressionNode.java | 5 +++ .../binaryexpression/BinaryExpression.java | 4 --- .../BinaryExpressionNode.java | 7 ++++ .../CalculationExpressionNode.java | 2 +- .../binaryexpression/DotExpressionNode.java | 2 +- .../DotSubstractionExpressionNode.java | 2 +- .../NonCalculationExpressionNode.java | 8 ++--- .../unaryexpression/NotExpressionNode.java | 6 ++-- .../unaryexpression/UnaryExpressionNode.java | 15 ++++---- src/main/java/ast/member/ConstructorNode.java | 12 ++----- src/main/java/ast/member/FieldNode.java | 16 +-------- src/main/java/ast/member/MethodNode.java | 12 +++---- .../java/ast/statement/ForStatementNode.java | 16 ++++----- .../java/ast/statement/IStatementNode.java | 6 ++++ .../LocalVariableDeclarationNode.java | 8 ++--- .../ast/statement/ReturnStatementNode.java | 12 +++---- .../java/ast/statement/StatementNode.java | 4 --- .../ast/statement/WhileStatementNode.java | 8 ++--- .../ifstatement/ElseStatementNode.java | 3 +- .../ifstatement/IfElseStatementNode.java | 3 +- .../ifstatement/IfStatementNode.java | 9 ++--- .../AssignStatementExpressionNode.java | 8 ++--- .../AssignableExpressionNode.java | 2 +- .../IStatementExpressionNode.java | 5 +++ ...NewDeclarationStatementExpressionNode.java | 8 ++--- .../DecrementExpressionNode.java | 3 +- .../IncrementExpressionNode.java | 3 +- .../ChainedMethodNode.java | 6 ++-- .../MethodCallStatementExpressionNode.java | 9 ++--- .../java/parser/astBuilder/ASTBuilder.java | 36 +++++++++---------- src/main/resources/CompilerInput.java | 5 ++- 36 files changed, 131 insertions(+), 175 deletions(-) delete mode 100644 src/main/java/ast/expression/ExpressionNode.java create mode 100644 src/main/java/ast/expression/IExpressionNode.java delete mode 100644 src/main/java/ast/expression/binaryexpression/BinaryExpression.java create mode 100644 src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java create mode 100644 src/main/java/ast/statement/IStatementNode.java delete mode 100644 src/main/java/ast/statement/StatementNode.java create mode 100644 src/main/java/ast/statement/statementexpression/IStatementExpressionNode.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 779e5d1..0551ed9 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,7 +1,7 @@ -import oldAst.ASTNode; +import ast.ASTNode; import org.antlr.v4.runtime.*; -import oldAst.ProgramNode; -import bytecode.ByteCodeGenerator; +import ast.ProgramNode; +//import bytecode.ByteCodeGenerator; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.tree.ParseTree; @@ -9,7 +9,7 @@ import org.antlr.v4.runtime.CommonTokenStream; import parser.astBuilder.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; -import semantic.SemanticAnalyzer; +//import semantic.SemanticAnalyzer; import java.io.IOException; import java.nio.file.Paths; @@ -60,7 +60,7 @@ public class Main { /* ------------------------- AST builder -> AST ------------------------- */ ASTBuilder astBuilder = new ASTBuilder(); ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); - + System.out.println(abstractSyntaxTree); // Printing the AST // System.out.println("-------------------- AST builder -> AST --------------------"); // // System.out.println("AST: " + ast.toString()); @@ -70,8 +70,8 @@ public class Main { /* * ------------------------- Semantic Analyzer -> Tast ------------------------- */ - SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); - ProgramNode typedAst = (ProgramNode) semanticAnalyzer.generateTast(abstractSyntaxTree); + //SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); + //ProgramNode typedAst = (ProgramNode) semanticAnalyzer.generateTast(abstractSyntaxTree); // Printing the Tast System.out.println("Tast generated"); @@ -80,9 +80,9 @@ public class Main { * ------------------------- Bytecode Generator -> Bytecode * ------------------------- */ - ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); + //ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); //byteCodeGenerator.generateByteCode(abstractSyntaxTree); - byteCodeGenerator.visit(typedAst); + //byteCodeGenerator.visit(typedAst); System.out.println("Bytecode generated"); } diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index a21044a..783d4f8 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -1,19 +1,14 @@ package ast; import ast.type.AccessModifierNode; -import ast.type.EnumAccessModifierNode; -import bytecode.visitor.ClassVisitor; import ast.member.ConstructorNode; import ast.member.MemberNode; import ast.member.MethodNode; -import semantic.SemanticVisitor; -import typechecker.TypeCheckResult; -import visitor.Visitable; import java.util.ArrayList; import java.util.List; -public class ClassNode implements ASTNode, Visitable { +public class ClassNode implements ASTNode { public AccessModifierNode accessType; public String identifier; public List members = new ArrayList<>(); @@ -50,14 +45,4 @@ public class ClassNode implements ASTNode, Visitable { } return methods; } - - @Override - public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.analyze(this); - } - - @Override - public void accept(ClassVisitor classVisitor) { - classVisitor.visit(this); - } } diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index f8ad19a..9174692 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -1,27 +1,13 @@ package ast; -import bytecode.visitor.ProgramVisitor; -import semantic.SemanticVisitor; -import typechecker.TypeCheckResult; -import visitor.Visitable; - import java.util.ArrayList; import java.util.List; -public class ProgramNode implements ASTNode, Visitable { +public class ProgramNode implements ASTNode { public List classes = new ArrayList<>(); public void addClass(ClassNode classNode) { classes.add(classNode); } - @Override - public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.analyze(this); - } - - @Override - public void accept(ProgramVisitor programVisitor) { - programVisitor.visit(this); - } } diff --git a/src/main/java/ast/block/BlockNode.java b/src/main/java/ast/block/BlockNode.java index a5ff3f7..9de2e5c 100644 --- a/src/main/java/ast/block/BlockNode.java +++ b/src/main/java/ast/block/BlockNode.java @@ -1,17 +1,17 @@ package ast.block; import ast.ASTNode; -import ast.statement.StatementNode; +import ast.statement.IStatementNode; import java.util.ArrayList; import java.util.List; public class BlockNode implements ASTNode { - public List statements = new ArrayList<>(); + public List statements = new ArrayList<>(); public BlockNode() {} - public void addStatement(StatementNode statement) { + public void addStatement(IStatementNode statement) { statements.add(statement); } } diff --git a/src/main/java/ast/expression/ExpressionNode.java b/src/main/java/ast/expression/ExpressionNode.java deleted file mode 100644 index 1566f3b..0000000 --- a/src/main/java/ast/expression/ExpressionNode.java +++ /dev/null @@ -1,4 +0,0 @@ -package ast.expression; - -public class ExpressionNode { -} diff --git a/src/main/java/ast/expression/IExpressionNode.java b/src/main/java/ast/expression/IExpressionNode.java new file mode 100644 index 0000000..775ac7a --- /dev/null +++ b/src/main/java/ast/expression/IExpressionNode.java @@ -0,0 +1,5 @@ +package ast.expression; + +import ast.ASTNode; + +public interface IExpressionNode extends ASTNode {} diff --git a/src/main/java/ast/expression/binaryexpression/BinaryExpression.java b/src/main/java/ast/expression/binaryexpression/BinaryExpression.java deleted file mode 100644 index fb161f3..0000000 --- a/src/main/java/ast/expression/binaryexpression/BinaryExpression.java +++ /dev/null @@ -1,4 +0,0 @@ -package ast.expression.binaryexpression; - -public class BinaryExpression { -} diff --git a/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java new file mode 100644 index 0000000..4afdff4 --- /dev/null +++ b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java @@ -0,0 +1,7 @@ +package ast.expression.binaryexpression; + +import ast.expression.IExpressionNode; + +import java.beans.Expression; + +public class BinaryExpressionNode implements IExpressionNode {} diff --git a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java index 4d29cf5..442d44e 100644 --- a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java @@ -2,7 +2,7 @@ package ast.expression.binaryexpression; import ast.ASTNode; -public class CalculationExpressionNode implements ASTNode { +public class CalculationExpressionNode extends BinaryExpressionNode { public CalculationExpressionNode calculationExpression; public String operator; public DotExpressionNode dotExpression; diff --git a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java index 5a0f5bb..c335d52 100644 --- a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java @@ -2,7 +2,7 @@ package ast.expression.binaryexpression; import ast.ASTNode; -public class DotExpressionNode implements ASTNode { +public class DotExpressionNode extends BinaryExpressionNode { public DotExpressionNode dotExpression; public String operator; public DotSubstractionExpressionNode dotSubstractionExpression; diff --git a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java index 848ea14..69d467d 100644 --- a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java @@ -5,7 +5,7 @@ import ast.expression.unaryexpression.MemberAccessNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.type.ValueNode; -public class DotSubstractionExpressionNode implements ASTNode { +public class DotSubstractionExpressionNode extends BinaryExpressionNode { public ValueNode value; public String identifier; public MemberAccessNode memberAccess; diff --git a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java index ab3f3bd..84f96c8 100644 --- a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java @@ -1,15 +1,15 @@ package ast.expression.binaryexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; -public class NonCalculationExpressionNode implements ASTNode { +public class NonCalculationExpressionNode extends BinaryExpressionNode { public UnaryExpressionNode unaryExpression; public String operator; - public ExpressionNode expression; + public IExpressionNode expression; - public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, ExpressionNode expression) { + public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, IExpressionNode expression) { this.unaryExpression = unaryExpression; this.operator = operator; this.expression = expression; diff --git a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java index 9f3192a..e1e269d 100644 --- a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java @@ -1,12 +1,12 @@ package ast.expression.unaryexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; public class NotExpressionNode implements ASTNode { - public ExpressionNode expression; + public IExpressionNode expression; - public NotExpressionNode(ExpressionNode expression) { + public NotExpressionNode(IExpressionNode expression) { this.expression = expression; } } diff --git a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java index db9ab53..6c23545 100644 --- a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java @@ -1,20 +1,19 @@ package ast.expression.unaryexpression; -import ast.ASTNode; -import ast.expression.ExpressionNode; -import ast.statement.StatementNode; +import ast.expression.IExpressionNode; +import ast.statement.IStatementNode; import ast.type.ValueNode; import java.util.Objects; -public class UnaryExpressionNode implements ASTNode { +public class UnaryExpressionNode implements IExpressionNode { public String thisExp; public String identifier; public MemberAccessNode memberAccess; public ValueNode value; public NotExpressionNode notExpression; - public StatementNode statement; - public ExpressionNode expression; + public IStatementNode statement; + public IExpressionNode expression; public UnaryExpressionNode(String value) { if(Objects.equals(value, "this")) { @@ -36,11 +35,11 @@ public class UnaryExpressionNode implements ASTNode { this.notExpression = notExpression; } - public UnaryExpressionNode(StatementNode statement) { + public UnaryExpressionNode(IStatementNode statement) { this.statement = statement; } - public UnaryExpressionNode(ExpressionNode expression) { + public UnaryExpressionNode(IExpressionNode expression) { this.expression = expression; } } diff --git a/src/main/java/ast/member/ConstructorNode.java b/src/main/java/ast/member/ConstructorNode.java index c78f8d4..0f7a200 100644 --- a/src/main/java/ast/member/ConstructorNode.java +++ b/src/main/java/ast/member/ConstructorNode.java @@ -3,8 +3,6 @@ package ast.member; import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; -import bytecode.visitor.MethodVisitor; -import visitor.Visitable; import java.util.ArrayList; import java.util.List; @@ -20,8 +18,8 @@ public class ConstructorNode extends MethodNode { this.identifier = identifier; } - public ConstructorNode(AccessModifierNode accessType, String identifier, BlockNode body) { - this.accessType = accessType; + public ConstructorNode(String accessType, String identifier, BlockNode body) { + this.accessType = new AccessModifierNode(accessType); this.identifier = identifier; this.body = body; } @@ -30,10 +28,4 @@ public class ConstructorNode extends MethodNode { parameters.add(parameterNode); } - /* - @Override - public void accept(MethodVisitor methodVisitor) { - methodVisitor.visit(this); - } - */ } diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java index 2518d58..aaaa0fe 100644 --- a/src/main/java/ast/member/FieldNode.java +++ b/src/main/java/ast/member/FieldNode.java @@ -2,12 +2,8 @@ package ast.member; import ast.type.AccessModifierNode; import ast.type.TypeNode; -import bytecode.visitor.ClassVisitor; -import semantic.SemanticVisitor; -import typechecker.TypeCheckResult; -import visitor.Visitable; -public class FieldNode implements MemberNode, Visitable { +public class FieldNode implements MemberNode { public AccessModifierNode accessTypeNode; public TypeNode type; public String identifier; @@ -17,14 +13,4 @@ public class FieldNode implements MemberNode, Visitable { this.type = type; this.identifier = name; } - - @Override - public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.analyze(this); - } - - @Override - public void accept(ClassVisitor classVisitor) { - classVisitor.visit(this); - } } diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index 18932af..b435dca 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -4,10 +4,6 @@ import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; import ast.type.TypeNode; -import bytecode.visitor.MethodVisitor; -import semantic.SemanticVisitor; -import typechecker.TypeCheckResult; -import visitor.Visitable; import java.util.ArrayList; import java.util.List; @@ -17,7 +13,7 @@ public class MethodNode implements MemberNode { public TypeNode type; public Boolean voidType; public String identifier; - public List parameters; + public List parameters = new ArrayList<>(); public BlockNode block; public MethodNode() {} @@ -26,9 +22,9 @@ public class MethodNode implements MemberNode { this.block = block; } - public MethodNode(AccessModifierNode accessModifier, TypeNode type, Boolean voidType, String identifier, BlockNode block){ - this.accesModifier = accessModifier; - this.type = type; + public MethodNode(String accessModifier, String type, Boolean voidType, String identifier, BlockNode block){ + this.accesModifier = new AccessModifierNode(accessModifier); + this.type = new TypeNode(type); this.voidType = voidType; this.identifier = identifier; this.block = block; diff --git a/src/main/java/ast/statement/ForStatementNode.java b/src/main/java/ast/statement/ForStatementNode.java index 7b3219e..e71534d 100644 --- a/src/main/java/ast/statement/ForStatementNode.java +++ b/src/main/java/ast/statement/ForStatementNode.java @@ -1,21 +1,21 @@ package ast.statement; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; -public class ForStatementNode implements ASTNode { - public ExpressionNode statementExpressionInit; - public StatementNode localVariableDeclarationInit; - public ExpressionNode expression; - public ExpressionNode statementExpression; +public class ForStatementNode implements IStatementNode { + public IExpressionNode statementExpressionInit; + public IStatementNode localVariableDeclarationInit; + public IExpressionNode expression; + public IExpressionNode statementExpression; - public ForStatementNode(ExpressionNode statementExpressionInit, ExpressionNode expression, ExpressionNode statementExpression) { + public ForStatementNode(IExpressionNode statementExpressionInit, IExpressionNode expression, IExpressionNode statementExpression) { this.statementExpressionInit = statementExpressionInit; this.expression = expression; this.statementExpression = statementExpression; } - public ForStatementNode(StatementNode localVariableDeclarationInit, ExpressionNode expression, ExpressionNode statementExpression) { + public ForStatementNode(IStatementNode localVariableDeclarationInit, IExpressionNode expression, IExpressionNode statementExpression) { this.localVariableDeclarationInit = localVariableDeclarationInit; this.expression = expression; this.statementExpression = statementExpression; diff --git a/src/main/java/ast/statement/IStatementNode.java b/src/main/java/ast/statement/IStatementNode.java new file mode 100644 index 0000000..d920bb9 --- /dev/null +++ b/src/main/java/ast/statement/IStatementNode.java @@ -0,0 +1,6 @@ +package ast.statement; + +import ast.ASTNode; + +public interface IStatementNode extends ASTNode { +} diff --git a/src/main/java/ast/statement/LocalVariableDeclarationNode.java b/src/main/java/ast/statement/LocalVariableDeclarationNode.java index 7c0ddaf..21c6cc3 100644 --- a/src/main/java/ast/statement/LocalVariableDeclarationNode.java +++ b/src/main/java/ast/statement/LocalVariableDeclarationNode.java @@ -1,16 +1,16 @@ package ast.statement; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; import ast.type.TypeNode; -public class LocalVariableDeclarationNode implements ASTNode { +public class LocalVariableDeclarationNode implements IStatementNode { public TypeNode type; public String identifier; public String assign; - public ExpressionNode expression; + public IExpressionNode expression; - public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, ExpressionNode expression) { + public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, IExpressionNode expression) { this.type = type; this.identifier = identifier; this.assign = assign; diff --git a/src/main/java/ast/statement/ReturnStatementNode.java b/src/main/java/ast/statement/ReturnStatementNode.java index ab111c5..4da2ecb 100644 --- a/src/main/java/ast/statement/ReturnStatementNode.java +++ b/src/main/java/ast/statement/ReturnStatementNode.java @@ -1,16 +1,12 @@ package ast.statement; import ast.ASTNode; -import ast.expression.ExpressionNode; -import ast.type.TypeNode; +import ast.expression.IExpressionNode; -import java.util.ArrayList; -import java.util.List; +public class ReturnStatementNode implements IStatementNode { + public IExpressionNode expression; -public class ReturnStatementNode implements ASTNode { - public ExpressionNode expression; - - public ReturnStatementNode(ExpressionNode expression) { + public ReturnStatementNode(IExpressionNode expression) { this.expression = expression; } } diff --git a/src/main/java/ast/statement/StatementNode.java b/src/main/java/ast/statement/StatementNode.java deleted file mode 100644 index 544b8b8..0000000 --- a/src/main/java/ast/statement/StatementNode.java +++ /dev/null @@ -1,4 +0,0 @@ -package ast.statement; - -public class StatementNode { -} diff --git a/src/main/java/ast/statement/WhileStatementNode.java b/src/main/java/ast/statement/WhileStatementNode.java index 8a34d66..b1c1c13 100644 --- a/src/main/java/ast/statement/WhileStatementNode.java +++ b/src/main/java/ast/statement/WhileStatementNode.java @@ -2,13 +2,13 @@ package ast.statement; import ast.ASTNode; import ast.block.BlockNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; -public class WhileStatementNode implements ASTNode { - public ExpressionNode expression; +public class WhileStatementNode implements IStatementNode { + public IExpressionNode expression; public BlockNode block; - public WhileStatementNode(ExpressionNode expression, BlockNode block) { + public WhileStatementNode(IExpressionNode expression, BlockNode block) { this.expression = expression; this.block = block; } diff --git a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java index 18f4e0e..74bc6c2 100644 --- a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java @@ -2,8 +2,9 @@ package ast.statement.ifstatement; import ast.ASTNode; import ast.block.BlockNode; +import ast.statement.IStatementNode; -public class ElseStatementNode implements ASTNode { +public class ElseStatementNode implements IStatementNode { public BlockNode block; public ElseStatementNode(BlockNode block) { diff --git a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java index 9b7ac8e..75827fd 100644 --- a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java @@ -1,11 +1,12 @@ package ast.statement.ifstatement; import ast.ASTNode; +import ast.statement.IStatementNode; import java.util.ArrayList; import java.util.List; -public class IfElseStatementNode implements ASTNode { +public class IfElseStatementNode implements IStatementNode { public IfStatementNode ifStatement; public List elseStatements = new ArrayList<>(); diff --git a/src/main/java/ast/statement/ifstatement/IfStatementNode.java b/src/main/java/ast/statement/ifstatement/IfStatementNode.java index 2b383fc..d0815e3 100644 --- a/src/main/java/ast/statement/ifstatement/IfStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfStatementNode.java @@ -2,13 +2,14 @@ package ast.statement.ifstatement; import ast.ASTNode; import ast.block.BlockNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import ast.statement.IStatementNode; -public class IfStatementNode implements ASTNode { - public ExpressionNode expression; +public class IfStatementNode implements IStatementNode { + public IExpressionNode expression; public BlockNode block; - public IfStatementNode(ExpressionNode expression, BlockNode block) { + public IfStatementNode(IExpressionNode expression, BlockNode block) { this.expression = expression; this.block = block; } diff --git a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java index 8dbad08..286d180 100644 --- a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java @@ -1,13 +1,13 @@ package ast.statement.statementexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; -public class AssignStatementExpressionNode implements ASTNode { +public class AssignStatementExpressionNode implements IStatementExpressionNode { public AssignableExpressionNode assignable; - public ExpressionNode expression; + public IExpressionNode expression; - public AssignStatementExpressionNode(AssignableExpressionNode assignable, ExpressionNode expression) { + public AssignStatementExpressionNode(AssignableExpressionNode assignable, IExpressionNode expression) { this.assignable = assignable; this.expression = expression; } diff --git a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java index e9d0d30..d669fb4 100644 --- a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java @@ -3,7 +3,7 @@ package ast.statement.statementexpression; import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; -public class AssignableExpressionNode implements ASTNode { +public class AssignableExpressionNode implements IStatementExpressionNode { public String identifier; public MemberAccessNode memberAccess; diff --git a/src/main/java/ast/statement/statementexpression/IStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/IStatementExpressionNode.java new file mode 100644 index 0000000..30998f6 --- /dev/null +++ b/src/main/java/ast/statement/statementexpression/IStatementExpressionNode.java @@ -0,0 +1,5 @@ +package ast.statement.statementexpression; + +import ast.statement.IStatementNode; + +public interface IStatementExpressionNode extends IStatementNode {} diff --git a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java index 69a61c2..fa3f86d 100644 --- a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java @@ -1,20 +1,20 @@ package ast.statement.statementexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; import java.util.ArrayList; import java.util.List; -public class NewDeclarationStatementExpressionNode implements ASTNode { +public class NewDeclarationStatementExpressionNode implements IStatementExpressionNode { public String identifier; - public List expressions = new ArrayList<>(); + public List expressions = new ArrayList<>(); public NewDeclarationStatementExpressionNode(String identifier) { this.identifier = identifier; } - public void addExpression(ExpressionNode expression) { + public void addExpression(IExpressionNode expression) { expressions.add(expression); } } diff --git a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java index 0d09c5d..d14107d 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java @@ -2,8 +2,9 @@ package ast.statement.statementexpression.crementExpression; import ast.ASTNode; import ast.statement.statementexpression.AssignableExpressionNode; +import ast.statement.statementexpression.IStatementExpressionNode; -public class DecrementExpressionNode implements ASTNode { +public class DecrementExpressionNode implements IStatementExpressionNode { public CrementType crementType; public AssignableExpressionNode assignableExpression; diff --git a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java index 815482d..8bf8c16 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java @@ -2,8 +2,9 @@ package ast.statement.statementexpression.crementExpression; import ast.ASTNode; import ast.statement.statementexpression.AssignableExpressionNode; +import ast.statement.statementexpression.IStatementExpressionNode; -public class IncrementExpressionNode implements ASTNode { +public class IncrementExpressionNode implements IStatementExpressionNode { public CrementType crementType; public AssignableExpressionNode assignableExpression; diff --git a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java index a196f73..c20e9bc 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java @@ -1,20 +1,20 @@ package ast.statement.statementexpression.methodcallstatementnexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; import java.util.ArrayList; import java.util.List; public class ChainedMethodNode implements ASTNode { public String identifier; - public List expressions = new ArrayList<>(); + public List expressions = new ArrayList<>(); public ChainedMethodNode(String identifier) { this.identifier = identifier; } - public void addExpression(ExpressionNode expression) { + public void addExpression(IExpressionNode expression) { expressions.add(expression); } } diff --git a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java index 1dc6a07..5646f07 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java @@ -1,16 +1,17 @@ package ast.statement.statementexpression.methodcallstatementnexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import ast.statement.statementexpression.IStatementExpressionNode; import java.util.ArrayList; import java.util.List; -public class MethodCallStatementExpressionNode implements ASTNode { +public class MethodCallStatementExpressionNode implements IStatementExpressionNode { public TargetNode target; public List chainedMethods = new ArrayList<>(); public String identifier; - public List expressions = new ArrayList<>(); + public List expressions = new ArrayList<>(); public MethodCallStatementExpressionNode(TargetNode target, String identifier) { this.target = target; @@ -21,7 +22,7 @@ public class MethodCallStatementExpressionNode implements ASTNode { chainedMethods.add(chainedMethode); } - public void addExpression(ExpressionNode expression) { + public void addExpression(IExpressionNode expression) { expressions.add(expression); } diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index 7760b5c..eae8647 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -53,7 +53,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitConstructorDeclaration(SimpleJavaParser.ConstructorDeclarationContext ctx) { - ConstructorNode constructorNode = new ConstructorNode((AccessModifierNode) visit(ctx.AccessModifier()), ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); + ConstructorNode constructorNode = new ConstructorNode(ctx.AccessModifier().getText(), ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { constructorNode.addParameter((ParameterNode) visit(parameter)); } @@ -66,13 +66,13 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { return new MethodNode((BlockNode) visit(ctx.block())); } else { if(ctx.type() != null) { - MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), (TypeNode) visit(ctx.type()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); + MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), ctx.type().getText(), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { methodNode.addParameter((ParameterNode) visit(parameter)); } return methodNode; } else { - MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); + MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { methodNode.addParameter((ParameterNode) visit(parameter)); } @@ -108,34 +108,34 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitReturnStatement(SimpleJavaParser.ReturnStatementContext ctx) { - return new ReturnStatementNode((ExpressionNode) visit(ctx.expression())); + return new ReturnStatementNode((IExpressionNode) visit(ctx.expression())); } @Override public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) { - return new LocalVariableDeclarationNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (ExpressionNode) visit(ctx.expression())); + return new LocalVariableDeclarationNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression())); } @Override public ASTNode visitBlock(SimpleJavaParser.BlockContext ctx) { BlockNode blockNode = new BlockNode(); for(SimpleJavaParser.StatementContext statement : ctx.statement()) { - blockNode.addStatement((StatementNode) visit(statement)); + blockNode.addStatement((IStatementNode) visit(statement)); } return blockNode; } @Override public ASTNode visitWhileStatement(SimpleJavaParser.WhileStatementContext ctx) { - return new WhileStatementNode((ExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block())); + return new WhileStatementNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block())); } @Override public ASTNode visitForStatement(SimpleJavaParser.ForStatementContext ctx) { if(ctx.statementExpression(0) != null) { - return new ForStatementNode((ExpressionNode) visit(ctx.statementExpression(0)), (ExpressionNode) visit(ctx.expression()), (ExpressionNode) visit(ctx.statementExpression(1))); + return new ForStatementNode((IExpressionNode) visit(ctx.statementExpression(0)), (IExpressionNode) visit(ctx.expression()), (IExpressionNode) visit(ctx.statementExpression(1))); } else if(ctx.localVariableDeclaration() != null) { - return new ForStatementNode((StatementNode) visit(ctx.localVariableDeclaration()), (ExpressionNode) visit(ctx.expression()), (ExpressionNode) visit(ctx.statementExpression(1))); + return new ForStatementNode((IStatementNode) visit(ctx.localVariableDeclaration()), (IExpressionNode) visit(ctx.expression()), (IExpressionNode) visit(ctx.statementExpression(1))); } return null; } @@ -151,7 +151,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitIfStatement(SimpleJavaParser.IfStatementContext ctx) { - return new IfStatementNode((ExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block())); + return new IfStatementNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block())); } @Override @@ -175,14 +175,14 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitAssign(SimpleJavaParser.AssignContext ctx) { - return new AssignStatementExpressionNode((AssignableExpressionNode) visit(ctx.assignableExpression()), (ExpressionNode) visit(ctx.expression())); + return new AssignStatementExpressionNode((AssignableExpressionNode) visit(ctx.assignableExpression()), (IExpressionNode) visit(ctx.expression())); } @Override public ASTNode visitNewDeclaration(SimpleJavaParser.NewDeclarationContext ctx) { NewDeclarationStatementExpressionNode newDeclarationStatementExpressionNode = new NewDeclarationStatementExpressionNode(ctx.Identifier().getText()); for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) { - newDeclarationStatementExpressionNode.addExpression((ExpressionNode) visit(expression)); + newDeclarationStatementExpressionNode.addExpression((IExpressionNode) visit(expression)); } return newDeclarationStatementExpressionNode; } @@ -194,7 +194,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { methodCallStatementExpressionNode.addChainedMethod((ChainedMethodNode) visit(chainedMethod)); } for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) { - methodCallStatementExpressionNode.addExpression((ExpressionNode) visit(expression)); + methodCallStatementExpressionNode.addExpression((IExpressionNode) visit(expression)); } return methodCallStatementExpressionNode; } @@ -217,7 +217,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { public ASTNode visitChainedMethod(SimpleJavaParser.ChainedMethodContext ctx) { ChainedMethodNode chainedMethodNode = new ChainedMethodNode(ctx.Identifier().getText()); for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) { - chainedMethodNode.addExpression((ExpressionNode) visit(expression)); + chainedMethodNode.addExpression((IExpressionNode) visit(expression)); } return chainedMethodNode; } @@ -295,9 +295,9 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { } else if(ctx.notExpression() != null) { return new UnaryExpressionNode((NotExpressionNode) visitNotExpression(ctx.notExpression())); } else if(ctx.statementExpression() != null) { - return new UnaryExpressionNode((StatementNode) visitStatementExpression(ctx.statementExpression())); + return new UnaryExpressionNode((IStatementNode) visitStatementExpression(ctx.statementExpression())); } else if(ctx.expression() != null) { - return new UnaryExpressionNode((ExpressionNode) visitExpression(ctx.expression())); + return new UnaryExpressionNode((IExpressionNode) visitExpression(ctx.expression())); } return null; } @@ -332,7 +332,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitNotExpression(SimpleJavaParser.NotExpressionContext ctx) { - return new NotExpressionNode((ExpressionNode) visitExpression(ctx.expression())); + return new NotExpressionNode((IExpressionNode) visitExpression(ctx.expression())); } @@ -382,7 +382,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitNonCalculationExpression(SimpleJavaParser.NonCalculationExpressionContext ctx) { - return new NonCalculationExpressionNode((UnaryExpressionNode) visit(ctx.unaryExpression()), ctx.nonCalculationOperator().getText(), (ExpressionNode) visit(ctx.expression())); + return new NonCalculationExpressionNode((UnaryExpressionNode) visit(ctx.unaryExpression()), ctx.nonCalculationOperator().getText(), (IExpressionNode) visit(ctx.expression())); } @Override diff --git a/src/main/resources/CompilerInput.java b/src/main/resources/CompilerInput.java index 1cbe5ca..ba8a8e5 100644 --- a/src/main/resources/CompilerInput.java +++ b/src/main/resources/CompilerInput.java @@ -11,8 +11,7 @@ public class Example { public class Test { public static int testMethod(char x, int a){ - - - + x = x + a; + return x; } } \ No newline at end of file From b9ada16dd1bd9c9dc17f736aea6625cf6e839c32 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Fri, 21 Jun 2024 15:23:48 +0200 Subject: [PATCH 19/25] Fixed SemanticCheck for new AST and added Some Test --- src/main/java/ast/ClassNode.java | 11 +- src/main/java/ast/ProgramNode.java | 10 +- src/main/java/ast/block/BlockNode.java | 6 +- .../java/ast/expression/IExpressionNode.java | 8 +- .../BinaryExpressionNode.java | 16 +- .../CalculationExpressionNode.java | 15 +- .../binaryexpression/DotExpressionNode.java | 15 +- .../DotSubstractionExpressionNode.java | 15 +- .../NonCalculationExpressionNode.java | 15 +- .../unaryexpression/MemberAccessNode.java | 1 + .../unaryexpression/NotExpressionNode.java | 1 + .../unaryexpression/UnaryExpressionNode.java | 19 ++ src/main/java/ast/member/FieldNode.java | 13 +- src/main/java/ast/member/MethodNode.java | 22 +- .../java/ast/parameter/ParameterNode.java | 2 +- .../java/ast/statement/ForStatementNode.java | 8 + .../java/ast/statement/IStatementNode.java | 3 +- .../LocalVariableDeclarationNode.java | 11 +- .../ast/statement/ReturnStatementNode.java | 8 + .../ast/statement/WhileStatementNode.java | 8 + .../ifstatement/ElseStatementNode.java | 8 + .../ifstatement/IfElseStatementNode.java | 7 + .../ifstatement/IfStatementNode.java | 8 + .../AssignStatementExpressionNode.java | 9 + .../AssignableExpressionNode.java | 10 + ...NewDeclarationStatementExpressionNode.java | 8 + .../DecrementExpressionNode.java | 8 + .../IncrementExpressionNode.java | 8 + .../MethodCallStatementExpressionNode.java | 6 + src/main/java/ast/type/type/BaseType.java | 4 + .../java/ast/type/type/ReferenceType.java | 4 + .../java/ast/type/{ => type}/TypeNode.java | 4 +- src/main/java/bytecode/ByteCodeGenerator.java | 2 +- src/main/java/bytecode/ClassCodeGen.java | 2 +- .../java/parser/astBuilder/ASTBuilder.java | 9 +- src/main/java/semantic/Scope.java | 5 +- src/main/java/semantic/SemanticAnalyzer.java | 227 +++++++++++++++-- src/main/java/semantic/SemanticVisitor.java | 39 +++ .../java/semantic/context/FieldContext.java | 1 + .../exeptions/AlreadyDefinedException.java | 9 + .../java/typechecker/TypeCheckResult.java | 2 +- src/test/java/semantic/EndToTAST.java | 231 ++++++++++++++++++ src/test/java/semantic/Mocker.java | 17 +- src/test/java/semantic/SemanticTest.java | 28 +-- .../java/semantic/endToTAST/CorrectTest.java | 51 ---- .../semantic/endToTAST/CorrectInstVar.java | 18 ++ .../semantic/endToTAST/CorrectTest.java | 16 ++ .../endToTAST/FieldAlreadyDecleared.java | 10 + .../semantic/endToTAST/NotDecleared.java | 6 + .../endToTAST/ParameterAlreadyDecleared.java | 7 + .../resources/semantic/endToTAST/Test.java | 6 - .../endToTAST/TypeMismatchIntBool.java | 10 + .../endToTAST/TypeMismatchRefType.java | 16 ++ 53 files changed, 868 insertions(+), 135 deletions(-) create mode 100644 src/main/java/ast/type/type/BaseType.java create mode 100644 src/main/java/ast/type/type/ReferenceType.java rename src/main/java/ast/type/{ => type}/TypeNode.java (92%) create mode 100644 src/main/java/semantic/exeptions/AlreadyDefinedException.java create mode 100644 src/test/java/semantic/EndToTAST.java delete mode 100644 src/test/java/semantic/endToTAST/CorrectTest.java create mode 100644 src/test/resources/semantic/endToTAST/CorrectInstVar.java create mode 100644 src/test/resources/semantic/endToTAST/CorrectTest.java create mode 100644 src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java create mode 100644 src/test/resources/semantic/endToTAST/NotDecleared.java create mode 100644 src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java delete mode 100644 src/test/resources/semantic/endToTAST/Test.java create mode 100644 src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java create mode 100644 src/test/resources/semantic/endToTAST/TypeMismatchRefType.java diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index 783d4f8..75f92b1 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -4,11 +4,14 @@ import ast.type.AccessModifierNode; import ast.member.ConstructorNode; import ast.member.MemberNode; import ast.member.MethodNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; import java.util.ArrayList; import java.util.List; -public class ClassNode implements ASTNode { +public class ClassNode implements ASTNode, Visitable { public AccessModifierNode accessType; public String identifier; public List members = new ArrayList<>(); @@ -45,4 +48,10 @@ public class ClassNode implements ASTNode { } return methods; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/ProgramNode.java b/src/main/java/ast/ProgramNode.java index 9174692..7fbe3e0 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -1,13 +1,21 @@ package ast; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; + import java.util.ArrayList; import java.util.List; -public class ProgramNode implements ASTNode { +public class ProgramNode implements ASTNode, Visitable { public List classes = new ArrayList<>(); public void addClass(ClassNode classNode) { classes.add(classNode); } + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/ast/block/BlockNode.java b/src/main/java/ast/block/BlockNode.java index 73d99de..9987cf9 100644 --- a/src/main/java/ast/block/BlockNode.java +++ b/src/main/java/ast/block/BlockNode.java @@ -2,11 +2,15 @@ package ast.block; import ast.ASTNode; import ast.statement.IStatementNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; +import java.beans.Visibility; import java.util.ArrayList; import java.util.List; -public class BlockNode implements ASTNode { +public class BlockNode implements ASTNode, Visitable { public List statements = new ArrayList<>(); public BlockNode() {} diff --git a/src/main/java/ast/expression/IExpressionNode.java b/src/main/java/ast/expression/IExpressionNode.java index 775ac7a..c4c72f5 100644 --- a/src/main/java/ast/expression/IExpressionNode.java +++ b/src/main/java/ast/expression/IExpressionNode.java @@ -1,5 +1,11 @@ package ast.expression; import ast.ASTNode; +import ast.type.type.TypeNode; +import visitor.Visitable; -public interface IExpressionNode extends ASTNode {} +public interface IExpressionNode extends ASTNode, Visitable { + + TypeNode getType(); + +} diff --git a/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java index 4afdff4..d4db5ab 100644 --- a/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java @@ -1,7 +1,19 @@ package ast.expression.binaryexpression; import ast.expression.IExpressionNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -import java.beans.Expression; +public class BinaryExpressionNode implements IExpressionNode { -public class BinaryExpressionNode implements IExpressionNode {} + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public TypeNode getType() { + return null; + } +} diff --git a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java index 442d44e..53adaa2 100644 --- a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java @@ -1,6 +1,8 @@ package ast.expression.binaryexpression; -import ast.ASTNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class CalculationExpressionNode extends BinaryExpressionNode { public CalculationExpressionNode calculationExpression; @@ -16,4 +18,15 @@ public class CalculationExpressionNode extends BinaryExpressionNode { public CalculationExpressionNode(DotExpressionNode dotExpression) { this.dotExpression = dotExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public TypeNode getType() { + return null; + } + } diff --git a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java index c335d52..9ea8170 100644 --- a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java @@ -1,6 +1,8 @@ package ast.expression.binaryexpression; -import ast.ASTNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class DotExpressionNode extends BinaryExpressionNode { public DotExpressionNode dotExpression; @@ -16,4 +18,15 @@ public class DotExpressionNode extends BinaryExpressionNode { public DotExpressionNode(DotSubstractionExpressionNode dotSubstractionExpression) { this.dotSubstractionExpression = dotSubstractionExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public TypeNode getType() { + return null; + } + } diff --git a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java index 69d467d..17c9604 100644 --- a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java @@ -1,9 +1,11 @@ package ast.expression.binaryexpression; -import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; +import ast.type.type.TypeNode; import ast.type.ValueNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class DotSubstractionExpressionNode extends BinaryExpressionNode { public ValueNode value; @@ -28,4 +30,15 @@ public class DotSubstractionExpressionNode extends BinaryExpressionNode { this.methodCall = methodCall; this.calculationExpression = calculationExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public TypeNode getType() { + return null; + } + } diff --git a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java index 84f96c8..8051bd2 100644 --- a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java @@ -1,8 +1,10 @@ package ast.expression.binaryexpression; -import ast.ASTNode; import ast.expression.IExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class NonCalculationExpressionNode extends BinaryExpressionNode { public UnaryExpressionNode unaryExpression; @@ -14,4 +16,15 @@ public class NonCalculationExpressionNode extends BinaryExpressionNode { this.operator = operator; this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public TypeNode getType() { + return null; + } + } diff --git a/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java b/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java index 1a50aa9..f5f7090 100644 --- a/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java +++ b/src/main/java/ast/expression/unaryexpression/MemberAccessNode.java @@ -16,4 +16,5 @@ public class MemberAccessNode implements ASTNode { public void addIdentifier(String identifier) { identifiers.add(identifier); } + } diff --git a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java index e1e269d..f225f39 100644 --- a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java @@ -9,4 +9,5 @@ public class NotExpressionNode implements ASTNode { public NotExpressionNode(IExpressionNode expression) { this.expression = expression; } + } diff --git a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java index 6c23545..74be5ff 100644 --- a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java @@ -2,7 +2,10 @@ package ast.expression.unaryexpression; import ast.expression.IExpressionNode; import ast.statement.IStatementNode; +import ast.type.type.TypeNode; import ast.type.ValueNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import java.util.Objects; @@ -14,6 +17,7 @@ public class UnaryExpressionNode implements IExpressionNode { public NotExpressionNode notExpression; public IStatementNode statement; public IExpressionNode expression; + private TypeNode type; public UnaryExpressionNode(String value) { if(Objects.equals(value, "this")) { @@ -42,4 +46,19 @@ public class UnaryExpressionNode implements IExpressionNode { public UnaryExpressionNode(IExpressionNode expression) { this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public TypeNode getType() { + return type; + } + + public void setType(TypeNode type) { + this.type = type; + } + } diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java index aaaa0fe..4377f09 100644 --- a/src/main/java/ast/member/FieldNode.java +++ b/src/main/java/ast/member/FieldNode.java @@ -1,9 +1,12 @@ package ast.member; import ast.type.AccessModifierNode; -import ast.type.TypeNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; -public class FieldNode implements MemberNode { +public class FieldNode implements MemberNode, Visitable { public AccessModifierNode accessTypeNode; public TypeNode type; public String identifier; @@ -13,4 +16,10 @@ public class FieldNode implements MemberNode { this.type = type; this.identifier = name; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index c6b4337..e318068 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -3,16 +3,21 @@ package ast.member; import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; -import ast.type.TypeNode; +import ast.type.type.TypeNode; +import bytecode.visitor.MethodVisitor; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; -public class MethodNode implements MemberNode { +public class MethodNode implements MemberNode, Visitable { public AccessModifierNode accesModifier; public TypeNode type; public Boolean voidType; - public String identifier; + private String identifier; public List parameters = new ArrayList<>(); public BlockNode block; @@ -39,8 +44,8 @@ public class MethodNode implements MemberNode { } public boolean isSame(MethodNode methodNode){ - if (!this.identifier.equals(methodNode.identifier) || this.type.equals(methodNode.type) - || this.getParameters().size() != methodNode.getParameters().size()) { + if (!(Objects.equals(this.identifier, methodNode.getIdentifier())) || type.equals(methodNode.type) + || getParameters().size() != methodNode.getParameters().size()) { return false; } @@ -62,5 +67,12 @@ public class MethodNode implements MemberNode { methodVisitor.visit(this); } + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } } diff --git a/src/main/java/ast/parameter/ParameterNode.java b/src/main/java/ast/parameter/ParameterNode.java index 9050f30..4c81620 100644 --- a/src/main/java/ast/parameter/ParameterNode.java +++ b/src/main/java/ast/parameter/ParameterNode.java @@ -1,7 +1,7 @@ package ast.parameter; import ast.ASTNode; -import ast.type.TypeNode; +import ast.type.type.TypeNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; diff --git a/src/main/java/ast/statement/ForStatementNode.java b/src/main/java/ast/statement/ForStatementNode.java index e71534d..3d4ad16 100644 --- a/src/main/java/ast/statement/ForStatementNode.java +++ b/src/main/java/ast/statement/ForStatementNode.java @@ -2,6 +2,8 @@ package ast.statement; import ast.ASTNode; import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class ForStatementNode implements IStatementNode { public IExpressionNode statementExpressionInit; @@ -20,4 +22,10 @@ public class ForStatementNode implements IStatementNode { this.expression = expression; this.statementExpression = statementExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/IStatementNode.java b/src/main/java/ast/statement/IStatementNode.java index d920bb9..c726bb3 100644 --- a/src/main/java/ast/statement/IStatementNode.java +++ b/src/main/java/ast/statement/IStatementNode.java @@ -1,6 +1,7 @@ package ast.statement; import ast.ASTNode; +import visitor.Visitable; -public interface IStatementNode extends ASTNode { +public interface IStatementNode extends ASTNode, Visitable { } diff --git a/src/main/java/ast/statement/LocalVariableDeclarationNode.java b/src/main/java/ast/statement/LocalVariableDeclarationNode.java index 21c6cc3..3493c3b 100644 --- a/src/main/java/ast/statement/LocalVariableDeclarationNode.java +++ b/src/main/java/ast/statement/LocalVariableDeclarationNode.java @@ -1,8 +1,9 @@ package ast.statement; -import ast.ASTNode; import ast.expression.IExpressionNode; -import ast.type.TypeNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class LocalVariableDeclarationNode implements IStatementNode { public TypeNode type; @@ -16,4 +17,10 @@ public class LocalVariableDeclarationNode implements IStatementNode { this.assign = assign; this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/ReturnStatementNode.java b/src/main/java/ast/statement/ReturnStatementNode.java index 4da2ecb..66d3846 100644 --- a/src/main/java/ast/statement/ReturnStatementNode.java +++ b/src/main/java/ast/statement/ReturnStatementNode.java @@ -2,6 +2,8 @@ package ast.statement; import ast.ASTNode; import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class ReturnStatementNode implements IStatementNode { public IExpressionNode expression; @@ -9,4 +11,10 @@ public class ReturnStatementNode implements IStatementNode { public ReturnStatementNode(IExpressionNode expression) { this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/WhileStatementNode.java b/src/main/java/ast/statement/WhileStatementNode.java index b1c1c13..3aabb73 100644 --- a/src/main/java/ast/statement/WhileStatementNode.java +++ b/src/main/java/ast/statement/WhileStatementNode.java @@ -3,6 +3,8 @@ package ast.statement; import ast.ASTNode; import ast.block.BlockNode; import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class WhileStatementNode implements IStatementNode { public IExpressionNode expression; @@ -12,4 +14,10 @@ public class WhileStatementNode implements IStatementNode { this.expression = expression; this.block = block; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java index 74bc6c2..709fe2f 100644 --- a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java @@ -3,6 +3,8 @@ package ast.statement.ifstatement; import ast.ASTNode; import ast.block.BlockNode; import ast.statement.IStatementNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class ElseStatementNode implements IStatementNode { public BlockNode block; @@ -10,4 +12,10 @@ public class ElseStatementNode implements IStatementNode { public ElseStatementNode(BlockNode block) { this.block = block; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java index 75827fd..6967f75 100644 --- a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java @@ -2,6 +2,8 @@ package ast.statement.ifstatement; import ast.ASTNode; import ast.statement.IStatementNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import java.util.ArrayList; import java.util.List; @@ -18,4 +20,9 @@ public class IfElseStatementNode implements IStatementNode { elseStatements.add(elseStatement); } + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/ifstatement/IfStatementNode.java b/src/main/java/ast/statement/ifstatement/IfStatementNode.java index d0815e3..7bcbabf 100644 --- a/src/main/java/ast/statement/ifstatement/IfStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfStatementNode.java @@ -4,6 +4,8 @@ import ast.ASTNode; import ast.block.BlockNode; import ast.expression.IExpressionNode; import ast.statement.IStatementNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class IfStatementNode implements IStatementNode { public IExpressionNode expression; @@ -13,4 +15,10 @@ public class IfStatementNode implements IStatementNode { this.expression = expression; this.block = block; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java index 286d180..19b34e5 100644 --- a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java @@ -2,6 +2,9 @@ package ast.statement.statementexpression; import ast.ASTNode; import ast.expression.IExpressionNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class AssignStatementExpressionNode implements IStatementExpressionNode { public AssignableExpressionNode assignable; @@ -11,4 +14,10 @@ public class AssignStatementExpressionNode implements IStatementExpressionNode { this.assignable = assignable; this.expression = expression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java index d669fb4..9ccdfec 100644 --- a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java @@ -2,9 +2,13 @@ package ast.statement.statementexpression; import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; +import ast.type.type.TypeNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class AssignableExpressionNode implements IStatementExpressionNode { public String identifier; + public MemberAccessNode memberAccess; public AssignableExpressionNode(String identifier) { @@ -14,4 +18,10 @@ public class AssignableExpressionNode implements IStatementExpressionNode { public AssignableExpressionNode(MemberAccessNode memberAccess) { this.memberAccess = memberAccess; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java index fa3f86d..20541bb 100644 --- a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java @@ -2,6 +2,8 @@ package ast.statement.statementexpression; import ast.ASTNode; import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import java.util.ArrayList; import java.util.List; @@ -17,4 +19,10 @@ public class NewDeclarationStatementExpressionNode implements IStatementExpressi public void addExpression(IExpressionNode expression) { expressions.add(expression); } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java index d14107d..372b4ea 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java @@ -3,6 +3,8 @@ package ast.statement.statementexpression.crementExpression; import ast.ASTNode; import ast.statement.statementexpression.AssignableExpressionNode; import ast.statement.statementexpression.IStatementExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class DecrementExpressionNode implements IStatementExpressionNode { public CrementType crementType; @@ -11,4 +13,10 @@ public class DecrementExpressionNode implements IStatementExpressionNode { public DecrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) { this.assignableExpression = assignableExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java index 8bf8c16..a87934d 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java @@ -3,6 +3,8 @@ package ast.statement.statementexpression.crementExpression; import ast.ASTNode; import ast.statement.statementexpression.AssignableExpressionNode; import ast.statement.statementexpression.IStatementExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; public class IncrementExpressionNode implements IStatementExpressionNode { public CrementType crementType; @@ -11,4 +13,10 @@ public class IncrementExpressionNode implements IStatementExpressionNode { public IncrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) { this.assignableExpression = assignableExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + } diff --git a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java index 5646f07..6a2f69b 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java @@ -3,6 +3,8 @@ package ast.statement.statementexpression.methodcallstatementnexpression; import ast.ASTNode; import ast.expression.IExpressionNode; import ast.statement.statementexpression.IStatementExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import java.util.ArrayList; import java.util.List; @@ -26,5 +28,9 @@ public class MethodCallStatementExpressionNode implements IStatementExpressionNo expressions.add(expression); } + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } } diff --git a/src/main/java/ast/type/type/BaseType.java b/src/main/java/ast/type/type/BaseType.java new file mode 100644 index 0000000..d88fd99 --- /dev/null +++ b/src/main/java/ast/type/type/BaseType.java @@ -0,0 +1,4 @@ +package ast.type.type; + +public class BaseType { +} diff --git a/src/main/java/ast/type/type/ReferenceType.java b/src/main/java/ast/type/type/ReferenceType.java new file mode 100644 index 0000000..4078c3f --- /dev/null +++ b/src/main/java/ast/type/type/ReferenceType.java @@ -0,0 +1,4 @@ +package ast.type.type; + +public class ReferenceType { +} diff --git a/src/main/java/ast/type/TypeNode.java b/src/main/java/ast/type/type/TypeNode.java similarity index 92% rename from src/main/java/ast/type/TypeNode.java rename to src/main/java/ast/type/type/TypeNode.java index 6e5d192..55bf1b2 100644 --- a/src/main/java/ast/type/TypeNode.java +++ b/src/main/java/ast/type/type/TypeNode.java @@ -1,4 +1,6 @@ -package ast.type; +package ast.type.type; + +import ast.type.EnumTypeNode; public class TypeNode { public EnumTypeNode type; diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index 5494255..d85935a 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -10,7 +10,7 @@ public class ByteCodeGenerator implements ProgramVisitor { public void visit(ProgramNode programNode) { for (ClassNode classDeclarationNode : programNode.classes) { ClassCodeGen classCodeGen = new ClassCodeGen(); - classDeclarationNode.accept(classCodeGen); +// classDeclarationNode.accept(classCodeGen); } } } diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index c65c3c6..c666881 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -4,7 +4,7 @@ import ast.ClassNode; import ast.member.FieldNode; import ast.member.MemberNode; import ast.member.MethodNode; -import ast.type.TypeNode; +import ast.type.type.TypeNode; import bytecode.visitor.ClassVisitor; import java.io.File; import org.objectweb.asm.ClassWriter; diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index 8fc6c4f..642355b 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -10,6 +10,7 @@ import ast.expression.binaryexpression.NonCalculationExpressionNode; import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.NotExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; +import ast.member.FieldNode; import ast.member.MethodNode; import ast.statement.ifstatement.ElseStatementNode; import ast.statement.ifstatement.IfElseStatementNode; @@ -28,6 +29,7 @@ import ast.statement.statementexpression.methodcallstatementnexpression.ChainedM import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.TargetNode; import ast.type.*; +import ast.type.type.TypeNode; import org.antlr.v4.runtime.tree.TerminalNode; import parser.generated.*; @@ -74,13 +76,18 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { } else { MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { -// methodNode.addParameter((ParameterNode) visit(parameter)); + methodNode.addParameter((ParameterNode) visit(parameter)); } return methodNode; } } } + @Override + public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { + return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), new TypeNode(ctx.type().getText()), ctx.Identifier().getText()); + } + @Override public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) { return new ParameterNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText()); diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java index 7cf4cc9..724aed4 100644 --- a/src/main/java/semantic/Scope.java +++ b/src/main/java/semantic/Scope.java @@ -1,6 +1,7 @@ package semantic; -import ast.type.TypeNode; +import ast.type.type.TypeNode; +import semantic.exeptions.AlreadyDeclearedException; import java.util.HashMap; import java.util.Stack; @@ -15,7 +16,7 @@ public class Scope { public void addLocalVar(String name, TypeNode type) { if (this.contains(name)) { - throw new RuntimeException("Variable " + name + " already exists in this scope"); + throw new AlreadyDeclearedException("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 8c7e833..739f04e 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -8,13 +8,28 @@ import java.util.Objects; import ast.*; import ast.block.BlockNode; +import ast.expression.IExpressionNode; +import ast.expression.binaryexpression.*; +import ast.expression.unaryexpression.UnaryExpressionNode; import ast.member.*; import ast.parameter.ParameterNode; import ast.statement.*; +import ast.statement.ifstatement.ElseStatementNode; +import ast.statement.ifstatement.IfElseStatementNode; import ast.statement.ifstatement.IfStatementNode; -import ast.type.*; +import ast.statement.statementexpression.AssignStatementExpressionNode; +import ast.statement.statementexpression.AssignableExpressionNode; +import ast.statement.statementexpression.NewDeclarationStatementExpressionNode; +import ast.statement.statementexpression.crementExpression.DecrementExpressionNode; +import ast.statement.statementexpression.crementExpression.IncrementExpressionNode; +import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; +import ast.type.type.BaseType; +import ast.type.type.ReferenceType; +import ast.type.type.TypeNode; import semantic.context.Context; import semantic.exeptions.AlreadyDeclearedException; +import semantic.exeptions.AlreadyDefinedException; +import semantic.exeptions.NotDeclearedException; import semantic.exeptions.TypeMismatchException; import typechecker.TypeCheckResult; @@ -24,9 +39,10 @@ public class SemanticAnalyzer implements SemanticVisitor { public static ArrayList errors = new ArrayList<>(); - private Context context; + private static Context context; private static Scope currentScope; private static ClassNode currentClass; + private static TypeNode currentNullType; public static ASTNode generateTast(ASTNode node) { SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); @@ -42,7 +58,7 @@ public class SemanticAnalyzer implements SemanticVisitor { return null; } - public static void clearAnalyzier(){ + public static void clearAnalyzer() { currentFields.clear(); errors.clear(); currentScope = null; @@ -79,8 +95,8 @@ public class SemanticAnalyzer implements SemanticVisitor { valid = valid && result.isValid(); } else if (memberNode instanceof MethodNode methodNode) { //Methods - for(MethodNode methode : currentClass.getMethods()){ - if(methode.equals(methodNode)) + for (MethodNode methode : currentClass.getMethods()) { + if (methode.equals(methodNode)) break; } @@ -98,11 +114,11 @@ public class SemanticAnalyzer implements SemanticVisitor { var valid = true; for (var otherMethod : currentClass.getMethods()) { - if (Objects.equals(otherMethod , methodNode)) + if (Objects.equals(otherMethod, methodNode)) break; if (otherMethod.isSame(methodNode)) { errors.add(new AlreadyDeclearedException( - "Method " + methodNode.identifier + " is already defined in class " + "Method " + methodNode.getIdentifier() + " is already defined in class " + currentClass.identifier)); valid = false; } @@ -112,31 +128,41 @@ public class SemanticAnalyzer implements SemanticVisitor { for (var parameter : methodNode.getParameters()) { var result = parameter.accept(this); valid = valid && result.isValid(); - currentScope.addLocalVar(parameter.identifier, parameter.type); + try { + currentScope.addLocalVar(parameter.identifier, parameter.type); + } catch (AlreadyDeclearedException e) { + errors.add(new AlreadyDeclearedException(parameter.identifier)); + } + } // Check if this method is already declared // currentMethodReturnType = methodDecl.getType(); // currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ - // gesetzt ist, ist dieser der Rückgabewert der Methode - var result = methodNode.block.accept(this); - valid = valid && result.isValid(); - currentScope.popScope(); - var resultType = result.getType(); + TypeNode resultType = new TypeNode("void"); - /* - if (resultType == null) { - resultType = new BaseType(Primitives.VOID); - } - if (!resultType.equals(methodDecl.getType())) { - errors.add(new TypeMismatchException("Method-Declaration " + methodDecl.getIdentifier() + " with type " - + methodDecl.getType() + " has at least one Mismatching return Type:" - + TypeHelper.generateLocationString(methodDecl.line, methodDecl.column, fileName))); - valid = false; + if (methodNode.block != null) { + // gesetzt ist, ist dieser der Rückgabewert der Methode + var result = methodNode.block.accept(this); + valid = valid && result.isValid(); + currentScope.popScope(); + resultType = result.getType(); + + /* + if (resultType == null) { + resultType = new BaseType(Primitives.VOID); + } + if (!resultType.equals(methodDecl.getType())) { + errors.add(new TypeMismatchException("Method-Declaration " + methodDecl.getIdentifier() + " with type " + + methodDecl.getType() + " has at least one Mismatching return Type:" + + TypeHelper.generateLocationString(methodDecl.line, methodDecl.column, fileName))); + valid = false; + } + + */ } - */ return new TypeCheckResult(valid, resultType); } @@ -168,12 +194,165 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(ParameterNode toCheck) { + + return new TypeCheckResult(true, null); } @Override - public TypeCheckResult analyze(BlockNode toCheck) { + public TypeCheckResult analyze(BlockNode blockNode) { + + for (IStatementNode statementNode : blockNode.statements) { + statementNode.accept(this); + } return new TypeCheckResult(true, null); } + @Override + public TypeCheckResult analyze(AssignableExpressionNode toCheck) { + return new TypeCheckResult(true, currentFields.get(toCheck.identifier)); + + } + + @Override + public TypeCheckResult analyze(ElseStatementNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(ForStatementNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(AssignStatementExpressionNode toCheck) { + AssignableExpressionNode assignable = toCheck.assignable; + var oldNullType = currentNullType; + currentNullType = currentFields.get(toCheck.assignable.identifier); + IExpressionNode rExpression = toCheck.expression; + currentNullType = oldNullType; + var valid = true; + + // This check currently handles things like : + /** + * private int i; + * void foo(int i){ + * i = i; + * } + */ + if (assignable.equals(rExpression)) { + errors.add(new TypeMismatchException("Cannot assign to self")); + valid = false; + } + + var lResult = assignable.accept(this); + currentNullType = lResult.getType(); + var rResult = rExpression.accept(this); + + if (!Objects.equals(currentFields.get(toCheck.assignable.identifier), rExpression.getType())) { + errors.add(new TypeMismatchException( + "Mismatch types in Assign-Statement: cannot convert from \"" + lResult.getType() + "\" to \"" + + rResult.getType() + "\"")); + valid = false; + } +// else { +// toCheck.setType(assignable.getType()); +// } + valid = valid && lResult.isValid() && rResult.isValid(); + currentNullType = null; + return new TypeCheckResult(valid, null); // return type is null to get the return type sufficently + } + + @Override + public TypeCheckResult analyze(DecrementExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(IfElseStatementNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(MethodCallStatementExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(LocalVariableDeclarationNode localVarDecl) { + var valid = true; + + if (localVarDecl.expression != null) { + TypeCheckResult result = localVarDecl.expression.accept(this); + + var resultType = localVarDecl.expression.getType(); + valid = result.isValid() && valid; + + if (!Objects.equals(resultType, localVarDecl.type)) { + errors.add(new TypeMismatchException( + "Type mismatch: cannot convert from " + resultType + " to " + localVarDecl.type)); + valid = false; + } + + } + + try { + currentScope.addLocalVar(localVarDecl.identifier, localVarDecl.type); + } catch (AlreadyDefinedException e) { + errors.add(new AlreadyDefinedException(e.getMessage())); + valid = false; + } + return new TypeCheckResult(valid, null); + } + + @Override + public TypeCheckResult analyze(NewDeclarationStatementExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(IncrementExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(BinaryExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(CalculationExpressionNode calcNode) { + if(calcNode.calculationExpression != null){ + calcNode.calculationExpression.accept(this); + } + return null; + } + + @Override + public TypeCheckResult analyze(DotExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(DotSubstractionExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(NonCalculationExpressionNode toCheck) { + return null; + } + + @Override + public TypeCheckResult analyze(UnaryExpressionNode unary) { + var valid = true; + + if (!currentScope.contains(unary.identifier)) { + errors.add(new NotDeclearedException("Not declared " + unary.identifier)); + return new TypeCheckResult(false, null); + } + + return new TypeCheckResult(valid, unary.getType()); + } + } \ No newline at end of file diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index aca196b..6b6942f 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -3,10 +3,18 @@ package semantic; import ast.*; import ast.block.BlockNode; +import ast.expression.binaryexpression.*; +import ast.expression.unaryexpression.UnaryExpressionNode; import ast.member.*; import ast.parameter.ParameterNode; import ast.statement.*; import ast.statement.ifstatement.*; +import ast.statement.statementexpression.AssignStatementExpressionNode; +import ast.statement.statementexpression.AssignableExpressionNode; +import ast.statement.statementexpression.NewDeclarationStatementExpressionNode; +import ast.statement.statementexpression.crementExpression.DecrementExpressionNode; +import ast.statement.statementexpression.crementExpression.IncrementExpressionNode; +import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import typechecker.TypeCheckResult; public interface SemanticVisitor { @@ -29,5 +37,36 @@ public interface SemanticVisitor { TypeCheckResult analyze(BlockNode toCheck); + TypeCheckResult analyze(AssignableExpressionNode toCheck); + + TypeCheckResult analyze(ElseStatementNode toCheck); + + TypeCheckResult analyze(ForStatementNode toCheck); + + TypeCheckResult analyze(AssignStatementExpressionNode toCheck); + + TypeCheckResult analyze(DecrementExpressionNode toCheck); + + TypeCheckResult analyze(IfElseStatementNode toCheck); + + TypeCheckResult analyze(MethodCallStatementExpressionNode toCheck); + + TypeCheckResult analyze(LocalVariableDeclarationNode toCheck); + + TypeCheckResult analyze(NewDeclarationStatementExpressionNode toCheck); + + TypeCheckResult analyze(IncrementExpressionNode toCheck); + + TypeCheckResult analyze(BinaryExpressionNode toCheck); + + TypeCheckResult analyze(CalculationExpressionNode toCheck); + + TypeCheckResult analyze(DotExpressionNode toCheck); + + TypeCheckResult analyze(DotSubstractionExpressionNode toCheck); + + TypeCheckResult analyze(NonCalculationExpressionNode toCheck); + + TypeCheckResult analyze(UnaryExpressionNode toCheck); } \ No newline at end of file diff --git a/src/main/java/semantic/context/FieldContext.java b/src/main/java/semantic/context/FieldContext.java index 35c1f46..6c594c9 100644 --- a/src/main/java/semantic/context/FieldContext.java +++ b/src/main/java/semantic/context/FieldContext.java @@ -2,6 +2,7 @@ package semantic.context; import ast.member.FieldNode; import ast.type.*; +import ast.type.type.TypeNode; public class FieldContext { diff --git a/src/main/java/semantic/exeptions/AlreadyDefinedException.java b/src/main/java/semantic/exeptions/AlreadyDefinedException.java new file mode 100644 index 0000000..441a5d9 --- /dev/null +++ b/src/main/java/semantic/exeptions/AlreadyDefinedException.java @@ -0,0 +1,9 @@ +package semantic.exeptions; + +public class AlreadyDefinedException extends RuntimeException { + + public AlreadyDefinedException(String message) { + super(message); + } + +} diff --git a/src/main/java/typechecker/TypeCheckResult.java b/src/main/java/typechecker/TypeCheckResult.java index 12143b2..21c12df 100644 --- a/src/main/java/typechecker/TypeCheckResult.java +++ b/src/main/java/typechecker/TypeCheckResult.java @@ -1,7 +1,7 @@ package typechecker; -import ast.type.TypeNode; +import ast.type.type.TypeNode; public class TypeCheckResult { diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java new file mode 100644 index 0000000..2d14077 --- /dev/null +++ b/src/test/java/semantic/EndToTAST.java @@ -0,0 +1,231 @@ +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.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 correctInstVarTest(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectInstVar.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 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/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()); + + } + +} diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java index 5a5e014..c38a37e 100644 --- a/src/test/java/semantic/Mocker.java +++ b/src/test/java/semantic/Mocker.java @@ -5,15 +5,8 @@ import ast.block.BlockNode; import ast.member.FieldNode; import ast.member.MethodNode; import ast.parameter.ParameterNode; -import ast.statement.StatementNode; -import ast.statement.statementexpression.NewDeclarationStatementExpressionNode; import ast.type.AccessModifierNode; -import ast.type.TypeNode; - -import java.util.ArrayList; -import java.util.List; - -import static parser.generated.SimpleJavaParser.Identifier; +import ast.type.type.TypeNode; public class Mocker { @@ -68,7 +61,7 @@ public class Mocker { methodNode.block = new BlockNode(); methodNode.type = new TypeNode("int"); - methodNode.identifier = "testMethod"; + methodNode.setIdentifier("testMethod"); c.members.add(methodNode); @@ -76,7 +69,7 @@ public class Mocker { methodNode1.block = new BlockNode(); methodNode1.type = new TypeNode("int"); - methodNode1.identifier = "testMethod"; + methodNode1.setIdentifier("testMethod"); c.members.add(methodNode1); @@ -92,13 +85,13 @@ public class Mocker { MethodNode methodNode = new MethodNode(); methodNode.block = new BlockNode(); - methodNode.identifier = "testMethod"; + methodNode.setIdentifier("testMethod"); c.members.add(methodNode); MethodNode methodNode1 = new MethodNode(); methodNode1.block = new BlockNode(); - methodNode1.identifier = "testMethod1"; + methodNode1.setIdentifier("testMethod1"); c.members.add(methodNode1); diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index 7ebc7ad..7000876 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -9,20 +9,17 @@ import static org.junit.jupiter.api.Assertions.*; public class SemanticTest { - @BeforeEach - public void setup(){ - SemanticAnalyzer.clearAnalyzier(); - } @Test public void twoFieldsSameName() { ASTNode ast = Mocker.mockTwoSameFields(); - ASTNode tast = SemanticAnalyzer.generateTast(ast); + SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); + ASTNode tast = semanticAnalyzer.generateTast(ast); - assertEquals(SemanticAnalyzer.errors.size(), 1); - assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + assertEquals(semanticAnalyzer.errors.size(), 1); + assertInstanceOf(AlreadyDeclearedException.class, semanticAnalyzer.errors.getFirst()); assertNull(tast); } @@ -32,9 +29,10 @@ public class SemanticTest { ASTNode ast = Mocker.mockSimpleMethod(); - ASTNode tast = SemanticAnalyzer.generateTast(ast); + SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); + ASTNode tast = semanticAnalyzer.generateTast(ast); - assertEquals(SemanticAnalyzer.errors.size(), 0); + assertEquals(semanticAnalyzer.errors.size(), 0); assertNotNull(tast); } @@ -43,10 +41,11 @@ public class SemanticTest { public void twoSameMethods(){ ASTNode ast = Mocker.mockTwoSameMethods(); - ASTNode tast = SemanticAnalyzer.generateTast(ast); + SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); + ASTNode tast = semanticAnalyzer.generateTast(ast); - assertEquals(1, SemanticAnalyzer.errors.size()); - assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + assertEquals(1, semanticAnalyzer.errors.size()); + assertInstanceOf(AlreadyDeclearedException.class, semanticAnalyzer.errors.getFirst()); assertNull(tast); } @@ -54,9 +53,10 @@ public class SemanticTest { public void twoDifferentMethods(){ ASTNode ast = Mocker.mockTwoDifferentMethods(); - ASTNode tast = SemanticAnalyzer.generateTast(ast); + SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); + ASTNode tast = semanticAnalyzer.generateTast(ast); - assertEquals(SemanticAnalyzer.errors.size(), 0); + assertEquals(semanticAnalyzer.errors.size(), 0); assertNotNull(tast); } diff --git a/src/test/java/semantic/endToTAST/CorrectTest.java b/src/test/java/semantic/endToTAST/CorrectTest.java deleted file mode 100644 index e3a7a08..0000000 --- a/src/test/java/semantic/endToTAST/CorrectTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package semantic.endToTAST; - -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.Test; -import parser.astBuilder.ASTBuilder; -import parser.generated.SimpleJavaLexer; -import parser.generated.SimpleJavaParser; -import semantic.SemanticAnalyzer; - -import java.io.IOException; -import java.nio.file.Paths; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class CorrectTest { - - @Test - public void first(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/Test.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); - - System.out.println("Test"); - - ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); - - System.out.println("Errors: " + SemanticAnalyzer.errors.size()); - - assertEquals(SemanticAnalyzer.errors.size(), 0); - - } - -} diff --git a/src/test/resources/semantic/endToTAST/CorrectInstVar.java b/src/test/resources/semantic/endToTAST/CorrectInstVar.java new file mode 100644 index 0000000..5c20dab --- /dev/null +++ b/src/test/resources/semantic/endToTAST/CorrectInstVar.java @@ -0,0 +1,18 @@ +public class Test { + + public Example ex; + + public static int testMethod(char x){ + + int b = this.ex.a; + + return x; + } + +} + +public class Example { + + public int a; + +} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/CorrectTest.java b/src/test/resources/semantic/endToTAST/CorrectTest.java new file mode 100644 index 0000000..8e3bf62 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/CorrectTest.java @@ -0,0 +1,16 @@ +public class Example { + + public int a; + + public static int testMethod(char x){ + + } + +} + +public class Test { + + public static int testMethod(char x, int a){ + return x; + } +} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java b/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java new file mode 100644 index 0000000..535a592 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java @@ -0,0 +1,10 @@ +public class Example { + + public int a; + public int a; + + public static int testMethod(char a){ + + } + +} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/NotDecleared.java b/src/test/resources/semantic/endToTAST/NotDecleared.java new file mode 100644 index 0000000..4aba5f8 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/NotDecleared.java @@ -0,0 +1,6 @@ +public class Test { + public static int testMethod(int x){ + int a = b; + return x; + } +} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java b/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java new file mode 100644 index 0000000..d2b3425 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java @@ -0,0 +1,7 @@ +public class Example { + + public static int testMethod(char a, int a){ + + } + +} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/Test.java b/src/test/resources/semantic/endToTAST/Test.java deleted file mode 100644 index d067998..0000000 --- a/src/test/resources/semantic/endToTAST/Test.java +++ /dev/null @@ -1,6 +0,0 @@ -public class Test { - - public boolean b; - public boolean b; - -} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java b/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java new file mode 100644 index 0000000..9b609b6 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java @@ -0,0 +1,10 @@ +public class Test { + + public boolean b; + + public static int testMethod(int a){ + + b = a; + + } +} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java b/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java new file mode 100644 index 0000000..a7b8cc9 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/TypeMismatchRefType.java @@ -0,0 +1,16 @@ +public class Test { + + public static int testMethod(ExampleA exampleA, ExampleB exampleB){ + + exampleA = exampleB; + + } +} + +public class ExampleA{ + public int a; +} + +public class ExampleB{ + public int a; +} \ No newline at end of file From cf41babcb7818c523c6efa4de0deb5f07492d33b Mon Sep 17 00:00:00 2001 From: Bruder John Date: Fri, 21 Jun 2024 16:42:27 +0200 Subject: [PATCH 20/25] Added BaseType And refferenz Type --- .../java/ast/expression/IExpressionNode.java | 4 +- .../BinaryExpressionNode.java | 4 +- .../CalculationExpressionNode.java | 4 +- .../binaryexpression/DotExpressionNode.java | 4 +- .../DotSubstractionExpressionNode.java | 4 +- .../NonCalculationExpressionNode.java | 4 +- .../unaryexpression/UnaryExpressionNode.java | 8 +- src/main/java/ast/member/ConstructorNode.java | 5 +- src/main/java/ast/member/FieldNode.java | 6 +- src/main/java/ast/member/MethodNode.java | 16 ++- .../java/ast/parameter/ParameterNode.java | 6 +- .../LocalVariableDeclarationNode.java | 6 +- .../AssignStatementExpressionNode.java | 2 - .../AssignableExpressionNode.java | 2 - src/main/java/ast/type/type/BaseType.java | 28 ++++- src/main/java/ast/type/type/ITypeNode.java | 5 + .../java/ast/type/type/ReferenceType.java | 31 +++++- src/main/java/ast/type/type/TypeEnum.java | 9 ++ src/main/java/ast/type/type/TypeNode.java | 33 ------ src/main/java/bytecode/ClassCodeGen.java | 4 +- .../java/parser/astBuilder/ASTBuilder.java | 21 +++- src/main/java/semantic/Scope.java | 19 +++- src/main/java/semantic/SemanticAnalyzer.java | 105 +++++++++--------- .../java/semantic/context/FieldContext.java | 6 +- .../exeptions/MultipleReturnTypes.java | 9 ++ .../java/typechecker/TypeCheckResult.java | 8 +- src/test/java/semantic/EndToTAST.java | 52 ++++++++- src/test/java/semantic/Mocker.java | 12 +- .../semantic/endToTAST/CorrectRetType.java | 7 ++ .../semantic/endToTAST/CorrectTest.java | 4 +- .../semantic/endToTAST/MultipleRetTypes.java | 8 ++ .../semantic/endToTAST/retTypeMismatch.java | 7 ++ 32 files changed, 296 insertions(+), 147 deletions(-) create mode 100644 src/main/java/ast/type/type/ITypeNode.java create mode 100644 src/main/java/ast/type/type/TypeEnum.java delete mode 100644 src/main/java/ast/type/type/TypeNode.java create mode 100644 src/main/java/semantic/exeptions/MultipleReturnTypes.java create mode 100644 src/test/resources/semantic/endToTAST/CorrectRetType.java create mode 100644 src/test/resources/semantic/endToTAST/MultipleRetTypes.java create mode 100644 src/test/resources/semantic/endToTAST/retTypeMismatch.java diff --git a/src/main/java/ast/expression/IExpressionNode.java b/src/main/java/ast/expression/IExpressionNode.java index c4c72f5..28b45e3 100644 --- a/src/main/java/ast/expression/IExpressionNode.java +++ b/src/main/java/ast/expression/IExpressionNode.java @@ -1,11 +1,11 @@ package ast.expression; import ast.ASTNode; -import ast.type.type.TypeNode; +import ast.type.type.ITypeNode; import visitor.Visitable; public interface IExpressionNode extends ASTNode, Visitable { - TypeNode getType(); + ITypeNode getType(); } diff --git a/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java index d4db5ab..655a3f5 100644 --- a/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java @@ -1,7 +1,7 @@ package ast.expression.binaryexpression; import ast.expression.IExpressionNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -13,7 +13,7 @@ public class BinaryExpressionNode implements IExpressionNode { } @Override - public TypeNode getType() { + public ITypeNode getType() { return null; } } diff --git a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java index 53adaa2..70451d8 100644 --- a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java @@ -1,6 +1,6 @@ package ast.expression.binaryexpression; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -25,7 +25,7 @@ public class CalculationExpressionNode extends BinaryExpressionNode { } @Override - public TypeNode getType() { + public ITypeNode getType() { return null; } diff --git a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java index 9ea8170..cc5f2c6 100644 --- a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java @@ -1,6 +1,6 @@ package ast.expression.binaryexpression; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -25,7 +25,7 @@ public class DotExpressionNode extends BinaryExpressionNode { } @Override - public TypeNode getType() { + public ITypeNode getType() { return null; } diff --git a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java index 17c9604..1b43a9f 100644 --- a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java @@ -2,7 +2,7 @@ package ast.expression.binaryexpression; import ast.expression.unaryexpression.MemberAccessNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import ast.type.ValueNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -37,7 +37,7 @@ public class DotSubstractionExpressionNode extends BinaryExpressionNode { } @Override - public TypeNode getType() { + public ITypeNode getType() { return null; } diff --git a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java index 8051bd2..5cdebc2 100644 --- a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java @@ -2,7 +2,7 @@ package ast.expression.binaryexpression; import ast.expression.IExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -23,7 +23,7 @@ public class NonCalculationExpressionNode extends BinaryExpressionNode { } @Override - public TypeNode getType() { + public ITypeNode getType() { return null; } diff --git a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java index 74be5ff..4393e84 100644 --- a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java @@ -2,7 +2,7 @@ package ast.expression.unaryexpression; import ast.expression.IExpressionNode; import ast.statement.IStatementNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import ast.type.ValueNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -17,7 +17,7 @@ public class UnaryExpressionNode implements IExpressionNode { public NotExpressionNode notExpression; public IStatementNode statement; public IExpressionNode expression; - private TypeNode type; + private ITypeNode type; public UnaryExpressionNode(String value) { if(Objects.equals(value, "this")) { @@ -53,11 +53,11 @@ public class UnaryExpressionNode implements IExpressionNode { } @Override - public TypeNode getType() { + public ITypeNode getType() { return type; } - public void setType(TypeNode type) { + public void setType(ITypeNode type) { this.type = type; } diff --git a/src/main/java/ast/member/ConstructorNode.java b/src/main/java/ast/member/ConstructorNode.java index 0f7a200..52d7604 100644 --- a/src/main/java/ast/member/ConstructorNode.java +++ b/src/main/java/ast/member/ConstructorNode.java @@ -3,11 +3,14 @@ package ast.member; import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; import java.util.ArrayList; import java.util.List; -public class ConstructorNode extends MethodNode { +public class ConstructorNode extends MethodNode { public AccessModifierNode accessType; public String identifier; public List parameters = new ArrayList<>(); diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java index 4377f09..f269c40 100644 --- a/src/main/java/ast/member/FieldNode.java +++ b/src/main/java/ast/member/FieldNode.java @@ -1,17 +1,17 @@ package ast.member; import ast.type.AccessModifierNode; -import ast.type.type.TypeNode; +import ast.type.type.ITypeNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; public class FieldNode implements MemberNode, Visitable { public AccessModifierNode accessTypeNode; - public TypeNode type; + public ITypeNode type; public String identifier; - public FieldNode(AccessModifierNode accessTypeNode, TypeNode type, String name){ + public FieldNode(AccessModifierNode accessTypeNode, ITypeNode type, String name){ this.accessTypeNode = accessTypeNode; this.type = type; this.identifier = name; diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index e318068..ecfd598 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -3,7 +3,7 @@ package ast.member; import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import bytecode.visitor.MethodVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; @@ -15,7 +15,7 @@ import java.util.Objects; public class MethodNode implements MemberNode, Visitable { public AccessModifierNode accesModifier; - public TypeNode type; + private ITypeNode type; public Boolean voidType; private String identifier; public List parameters = new ArrayList<>(); @@ -27,9 +27,9 @@ public class MethodNode implements MemberNode, Visitable { this.block = block; } - public MethodNode(String accessModifier, String type, Boolean voidType, String identifier, BlockNode block){ + public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){ this.accesModifier = new AccessModifierNode(accessModifier); - this.type = new TypeNode(type); + this.type = type; this.voidType = voidType; this.identifier = identifier; this.block = block; @@ -71,6 +71,14 @@ public class MethodNode implements MemberNode, Visitable { return identifier; } + public ITypeNode getType() { + return type; + } + + public void setType(ITypeNode type) { + this.type = type; + } + public void setIdentifier(String identifier) { this.identifier = identifier; } diff --git a/src/main/java/ast/parameter/ParameterNode.java b/src/main/java/ast/parameter/ParameterNode.java index 4c81620..257eb68 100644 --- a/src/main/java/ast/parameter/ParameterNode.java +++ b/src/main/java/ast/parameter/ParameterNode.java @@ -1,16 +1,16 @@ package ast.parameter; import ast.ASTNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; public class ParameterNode implements ASTNode, Visitable { - public TypeNode type; + public ITypeNode type; public String identifier; - public ParameterNode(TypeNode type, String identifier) { + public ParameterNode(ITypeNode type, String identifier) { this.type = type; this.identifier = identifier; } diff --git a/src/main/java/ast/statement/LocalVariableDeclarationNode.java b/src/main/java/ast/statement/LocalVariableDeclarationNode.java index 3493c3b..3ab54e0 100644 --- a/src/main/java/ast/statement/LocalVariableDeclarationNode.java +++ b/src/main/java/ast/statement/LocalVariableDeclarationNode.java @@ -1,17 +1,17 @@ package ast.statement; import ast.expression.IExpressionNode; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; public class LocalVariableDeclarationNode implements IStatementNode { - public TypeNode type; + public ITypeNode type; public String identifier; public String assign; public IExpressionNode expression; - public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, IExpressionNode expression) { + public LocalVariableDeclarationNode(ITypeNode type, String identifier, String assign, IExpressionNode expression) { this.type = type; this.identifier = identifier; this.assign = assign; diff --git a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java index 19b34e5..df8fe79 100644 --- a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java @@ -1,8 +1,6 @@ package ast.statement.statementexpression; -import ast.ASTNode; import ast.expression.IExpressionNode; -import ast.type.type.TypeNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; diff --git a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java index 9ccdfec..0fb9fa9 100644 --- a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java @@ -1,8 +1,6 @@ package ast.statement.statementexpression; -import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; -import ast.type.type.TypeNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; diff --git a/src/main/java/ast/type/type/BaseType.java b/src/main/java/ast/type/type/BaseType.java index d88fd99..fdfb293 100644 --- a/src/main/java/ast/type/type/BaseType.java +++ b/src/main/java/ast/type/type/BaseType.java @@ -1,4 +1,30 @@ package ast.type.type; -public class BaseType { +public class BaseType implements ITypeNode { + + private TypeEnum typeEnum; + + public BaseType(TypeEnum typeEnum) { + this.typeEnum = typeEnum; + } + + public TypeEnum getTypeEnum() { + return typeEnum; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BaseType other = (BaseType) obj; + if (typeEnum != other.typeEnum) + return false; + return true; + } + + } diff --git a/src/main/java/ast/type/type/ITypeNode.java b/src/main/java/ast/type/type/ITypeNode.java new file mode 100644 index 0000000..e449e3c --- /dev/null +++ b/src/main/java/ast/type/type/ITypeNode.java @@ -0,0 +1,5 @@ +package ast.type.type; + +public interface ITypeNode { + +} diff --git a/src/main/java/ast/type/type/ReferenceType.java b/src/main/java/ast/type/type/ReferenceType.java index 4078c3f..2292046 100644 --- a/src/main/java/ast/type/type/ReferenceType.java +++ b/src/main/java/ast/type/type/ReferenceType.java @@ -1,4 +1,33 @@ package ast.type.type; -public class ReferenceType { +public class ReferenceType implements ITypeNode{ + + private String identifier; + + public ReferenceType(String identifier) { + this.identifier = identifier; + } + + public String getIdentifier() { + return identifier; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ReferenceType other = (ReferenceType) obj; + if (identifier == null) { + if (other.identifier != null) + return false; + } else if (!identifier.equals(other.identifier)) + return false; + return true; + } + + } diff --git a/src/main/java/ast/type/type/TypeEnum.java b/src/main/java/ast/type/type/TypeEnum.java new file mode 100644 index 0000000..d46fac3 --- /dev/null +++ b/src/main/java/ast/type/type/TypeEnum.java @@ -0,0 +1,9 @@ +package ast.type.type; + +public enum TypeEnum { + VOID, + INT, + CHAR, + BOOL; + +} diff --git a/src/main/java/ast/type/type/TypeNode.java b/src/main/java/ast/type/type/TypeNode.java deleted file mode 100644 index 55bf1b2..0000000 --- a/src/main/java/ast/type/type/TypeNode.java +++ /dev/null @@ -1,33 +0,0 @@ -package ast.type.type; - -import ast.type.EnumTypeNode; - -public class TypeNode { - public EnumTypeNode type; - - public TypeNode(String type) { - setType(type); - } - - private void setType(String type) { - switch(type) { - case "int": - this.type = EnumTypeNode.INT; - break; - case "boolean": - this.type = EnumTypeNode.BOOLEAN; - break; - case "char": - this.type = EnumTypeNode.CHAR; - break; - default: - this.type = EnumTypeNode.IDENTIFIER; - } - } - - - public boolean equals(TypeNode o) { - return !o.type.equals(this.type); - } - -} diff --git a/src/main/java/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index c666881..c911199 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -4,7 +4,7 @@ import ast.ClassNode; import ast.member.FieldNode; import ast.member.MemberNode; import ast.member.MethodNode; -import ast.type.type.TypeNode; +import ast.type.type.BaseType; import bytecode.visitor.ClassVisitor; import java.io.File; import org.objectweb.asm.ClassWriter; @@ -44,7 +44,7 @@ public class ClassCodeGen implements ClassVisitor { @Override public void visit(FieldNode fieldNode) { - if(fieldNode.type instanceof TypeNode baseTypeNode){ + if(fieldNode.type instanceof BaseType baseTypeNode){ // classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null ); } classWriter.visitEnd(); diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index 642355b..31a8b82 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -29,7 +29,7 @@ import ast.statement.statementexpression.methodcallstatementnexpression.ChainedM import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.TargetNode; import ast.type.*; -import ast.type.type.TypeNode; +import ast.type.type.*; import org.antlr.v4.runtime.tree.TerminalNode; import parser.generated.*; @@ -68,7 +68,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { return new MethodNode((BlockNode) visit(ctx.block())); } else { if(ctx.type() != null) { - MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), ctx.type().getText(), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); + MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { methodNode.addParameter((ParameterNode) visit(parameter)); } @@ -85,12 +85,12 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { - return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), new TypeNode(ctx.type().getText()), ctx.Identifier().getText()); + return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText()); } @Override public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) { - return new ParameterNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText()); + return new ParameterNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText()); } @Override @@ -120,7 +120,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) { - return new LocalVariableDeclarationNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression())); + return new LocalVariableDeclarationNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression())); } @Override @@ -401,4 +401,15 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { } return null; } + + public ITypeNode createTypeNode(String identifier){ + return switch (identifier) { + case "int" -> new BaseType(TypeEnum.INT); + case "boolean" -> new BaseType(TypeEnum.BOOL); + case "char" -> new BaseType(TypeEnum.CHAR); + case "void" -> new BaseType(TypeEnum.VOID); + default -> new ReferenceType(identifier); + }; + } + } diff --git a/src/main/java/semantic/Scope.java b/src/main/java/semantic/Scope.java index 724aed4..39dd2f8 100644 --- a/src/main/java/semantic/Scope.java +++ b/src/main/java/semantic/Scope.java @@ -1,6 +1,6 @@ package semantic; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.exeptions.AlreadyDeclearedException; import java.util.HashMap; @@ -8,21 +8,28 @@ import java.util.Stack; public class Scope { - private Stack> localVars; + private Stack> localVars; public Scope() { - localVars = new Stack>(); + localVars = new Stack>(); } - public void addLocalVar(String name, TypeNode type) { + public void addLocalVar(String name, ITypeNode type) { if (this.contains(name)) { throw new AlreadyDeclearedException("Variable " + name + " already exists in this scope"); } localVars.peek().put(name, type); } + public ITypeNode getLocalVar(String name) { + for (HashMap map : localVars) { + return map.get(name); + } + return null; + } + public boolean contains(String name) { - for (HashMap map : localVars) { + for (HashMap map : localVars) { if (map.containsKey(name)) { return true; } @@ -31,7 +38,7 @@ public class Scope { } public void pushScope() { - localVars.push(new HashMap()); + localVars.push(new HashMap()); } public void popScope() { diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 739f04e..1718d01 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -23,26 +23,22 @@ import ast.statement.statementexpression.NewDeclarationStatementExpressionNode; import ast.statement.statementexpression.crementExpression.DecrementExpressionNode; import ast.statement.statementexpression.crementExpression.IncrementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; -import ast.type.type.BaseType; -import ast.type.type.ReferenceType; -import ast.type.type.TypeNode; +import ast.type.type.*; import semantic.context.Context; -import semantic.exeptions.AlreadyDeclearedException; -import semantic.exeptions.AlreadyDefinedException; -import semantic.exeptions.NotDeclearedException; -import semantic.exeptions.TypeMismatchException; +import semantic.exeptions.*; import typechecker.TypeCheckResult; public class SemanticAnalyzer implements SemanticVisitor { - private static HashMap currentFields = new HashMap<>(); + private static HashMap currentFields = new HashMap<>(); public static ArrayList errors = new ArrayList<>(); private static Context context; private static Scope currentScope; private static ClassNode currentClass; - private static TypeNode currentNullType; + private static ITypeNode currentNullType; + private ITypeNode currentMethodReturnType; public static ASTNode generateTast(ASTNode node) { SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); @@ -111,59 +107,59 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(MethodNode methodNode) { - var valid = true; + if (methodNode instanceof ConstructorNode) { + return new TypeCheckResult(true, new BaseType(TypeEnum.VOID)); + } else { - for (var otherMethod : currentClass.getMethods()) { - if (Objects.equals(otherMethod, methodNode)) - break; - if (otherMethod.isSame(methodNode)) { - errors.add(new AlreadyDeclearedException( - "Method " + methodNode.getIdentifier() + " is already defined in class " - + currentClass.identifier)); - valid = false; - } - } + var valid = true; - currentScope.pushScope(); - for (var parameter : methodNode.getParameters()) { - var result = parameter.accept(this); - valid = valid && result.isValid(); - try { - currentScope.addLocalVar(parameter.identifier, parameter.type); - } catch (AlreadyDeclearedException e) { - errors.add(new AlreadyDeclearedException(parameter.identifier)); + for (var otherMethod : currentClass.getMethods()) { + if (Objects.equals(otherMethod, methodNode)) + break; + if (otherMethod.isSame(methodNode)) { + errors.add(new AlreadyDeclearedException( + "Method " + methodNode.getIdentifier() + " is already defined in class " + + currentClass.identifier)); + valid = false; + } } - } - // Check if this method is already declared + currentScope.pushScope(); + for (var parameter : methodNode.getParameters()) { + var result = parameter.accept(this); + valid = valid && result.isValid(); + try { + currentScope.addLocalVar(parameter.identifier, parameter.type); + } catch (AlreadyDeclearedException e) { + errors.add(new AlreadyDeclearedException(parameter.identifier)); + } -// currentMethodReturnType = methodDecl.getType(); -// currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ + } + // Check if this method is already declared - TypeNode resultType = new TypeNode("void"); + currentMethodReturnType = methodNode.getType(); + currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ + + ITypeNode resultType = new BaseType(TypeEnum.VOID); - if (methodNode.block != null) { // gesetzt ist, ist dieser der Rückgabewert der Methode var result = methodNode.block.accept(this); valid = valid && result.isValid(); currentScope.popScope(); resultType = result.getType(); - /* if (resultType == null) { - resultType = new BaseType(Primitives.VOID); + resultType = new BaseType(TypeEnum.VOID); } - if (!resultType.equals(methodDecl.getType())) { - errors.add(new TypeMismatchException("Method-Declaration " + methodDecl.getIdentifier() + " with type " - + methodDecl.getType() + " has at least one Mismatching return Type:" - + TypeHelper.generateLocationString(methodDecl.line, methodDecl.column, fileName))); + if (!resultType.equals(methodNode.getType())) { + errors.add(new TypeMismatchException("Method-Declaration " + methodNode.getIdentifier() + " with type " + + methodNode.getType() + " has at least one Mismatching return Type:")); valid = false; } - */ - } + return new TypeCheckResult(valid, resultType); - return new TypeCheckResult(valid, resultType); + } } @Override @@ -184,7 +180,9 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(ReturnStatementNode toCheck) { - return null; + + var result = toCheck.expression.accept(this); + return new TypeCheckResult(true, result.getType()); } @Override @@ -201,11 +199,18 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(BlockNode blockNode) { - + ITypeNode blockReturnType = null; for (IStatementNode statementNode : blockNode.statements) { - statementNode.accept(this); + var result = statementNode.accept(this); + if(result.getType() != null){ + if(blockReturnType == null){ + blockReturnType = result.getType(); + } else { + errors.add(new MultipleReturnTypes("There are multiple Return types")); + } + } } - return new TypeCheckResult(true, null); + return new TypeCheckResult(true, blockReturnType); } @Override @@ -260,7 +265,7 @@ public class SemanticAnalyzer implements SemanticVisitor { // } valid = valid && lResult.isValid() && rResult.isValid(); currentNullType = null; - return new TypeCheckResult(valid, null); // return type is null to get the return type sufficently + return new TypeCheckResult(valid, new BaseType(TypeEnum.VOID)); // return type is null to get the return type sufficently } @Override @@ -322,7 +327,7 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(CalculationExpressionNode calcNode) { - if(calcNode.calculationExpression != null){ + if (calcNode.calculationExpression != null) { calcNode.calculationExpression.accept(this); } return null; @@ -352,7 +357,7 @@ public class SemanticAnalyzer implements SemanticVisitor { return new TypeCheckResult(false, null); } - return new TypeCheckResult(valid, unary.getType()); + return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier)); } } \ No newline at end of file diff --git a/src/main/java/semantic/context/FieldContext.java b/src/main/java/semantic/context/FieldContext.java index 6c594c9..18e8cf7 100644 --- a/src/main/java/semantic/context/FieldContext.java +++ b/src/main/java/semantic/context/FieldContext.java @@ -2,19 +2,19 @@ package semantic.context; import ast.member.FieldNode; import ast.type.*; -import ast.type.type.TypeNode; +import ast.type.type.*; public class FieldContext { private AccessModifierNode accessModifier; - private TypeNode type; + private ITypeNode type; public FieldContext(FieldNode field) { accessModifier = field.accessTypeNode; type = field.type; } - public TypeNode getType() { + public ITypeNode getType() { return type; } diff --git a/src/main/java/semantic/exeptions/MultipleReturnTypes.java b/src/main/java/semantic/exeptions/MultipleReturnTypes.java new file mode 100644 index 0000000..59f92fa --- /dev/null +++ b/src/main/java/semantic/exeptions/MultipleReturnTypes.java @@ -0,0 +1,9 @@ +package semantic.exeptions; + +public class MultipleReturnTypes extends RuntimeException { + + public MultipleReturnTypes(String message) { + super(message); + } + +} diff --git a/src/main/java/typechecker/TypeCheckResult.java b/src/main/java/typechecker/TypeCheckResult.java index 21c12df..f52818d 100644 --- a/src/main/java/typechecker/TypeCheckResult.java +++ b/src/main/java/typechecker/TypeCheckResult.java @@ -1,14 +1,14 @@ package typechecker; -import ast.type.type.TypeNode; +import ast.type.type.ITypeNode; public class TypeCheckResult { private boolean valid; - private TypeNode type; + private ITypeNode type; - public TypeCheckResult(boolean valid, TypeNode type) { + public TypeCheckResult(boolean valid, ITypeNode type) { this.valid = valid; this.type = type; } @@ -17,7 +17,7 @@ public class TypeCheckResult { return valid; } - public TypeNode getType() { + public ITypeNode getType() { return type; } } \ No newline at end of file diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java index 2d14077..3da4043 100644 --- a/src/test/java/semantic/EndToTAST.java +++ b/src/test/java/semantic/EndToTAST.java @@ -12,6 +12,7 @@ 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; @@ -208,7 +209,31 @@ public class EndToTAST { CharStream codeCharStream = null; try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchRefType.java")); + 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); } @@ -228,4 +253,29 @@ public class EndToTAST { } + @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()); + + } + } diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java index c38a37e..1e404af 100644 --- a/src/test/java/semantic/Mocker.java +++ b/src/test/java/semantic/Mocker.java @@ -6,7 +6,7 @@ import ast.member.FieldNode; import ast.member.MethodNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; -import ast.type.type.TypeNode; +import ast.type.type.*; public class Mocker { @@ -16,11 +16,11 @@ public class Mocker { ClassNode c = new ClassNode(); c.identifier = "testClass"; - FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a"); + FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"); c.members.add(f1); - FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a"); + FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"); c.members.add(f2); @@ -36,7 +36,7 @@ public class Mocker { MethodNode methodNode = new MethodNode(); //Parameter - ParameterNode parameterNode = new ParameterNode(new TypeNode("int"), "a"); + ParameterNode parameterNode = new ParameterNode(new BaseType(TypeEnum.INT), "a"); methodNode.addParameter(parameterNode); @@ -59,7 +59,7 @@ public class Mocker { MethodNode methodNode = new MethodNode(); methodNode.block = new BlockNode(); - methodNode.type = new TypeNode("int"); + methodNode.setType(new BaseType(TypeEnum.INT)); methodNode.setIdentifier("testMethod"); @@ -67,7 +67,7 @@ public class Mocker { MethodNode methodNode1 = new MethodNode(); methodNode1.block = new BlockNode(); - methodNode1.type = new TypeNode("int"); + methodNode1.setType(new BaseType(TypeEnum.INT)); methodNode1.setIdentifier("testMethod"); diff --git a/src/test/resources/semantic/endToTAST/CorrectRetType.java b/src/test/resources/semantic/endToTAST/CorrectRetType.java new file mode 100644 index 0000000..473e8df --- /dev/null +++ b/src/test/resources/semantic/endToTAST/CorrectRetType.java @@ -0,0 +1,7 @@ +public class Example { + + public static int testMethod(int x){ + return x; + } + +} diff --git a/src/test/resources/semantic/endToTAST/CorrectTest.java b/src/test/resources/semantic/endToTAST/CorrectTest.java index 8e3bf62..ee71670 100644 --- a/src/test/resources/semantic/endToTAST/CorrectTest.java +++ b/src/test/resources/semantic/endToTAST/CorrectTest.java @@ -2,7 +2,9 @@ public class Example { public int a; - public static int testMethod(char x){ + public static int testMethod(int b){ + + a = b; } diff --git a/src/test/resources/semantic/endToTAST/MultipleRetTypes.java b/src/test/resources/semantic/endToTAST/MultipleRetTypes.java new file mode 100644 index 0000000..a5680ed --- /dev/null +++ b/src/test/resources/semantic/endToTAST/MultipleRetTypes.java @@ -0,0 +1,8 @@ +public class Example { + + public static int testMethod(int x, char c){ + return x; + return c; + } + +} diff --git a/src/test/resources/semantic/endToTAST/retTypeMismatch.java b/src/test/resources/semantic/endToTAST/retTypeMismatch.java new file mode 100644 index 0000000..d3a2674 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/retTypeMismatch.java @@ -0,0 +1,7 @@ +public class Example { + + public static int testMethod(char x){ + return x; + } + +} From 7b41c45cd5959cb198edfbf077335c3fcea2eb5d Mon Sep 17 00:00:00 2001 From: Bruder John Date: Fri, 21 Jun 2024 17:03:49 +0200 Subject: [PATCH 21/25] Fixed all Tests --- src/main/java/semantic/SemanticAnalyzer.java | 16 +++++++------ src/test/java/semantic/EndToTAST.java | 24 ------------------- .../semantic/endToTAST/CorrectInstVar.java | 18 -------------- .../semantic/endToTAST/CorrectTest.java | 9 +------ 4 files changed, 10 insertions(+), 57 deletions(-) delete mode 100644 src/test/resources/semantic/endToTAST/CorrectInstVar.java diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 1718d01..191e3a9 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -254,7 +254,7 @@ public class SemanticAnalyzer implements SemanticVisitor { currentNullType = lResult.getType(); var rResult = rExpression.accept(this); - if (!Objects.equals(currentFields.get(toCheck.assignable.identifier), rExpression.getType())) { + if (!Objects.equals(currentScope.getLocalVar(toCheck.assignable.identifier), rExpression.getType())) { errors.add(new TypeMismatchException( "Mismatch types in Assign-Statement: cannot convert from \"" + lResult.getType() + "\" to \"" + rResult.getType() + "\"")); @@ -265,7 +265,7 @@ public class SemanticAnalyzer implements SemanticVisitor { // } valid = valid && lResult.isValid() && rResult.isValid(); currentNullType = null; - return new TypeCheckResult(valid, new BaseType(TypeEnum.VOID)); // return type is null to get the return type sufficently + return new TypeCheckResult(valid, null); // return type is null to get the return type sufficently } @Override @@ -352,12 +352,14 @@ public class SemanticAnalyzer implements SemanticVisitor { public TypeCheckResult analyze(UnaryExpressionNode unary) { var valid = true; - if (!currentScope.contains(unary.identifier)) { - errors.add(new NotDeclearedException("Not declared " + unary.identifier)); - return new TypeCheckResult(false, null); + if (currentScope.contains(unary.identifier)) { + return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier)); + } else if(currentFields.get(unary.identifier) != null) { + return new TypeCheckResult(valid, currentFields.get(unary.identifier)); + } else { + errors.add(new NotDeclearedException("Var is not Decleared")); } - - return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier)); + return new TypeCheckResult(valid, null); } } \ No newline at end of file diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java index 3da4043..dc30e0b 100644 --- a/src/test/java/semantic/EndToTAST.java +++ b/src/test/java/semantic/EndToTAST.java @@ -155,30 +155,6 @@ public class EndToTAST { } - @Test - public void correctInstVarTest(){ - - CharStream codeCharStream = null; - try { - codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectInstVar.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 typeMismatchRefType(){ diff --git a/src/test/resources/semantic/endToTAST/CorrectInstVar.java b/src/test/resources/semantic/endToTAST/CorrectInstVar.java deleted file mode 100644 index 5c20dab..0000000 --- a/src/test/resources/semantic/endToTAST/CorrectInstVar.java +++ /dev/null @@ -1,18 +0,0 @@ -public class Test { - - public Example ex; - - public static int testMethod(char x){ - - int b = this.ex.a; - - return x; - } - -} - -public class Example { - - public int a; - -} \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/CorrectTest.java b/src/test/resources/semantic/endToTAST/CorrectTest.java index ee71670..f0cdb30 100644 --- a/src/test/resources/semantic/endToTAST/CorrectTest.java +++ b/src/test/resources/semantic/endToTAST/CorrectTest.java @@ -3,16 +3,9 @@ public class Example { public int a; public static int testMethod(int b){ - a = b; + return a; } -} - -public class Test { - - public static int testMethod(char x, int a){ - return x; - } } \ No newline at end of file From 6d36eb109c6a8097756870e61c20527db00df92d Mon Sep 17 00:00:00 2001 From: i22035 Date: Fri, 21 Jun 2024 18:02:29 +0200 Subject: [PATCH 22/25] Added Enums for Operators and MainMethodNode --- src/main/java/ast/block/BlockNode.java | 2 ++ .../CalculationExpressionNode.java | 12 ++++++++-- .../binaryexpression/DotExpressionNode.java | 14 +++++++++-- .../binaryexpression/EnumDotOperator.java | 5 ++++ .../binaryexpression/EnumLineOperator.java | 5 ++++ .../EnumNonCalculationOperator.java | 5 ++++ .../NonCalculationExpressionNode.java | 24 +++++++++++++++++-- src/main/java/ast/member/MainMethodNode.java | 11 +++++++++ src/main/java/ast/member/MethodNode.java | 4 ---- .../ast/statement/ReturnStatementNode.java | 8 +++++-- src/main/java/ast/type/EnumTypeNode.java | 5 ---- .../java/parser/astBuilder/ASTBuilder.java | 10 ++++---- 12 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 src/main/java/ast/expression/binaryexpression/EnumDotOperator.java create mode 100644 src/main/java/ast/expression/binaryexpression/EnumLineOperator.java create mode 100644 src/main/java/ast/expression/binaryexpression/EnumNonCalculationOperator.java create mode 100644 src/main/java/ast/member/MainMethodNode.java delete mode 100644 src/main/java/ast/type/EnumTypeNode.java diff --git a/src/main/java/ast/block/BlockNode.java b/src/main/java/ast/block/BlockNode.java index 9987cf9..ab2d70b 100644 --- a/src/main/java/ast/block/BlockNode.java +++ b/src/main/java/ast/block/BlockNode.java @@ -2,6 +2,7 @@ package ast.block; import ast.ASTNode; import ast.statement.IStatementNode; +import ast.statement.ReturnStatementNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; @@ -12,6 +13,7 @@ import java.util.List; public class BlockNode implements ASTNode, Visitable { public List statements = new ArrayList<>(); + public Boolean hasReturnStatement = false; public BlockNode() {} diff --git a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java index 70451d8..b594502 100644 --- a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java @@ -6,12 +6,12 @@ import typechecker.TypeCheckResult; public class CalculationExpressionNode extends BinaryExpressionNode { public CalculationExpressionNode calculationExpression; - public String operator; + public EnumLineOperator operator; public DotExpressionNode dotExpression; public CalculationExpressionNode(CalculationExpressionNode calculationExpression, String operator, DotExpressionNode dotExpression) { this.calculationExpression = calculationExpression; - this.operator = operator; + setOperator(operator); this.dotExpression = dotExpression; } @@ -19,6 +19,14 @@ public class CalculationExpressionNode extends BinaryExpressionNode { this.dotExpression = dotExpression; } + private void setOperator(String operator) { + if(operator.equals("+")) { + this.operator = EnumLineOperator.PLUS; + } else if(operator.equals("-")) { + this.operator = EnumLineOperator.MINUS; + } + } + @Override public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); diff --git a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java index cc5f2c6..2d56221 100644 --- a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java @@ -6,12 +6,12 @@ import typechecker.TypeCheckResult; public class DotExpressionNode extends BinaryExpressionNode { public DotExpressionNode dotExpression; - public String operator; + public EnumDotOperator operator; public DotSubstractionExpressionNode dotSubstractionExpression; public DotExpressionNode(DotExpressionNode dotExpression, String operator, DotSubstractionExpressionNode dotSubstractionExpression) { this.dotExpression = dotExpression; - this.operator = operator; + setOperator(operator); this.dotSubstractionExpression = dotSubstractionExpression; } @@ -19,6 +19,16 @@ public class DotExpressionNode extends BinaryExpressionNode { this.dotSubstractionExpression = dotSubstractionExpression; } + private void setOperator(String operator) { + if(operator.equals("*")) { + this.operator = EnumDotOperator.MULT; + } else if(operator.equals("/")) { + this.operator = EnumDotOperator.DIV; + } else if(operator.equals("%")) { + this.operator = EnumDotOperator.MOD; + } + } + @Override public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); diff --git a/src/main/java/ast/expression/binaryexpression/EnumDotOperator.java b/src/main/java/ast/expression/binaryexpression/EnumDotOperator.java new file mode 100644 index 0000000..3525266 --- /dev/null +++ b/src/main/java/ast/expression/binaryexpression/EnumDotOperator.java @@ -0,0 +1,5 @@ +package ast.expression.binaryexpression; + +public enum EnumDotOperator { + MULT, DIV, MOD +} diff --git a/src/main/java/ast/expression/binaryexpression/EnumLineOperator.java b/src/main/java/ast/expression/binaryexpression/EnumLineOperator.java new file mode 100644 index 0000000..27389ec --- /dev/null +++ b/src/main/java/ast/expression/binaryexpression/EnumLineOperator.java @@ -0,0 +1,5 @@ +package ast.expression.binaryexpression; + +public enum EnumLineOperator { + PLUS, MINUS +} diff --git a/src/main/java/ast/expression/binaryexpression/EnumNonCalculationOperator.java b/src/main/java/ast/expression/binaryexpression/EnumNonCalculationOperator.java new file mode 100644 index 0000000..40c3dfd --- /dev/null +++ b/src/main/java/ast/expression/binaryexpression/EnumNonCalculationOperator.java @@ -0,0 +1,5 @@ +package ast.expression.binaryexpression; + +public enum EnumNonCalculationOperator { + AND, OR, GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL +} diff --git a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java index 5cdebc2..f89fdf8 100644 --- a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java @@ -8,15 +8,35 @@ import typechecker.TypeCheckResult; public class NonCalculationExpressionNode extends BinaryExpressionNode { public UnaryExpressionNode unaryExpression; - public String operator; + public EnumNonCalculationOperator operator; public IExpressionNode expression; public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, IExpressionNode expression) { this.unaryExpression = unaryExpression; - this.operator = operator; + setOperator(operator); this.expression = expression; } + private void setOperator(String operator) { + if(operator.equals("&&")) { + this.operator = EnumNonCalculationOperator.AND; + } else if(operator.equals("||")) { + this.operator = EnumNonCalculationOperator.OR; + } else if(operator.equals(">")) { + this.operator = EnumNonCalculationOperator.GREATER; + } else if(operator.equals("<")) { + this.operator = EnumNonCalculationOperator.LESS; + } else if(operator.equals(">=")) { + this.operator = EnumNonCalculationOperator.GREATER_EQUAL; + } else if(operator.equals("<=")) { + this.operator = EnumNonCalculationOperator.LESS_EQUAL; + } else if(operator.equals("==")) { + this.operator = EnumNonCalculationOperator.EQUAL; + } else if(operator.equals("!=")) { + this.operator = EnumNonCalculationOperator.NOT_EQUAL; + } + } + @Override public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); diff --git a/src/main/java/ast/member/MainMethodNode.java b/src/main/java/ast/member/MainMethodNode.java new file mode 100644 index 0000000..e50cc4f --- /dev/null +++ b/src/main/java/ast/member/MainMethodNode.java @@ -0,0 +1,11 @@ +package ast.member; + +import ast.block.BlockNode; + +public class MainMethodNode extends MethodNode { + public BlockNode block; + + public MainMethodNode(BlockNode block) { + this.block = block; + } +} diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java index ecfd598..2aecf57 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -23,10 +23,6 @@ public class MethodNode implements MemberNode, Visitable { public MethodNode() {} - public MethodNode(BlockNode block){ - this.block = block; - } - public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){ this.accesModifier = new AccessModifierNode(accessModifier); this.type = type; diff --git a/src/main/java/ast/statement/ReturnStatementNode.java b/src/main/java/ast/statement/ReturnStatementNode.java index 66d3846..e525c3f 100644 --- a/src/main/java/ast/statement/ReturnStatementNode.java +++ b/src/main/java/ast/statement/ReturnStatementNode.java @@ -1,15 +1,19 @@ package ast.statement; -import ast.ASTNode; import ast.expression.IExpressionNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; public class ReturnStatementNode implements IStatementNode { public IExpressionNode expression; + public Boolean voidReturn = false; public ReturnStatementNode(IExpressionNode expression) { - this.expression = expression; + if(expression != null) { + this.expression = expression; + } else { + voidReturn = true; + } } @Override diff --git a/src/main/java/ast/type/EnumTypeNode.java b/src/main/java/ast/type/EnumTypeNode.java deleted file mode 100644 index 98c38ea..0000000 --- a/src/main/java/ast/type/EnumTypeNode.java +++ /dev/null @@ -1,5 +0,0 @@ -package ast.type; - -public enum EnumTypeNode { - INT, BOOLEAN, CHAR, IDENTIFIER -} diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index 31a8b82..95ac93c 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -10,12 +10,9 @@ import ast.expression.binaryexpression.NonCalculationExpressionNode; import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.NotExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; -import ast.member.FieldNode; -import ast.member.MethodNode; +import ast.member.*; import ast.statement.ifstatement.ElseStatementNode; import ast.statement.ifstatement.IfElseStatementNode; -import ast.member.ConstructorNode; -import ast.member.MemberNode; import ast.parameter.ParameterNode; import ast.statement.*; import ast.statement.ifstatement.IfStatementNode; @@ -65,7 +62,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) { if(ctx.MainMethodDeclaration() != null) { - return new MethodNode((BlockNode) visit(ctx.block())); + return new MainMethodNode((BlockNode) visit(ctx.block())); } else { if(ctx.type() != null) { MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); @@ -129,6 +126,9 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { for(SimpleJavaParser.StatementContext statement : ctx.statement()) { blockNode.addStatement((IStatementNode) visit(statement)); } + if(!blockNode.hasReturnStatement) { + blockNode.addStatement(new ReturnStatementNode(null)); + } return blockNode; } From 5bf9a4fc734192998429a146c3e8877e55d31894 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Fri, 21 Jun 2024 18:06:49 +0200 Subject: [PATCH 23/25] added wrong type in if clause --- src/main/java/semantic/SemanticAnalyzer.java | 4 +-- src/test/java/semantic/EndToTAST.java | 25 +++++++++++++++++++ .../semantic/endToTAST/CorrectTest.java | 9 ++++++- .../semantic/endToTAST/WrongIfClause.java | 7 ++++++ 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/semantic/endToTAST/WrongIfClause.java diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 191e3a9..8a16b47 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -175,7 +175,7 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(IfStatementNode toCheck) { - return null; + return new TypeCheckResult(true, null); } @Override @@ -275,7 +275,7 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(IfElseStatementNode toCheck) { - return null; + return new TypeCheckResult(true, null); } @Override diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java index dc30e0b..3189802 100644 --- a/src/test/java/semantic/EndToTAST.java +++ b/src/test/java/semantic/EndToTAST.java @@ -49,6 +49,7 @@ public class EndToTAST { ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + assertEquals(SemanticAnalyzer.errors.size(), 0); assertNotNull(tast); @@ -254,4 +255,28 @@ public class EndToTAST { } + @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/resources/semantic/endToTAST/CorrectTest.java b/src/test/resources/semantic/endToTAST/CorrectTest.java index f0cdb30..054a49b 100644 --- a/src/test/resources/semantic/endToTAST/CorrectTest.java +++ b/src/test/resources/semantic/endToTAST/CorrectTest.java @@ -2,10 +2,17 @@ public class Example { public int a; - public static int testMethod(int b){ + public static int testMethod(int b, boolean bo){ a = b; + if(bo){ + + } return a; } + public static void testMethod(int b){ + + } + } \ No newline at end of file diff --git a/src/test/resources/semantic/endToTAST/WrongIfClause.java b/src/test/resources/semantic/endToTAST/WrongIfClause.java new file mode 100644 index 0000000..f73f052 --- /dev/null +++ b/src/test/resources/semantic/endToTAST/WrongIfClause.java @@ -0,0 +1,7 @@ +public class Example { + + public static void testMethod(int x){ + + } + +} From 1b91e25d17c6ccd4e4399ac206d6a9a630102589 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Fri, 21 Jun 2024 18:09:32 +0200 Subject: [PATCH 24/25] fixed tests --- src/main/java/semantic/SemanticAnalyzer.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 8a16b47..c409c0d 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -181,8 +181,13 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(ReturnStatementNode toCheck) { - var result = toCheck.expression.accept(this); - return new TypeCheckResult(true, result.getType()); + if(toCheck.expression != null){ + var result = toCheck.expression.accept(this); + return new TypeCheckResult(true, result.getType()); + } else { + return new TypeCheckResult(false, null); + } + } @Override From c44118c872dc76de96a2b6b96e38fe48d92d4c68 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Fri, 21 Jun 2024 18:28:08 +0200 Subject: [PATCH 25/25] Fixed all --- src/main/java/bytecode/ByteCodeGenerator.java | 2 +- src/main/java/main/Main.java | 2 +- src/test/java/parser/ParserTest.java | 1 + src/test/java/semantic/SemanticTest.java | 203 +++++++++--------- 4 files changed, 99 insertions(+), 109 deletions(-) diff --git a/src/main/java/bytecode/ByteCodeGenerator.java b/src/main/java/bytecode/ByteCodeGenerator.java index 7db6395..5f3cb4b 100644 --- a/src/main/java/bytecode/ByteCodeGenerator.java +++ b/src/main/java/bytecode/ByteCodeGenerator.java @@ -15,7 +15,7 @@ public class ByteCodeGenerator implements ProgramVisitor { @Override public void visit(ProgramNode programNode) { for (ClassNode classDeclarationNode : programNode.classes) { - ClassCodeGen classCodeGen = new ClassCodeGen(); +// ClassCodeGen classCodeGen = new ClassCodeGen(); // classDeclarationNode.accept(classCodeGen); } } diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java index 8b858b4..69de2bc 100644 --- a/src/main/java/main/Main.java +++ b/src/main/java/main/Main.java @@ -2,7 +2,7 @@ package main; import ast.ASTNode; import ast.ProgramNode; -import parser.ASTBuilder; +import parser.astBuilder.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; import semantic.SemanticAnalyzer; diff --git a/src/test/java/parser/ParserTest.java b/src/test/java/parser/ParserTest.java index d599632..4c39828 100644 --- a/src/test/java/parser/ParserTest.java +++ b/src/test/java/parser/ParserTest.java @@ -4,6 +4,7 @@ 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; diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index d2d1887..04fda3d 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -1,22 +1,11 @@ package semantic; import ast.*; -import ast.expression.BinaryExpressionNode; -import ast.expression.ExpressionNode; -import ast.expression.ExpresssionOperator; -import ast.expression.IdentifierExpressionNode; import ast.member.FieldNode; import ast.member.MemberNode; import ast.member.MethodNode; -import ast.parameter.ParameterListNode; import ast.parameter.ParameterNode; -import ast.statement.AssignmentStatementNode; -import ast.statement.StatementNode; -import ast.type.AccessTypeNode; -import ast.type.BaseTypeNode; -import ast.type.EnumAccessTypeNode; -import ast.type.EnumTypeNode; -import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; import semantic.exeptions.AlreadyDeclearedException; import java.util.ArrayList; @@ -27,99 +16,99 @@ import static org.junit.jupiter.api.Assertions.*; public class SemanticTest { - @Test - public void alreadyDeclaredLocalFieldVar() { - ProgramNode programNode = new ProgramNode(); - List classList = new ArrayList<>(); - AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); - ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); - - SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); - ASTNode tast = semanticAnalyzer.generateTast(ast); - - MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); - classNode.members.add(memberNode2); - - classList.add(classNode); - programNode.classes = classList; - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - assertEquals(1, SemanticAnalyzer.errors.size()); - assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); - assertNull(typedAst); - } - - @Test - public void shouldWorkWithNoError() { - ProgramNode programNode = new ProgramNode(); - List classList = new ArrayList<>(); - AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); - ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); - - SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); - ASTNode tast = semanticAnalyzer.generateTast(ast); - - assertEquals(semanticAnalyzer.errors.size(), 0); - assertNotNull(tast); - - MemberNode memberNode3 = getMemberNode(accessTypeNode); - classNode.members.add(memberNode3); - - classList.add(classNode); - programNode.classes = classList; - - ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); - - assertEquals(0, SemanticAnalyzer.errors.size()); - assertEquals(programNode, typedAst); - } - - /** - * This method is used to create a MemberNode representing a method. - * It first creates a list of ParameterNodes and adds a ParameterNode to it. - * Then, it creates a ParameterListNode using the list of ParameterNodes. - * After that, it creates a list of StatementNodes and adds a StatementNode to it by calling the getStatementNode method. - * Finally, it creates a MethodNode using the provided AccessTypeNode, a BaseTypeNode representing the return type of the method, - * the method name, the ParameterListNode, and the list of StatementNodes, and returns this MethodNode. - * - * @param accessTypeNode The AccessTypeNode representing the access type of the method. - * @return The created MemberNode representing the method. - */ -private static MemberNode getMemberNode(AccessTypeNode accessTypeNode) { - List parameterNodeList = new ArrayList<>(); - ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1"); - parameterNodeList.add(parameterNode1); - ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList); - - List statementNodeList = new ArrayList<>(); - - StatementNode statementNode1 = getStatementNode(); - statementNodeList.add(statementNode1); - - return new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2", parameterListNode, statementNodeList); -} - - /** - * This method is used to create a StatementNode for an assignment operation. - * It first creates two IdentifierExpressionNodes for 'this' and 'objectVar'. - * Then, it creates a BinaryExpressionNode to represent the operation 'this.objectVar'. - * After that, it creates a LiteralNode to represent the integer value 1. - * Finally, it creates another BinaryExpressionNode to represent the assignment operation 'this.objectVar = 1', - * and wraps this expression in an AssignmentStatementNode. - * - * @return The created AssignmentStatementNode representing the assignment operation 'this.objectVar = 1'. - */ -private static StatementNode getStatementNode() { - ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this"); - ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar"); - - ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT); - - ExpressionNode expressionNodeRight = new LiteralNode(1); - - BinaryExpressionNode expressionNode = new BinaryExpressionNode(expressionNodeLeft, expressionNodeRight, ExpresssionOperator.ASSIGNMENT); - - return new AssignmentStatementNode(expressionNode); -} +// @Test +// public void alreadyDeclaredLocalFieldVar() { +// ProgramNode programNode = new ProgramNode(); +// List classList = new ArrayList<>(); +// AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); +// ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); +// +// SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); +// ASTNode tast = semanticAnalyzer.generateTast(ast); +// +// MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); +// classNode.members.add(memberNode2); +// +// classList.add(classNode); +// programNode.classes = classList; +// +// ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); +// +// assertEquals(1, SemanticAnalyzer.errors.size()); +// assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); +// assertNull(typedAst); +// } +// +// @Test +// public void shouldWorkWithNoError() { +// ProgramNode programNode = new ProgramNode(); +// List classList = new ArrayList<>(); +// AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC); +// ClassNode classNode = new ClassNode(accessTypeNode, "testClass"); +// +// SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); +// ASTNode tast = semanticAnalyzer.generateTast(ast); +// +// assertEquals(semanticAnalyzer.errors.size(), 0); +// assertNotNull(tast); +// +// MemberNode memberNode3 = getMemberNode(accessTypeNode); +// classNode.members.add(memberNode3); +// +// classList.add(classNode); +// programNode.classes = classList; +// +// ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); +// +// assertEquals(0, SemanticAnalyzer.errors.size()); +// assertEquals(programNode, typedAst); +// } +// +// /** +// * This method is used to create a MemberNode representing a method. +// * It first creates a list of ParameterNodes and adds a ParameterNode to it. +// * Then, it creates a ParameterListNode using the list of ParameterNodes. +// * After that, it creates a list of StatementNodes and adds a StatementNode to it by calling the getStatementNode method. +// * Finally, it creates a MethodNode using the provided AccessTypeNode, a BaseTypeNode representing the return type of the method, +// * the method name, the ParameterListNode, and the list of StatementNodes, and returns this MethodNode. +// * +// * @param accessTypeNode The AccessTypeNode representing the access type of the method. +// * @return The created MemberNode representing the method. +// */ +//private static MemberNode getMemberNode(AccessTypeNode accessTypeNode) { +// List parameterNodeList = new ArrayList<>(); +// ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1"); +// parameterNodeList.add(parameterNode1); +// ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList); +// +// List statementNodeList = new ArrayList<>(); +// +// StatementNode statementNode1 = getStatementNode(); +// statementNodeList.add(statementNode1); +// +// return new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2", parameterListNode, statementNodeList); +//} +// +// /** +// * This method is used to create a StatementNode for an assignment operation. +// * It first creates two IdentifierExpressionNodes for 'this' and 'objectVar'. +// * Then, it creates a BinaryExpressionNode to represent the operation 'this.objectVar'. +// * After that, it creates a LiteralNode to represent the integer value 1. +// * Finally, it creates another BinaryExpressionNode to represent the assignment operation 'this.objectVar = 1', +// * and wraps this expression in an AssignmentStatementNode. +// * +// * @return The created AssignmentStatementNode representing the assignment operation 'this.objectVar = 1'. +// */ +//private static StatementNode getStatementNode() { +// ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this"); +// ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar"); +// +// ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT); +// +// ExpressionNode expressionNodeRight = new LiteralNode(1); +// +// BinaryExpressionNode expressionNode = new BinaryExpressionNode(expressionNodeLeft, expressionNodeRight, ExpresssionOperator.ASSIGNMENT); +// +// return new AssignmentStatementNode(expressionNode); +//} }