diff --git a/.gitignore b/.gitignore index c134c76..8c5079b 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,10 @@ 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 +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/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 d81162c..99e9904 100644 --- a/pom.xml +++ b/pom.xml @@ -4,13 +4,14 @@ 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 - 21 - 21 + 22 + ${java.version} + ${java.version} UTF-8 @@ -53,7 +54,28 @@ maven-surefire-plugin 3.0.0-M5 + + maven-assembly-plugin + + + make-assembly + package + + single + + + + + + + main.Main + + + + jar-with-dependencies + + + - \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java deleted file mode 100644 index 779e5d1..0000000 --- a/src/main/java/Main.java +++ /dev/null @@ -1,132 +0,0 @@ -import oldAst.ASTNode; -import org.antlr.v4.runtime.*; -import oldAst.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.ASTBuilder; -import parser.generated.SimpleJavaLexer; -import parser.generated.SimpleJavaParser; -import semantic.SemanticAnalyzer; - -import java.io.IOException; -import java.nio.file.Paths; - -public class Main { - public static void main(String[] args) throws Exception { - if(args.length > 0) { - - } else { - try { - CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/CompilerInput.java")); - 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); - 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(); - - /* ------------------------- 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(); - - /* ------------------------- 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 -> Tast ------------------------- - */ - SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer(); - ProgramNode typedAst = (ProgramNode) semanticAnalyzer.generateTast(abstractSyntaxTree); - - // Printing the Tast - System.out.println("Tast generated"); - - /* - * ------------------------- 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 - * 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/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java index a21044a..75f92b1 100644 --- a/src/main/java/ast/ClassNode.java +++ b/src/main/java/ast/ClassNode.java @@ -1,8 +1,6 @@ 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; @@ -56,8 +54,4 @@ public class ClassNode implements ASTNode, Visitable { return visitor.analyze(this); } - @Override - public void accept(ClassVisitor classVisitor) { - classVisitor.visit(this); - } } 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/ProgramNode.java b/src/main/java/ast/ProgramNode.java index f8ad19a..7fbe3e0 100644 --- a/src/main/java/ast/ProgramNode.java +++ b/src/main/java/ast/ProgramNode.java @@ -1,6 +1,5 @@ package ast; -import bytecode.visitor.ProgramVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; @@ -19,9 +18,4 @@ public class ProgramNode implements ASTNode, Visitable { 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..ab2d70b 100644 --- a/src/main/java/ast/block/BlockNode.java +++ b/src/main/java/ast/block/BlockNode.java @@ -1,17 +1,29 @@ package ast.block; import ast.ASTNode; -import ast.statement.StatementNode; +import ast.statement.IStatementNode; +import ast.statement.ReturnStatementNode; +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 List statements = new ArrayList<>(); +public class BlockNode implements ASTNode, Visitable { + public List statements = new ArrayList<>(); + public Boolean hasReturnStatement = false; public BlockNode() {} - public void addStatement(StatementNode statement) { + public void addStatement(IStatementNode 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 deleted file mode 100644 index db3e742..0000000 --- a/src/main/java/ast/expression/ExpressionNode.java +++ /dev/null @@ -1,6 +0,0 @@ -package ast.expression; - -import visitor.Visitable; - -public abstract class ExpressionNode implements Visitable { -} diff --git a/src/main/java/ast/expression/IExpressionNode.java b/src/main/java/ast/expression/IExpressionNode.java new file mode 100644 index 0000000..28b45e3 --- /dev/null +++ b/src/main/java/ast/expression/IExpressionNode.java @@ -0,0 +1,11 @@ +package ast.expression; + +import ast.ASTNode; +import ast.type.type.ITypeNode; +import visitor.Visitable; + +public interface IExpressionNode extends ASTNode, Visitable { + + ITypeNode getType(); + +} 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..655a3f5 --- /dev/null +++ b/src/main/java/ast/expression/binaryexpression/BinaryExpressionNode.java @@ -0,0 +1,19 @@ +package ast.expression.binaryexpression; + +import ast.expression.IExpressionNode; +import ast.type.type.*; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; + +public class BinaryExpressionNode implements IExpressionNode { + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + 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 ec3ab61..b594502 100644 --- a/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/CalculationExpressionNode.java @@ -1,19 +1,40 @@ package ast.expression.binaryexpression; -import ast.ASTNode; +import ast.type.type.*; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class CalculationExpressionNode implements ASTNode { - CalculationExpressionNode calculationExpression; - String operator; - DotExpressionNode dotExpression; +public class CalculationExpressionNode extends BinaryExpressionNode { + public CalculationExpressionNode calculationExpression; + 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; } public CalculationExpressionNode(DotExpressionNode dotExpression) { 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); + } + + @Override + 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 1418fe5..2d56221 100644 --- a/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotExpressionNode.java @@ -1,19 +1,42 @@ package ast.expression.binaryexpression; -import ast.ASTNode; +import ast.type.type.*; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class DotExpressionNode implements ASTNode { - DotExpressionNode dotExpression; - String operator; - DotSubstractionExpressionNode dotSubstractionExpression; +public class DotExpressionNode extends BinaryExpressionNode { + public DotExpressionNode dotExpression; + 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; } public DotExpressionNode(DotSubstractionExpressionNode dotSubstractionExpression) { 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); + } + + @Override + 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 e32863c..1b43a9f 100644 --- a/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/DotSubstractionExpressionNode.java @@ -1,16 +1,18 @@ package ast.expression.binaryexpression; -import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; +import ast.type.type.*; import ast.type.ValueNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class DotSubstractionExpressionNode implements ASTNode { - ValueNode value; - String identifier; - MemberAccessNode memberAccess; - MethodCallStatementExpressionNode methodCall; - CalculationExpressionNode calculationExpression; +public class DotSubstractionExpressionNode extends BinaryExpressionNode { + public ValueNode value; + public String identifier; + public MemberAccessNode memberAccess; + public MethodCallStatementExpressionNode methodCall; + public CalculationExpressionNode calculationExpression; public DotSubstractionExpressionNode(ValueNode value) { this.value = value; @@ -28,4 +30,15 @@ public class DotSubstractionExpressionNode implements ASTNode { this.methodCall = methodCall; this.calculationExpression = calculationExpression; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public ITypeNode getType() { + return null; + } + } 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 1c1c674..f89fdf8 100644 --- a/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java +++ b/src/main/java/ast/expression/binaryexpression/NonCalculationExpressionNode.java @@ -1,17 +1,50 @@ package ast.expression.binaryexpression; -import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode; +import ast.type.type.*; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class NonCalculationExpressionNode implements ASTNode { - UnaryExpressionNode unaryExpression; - String operator; - ExpressionNode expression; +public class NonCalculationExpressionNode extends BinaryExpressionNode { + public UnaryExpressionNode unaryExpression; + public EnumNonCalculationOperator operator; + 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; + 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); + } + + @Override + public ITypeNode 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 e04a2fd..f225f39 100644 --- a/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/NotExpressionNode.java @@ -1,12 +1,13 @@ package ast.expression.unaryexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; public class NotExpressionNode implements ASTNode { - 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 fdb694a..4393e84 100644 --- a/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java +++ b/src/main/java/ast/expression/unaryexpression/UnaryExpressionNode.java @@ -1,20 +1,23 @@ 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.type.*; import ast.type.ValueNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import java.util.Objects; -public class UnaryExpressionNode implements ASTNode { - String thisExp; - String identifier; - MemberAccessNode memberAccess; - ValueNode value; - NotExpressionNode notExpression; - StatementNode statement; - ExpressionNode expression; +public class UnaryExpressionNode implements IExpressionNode { + public String thisExp; + public String identifier; + public MemberAccessNode memberAccess; + public ValueNode value; + public NotExpressionNode notExpression; + public IStatementNode statement; + public IExpressionNode expression; + private ITypeNode type; public UnaryExpressionNode(String value) { if(Objects.equals(value, "this")) { @@ -36,11 +39,26 @@ 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; } + + @Override + public TypeCheckResult accept(SemanticVisitor visitor) { + return visitor.analyze(this); + } + + @Override + public ITypeNode getType() { + return 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 ad46335..3956086 100644 --- a/src/main/java/ast/member/ConstructorNode.java +++ b/src/main/java/ast/member/ConstructorNode.java @@ -3,7 +3,8 @@ package ast.member; import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; -import bytecode.visitor.MethodVisitor; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import visitor.Visitable; import java.util.ArrayList; @@ -20,8 +21,8 @@ public class ConstructorNode extends MethodNode implements Visitable { 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; } diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java index 2518d58..f269c40 100644 --- a/src/main/java/ast/member/FieldNode.java +++ b/src/main/java/ast/member/FieldNode.java @@ -1,18 +1,17 @@ package ast.member; import ast.type.AccessModifierNode; -import ast.type.TypeNode; -import bytecode.visitor.ClassVisitor; +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; @@ -23,8 +22,4 @@ public class FieldNode implements MemberNode, Visitable { return visitor.analyze(this); } - @Override - public void accept(ClassVisitor classVisitor) { - classVisitor.visit(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 b660907..ec414c3 100644 --- a/src/main/java/ast/member/MethodNode.java +++ b/src/main/java/ast/member/MethodNode.java @@ -3,31 +3,28 @@ package ast.member; import ast.block.BlockNode; import ast.parameter.ParameterNode; import ast.type.AccessModifierNode; -import ast.type.TypeNode; +import ast.type.type.*; import bytecode.visitor.MethodVisitor; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; import visitor.Visitable; import java.util.List; +import java.util.Objects; public class MethodNode implements MemberNode, Visitable { public AccessModifierNode accesModifier; - public TypeNode type; + private ITypeNode type; public Boolean voidType; - public String identifier; - public List parameters; + private String identifier; + public List parameters = new ArrayList<>(); public BlockNode block; public MethodNode() { } - public MethodNode(BlockNode block) { - this.block = block; - } - - public MethodNode(AccessModifierNode accessModifier, TypeNode type, Boolean voidType, String identifier, BlockNode block) { - this.accesModifier = accessModifier; + public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){ + this.accesModifier = new AccessModifierNode(accessModifier); this.type = type; this.voidType = voidType; this.identifier = identifier; @@ -38,23 +35,24 @@ public class MethodNode implements MemberNode, Visitable { this.parameters.add(parameter); } - /* + public List getParameters() { + return parameters; + } + 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; - } - } - } + if (!(Objects.equals(this.identifier, methodNode.getIdentifier())) || type.equals(methodNode.type) + || 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 isSame; + return true; } -*/ + @Override public TypeCheckResult accept(SemanticVisitor visitor) { return visitor.analyze(this); @@ -65,5 +63,20 @@ public class MethodNode implements MemberNode, Visitable { methodVisitor.visit(this); } + public String getIdentifier() { + 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 1969e85..caa3976 100644 --- a/src/main/java/ast/parameter/ParameterNode.java +++ b/src/main/java/ast/parameter/ParameterNode.java @@ -1,14 +1,23 @@ package ast.parameter; import ast.ASTNode; -import ast.type.TypeNode; +import ast.type.type.*; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; +import visitor.Visitable; public class ParameterNode implements ASTNode { public TypeNode type; public String identifier; - public ParameterNode(TypeNode type, String identifier) { + public ParameterNode(ITypeNode 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/ForStatementNode.java b/src/main/java/ast/statement/ForStatementNode.java index 5a4b442..3d4ad16 100644 --- a/src/main/java/ast/statement/ForStatementNode.java +++ b/src/main/java/ast/statement/ForStatementNode.java @@ -1,23 +1,31 @@ package ast.statement; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class ForStatementNode implements ASTNode { - ExpressionNode statementExpressionInit; - StatementNode localVariableDeclarationInit; - ExpressionNode expression; - 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; } + + @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 new file mode 100644 index 0000000..c726bb3 --- /dev/null +++ b/src/main/java/ast/statement/IStatementNode.java @@ -0,0 +1,7 @@ +package ast.statement; + +import ast.ASTNode; +import visitor.Visitable; + +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 7c0ddaf..3ab54e0 100644 --- a/src/main/java/ast/statement/LocalVariableDeclarationNode.java +++ b/src/main/java/ast/statement/LocalVariableDeclarationNode.java @@ -1,19 +1,26 @@ package ast.statement; -import ast.ASTNode; -import ast.expression.ExpressionNode; -import ast.type.TypeNode; +import ast.expression.IExpressionNode; +import ast.type.type.*; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class LocalVariableDeclarationNode implements ASTNode { - public TypeNode type; +public class LocalVariableDeclarationNode implements IStatementNode { + public ITypeNode 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(ITypeNode type, String identifier, String assign, IExpressionNode expression) { this.type = type; this.identifier = identifier; 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 16fa05f..e525c3f 100644 --- a/src/main/java/ast/statement/ReturnStatementNode.java +++ b/src/main/java/ast/statement/ReturnStatementNode.java @@ -1,30 +1,24 @@ package ast.statement; -import ast.ASTNode; -import ast.expression.ExpressionNode; -import ast.type.TypeNode; -import bytecode.visitor.MethodVisitor; +import ast.expression.IExpressionNode; import semantic.SemanticVisitor; import typechecker.TypeCheckResult; -import visitor.Visitable; -import java.util.ArrayList; -import java.util.List; +public class ReturnStatementNode implements IStatementNode { + public IExpressionNode expression; + public Boolean voidReturn = false; -public class ReturnStatementNode implements ASTNode, Visitable { - public ExpressionNode expression; - - public ReturnStatementNode(ExpressionNode expression) { - this.expression = expression; - } - - @Override - public void accept(MethodVisitor methodVisitor) { - methodVisitor.visit(this); + public ReturnStatementNode(IExpressionNode expression) { + if(expression != null) { + this.expression = expression; + } else { + voidReturn = true; + } } @Override public TypeCheckResult accept(SemanticVisitor visitor) { - return null; + return visitor.analyze(this); } + } diff --git a/src/main/java/ast/statement/StatementNode.java b/src/main/java/ast/statement/StatementNode.java deleted file mode 100644 index 118ff01..0000000 --- a/src/main/java/ast/statement/StatementNode.java +++ /dev/null @@ -1,6 +0,0 @@ -package ast.statement; - -import visitor.Visitable; - -public abstract class StatementNode implements Visitable { -} diff --git a/src/main/java/ast/statement/WhileStatementNode.java b/src/main/java/ast/statement/WhileStatementNode.java index 72d017d..3aabb73 100644 --- a/src/main/java/ast/statement/WhileStatementNode.java +++ b/src/main/java/ast/statement/WhileStatementNode.java @@ -2,14 +2,22 @@ package ast.statement; import ast.ASTNode; import ast.block.BlockNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class WhileStatementNode implements ASTNode { - ExpressionNode expression; - BlockNode block; +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; } + + @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 cedfefc..709fe2f 100644 --- a/src/main/java/ast/statement/ifstatement/ElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/ElseStatementNode.java @@ -2,11 +2,20 @@ 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 ASTNode { - BlockNode block; +public class ElseStatementNode implements IStatementNode { + public BlockNode block; 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 dcdc6ca..6967f75 100644 --- a/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfElseStatementNode.java @@ -1,13 +1,16 @@ 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; -public class IfElseStatementNode implements ASTNode { - IfStatementNode ifStatement; - List elseStatements = new ArrayList<>(); +public class IfElseStatementNode implements IStatementNode { + public IfStatementNode ifStatement; + public List elseStatements = new ArrayList<>(); public IfElseStatementNode(IfStatementNode ifStatement) { this.ifStatement = ifStatement; @@ -17,4 +20,9 @@ public class IfElseStatementNode implements ASTNode { 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 4731758..7bcbabf 100644 --- a/src/main/java/ast/statement/ifstatement/IfStatementNode.java +++ b/src/main/java/ast/statement/ifstatement/IfStatementNode.java @@ -2,14 +2,23 @@ package ast.statement.ifstatement; import ast.ASTNode; import ast.block.BlockNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import ast.statement.IStatementNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class IfStatementNode implements ASTNode { - ExpressionNode expression; - BlockNode block; +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; } + + @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 8dbad08..df8fe79 100644 --- a/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignStatementExpressionNode.java @@ -1,14 +1,21 @@ package ast.statement.statementexpression; -import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -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; } + + @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 e9d0d30..0fb9fa9 100644 --- a/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/AssignableExpressionNode.java @@ -1,10 +1,12 @@ package ast.statement.statementexpression; -import ast.ASTNode; import ast.expression.unaryexpression.MemberAccessNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; -public class AssignableExpressionNode implements ASTNode { +public class AssignableExpressionNode implements IStatementExpressionNode { public String identifier; + public MemberAccessNode memberAccess; public AssignableExpressionNode(String identifier) { @@ -14,4 +16,10 @@ public class AssignableExpressionNode implements ASTNode { 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/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/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..20541bb 100644 --- a/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/NewDeclarationStatementExpressionNode.java @@ -1,20 +1,28 @@ package ast.statement.statementexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; import java.util.ArrayList; import java.util.List; -public class NewDeclarationStatementExpressionNode implements ASTNode { - String identifier; - List expressions = new ArrayList<>(); +public class NewDeclarationStatementExpressionNode implements IStatementExpressionNode { + public String identifier; + 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); } + + @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 5b4a9d9..372b4ea 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/DecrementExpressionNode.java @@ -2,12 +2,21 @@ 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 ASTNode { - CrementType crementType; - AssignableExpressionNode assignableExpression; +public class DecrementExpressionNode implements IStatementExpressionNode { + public CrementType crementType; + public AssignableExpressionNode assignableExpression; 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 a16233f..a87934d 100644 --- a/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/crementExpression/IncrementExpressionNode.java @@ -2,12 +2,21 @@ 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 ASTNode { - CrementType crementType; - AssignableExpressionNode assignableExpression; +public class IncrementExpressionNode implements IStatementExpressionNode { + public CrementType crementType; + public AssignableExpressionNode assignableExpression; 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/ChainedMethodNode.java b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/ChainedMethodNode.java index 759f197..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 { - String identifier; - List expressions = new ArrayList<>(); + public String identifier; + 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 5fcaba1..6a2f69b 100644 --- a/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java +++ b/src/main/java/ast/statement/statementexpression/methodcallstatementnexpression/MethodCallStatementExpressionNode.java @@ -1,16 +1,19 @@ package ast.statement.statementexpression.methodcallstatementnexpression; import ast.ASTNode; -import ast.expression.ExpressionNode; +import ast.expression.IExpressionNode; +import ast.statement.statementexpression.IStatementExpressionNode; +import semantic.SemanticVisitor; +import typechecker.TypeCheckResult; 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 class MethodCallStatementExpressionNode implements IStatementExpressionNode { + 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; @@ -21,9 +24,13 @@ public class MethodCallStatementExpressionNode implements ASTNode { chainedMethods.add(chainedMethode); } - public void addExpression(ExpressionNode expression) { + 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/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/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/ast/type/TypeNode.java b/src/main/java/ast/type/TypeNode.java deleted file mode 100644 index 8a831cc..0000000 --- a/src/main/java/ast/type/TypeNode.java +++ /dev/null @@ -1,25 +0,0 @@ -package ast.type; - -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; - } - } -} 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; 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..fdfb293 --- /dev/null +++ b/src/main/java/ast/type/type/BaseType.java @@ -0,0 +1,30 @@ +package ast.type.type; + +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 new file mode 100644 index 0000000..2292046 --- /dev/null +++ b/src/main/java/ast/type/type/ReferenceType.java @@ -0,0 +1,33 @@ +package ast.type.type; + +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/bytecode/ClassCodeGen.java b/src/main/java/bytecode/ClassCodeGen.java index 79011b8..7f544d9 100644 --- a/src/main/java/bytecode/ClassCodeGen.java +++ b/src/main/java/bytecode/ClassCodeGen.java @@ -9,7 +9,6 @@ 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; @@ -30,8 +29,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) { @@ -62,7 +61,7 @@ public class ClassCodeGen implements ClassVisitor { 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/Mapper.java b/src/main/java/bytecode/Mapper.java index aff0c5e..49ad62b 100644 --- a/src/main/java/bytecode/Mapper.java +++ b/src/main/java/bytecode/Mapper.java @@ -1,6 +1,5 @@ package bytecode; -import ast.parameter.ParameterNode; import ast.type.*; import org.objectweb.asm.Opcodes; @@ -31,19 +30,19 @@ public class Mapper { 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/visitor/ClassVisitor.java b/src/main/java/bytecode/visitor/ClassVisitor.java index 903775a..078f211 100644 --- a/src/main/java/bytecode/visitor/ClassVisitor.java +++ b/src/main/java/bytecode/visitor/ClassVisitor.java @@ -4,6 +4,7 @@ import ast.ClassNode; import ast.member.FieldNode; public interface ClassVisitor { - void visit(ClassNode classNode); - void visit(FieldNode fieldNode); + void visit(ClassNode classNode); + + void visit(FieldNode fieldNode); } diff --git a/src/main/java/classFileOutput/Example.class b/src/main/java/classFileOutput/Example.class deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/classFileOutput/Test.class b/src/main/java/classFileOutput/Test.class deleted file mode 100644 index 98f2799..0000000 Binary files a/src/main/java/classFileOutput/Test.class and /dev/null differ diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java new file mode 100644 index 0000000..69de2bc --- /dev/null +++ b/src/main/java/main/Main.java @@ -0,0 +1,108 @@ +package main; + +import ast.ASTNode; +import ast.ProgramNode; +import parser.astBuilder.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 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 == 2) { + // 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 (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")); + 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/RaupenLogger.java b/src/main/java/main/RaupenLogger.java new file mode 100644 index 0000000..4ea499f --- /dev/null +++ b/src/main/java/main/RaupenLogger.java @@ -0,0 +1,180 @@ +package main; + +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 RaupenLogger { + + static Logger logger = Logger.getLogger("RaupenLogs"); + + public RaupenLogger() { + // ------------------------- 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 abstractSyntaxTree) { + // Printing the AST + logger.info("-------------------- AST builder -> AST --------------------"); + // logger.info("AST: " + ast.toString()); + logAST(abstractSyntaxTree, 0); + logger.info("\n"); + } + + public static void logSemanticAnalyzer(ASTNode typedAst) { + // Printing the typed AST + logger.info("-------------------- Semantic Analyzer -> typed AST --------------------"); + logAST(typedAst, 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 abstractSyntaxTree, int indent) { + if (abstractSyntaxTree == null) { + logger.severe("AST is null !!!"); + return; + } + String indentString = " ".repeat(indent * 2); + logger.info(indentString + abstractSyntaxTree.getClass()); + + // for (ASTNode child : node.) { + // printAST(child, indent + 1); + // } + } +} diff --git a/src/main/java/parser/astBuilder/ASTBuilder.java b/src/main/java/parser/astBuilder/ASTBuilder.java index 7760b5c..95ac93c 100644 --- a/src/main/java/parser/astBuilder/ASTBuilder.java +++ b/src/main/java/parser/astBuilder/ASTBuilder.java @@ -10,11 +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.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; @@ -28,6 +26,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.*; import org.antlr.v4.runtime.tree.TerminalNode; import parser.generated.*; @@ -53,7 +52,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)); } @@ -63,16 +62,16 @@ 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((AccessModifierNode) visit(ctx.AccessModifier()), (TypeNode) visit(ctx.type()), 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)); } 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)); } @@ -81,9 +80,14 @@ public class ASTBuilder extends SimpleJavaBaseVisitor { } } + @Override + public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { + 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 @@ -108,34 +112,37 @@ 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(createTypeNode(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)); + } + if(!blockNode.hasReturnStatement) { + blockNode.addStatement(new ReturnStatementNode(null)); } 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 +158,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 +182,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 +201,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 +224,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 +302,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 +339,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 +389,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 @@ -394,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 60e9d2b..39dd2f8 100644 --- a/src/main/java/semantic/Scope.java +++ b/src/main/java/semantic/Scope.java @@ -1,27 +1,35 @@ package semantic; -import oldAst.type.TypeNode; +import ast.type.type.*; +import semantic.exeptions.AlreadyDeclearedException; import java.util.HashMap; 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 RuntimeException("Variable " + name + " already exists in this scope"); + 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; } @@ -30,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 3bce422..c409c0d 100644 --- a/src/main/java/semantic/SemanticAnalyzer.java +++ b/src/main/java/semantic/SemanticAnalyzer.java @@ -1,40 +1,44 @@ 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.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.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.*; import semantic.context.Context; -import semantic.exeptions.AlreadyDeclearedException; -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 Context context; + private static Context context; private static Scope currentScope; private static ClassNode currentClass; + private static ITypeNode currentNullType; + private ITypeNode currentMethodReturnType; public static ASTNode generateTast(ASTNode node) { SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); @@ -50,7 +54,7 @@ public class SemanticAnalyzer implements SemanticVisitor { return null; } - public static void clearAnalyzier(){ + public static void clearAnalyzer() { currentFields.clear(); errors.clear(); currentScope = null; @@ -87,13 +91,10 @@ 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; - 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(); @@ -106,38 +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 { - currentScope.pushScope(); + var valid = true; - //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); + 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; } } - } - //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); + 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)); + } + } - } + // Check if this method is already declared - currentScope.popScope(); - return new TypeCheckResult(valid, null); + currentMethodReturnType = methodNode.getType(); + currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ + + ITypeNode resultType = new BaseType(TypeEnum.VOID); + + // 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(TypeEnum.VOID); + } + 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); + + } } @Override @@ -152,87 +174,20 @@ public class SemanticAnalyzer implements SemanticVisitor { } @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); - } + public TypeCheckResult analyze(IfStatementNode toCheck) { return new TypeCheckResult(true, null); } - @Override - public TypeCheckResult analyze(IfStatementNode toCheck) { - return null; - } - @Override public TypeCheckResult analyze(ReturnStatementNode toCheck) { - return null; + + if(toCheck.expression != null){ + var result = toCheck.expression.accept(this); + return new TypeCheckResult(true, result.getType()); + } else { + return new TypeCheckResult(false, null); + } + } @Override @@ -241,39 +196,175 @@ public class SemanticAnalyzer implements SemanticVisitor { } @Override - public TypeCheckResult analyze(LiteralNode toCheck) { - return new TypeCheckResult(true, toCheck.getType()); + public TypeCheckResult analyze(ParameterNode toCheck) { + + + return new TypeCheckResult(true, null); } @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()); + public TypeCheckResult analyze(BlockNode blockNode) { + ITypeNode blockReturnType = null; + for (IStatementNode statementNode : blockNode.statements) { + 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, blockReturnType); + } + + @Override + public TypeCheckResult analyze(AssignableExpressionNode toCheck) { + return new TypeCheckResult(true, currentFields.get(toCheck.identifier)); } @Override - public TypeCheckResult analyze(This toCheck) { - return new TypeCheckResult(true, toCheck.getType()); + 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(currentScope.getLocalVar(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 new TypeCheckResult(true, 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)) { + 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, null); } } \ No newline at end of file diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java index 7139261..6b6942f 100644 --- a/src/main/java/semantic/SemanticVisitor.java +++ b/src/main/java/semantic/SemanticVisitor.java @@ -1,18 +1,20 @@ 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.*; +import ast.block.BlockNode; +import ast.expression.binaryexpression.*; import ast.expression.unaryexpression.UnaryExpressionNode; -import ast.member.FieldNode; -import ast.member.MethodNode; +import ast.member.*; +import ast.parameter.ParameterNode; import ast.statement.*; -import ast.expression.This; -import ast.statement.ifstatement.IfStatementNode; +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 { @@ -25,25 +27,46 @@ 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(ParameterNode toCheck); - TypeCheckResult analyze(InstVar toCheck); + 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); - 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..18e8cf7 100644 --- a/src/main/java/semantic/context/FieldContext.java +++ b/src/main/java/semantic/context/FieldContext.java @@ -1,20 +1,20 @@ package semantic.context; -import oldAst.member.FieldNode; -import oldAst.type.AccessTypeNode; -import oldAst.type.TypeNode; +import ast.member.FieldNode; +import ast.type.*; +import ast.type.type.*; public class FieldContext { - private AccessTypeNode accessModifier; - private TypeNode type; + private AccessModifierNode accessModifier; + 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/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/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 a06d359..f52818d 100644 --- a/src/main/java/typechecker/TypeCheckResult.java +++ b/src/main/java/typechecker/TypeCheckResult.java @@ -1,14 +1,14 @@ package typechecker; -import oldAst.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/main/resources/CompilerInput.java b/src/main/resources/CompilerInput.java deleted file mode 100644 index 0f8297b..0000000 --- a/src/main/resources/CompilerInput.java +++ /dev/null @@ -1,22 +0,0 @@ -public class Example { - - public int a; - - public static int testMethod(char x){ - - a = 12; - - a = x; - - } - -} - -public class Test { - - public static int testMethod(char x, int a){ - - - - } -} \ No newline at end of file diff --git a/src/main/resources/input/CompilerInput.java b/src/main/resources/input/CompilerInput.java new file mode 100644 index 0000000..d850a3e --- /dev/null +++ b/src/main/resources/input/CompilerInput.java @@ -0,0 +1,16 @@ +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; + } + } +} + diff --git a/src/main/test/java/EmptyClassExample.class b/src/main/test/java/EmptyClassExample.class deleted file mode 100644 index 7a73bad..0000000 Binary files a/src/main/test/java/EmptyClassExample.class and /dev/null differ diff --git a/src/main/test/java/Tester.java b/src/main/test/java/Tester.java deleted file mode 100644 index 777c50b..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/make.md b/src/main/test/java/make.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 0000000..e3e7d75 --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,29 @@ +# 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 clean" etc. + +all: compile-javac compile-raupenpiler + +compile-javac: + javac -d .\resources\output\javac .\resources\input\CompilerInput.java + +compile-raupenpiler: + cd ../.. ; mvn -DskipTests install + cd ../.. ; mvn exec:java -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' " + +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 + 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/main/test/TestSpecs.md b/src/test/TestSpecs.md similarity index 58% rename from src/main/test/TestSpecs.md rename to src/test/TestSpecs.md index 6fd5a41..0911765 100644 --- a/src/main/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,64 +17,76 @@ "}" ## Scanner Output + +CommonTokenStream + ### 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 - - [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 + +## Parser Input + +CommonTokenStream (Scanner Output) ## Parser Output (AST) + +(program (classDeclaration (accessType public) class Name { })) + +ParseTree + ### 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 { } +## E2E Tests: +- Testdatei mit Main ausführen/kompilieren +- Testdatei mit "javac -d output .\CompilerInput.java" kompilieren +- -> Dateien mit javap vergleichen -### Beispiel 2: Filled Class - \ No newline at end of file +wenn beides erfolgreich + +- Ergebnis vom eigenen Compiler mithilfe von main.TestCompilerOutput ausführen +- (Ergebnis von javac mithilfe von main.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 main.TestCompilerOutput.java \ No newline at end of file diff --git a/src/main/test/java/EmptyClassExample.java b/src/test/java/main/EmptyClassExample.java similarity index 65% rename from src/main/test/java/EmptyClassExample.java rename to src/test/java/main/EmptyClassExample.java index 9f54ec6..e7715be 100644 --- a/src/main/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/main/test/java/FailureTest.java b/src/test/java/main/FailureTest.java similarity index 68% rename from src/main/test/java/FailureTest.java rename to src/test/java/main/FailureTest.java index bc63d91..5a2e1c8 100644 --- a/src/main/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; @@ -15,17 +17,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" ); /** @@ -62,8 +64,8 @@ public class FailureTest { void typedASTTest() throws IOException { CharStream codeCharStream = null; try { - codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); - Main.parsefile(codeCharStream); + 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/main/test/java/MainTest.java b/src/test/java/main/MainTest.java similarity index 65% rename from src/main/test/java/MainTest.java rename to src/test/java/main/MainTest.java index d4899fd..363fa35 100644 --- a/src/main/test/java/MainTest.java +++ b/src/test/java/main/MainTest.java @@ -1,12 +1,8 @@ +package main; + 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 oldAst.ClassNode; -import oldAst.ProgramNode; -import bytecode.ByteCodeGenerator; import java.io.IOException; import java.nio.file.Paths; @@ -21,8 +17,8 @@ public class MainTest { void testEmptyClass() { CharStream codeCharStream = null; try { - codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java")); - Main.parsefile(codeCharStream); + codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.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/main/TestCompilerOutput.java b/src/test/java/main/TestCompilerOutput.java new file mode 100644 index 0000000..6a30e14 --- /dev/null +++ b/src/test/java/main/TestCompilerOutput.java @@ -0,0 +1,45 @@ +package main; + +/** + * This class is used to test the output of the compiler. + * + *

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

+ * + *

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

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

+ * + *

PROBLEM: Hier kommen Errors, was eigentlich heißt, dass der Compiler nicht funktioniert, der Test sollte eigentlich passen. + *
DENN: Wenn ich statt unserem CompilerInput.class die CompilerInput.class von javac verwende (aus src/test/resources/output/javac ), dann funktioniert es.

+ */ +public class TestCompilerOutput { + public 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/parser/ParserTest.java b/src/test/java/parser/ParserTest.java new file mode 100644 index 0000000..4c39828 --- /dev/null +++ b/src/test/java/parser/ParserTest.java @@ -0,0 +1,185 @@ +package parser; + +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; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; + +public class ParserTest { + @BeforeEach + public void init() { // noch nicht benötigt + String inputFilePath = "src/main/resources/input/CompilerInput.java"; + String outputDirectoryPath = "src/main/resources/output"; + } + + /** + * This test method is used to test the scanner functionality of the SimpleJavaLexer. + * It creates a CharStream from a string representing a simple Java class declaration, + * and uses the SimpleJavaLexer to tokenize this input. + * It then compares the actual tokens and their types produced by the lexer to the expected tokens and their types. + */ + @Test + public void scannerTest() { + // Create a CharStream from a string representing a simple Java class declaration + CharStream inputCharStream = CharStreams.fromString("public class Name {}"); + + // Use the SimpleJavaLexer to tokenize the input + SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + tokenStream.fill(); + + // Prepare the expected results + List actualTokens = tokenStream.getTokens(); + List expectedTokens = Arrays.asList("public", "class", "Name", "{", "}", ""); + List expectedTokenTypes = Arrays.asList(null, null, "IDENTIFIER", null, null, "EOF"); + + // Compare the actual tokens and their types to the expected tokens and their types + assertEquals(expectedTokens.size(), actualTokens.size()); + for (int i = 0; i < expectedTokens.size(); i++) { + assertEquals(expectedTokens.get(i), actualTokens.get(i).getText()); + assertEquals(expectedTokenTypes.get(i), SimpleJavaLexer.VOCABULARY.getSymbolicName(actualTokens.get(i).getType())); + } + } + + + @Test + public void parserTest() { + // 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; + } +} diff --git a/src/test/java/semantic/EndToTAST.java b/src/test/java/semantic/EndToTAST.java new file mode 100644 index 0000000..3189802 --- /dev/null +++ b/src/test/java/semantic/EndToTAST.java @@ -0,0 +1,282 @@ +package semantic; + +import ast.ASTNode; +import ast.ProgramNode; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import parser.astBuilder.ASTBuilder; +import parser.generated.SimpleJavaLexer; +import parser.generated.SimpleJavaParser; +import semantic.exeptions.AlreadyDeclearedException; +import semantic.exeptions.MultipleReturnTypes; +import semantic.exeptions.NotDeclearedException; +import semantic.exeptions.TypeMismatchException; + +import java.io.IOException; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.*; + +public class EndToTAST { + + @BeforeEach + public void setup(){ + SemanticAnalyzer.clearAnalyzer(); + } + + @Test + public void CorrectTest(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectTest.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); // parse the input + + /* ------------------------- AST builder -> AST ------------------------- */ + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + + assertEquals(SemanticAnalyzer.errors.size(), 0); + assertNotNull(tast); + + } + + @Test + public void notDecleared() { + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/NotDecleared.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); // parse the input + + /* ------------------------- AST builder -> AST ------------------------- */ + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(NotDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void typeMismatch(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchIntBool.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void parameterAlreadyDecleared(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/ParameterAlreadyDecleared.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void fieldAlreadyDecleared(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/FieldAlreadyDecleared.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void typeMismatchRefType(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/TypeMismatchRefType.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void correctRetType(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/CorrectRetType.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertTrue(SemanticAnalyzer.errors.isEmpty()); + + } + + @Test + public void retTypeMismatch(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/retTypeMismatch.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void multipleRetType(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/MultipleRetTypes.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + assertInstanceOf(MultipleReturnTypes.class, SemanticAnalyzer.errors.getFirst()); + + } + + @Test + public void wrongTypeInIfClause(){ + + CharStream codeCharStream = null; + try { + codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/WrongIfClause.java")); + } catch (IOException e) { + throw new RuntimeException(e); + } + SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + + SimpleJavaParser parser = new SimpleJavaParser(tokenStream); + ParseTree parseTree = parser.program(); + + ASTBuilder astBuilder = new ASTBuilder(); + ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree); + + ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree); + + assertFalse(SemanticAnalyzer.errors.isEmpty()); + + } + +} diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java index 8ab9434..1e404af 100644 --- a/src/test/java/semantic/Mocker.java +++ b/src/test/java/semantic/Mocker.java @@ -1,76 +1,103 @@ 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 java.util.ArrayList; -import java.util.List; +import ast.*; +import ast.block.BlockNode; +import ast.member.FieldNode; +import ast.member.MethodNode; +import ast.parameter.ParameterNode; +import ast.type.AccessModifierNode; +import ast.type.type.*; public class Mocker { - public static ProgramNode mockCorrectProgrammNode(){ + public static ASTNode mockTwoSameFields(){ + 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); + FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"); - MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "objectVar"); - classNode.members.add(memberNode2); + c.members.add(f1); - List parameterNodeList = new ArrayList(); - ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1"); - parameterNodeList.add(parameterNode1); - ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList); + FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"); - List statementNodeList = new ArrayList(); - - ExpressionNode expressionNodeLeft = new InstVar(new This("testClass"), "objectVar"); - - LiteralNode expressionNodeRight = new LiteralNode(); - expressionNodeRight.setType(new BaseTypeNode(EnumTypeNode.INT)); - - 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(f2); + 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"); + public static ASTNode mockSimpleMethod(){ + ProgramNode p = new ProgramNode(); - MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); - classNode.members.add(memberNode1); + ClassNode c = new ClassNode(); - MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); - classNode.members.add(memberNode2); + MethodNode methodNode = new MethodNode(); - classList.add(classNode); - programNode.classes = classList; + //Parameter + ParameterNode parameterNode = new ParameterNode(new BaseType(TypeEnum.INT), "a"); - return programNode; + 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.setType(new BaseType(TypeEnum.INT)); + + methodNode.setIdentifier("testMethod"); + + c.members.add(methodNode); + + MethodNode methodNode1 = new MethodNode(); + methodNode1.block = new BlockNode(); + methodNode1.setType(new BaseType(TypeEnum.INT)); + + methodNode1.setIdentifier("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.setIdentifier("testMethod"); + + c.members.add(methodNode); + + MethodNode methodNode1 = new MethodNode(); + methodNode1.block = new BlockNode(); + methodNode1.setIdentifier("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 cc413a2..04fda3d 100644 --- a/src/test/java/semantic/SemanticTest.java +++ b/src/test/java/semantic/SemanticTest.java @@ -1,162 +1,114 @@ package semantic; +import ast.*; +import ast.member.FieldNode; +import ast.member.MemberNode; +import ast.member.MethodNode; +import ast.parameter.ParameterNode; -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.util.ArrayList; +import java.util.List; -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; +import static org.junit.jupiter.api.Assertions.*; public class SemanticTest { - @BeforeEach - public void init() { - SemanticAnalyzer.clearAnalyzier(); - } - - @Test - public void alreadyDeclaredLocalFieldVar() { - - //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); - - } +// @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); +//} } diff --git a/src/main/test/resources/AllFeaturesClassExample.java b/src/test/resources/input/AllFeaturesClassExample.java similarity index 100% rename from src/main/test/resources/AllFeaturesClassExample.java rename to src/test/resources/input/AllFeaturesClassExample.java diff --git a/src/main/test/resources/CombinedExample.java b/src/test/resources/input/CombinedExample.java similarity index 100% rename from src/main/test/resources/CombinedExample.java rename to src/test/resources/input/CombinedExample.java diff --git a/src/test/resources/input/CompilerInput.java b/src/test/resources/input/CompilerInput.java new file mode 100644 index 0000000..d850a3e --- /dev/null +++ b/src/test/resources/input/CompilerInput.java @@ -0,0 +1,16 @@ +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; + } + } +} + diff --git a/src/main/test/resources/MoreFeaturesClassExample.java b/src/test/resources/input/MoreFeaturesClassExample.java similarity index 100% rename from src/main/test/resources/MoreFeaturesClassExample.java rename to src/test/resources/input/MoreFeaturesClassExample.java diff --git a/src/main/test/resources/failureTests/TestClass1.java b/src/test/resources/input/failureTests/TestClass1.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass1.java rename to src/test/resources/input/failureTests/TestClass1.java diff --git a/src/main/test/resources/failureTests/TestClass10.java b/src/test/resources/input/failureTests/TestClass10.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass10.java rename to src/test/resources/input/failureTests/TestClass10.java diff --git a/src/main/test/resources/failureTests/TestClass11.java b/src/test/resources/input/failureTests/TestClass11.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass11.java rename to src/test/resources/input/failureTests/TestClass11.java diff --git a/src/main/test/resources/failureTests/TestClass2.java b/src/test/resources/input/failureTests/TestClass2.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass2.java rename to src/test/resources/input/failureTests/TestClass2.java diff --git a/src/main/test/resources/failureTests/TestClass3.java b/src/test/resources/input/failureTests/TestClass3.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass3.java rename to src/test/resources/input/failureTests/TestClass3.java diff --git a/src/main/test/resources/failureTests/TestClass4.java b/src/test/resources/input/failureTests/TestClass4.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass4.java rename to src/test/resources/input/failureTests/TestClass4.java diff --git a/src/main/test/resources/failureTests/TestClass5.java b/src/test/resources/input/failureTests/TestClass5.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass5.java rename to src/test/resources/input/failureTests/TestClass5.java diff --git a/src/main/test/resources/failureTests/TestClass6.java b/src/test/resources/input/failureTests/TestClass6.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass6.java rename to src/test/resources/input/failureTests/TestClass6.java diff --git a/src/main/test/resources/failureTests/TestClass7.java b/src/test/resources/input/failureTests/TestClass7.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass7.java rename to src/test/resources/input/failureTests/TestClass7.java diff --git a/src/main/test/resources/failureTests/TestClass8.java b/src/test/resources/input/failureTests/TestClass8.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass8.java rename to src/test/resources/input/failureTests/TestClass8.java diff --git a/src/main/test/resources/failureTests/TestClass9.java b/src/test/resources/input/failureTests/TestClass9.java similarity index 100% rename from src/main/test/resources/failureTests/TestClass9.java rename to src/test/resources/input/failureTests/TestClass9.java diff --git a/src/main/test/resources/featureTests/BooleanOperations.java b/src/test/resources/input/featureTests/BooleanOperations.java similarity index 100% rename from src/main/test/resources/featureTests/BooleanOperations.java rename to src/test/resources/input/featureTests/BooleanOperations.java diff --git a/src/main/test/resources/featureTests/CharManipulation.java b/src/test/resources/input/featureTests/CharManipulation.java similarity index 100% rename from src/main/test/resources/featureTests/CharManipulation.java rename to src/test/resources/input/featureTests/CharManipulation.java diff --git a/src/main/test/resources/featureTests/ConditionalStatements.java b/src/test/resources/input/featureTests/ConditionalStatements.java similarity index 100% rename from src/main/test/resources/featureTests/ConditionalStatements.java rename to src/test/resources/input/featureTests/ConditionalStatements.java diff --git a/src/main/test/resources/featureTests/LoopExamples.java b/src/test/resources/input/featureTests/LoopExamples.java similarity index 100% rename from src/main/test/resources/featureTests/LoopExamples.java rename to src/test/resources/input/featureTests/LoopExamples.java diff --git a/src/main/test/resources/featureTests/MethodOverloading.java b/src/test/resources/input/featureTests/MethodOverloading.java similarity index 100% rename from src/main/test/resources/featureTests/MethodOverloading.java rename to src/test/resources/input/featureTests/MethodOverloading.java 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 new file mode 100644 index 0000000..054a49b --- /dev/null +++ b/src/test/resources/semantic/endToTAST/CorrectTest.java @@ -0,0 +1,18 @@ +public class Example { + + public int a; + + 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/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/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/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/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 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){ + + } + +} 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; + } + +}