From 9d6717a9ceba0e31e9bfb1d1b5118c529d293b6f Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Wed, 8 May 2024 16:11:28 +0200 Subject: [PATCH 1/7] nix --- src/main/java/CompilerInput.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/CompilerInput.txt b/src/main/java/CompilerInput.txt index 75d8cd9..106dace 100644 --- a/src/main/java/CompilerInput.txt +++ b/src/main/java/CompilerInput.txt @@ -1,3 +1,3 @@ -public class Example() { +public class Example { } \ No newline at end of file From 1d9d7e1f00eb1e2012d1e2da1417869c5c46db95 Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Tue, 14 May 2024 11:22:33 +0200 Subject: [PATCH 2/7] Testsuite, MainTest, Main --- src/main/java/CompilerInput.txt | 6 ---- src/main/java/Main.java | 34 ++++++++++++++++-- .../classFileOutput/EmptyClassExample.class | Bin 0 -> 92 bytes src/main/test/{java => }/TestSpecs.md | 0 src/main/test/java/MainTest.java | 2 +- src/main/test/java/Tester.java | 3 +- .../AllFeaturesClassExample.java | 2 ++ src/main/test/resources/CombinedExample.java | 25 +++++++++++++ .../EmptyClassExample.java | 2 ++ .../MoreFeaturesClassExample.java | 2 ++ .../featureTests/BooleanOperations.java | 24 +++++++++++++ .../featureTests/CharManipulation.java | 24 +++++++++++++ .../featureTests/ConditionalStatements.java | 30 ++++++++++++++++ .../resources/featureTests/LoopExamples.java | 18 ++++++++++ .../featureTests/MethodOverloading.java | 18 ++++++++++ 15 files changed, 179 insertions(+), 11 deletions(-) create mode 100644 src/main/java/classFileOutput/EmptyClassExample.class rename src/main/test/{java => }/TestSpecs.md (100%) rename src/main/test/{java => resources}/AllFeaturesClassExample.java (98%) create mode 100644 src/main/test/resources/CombinedExample.java rename src/main/test/{java => resources}/EmptyClassExample.java (75%) rename src/main/test/{java => resources}/MoreFeaturesClassExample.java (84%) create mode 100644 src/main/test/resources/featureTests/BooleanOperations.java create mode 100644 src/main/test/resources/featureTests/CharManipulation.java create mode 100644 src/main/test/resources/featureTests/ConditionalStatements.java create mode 100644 src/main/test/resources/featureTests/LoopExamples.java create mode 100644 src/main/test/resources/featureTests/MethodOverloading.java diff --git a/src/main/java/CompilerInput.txt b/src/main/java/CompilerInput.txt index 49da971..f59b7ae 100644 --- a/src/main/java/CompilerInput.txt +++ b/src/main/java/CompilerInput.txt @@ -1,13 +1,7 @@ public class Example { - public int testVar; - public static int testMethod(char b){ - int a; a = 3; - - } - } \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java index e1673c1..9874ef4 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,9 +1,9 @@ -import ast.ClassNode; import ast.ProgramNode; import bytecode.ByteCodeGenerator; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; import parser.ASTBuilder; import parser.generated.SimpleJavaLexer; @@ -12,6 +12,8 @@ import semantic.SemanticAnalyzer; import java.io.IOException; import java.nio.file.Paths; +import java.sql.SQLOutput; +import java.util.List; public class Main { public static void main(String[] args) throws Exception { @@ -25,18 +27,44 @@ public class Main { static void parsefile(CharStream codeCharStream){ + /* ------------------------- Scanner -> tokens ------------------------- */ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); - CommonTokenStream tokens = new CommonTokenStream(lexer); - SimpleJavaParser parser = new SimpleJavaParser(tokens); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + // Printing the tokens + tokenStream.fill(); + 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); + } + + /* ------------------------- Parser -> Parsetree ------------------------- */ + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); ParseTree tree = parser.program(); // parse the input + // Printing the parse tree + System.out.println ("Parse tree: " + tree.toStringTree(parser)); + + /* AST builder -> AST*/ ASTBuilder builder = new ASTBuilder(); ProgramNode ast = (ProgramNode) builder.visit(tree); // build the AST + // Printing the AST + System.out.println("AST: " + ast.toString()); + + /* ------------------------- Semantic Analyzer -> Tast ------------------------- */ SemanticAnalyzer.generateTast(ast); + // Printing the Tast + System.out.println("Tast generated"); + + /* ------------------------- Bytecode Generator -> Bytecode ------------------------- */ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); byteCodeGenerator.generateByteCode(ast); + System.out.println("Bytecode generated"); + } } \ No newline at end of file diff --git a/src/main/java/classFileOutput/EmptyClassExample.class b/src/main/java/classFileOutput/EmptyClassExample.class new file mode 100644 index 0000000000000000000000000000000000000000..7a73bad66b1cc2283850e64b17c439c901c27cc4 GIT binary patch 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?` literal 0 HcmV?d00001 diff --git a/src/main/test/java/TestSpecs.md b/src/main/test/TestSpecs.md similarity index 100% rename from src/main/test/java/TestSpecs.md rename to src/main/test/TestSpecs.md diff --git a/src/main/test/java/MainTest.java b/src/main/test/java/MainTest.java index 234add6..f9e848e 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/java/EmptyClassExample.java")); + codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); Main.parsefile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); diff --git a/src/main/test/java/Tester.java b/src/main/test/java/Tester.java index b0e86c8..f68ae7a 100644 --- a/src/main/test/java/Tester.java +++ b/src/main/test/java/Tester.java @@ -1,5 +1,6 @@ +//import main.test.resources.EmptyClassExample.java public class Tester { public static void main(String[] args) { - new EmptyClassExample(); + // new EmptyClassExample(); } } diff --git a/src/main/test/java/AllFeaturesClassExample.java b/src/main/test/resources/AllFeaturesClassExample.java similarity index 98% rename from src/main/test/java/AllFeaturesClassExample.java rename to src/main/test/resources/AllFeaturesClassExample.java index 1a8493d..69ab631 100644 --- a/src/main/test/java/AllFeaturesClassExample.java +++ b/src/main/test/resources/AllFeaturesClassExample.java @@ -1,3 +1,5 @@ +package resources; + public class AllFeaturesClassExample { int a; boolean b; diff --git a/src/main/test/resources/CombinedExample.java b/src/main/test/resources/CombinedExample.java new file mode 100644 index 0000000..e3dae84 --- /dev/null +++ b/src/main/test/resources/CombinedExample.java @@ -0,0 +1,25 @@ +package resources; + +public class CombinedExample { + int number; + boolean flag; + char letter; + + public CombinedExample(int number, boolean flag, char letter) { + this.number = number; + this.flag = flag; + this.letter = letter; + } + + public void displayValues() { + System.out.println("Number: " + number); + System.out.println("Flag: " + flag); + System.out.println("Letter: " + letter); + } + + public static void main(String[] args) { + CombinedExample obj = new CombinedExample(10, true, 'X'); + obj.displayValues(); + } +} + diff --git a/src/main/test/java/EmptyClassExample.java b/src/main/test/resources/EmptyClassExample.java similarity index 75% rename from src/main/test/java/EmptyClassExample.java rename to src/main/test/resources/EmptyClassExample.java index 290e747..9bc5365 100644 --- a/src/main/test/java/EmptyClassExample.java +++ b/src/main/test/resources/EmptyClassExample.java @@ -1,3 +1,5 @@ +package resources; + public class EmptyClassExample { private class Inner { } diff --git a/src/main/test/java/MoreFeaturesClassExample.java b/src/main/test/resources/MoreFeaturesClassExample.java similarity index 84% rename from src/main/test/java/MoreFeaturesClassExample.java rename to src/main/test/resources/MoreFeaturesClassExample.java index 4f6fbf3..c58b5a2 100644 --- a/src/main/test/java/MoreFeaturesClassExample.java +++ b/src/main/test/resources/MoreFeaturesClassExample.java @@ -1,3 +1,5 @@ +package resources; + public class MoreFeaturesClassExample { int hallo; private class Inner { diff --git a/src/main/test/resources/featureTests/BooleanOperations.java b/src/main/test/resources/featureTests/BooleanOperations.java new file mode 100644 index 0000000..17d4a15 --- /dev/null +++ b/src/main/test/resources/featureTests/BooleanOperations.java @@ -0,0 +1,24 @@ +package resources.featureTests; + +public class BooleanOperations { + boolean flag; + + public BooleanOperations(boolean flag) { + this.flag = flag; + } + + public boolean isFlag() { + return flag; + } + + public void toggleFlag() { + flag = !flag; + } + + public static void main(String[] args) { + BooleanOperations obj = new BooleanOperations(true); + System.out.println(obj.isFlag()); + obj.toggleFlag(); + System.out.println(obj.isFlag()); + } +} diff --git a/src/main/test/resources/featureTests/CharManipulation.java b/src/main/test/resources/featureTests/CharManipulation.java new file mode 100644 index 0000000..7b70ad2 --- /dev/null +++ b/src/main/test/resources/featureTests/CharManipulation.java @@ -0,0 +1,24 @@ +package resources.featureTests; + +public class CharManipulation { + char letter; + + public CharManipulation(char letter) { + this.letter = letter; + } + + public char getLetter() { + return letter; + } + + public void setLetter(char letter) { + this.letter = letter; + } + + public static void main(String[] args) { + CharManipulation obj = new CharManipulation('A'); + System.out.println(obj.getLetter()); + obj.setLetter('B'); + System.out.println(obj.getLetter()); + } +} diff --git a/src/main/test/resources/featureTests/ConditionalStatements.java b/src/main/test/resources/featureTests/ConditionalStatements.java new file mode 100644 index 0000000..8b26079 --- /dev/null +++ b/src/main/test/resources/featureTests/ConditionalStatements.java @@ -0,0 +1,30 @@ +package resources.featureTests; + +public class ConditionalStatements { + int number; + + public ConditionalStatements(int number) { + this.number = number; + } + + public void checkNumber() { + if (number > 0) { + System.out.println("The number is positive."); + } else if (number < 0) { + System.out.println("The number is negative."); + } else { + System.out.println("The number is zero."); + } + } + + public static void main(String[] args) { + ConditionalStatements obj1 = new ConditionalStatements(5); + ConditionalStatements obj2 = new ConditionalStatements(-3); + ConditionalStatements obj3 = new ConditionalStatements(0); + + obj1.checkNumber(); + obj2.checkNumber(); + obj3.checkNumber(); + } +} + diff --git a/src/main/test/resources/featureTests/LoopExamples.java b/src/main/test/resources/featureTests/LoopExamples.java new file mode 100644 index 0000000..2eb2927 --- /dev/null +++ b/src/main/test/resources/featureTests/LoopExamples.java @@ -0,0 +1,18 @@ +package resources.featureTests; + +public class LoopExamples { + public static void main(String[] args) { + // For loop example + for (int i = 0; i < 5; i++) { + System.out.println("For loop iteration: " + i); + } + + // While loop example + int j = 0; + while (j < 5) { + System.out.println("While loop iteration: " + j); + j++; + } + } +} + diff --git a/src/main/test/resources/featureTests/MethodOverloading.java b/src/main/test/resources/featureTests/MethodOverloading.java new file mode 100644 index 0000000..3ca1d13 --- /dev/null +++ b/src/main/test/resources/featureTests/MethodOverloading.java @@ -0,0 +1,18 @@ +package resources.featureTests; + +public class MethodOverloading { + public int add(int a, int b) { + return a + b; + } + + public int add(int a, int b, int c) { + return a + b + c; + } + + public static void main(String[] args) { + MethodOverloading obj = new MethodOverloading(); + System.out.println("Sum of 2 and 3: " + obj.add(2, 3)); + System.out.println("Sum of 1, 2, and 3: " + obj.add(1, 2, 3)); + } +} + From 8b6189ea333296573ab84524a739a0d0be2c77cb Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Tue, 14 May 2024 13:16:28 +0200 Subject: [PATCH 3/7] Tests and Main --- src/main/java/Main.java | 76 +++++++++++++++---- src/main/test/TestSpecs.md | 6 ++ .../resources/failureTests/TestClass1.java | 6 ++ .../resources/failureTests/TestClass10.java | 10 +++ .../resources/failureTests/TestClass11.java | 10 +++ .../resources/failureTests/TestClass2.java | 6 ++ .../resources/failureTests/TestClass3.java | 10 +++ .../resources/failureTests/TestClass4.java | 4 + .../resources/failureTests/TestClass5.java | 7 ++ .../resources/failureTests/TestClass6.java | 10 +++ .../resources/failureTests/TestClass7.java | 5 ++ .../resources/failureTests/TestClass8.java | 14 ++++ .../resources/failureTests/TestClass9.java | 6 ++ 13 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 src/main/test/resources/failureTests/TestClass1.java create mode 100644 src/main/test/resources/failureTests/TestClass10.java create mode 100644 src/main/test/resources/failureTests/TestClass11.java create mode 100644 src/main/test/resources/failureTests/TestClass2.java create mode 100644 src/main/test/resources/failureTests/TestClass3.java create mode 100644 src/main/test/resources/failureTests/TestClass4.java create mode 100644 src/main/test/resources/failureTests/TestClass5.java create mode 100644 src/main/test/resources/failureTests/TestClass6.java create mode 100644 src/main/test/resources/failureTests/TestClass7.java create mode 100644 src/main/test/resources/failureTests/TestClass8.java create mode 100644 src/main/test/resources/failureTests/TestClass9.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 9874ef4..13ee197 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,18 +1,19 @@ -import ast.ProgramNode; -import bytecode.ByteCodeGenerator; +import ast.ASTNode; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.CommonTokenStream; import parser.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; +import ast.ProgramNode; import semantic.SemanticAnalyzer; +import bytecode.ByteCodeGenerator; import java.io.IOException; import java.nio.file.Paths; -import java.sql.SQLOutput; import java.util.List; public class Main { @@ -34,37 +35,86 @@ public class Main { // 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(); /* ------------------------- Parser -> Parsetree ------------------------- */ SimpleJavaParser parser = new SimpleJavaParser(tokenStream); - ParseTree tree = parser.program(); // parse the input + ParseTree parseTree = parser.program(); // parse the input // Printing the parse tree - System.out.println ("Parse tree: " + tree.toStringTree(parser)); + System.out.println("-------------------- Parser -> Parsetree --------------------"); + System.out.println (parseTree.toStringTree(parser)); + printTree(parseTree, parser, 0); + System.out.println(); - /* AST builder -> AST*/ - ASTBuilder builder = new ASTBuilder(); - ProgramNode ast = (ProgramNode) builder.visit(tree); // build the AST + /* ------------------------- AST builder -> AST ------------------------- */ + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); // Printing the AST - System.out.println("AST: " + ast.toString()); + System.out.println("-------------------- AST builder -> AST --------------------"); + //System.out.println("AST: " + ast.toString()); + printAST(abstractSyntaxTree, 0); + System.out.println(); /* ------------------------- Semantic Analyzer -> Tast ------------------------- */ - SemanticAnalyzer.generateTast(ast); + SemanticAnalyzer.generateTast(abstractSyntaxTree); // Printing the Tast System.out.println("Tast generated"); /* ------------------------- Bytecode Generator -> Bytecode ------------------------- */ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); - byteCodeGenerator.generateByteCode(ast); + byteCodeGenerator.generateByteCode(abstractSyntaxTree); 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 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); + + // 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()); + } + + // 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); + } + } + + + public static void printAST(ASTNode node, int indent) { + String indentString = " ".repeat(indent * 2); + System.out.println(indentString + node.getClass().toString()); + + for (ASTNode child : node.) { + printAST(child, indent + 1); + } + } } \ No newline at end of file diff --git a/src/main/test/TestSpecs.md b/src/main/test/TestSpecs.md index f459ee6..6fd5a41 100644 --- a/src/main/test/TestSpecs.md +++ b/src/main/test/TestSpecs.md @@ -17,6 +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: [TokPublic,TokClass,TokIdentifier "Name",TokLeftBrace,TokRightBrace] ### Beispiel 2: Filled Class diff --git a/src/main/test/resources/failureTests/TestClass1.java b/src/main/test/resources/failureTests/TestClass1.java new file mode 100644 index 0000000..10001a9 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass1.java @@ -0,0 +1,6 @@ +// Syntax Error: Missing semicolon +public class TestClass1 { + public static void main(String[] args) { + System.out.println("Hello, World!") // Missing semicolon here + } +} diff --git a/src/main/test/resources/failureTests/TestClass10.java b/src/main/test/resources/failureTests/TestClass10.java new file mode 100644 index 0000000..9ed631e --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass10.java @@ -0,0 +1,10 @@ +// Semantic Error: Non-static method called from static context +public class TestClass10 { + public static void main(String[] args) { + greet(); // Non-static method 'greet' cannot be referenced from a static context + } + + public void greet() { + System.out.println("Hi!"); + } +} diff --git a/src/main/test/resources/failureTests/TestClass11.java b/src/main/test/resources/failureTests/TestClass11.java new file mode 100644 index 0000000..c944035 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass11.java @@ -0,0 +1,10 @@ +//Compile error: (4, 9) java: variable number is already defined in method main(java.lang.String[]) +public class TestClass10 { + public static void main(String[] args) { + // Declare and initialize an integer variable named 'number' with the value 12 + int number = 12; + + // This line will cause a compile-time error because 'number' is already defined in this scope + int number =13; + } +} \ No newline at end of file diff --git a/src/main/test/resources/failureTests/TestClass2.java b/src/main/test/resources/failureTests/TestClass2.java new file mode 100644 index 0000000..d04ea39 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass2.java @@ -0,0 +1,6 @@ +// Syntax Error: Unclosed string literal +public class TestClass2 { + public static void main(String[] args) { + System.out.println("Hello, World!); // Unclosed string literal + } +} diff --git a/src/main/test/resources/failureTests/TestClass3.java b/src/main/test/resources/failureTests/TestClass3.java new file mode 100644 index 0000000..75c1b39 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass3.java @@ -0,0 +1,10 @@ +// Syntax Error: Missing parentheses in method declaration +public class TestClass3 { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } + + public void greet { // Missing parentheses + System.out.println("Hi!"); + } +} diff --git a/src/main/test/resources/failureTests/TestClass4.java b/src/main/test/resources/failureTests/TestClass4.java new file mode 100644 index 0000000..cf18bf8 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass4.java @@ -0,0 +1,4 @@ +// Syntax Error: Missing class body +public class TestClass4 { + // Missing class body +} diff --git a/src/main/test/resources/failureTests/TestClass5.java b/src/main/test/resources/failureTests/TestClass5.java new file mode 100644 index 0000000..535ce99 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass5.java @@ -0,0 +1,7 @@ +// Semantic Error: Variable used before declaration +public class TestClass5 { + public static void main(String[] args) { + System.out.println(number); // Variable 'number' used before declaration + int number = 10; + } +} diff --git a/src/main/test/resources/failureTests/TestClass6.java b/src/main/test/resources/failureTests/TestClass6.java new file mode 100644 index 0000000..c8c3e60 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass6.java @@ -0,0 +1,10 @@ +// Semantic Error: Method with wrong return type +public class TestClass6 { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } + + public int greet() { // Method should return int, but no return statement is provided + System.out.println("Hi!"); + } +} diff --git a/src/main/test/resources/failureTests/TestClass7.java b/src/main/test/resources/failureTests/TestClass7.java new file mode 100644 index 0000000..0e89cbd --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass7.java @@ -0,0 +1,5 @@ +// Syntax Error: Unmatched braces +public class TestClass7 { + public static void main(String[] args) { + System.out.println("Hello, World!"); + // Missing closing brace for the class diff --git a/src/main/test/resources/failureTests/TestClass8.java b/src/main/test/resources/failureTests/TestClass8.java new file mode 100644 index 0000000..6aa2510 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass8.java @@ -0,0 +1,14 @@ +// Semantic Error: Duplicate method definition +public class TestClass8 { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } + + public void greet() { + System.out.println("Hi!"); + } + + public void greet() { // Duplicate method definition + System.out.println("Hello!"); + } +} diff --git a/src/main/test/resources/failureTests/TestClass9.java b/src/main/test/resources/failureTests/TestClass9.java new file mode 100644 index 0000000..fb873e6 --- /dev/null +++ b/src/main/test/resources/failureTests/TestClass9.java @@ -0,0 +1,6 @@ +// Syntax Error: Incompatible types +public class TestClass9 { + public static void main(String[] args) { + int number = "Hello"; // Incompatible types: String cannot be converted to int + } +} From dd424cda9963db3c0aa013209493f523c30d937a Mon Sep 17 00:00:00 2001 From: Lucas <89882946+notbad3500@users.noreply.github.com> Date: Tue, 14 May 2024 15:47:49 +0200 Subject: [PATCH 4/7] Tests and Main --- .idea/misc.xml | 2 +- src/main/java/Main.java | 11 ++- src/main/java/ast/ASTNode.java | 7 +- src/main/java/semantic/SemanticAnalyzer.java | 2 +- .../java}/EmptyClassExample.class | Bin .../EmptyClassExample.java | 4 +- src/main/test/java/FailureTest.java | 72 ++++++++++++++++++ src/main/test/java/Tester.java | 9 ++- src/main/test/java/make.md | 0 .../resources/failureTests/TestClass4.java | 2 +- 10 files changed, 94 insertions(+), 15 deletions(-) rename src/main/{java/classFileOutput => test/java}/EmptyClassExample.class (100%) rename src/main/test/{resources => java}/EmptyClassExample.java (75%) create mode 100644 src/main/test/java/FailureTest.java create mode 100644 src/main/test/java/make.md diff --git a/.idea/misc.xml b/.idea/misc.xml index f26d89f..eddc20d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 7f55626..24f129b 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,7 +1,6 @@ import ast.ASTNode; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.Token; -import ast.ClassNode; import ast.ProgramNode; import bytecode.ByteCodeGenerator; import org.antlr.v4.runtime.CharStream; @@ -11,7 +10,6 @@ import org.antlr.v4.runtime.CommonTokenStream; import parser.ASTBuilder; import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaParser; -import ast.ProgramNode; import semantic.SemanticAnalyzer; import bytecode.ByteCodeGenerator; @@ -23,12 +21,13 @@ public class Main { public static void main(String[] args) throws Exception { try { CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/java/CompilerInput.txt")); - parseFile(codeCharStream); + parsefile(codeCharStream); } catch (IOException e) { System.err.println("Error reading the file: " + e.getMessage()); } } + static void parsefile(CharStream codeCharStream) { /* ------------------------- Scanner -> tokens ------------------------- */ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); @@ -56,7 +55,6 @@ public class Main { System.out.println(parseTree.toStringTree(parser)); printTree(parseTree, parser, 0); System.out.println(); - ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(ast); /* ------------------------- AST builder -> AST ------------------------- */ ASTBuilder astBuilder = new ASTBuilder(); @@ -72,6 +70,7 @@ public class Main { * ------------------------- Semantic Analyzer -> Tast ------------------------- */ SemanticAnalyzer.generateTast(abstractSyntaxTree); + ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); // Printing the Tast System.out.println("Tast generated"); @@ -81,7 +80,8 @@ public class Main { * ------------------------- */ ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(); - byteCodeGenerator.generateByteCode(abstractSyntaxTree); + //byteCodeGenerator.generateByteCode(abstractSyntaxTree); + byteCodeGenerator.visit(typedAst); System.out.println("Bytecode generated"); } @@ -126,6 +126,5 @@ public class Main { // for (ASTNode child : node.) { // printAST(child, indent + 1); // } - byteCodeGenerator.visit(typedAst); } } \ No newline at end of file diff --git a/src/main/java/ast/ASTNode.java b/src/main/java/ast/ASTNode.java index 9944050..3ef48fa 100644 --- a/src/main/java/ast/ASTNode.java +++ b/src/main/java/ast/ASTNode.java @@ -1,7 +1,12 @@ package ast; -public interface ASTNode { +//import java.util.List; +public interface ASTNode { + /** + * Please implement this method to return a list of children of each node. + */ + // public List getChildren(); } diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 7a6002b..30271a6 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -68,7 +68,7 @@ public class SemanticAnalyzer implements SemanticVisitor { public TypeCheckResult analyze(MethodNode methodNode) { var valid = true; - currentLocalScope.pushScope(); + // currentLocalScope.pushScope(); List statements = methodNode.statements; for (StatementNode statement : statements) { diff --git a/src/main/java/classFileOutput/EmptyClassExample.class b/src/main/test/java/EmptyClassExample.class similarity index 100% rename from src/main/java/classFileOutput/EmptyClassExample.class rename to src/main/test/java/EmptyClassExample.class diff --git a/src/main/test/resources/EmptyClassExample.java b/src/main/test/java/EmptyClassExample.java similarity index 75% rename from src/main/test/resources/EmptyClassExample.java rename to src/main/test/java/EmptyClassExample.java index 9bc5365..9f54ec6 100644 --- a/src/main/test/resources/EmptyClassExample.java +++ b/src/main/test/java/EmptyClassExample.java @@ -1,6 +1,4 @@ -package resources; - public class EmptyClassExample { private class Inner { } -} \ No newline at end of file +} // -o für outout \ No newline at end of file diff --git a/src/main/test/java/FailureTest.java b/src/main/test/java/FailureTest.java new file mode 100644 index 0000000..bc63d91 --- /dev/null +++ b/src/main/test/java/FailureTest.java @@ -0,0 +1,72 @@ +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.junit.jupiter.api.Test; + +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +public class FailureTest { + private static final List TEST_FILES = Arrays.asList( + "src/main/test/resources/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" + ); + + /** + * This test method checks if invalid Java files fail to compile as expected. + * It uses the JavaCompiler from the ToolProvider to compile the files. + * The test passes if all the files fail to compile. + */ + @Test + public void invalidJavaFilesTest() { + // Get the system Java compiler + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + + // Assert that the compiler is available + assertNotNull(compiler, "Java Compiler is not available"); + + // Iterate over the test files + for (String fileName : TEST_FILES) { + // Create a File object for the current file + File file = new File(fileName); + + // Try to compile the file and get the result + // The run method returns 0 if the compilation was successful, and non-zero otherwise + int result = compiler.run(null, null, null, file.getPath()); + + // Assert that the compilation failed (i.e., the result is non-zero) + assertTrue(result != 0, "Expected compilation failure for " + fileName); + } + } + + // schmeißt John Fehler, wenn namen doppelt sind? + // Input: ParseTree mit genanntem Fehler + // Output: Fehlermeldung + @Test + void typedASTTest() throws IOException { + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); + Main.parsefile(codeCharStream); + } catch (IOException e) { + System.err.println("Error reading the file: " + e.getMessage()); + } + } +} + diff --git a/src/main/test/java/Tester.java b/src/main/test/java/Tester.java index f68ae7a..777c50b 100644 --- a/src/main/test/java/Tester.java +++ b/src/main/test/java/Tester.java @@ -1,6 +1,11 @@ -//import main.test.resources.EmptyClassExample.java public class Tester { public static void main(String[] args) { - // new EmptyClassExample(); + 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/make.md b/src/main/test/java/make.md new file mode 100644 index 0000000..e69de29 diff --git a/src/main/test/resources/failureTests/TestClass4.java b/src/main/test/resources/failureTests/TestClass4.java index cf18bf8..f1ee5ec 100644 --- a/src/main/test/resources/failureTests/TestClass4.java +++ b/src/main/test/resources/failureTests/TestClass4.java @@ -1,4 +1,4 @@ // Syntax Error: Missing class body -public class TestClass4 { +public class TestClass4 {- // Missing class body } From 8b9b70b9ee12870a24191f7c165840d03383def7 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Tue, 14 May 2024 17:47:26 +0200 Subject: [PATCH 5/7] Added Test for Semantic Analyzier --- .idea/misc.xml | 2 +- src/main/java/Main.java | 6 +- src/main/java/ast/VarNode.java | 7 +- src/main/java/classFileOutput/Example.class | Bin 125 -> 167 bytes src/main/java/parser/ASTBuilder.java | 2 +- src/main/java/semantic/SemanticAnalyzer.java | 13 ++- src/test/java/semantic/SemanticTester.java | 98 +++++++++++++++++++ 7 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 src/test/java/semantic/SemanticTester.java diff --git a/.idea/misc.xml b/.idea/misc.xml index eddc20d..f26d89f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 91fcd6e..d5aa802 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -32,7 +32,7 @@ public class Main { } - static void parsefile(CharStream codeCharStream) { + static void parseFile(CharStream codeCharStream) { /* ------------------------- Scanner -> tokens ------------------------- */ SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); @@ -73,8 +73,8 @@ public class Main { /* * ------------------------- Semantic Analyzer -> Tast ------------------------- */ - SemanticAnalyzer.generateTast(abstractSyntaxTree); - ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree); + SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); + ProgramNode typedAst = (ProgramNode) semanticAnalyzer.generateTast(abstractSyntaxTree); // Printing the Tast System.out.println("Tast generated"); diff --git a/src/main/java/ast/VarNode.java b/src/main/java/ast/VarNode.java index 9349eb4..519f552 100644 --- a/src/main/java/ast/VarNode.java +++ b/src/main/java/ast/VarNode.java @@ -1,5 +1,6 @@ package ast; +import ast.type.TypeNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; @@ -7,14 +8,14 @@ import visitor.Visitable; public class VarNode implements ASTNode, Visitable { private String identifier; - private String type; + private TypeNode type; - public VarNode(String type, String identifier){ + public VarNode(TypeNode type, String identifier){ this.type = type; this.identifier = identifier; } - public String getType(){ + public TypeNode getType(){ return type; } diff --git a/src/main/java/classFileOutput/Example.class b/src/main/java/classFileOutput/Example.class index 925c770cf46b781b3d6401539912811aecebfb50..522ae9edd25429b756d2dd98d755bdedb11f81c3 100644 GIT binary patch delta 125 zcmb!WO3=D=0d=t5hvUwO-8Q8cOSQywD85k3R*prcgt0c9!#5c7hBR_?a zfmOrPQxho2;+&t7%D~9L1XRlaq!}4F8MuHfCLjxF1d!wf@&v&$3=FJV+Zi}E0tG-y Jxfyss3;;S451{}6 delta 83 zcmZ3^Sj%!WO3=Ad=+!MKs92prH6M@*1k%6luwYbDLwIm}yg^__-L(`Lik%5VU c1*jA#&%n;W0c0@&S*#3fU@=YxE+EYS0Lw-TZvX%Q diff --git a/src/main/java/parser/ASTBuilder.java b/src/main/java/parser/ASTBuilder.java index ff41738..e32be97 100644 --- a/src/main/java/parser/ASTBuilder.java +++ b/src/main/java/parser/ASTBuilder.java @@ -144,7 +144,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitVar(SimpleJavaParser.VarContext ctx) { - return new VarNode("int", ctx.getText()); + return new VarNode(new BaseTypeNode(EnumTypeNode.INT), ctx.getText()); } @Override diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index e6cdc99..362af42 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -22,12 +22,12 @@ import typechecker.TypeCheckResult; public class SemanticAnalyzer implements SemanticVisitor { - private ArrayList currentFields = new ArrayList<>(); + private static ArrayList currentFields = new ArrayList<>(); public static ArrayList errors = new ArrayList<>(); - private Scope currentScope; - private ClassNode currentClass; + private static Scope currentScope; + private static ClassNode currentClass; public static ASTNode generateTast(ASTNode node) { SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); @@ -43,6 +43,13 @@ public class SemanticAnalyzer implements SemanticVisitor { return null; } + public static void clearAnalyzier(){ + currentFields.clear(); + errors.clear(); + currentScope = null; + currentClass = null; + } + @Override public TypeCheckResult analyze(ProgramNode node) { diff --git a/src/test/java/semantic/SemanticTester.java b/src/test/java/semantic/SemanticTester.java new file mode 100644 index 0000000..2c27e1c --- /dev/null +++ b/src/test/java/semantic/SemanticTester.java @@ -0,0 +1,98 @@ +package semantic; + + +import ast.*; +import ast.expression.ExpressionNode; +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; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SemanticTester { + + @BeforeEach + public void init() { + SemanticAnalyzer.clearAnalyzier(); + } + + @Test + public void alreadyDeclaredLocalFieldVar(){ + + 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; + + ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); + + assertEquals(1, SemanticAnalyzer.errors.size()); + assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException); + assertEquals(null, 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"); + + MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar1"); + classNode.members.add(memberNode1); + + 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(); + + VarNode varNode = new VarNode(new BaseTypeNode(EnumTypeNode.INT), "localVar1"); + ExpressionNode expressionNode = new LiteralNode(1); + + StatementNode statementNode1 = new AssignmentStatementNode(varNode, expressionNode); + 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; + + ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); + + assertEquals(0, SemanticAnalyzer.errors.size()); + assertEquals(programNode, typedAst); + + } + +} From d91e3ad819da108a487296eb24ee8df0c2ee7b9d Mon Sep 17 00:00:00 2001 From: Bruder John Date: Tue, 14 May 2024 17:59:53 +0200 Subject: [PATCH 6/7] added maven test --- .gitea/workflows/test.yml | 15 +++++++++++++++ .../{SemanticTester.java => SemanticTest.java} | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/test.yml rename src/test/java/semantic/{SemanticTester.java => SemanticTest.java} (99%) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml new file mode 100644 index 0000000..96ab991 --- /dev/null +++ b/.gitea/workflows/test.yml @@ -0,0 +1,15 @@ +name: Gitea Actions Demo +run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 +on: [push] + +jobs: + Explore-Gitea-Actions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + - name: Run the Maven verify phase + run: mvn --batch-mode --update-snapshots verify \ No newline at end of file diff --git a/src/test/java/semantic/SemanticTester.java b/src/test/java/semantic/SemanticTest.java similarity index 99% rename from src/test/java/semantic/SemanticTester.java rename to src/test/java/semantic/SemanticTest.java index 2c27e1c..d35a93f 100644 --- a/src/test/java/semantic/SemanticTester.java +++ b/src/test/java/semantic/SemanticTest.java @@ -23,7 +23,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; -public class SemanticTester { +public class SemanticTest { @BeforeEach public void init() { From 403ab706559ff91c954e4fdf218f19ff027b0520 Mon Sep 17 00:00:00 2001 From: Bruder John Date: Thu, 30 May 2024 19:07:29 +0200 Subject: [PATCH 7/7] Adapted Binary Expression --- .idea/misc.xml | 2 +- src/main/java/Main.java | 38 +++++++++---------- src/main/java/ast/VarNode.java | 30 --------------- .../ast/expression/BinaryExpressionNode.java | 4 +- .../ast/expression/ExpresssionOperator.java | 14 +++++++ .../ast/expression/UnaryExpressionNode.java | 2 + .../statement/AssignmentStatementNode.java | 9 ++--- src/main/java/parser/ASTBuilder.java | 12 +++--- src/main/java/semantic/SemanticAnalyzer.java | 18 ++++----- src/main/java/semantic/SemanticVisitor.java | 3 -- src/main/resources/CompilerInput.java | 12 +++++- src/test/java/semantic/SemanticTest.java | 15 ++++++-- 12 files changed, 76 insertions(+), 83 deletions(-) delete mode 100644 src/main/java/ast/VarNode.java create mode 100644 src/main/java/ast/expression/ExpresssionOperator.java diff --git a/.idea/misc.xml b/.idea/misc.xml index f26d89f..bb14756 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java index d5aa802..94d29cf 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -38,37 +38,37 @@ 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 ------------------------- diff --git a/src/main/java/ast/VarNode.java b/src/main/java/ast/VarNode.java deleted file mode 100644 index 519f552..0000000 --- a/src/main/java/ast/VarNode.java +++ /dev/null @@ -1,30 +0,0 @@ -package ast; - -import ast.type.TypeNode; -import semantic.SemanticVisitor; -import typechecker.TypeCheckResult; -import visitor.Visitable; - -public class VarNode implements ASTNode, Visitable { - - private String identifier; - private TypeNode type; - - public VarNode(TypeNode type, String identifier){ - this.type = type; - this.identifier = identifier; - } - - public TypeNode getType(){ - return type; - } - - public String getIdentifier(){ - return identifier; - } - - @Override - public TypeCheckResult accept(SemanticVisitor visitor) { - return visitor.analyze(this); - } -} diff --git a/src/main/java/ast/expression/BinaryExpressionNode.java b/src/main/java/ast/expression/BinaryExpressionNode.java index c912408..e4a0e41 100644 --- a/src/main/java/ast/expression/BinaryExpressionNode.java +++ b/src/main/java/ast/expression/BinaryExpressionNode.java @@ -7,9 +7,9 @@ import visitor.Visitable; public class BinaryExpressionNode implements ExpressionNode, Visitable { public ExpressionNode left; public ExpressionNode right; - public String operator; // Stores the operator as a string (e.g., "+", "-", "&&") + public ExpresssionOperator operator; // Stores the operator as a string (e.g., "+", "-", "&&") - public BinaryExpressionNode(ExpressionNode left, ExpressionNode right, String operator) { + public BinaryExpressionNode(ExpressionNode left, ExpressionNode right, ExpresssionOperator operator) { this.left = left; this.right = right; this.operator = operator; diff --git a/src/main/java/ast/expression/ExpresssionOperator.java b/src/main/java/ast/expression/ExpresssionOperator.java new file mode 100644 index 0000000..b1f62a3 --- /dev/null +++ b/src/main/java/ast/expression/ExpresssionOperator.java @@ -0,0 +1,14 @@ +package ast.expression; + +public enum ExpresssionOperator { + DOT, // . + PLUS, // + + MINUS, // - + MULTIPLY, // * + DIVIDE, // / + NOT, // ! + ASSIGNMENT, // = + EQUALS, // == + UNEQUALS, // != + ERROR //TODO: Remove This +} diff --git a/src/main/java/ast/expression/UnaryExpressionNode.java b/src/main/java/ast/expression/UnaryExpressionNode.java index 24d1832..be1a660 100644 --- a/src/main/java/ast/expression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/UnaryExpressionNode.java @@ -18,3 +18,5 @@ public class UnaryExpressionNode implements ExpressionNode, Visitable { return visitor.analyze(this); } } + + diff --git a/src/main/java/ast/statement/AssignmentStatementNode.java b/src/main/java/ast/statement/AssignmentStatementNode.java index 9f6a395..f9fd38e 100644 --- a/src/main/java/ast/statement/AssignmentStatementNode.java +++ b/src/main/java/ast/statement/AssignmentStatementNode.java @@ -1,17 +1,14 @@ package ast.statement; -import ast.VarNode; -import ast.expression.ExpressionNode; +import ast.expression.BinaryExpressionNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; public class AssignmentStatementNode extends StatementNode implements Visitable { - public VarNode varNode; - public ExpressionNode expression; + public BinaryExpressionNode expression; - public AssignmentStatementNode(VarNode varNode, ExpressionNode expression) { - this.varNode = varNode; + public AssignmentStatementNode(BinaryExpressionNode expression) { this.expression = expression; } diff --git a/src/main/java/parser/ASTBuilder.java b/src/main/java/parser/ASTBuilder.java index e32be97..0f3b09c 100644 --- a/src/main/java/parser/ASTBuilder.java +++ b/src/main/java/parser/ASTBuilder.java @@ -3,6 +3,7 @@ package parser; import ast.*; import ast.expression.BinaryExpressionNode; import ast.expression.ExpressionNode; +import ast.expression.ExpresssionOperator; import ast.expression.IdentifierExpressionNode; import ast.expression.UnaryExpressionNode; import ast.member.FieldNode; @@ -137,14 +138,14 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { @Override public ASTNode visitAssignmentStatement(SimpleJavaParser.AssignmentStatementContext ctx) { - VarNode varNode = (VarNode) visit(ctx.var()); - ExpressionNode expression = (ExpressionNode) visit(ctx.expression()); - return new AssignmentStatementNode(varNode, expression); + + BinaryExpressionNode expression = (BinaryExpressionNode) visit(ctx.expression()); + return new AssignmentStatementNode(expression); } @Override public ASTNode visitVar(SimpleJavaParser.VarContext ctx) { - return new VarNode(new BaseTypeNode(EnumTypeNode.INT), ctx.getText()); + return null; } @Override @@ -180,8 +181,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { if (ctx.getChildCount() == 3 && ctx.getChild(1) instanceof TerminalNode) { ExpressionNode left = (ExpressionNode) visit(ctx.expression(0)); ExpressionNode right = (ExpressionNode) visit(ctx.expression(1)); - String operator = ctx.getChild(1).getText(); - return new BinaryExpressionNode(left, right, operator); + return new BinaryExpressionNode(left, right, ExpresssionOperator.ERROR); } // Handle unary operations else if (ctx.getChildCount() == 2) { diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java index 362af42..9ccfe98 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -145,21 +145,17 @@ public class SemanticAnalyzer implements SemanticVisitor { @Override public TypeCheckResult analyze(AssignmentStatementNode assignmentStatementNode) { - if (assignmentStatementNode.expression instanceof LiteralNode literalNode) { - TypeCheckResult varResult = assignmentStatementNode.varNode.accept(this); - TypeCheckResult expressionResult = assignmentStatementNode.expression.accept(this); - } - return new TypeCheckResult(true, null); - } - - @Override - public TypeCheckResult analyze(VarNode toCheck) { - return new TypeCheckResult(true, null); + boolean valid = true; + BinaryExpressionNode binaryExpressionNode = assignmentStatementNode.expression; + var result = binaryExpressionNode.accept(this); + valid = valid && result.isValid(); + return new TypeCheckResult(valid, null); } @Override public TypeCheckResult analyze(BinaryExpressionNode toCheck) { - return null; + boolean valid = true; + return new TypeCheckResult(valid, null); } @Override diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index 99d0cb8..66db83e 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -3,7 +3,6 @@ package semantic; import ast.ClassNode; import ast.ProgramNode; -import ast.VarNode; import ast.expression.BinaryExpressionNode; import ast.expression.IdentifierExpressionNode; import ast.expression.UnaryExpressionNode; @@ -24,8 +23,6 @@ public interface SemanticVisitor { TypeCheckResult analyze(AssignmentStatementNode toCheck); - TypeCheckResult analyze(VarNode toCheck); - TypeCheckResult analyze(BinaryExpressionNode toCheck); TypeCheckResult analyze(IdentifierExpressionNode toCheck); diff --git a/src/main/resources/CompilerInput.java b/src/main/resources/CompilerInput.java index 2efd50e..1cbe5ca 100644 --- a/src/main/resources/CompilerInput.java +++ b/src/main/resources/CompilerInput.java @@ -2,9 +2,17 @@ public class Example { public int a; - public static int testMethod(char x, int a){ - + public static int testMethod(char x){ } +} + +public class Test { + + public static int testMethod(char x, int a){ + + + + } } \ No newline at end of file diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java index d35a93f..83287ca 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -2,7 +2,10 @@ 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; @@ -76,10 +79,16 @@ public class SemanticTest { List statementNodeList = new ArrayList(); - VarNode varNode = new VarNode(new BaseTypeNode(EnumTypeNode.INT), "localVar1"); - ExpressionNode expressionNode = new LiteralNode(1); + ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this"); + ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar"); - StatementNode statementNode1 = new AssignmentStatementNode(varNode, expressionNode); + 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 );