johns-branch #12

Merged
i22005 merged 23 commits from johns-branch into main 2024-06-21 16:30:56 +00:00
15 changed files with 261 additions and 44 deletions
Showing only changes of commit 0ec65af9f9 - Show all commits

View File

@ -2,11 +2,14 @@ package ast.block;
import ast.ASTNode; import ast.ASTNode;
import ast.statement.StatementNode; import ast.statement.StatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BlockNode implements ASTNode { public class BlockNode implements ASTNode, Visitable {
public List<StatementNode> statements = new ArrayList<>(); public List<StatementNode> statements = new ArrayList<>();
public BlockNode() {} public BlockNode() {}
@ -14,4 +17,10 @@ public class BlockNode implements ASTNode {
public void addStatement(StatementNode statement) { public void addStatement(StatementNode statement) {
statements.add(statement); statements.add(statement);
} }
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
} }

View File

@ -1,4 +1,6 @@
package ast.expression; package ast.expression;
public class ExpressionNode { import ast.ASTNode;
public class ExpressionNode implements ASTNode {
} }

View File

@ -7,7 +7,7 @@ import ast.type.ValueNode;
import java.util.Objects; import java.util.Objects;
public class UnaryExpressionNode implements ASTNode { public class UnaryExpressionNode extends ExpressionNode {
String thisExp; String thisExp;
String identifier; String identifier;
MemberAccessNode memberAccess; MemberAccessNode memberAccess;

View File

@ -9,14 +9,15 @@ import semantic.SemanticVisitor;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
import visitor.Visitable; import visitor.Visitable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class MethodNode implements MemberNode, Visitable { public class MethodNode implements MemberNode, Visitable {
AccessModifierNode accesModifier; AccessModifierNode accesModifier;
TypeNode type; public TypeNode type;
Boolean voidType; Boolean voidType;
String identifier; public String identifier;
List<ParameterNode> parameters; private List<ParameterNode> parameters = new ArrayList<>();
public BlockNode block; public BlockNode block;
public MethodNode() {} public MethodNode() {}
@ -37,24 +38,23 @@ public class MethodNode implements MemberNode, Visitable {
this.parameters.add(parameter); this.parameters.add(parameter);
} }
/* public List<ParameterNode> getParameters() {
public boolean isSame(MethodNode methodNode){ return parameters;
boolean isSame = false;
if(methodNode.identifier.equals(identifier)){
if(parameters != null && methodNode.parameters != null){
if(parameters.parameters.size() == methodNode.parameters.parameters.size()){
for(int i = 0; i < parameters.parameters.size(); i++){
if(parameters.parameters.get(i).identifier.equals(methodNode.parameters.parameters.get(i).identifier)){
isSame = true;
}
}
}
}
}
return isSame;
} }
*/ public boolean isSame(MethodNode methodNode){
if (!this.identifier.equals(methodNode.identifier) || this.type.equals(methodNode.type)
|| this.getParameters().size() != methodNode.getParameters().size()) {
return false;
}
for (int i = 0; i < this.getParameters().size(); i++) {
if (this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) {
return false;
}
}
return true;
}
@Override @Override
public TypeCheckResult accept(SemanticVisitor visitor) { public TypeCheckResult accept(SemanticVisitor visitor) {

View File

@ -2,13 +2,22 @@ package ast.parameter;
import ast.ASTNode; import ast.ASTNode;
import ast.type.TypeNode; import ast.type.TypeNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
public class ParameterNode implements ASTNode { public class ParameterNode implements ASTNode, Visitable {
TypeNode type; public TypeNode type;
String identifier; public String identifier;
public ParameterNode(TypeNode type, String identifier) { public ParameterNode(TypeNode type, String identifier) {
this.type = type; this.type = type;
this.identifier = identifier; this.identifier = identifier;
} }
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
} }

View File

@ -4,7 +4,7 @@ import ast.ASTNode;
import ast.expression.ExpressionNode; import ast.expression.ExpressionNode;
import ast.type.TypeNode; import ast.type.TypeNode;
public class LocalVariableDeclarationNode implements ASTNode { public class LocalVariableDeclarationNode extends StatementNode {
TypeNode type; TypeNode type;
String identifier; String identifier;
String assign; String assign;

View File

@ -1,2 +1,6 @@
package ast.statement;public class StatementNode { package ast.statement;
import ast.ASTNode;
public class StatementNode implements ASTNode {
} }

View File

@ -22,4 +22,10 @@ public class TypeNode {
this.type = EnumTypeNode.IDENTIFIER; this.type = EnumTypeNode.IDENTIFIER;
} }
} }
public boolean equals(TypeNode o) {
return !o.type.equals(this.type);
}
} }

View File

@ -74,7 +74,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
} else { } else {
MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block())); MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block()));
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) { for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
methodNode.addParameter((ParameterNode) visit(parameter)); // methodNode.addParameter((ParameterNode) visit(parameter));
} }
return methodNode; return methodNode;
} }

View File

@ -7,13 +7,14 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import ast.*; import ast.*;
import ast.block.BlockNode;
import ast.member.*; import ast.member.*;
import ast.parameter.ParameterNode;
import ast.statement.*; import ast.statement.*;
import ast.statement.ifstatement.IfStatementNode; import ast.statement.ifstatement.IfStatementNode;
import ast.type.*; import ast.type.*;
import semantic.context.Context; import semantic.context.Context;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException; import semantic.exeptions.TypeMismatchException;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -96,10 +97,47 @@ public class SemanticAnalyzer implements SemanticVisitor {
public TypeCheckResult analyze(MethodNode methodNode) { public TypeCheckResult analyze(MethodNode methodNode) {
var valid = true; var valid = true;
currentScope.pushScope(); for (var otherMethod : currentClass.getMethods()) {
if (Objects.equals(otherMethod , methodNode))
break;
if (otherMethod.isSame(methodNode)) {
errors.add(new AlreadyDeclearedException(
"Method " + methodNode.identifier + " is already defined in class "
+ currentClass.identifier));
valid = false;
}
}
currentScope.pushScope();
for (var parameter : methodNode.getParameters()) {
var result = parameter.accept(this);
valid = valid && result.isValid();
currentScope.addLocalVar(parameter.identifier, parameter.type);
}
// Check if this method is already declared
// currentMethodReturnType = methodDecl.getType();
// currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ
// gesetzt ist, ist dieser der Rückgabewert der Methode
var result = methodNode.block.accept(this);
valid = valid && result.isValid();
currentScope.popScope(); currentScope.popScope();
return new TypeCheckResult(valid, null); var resultType = result.getType();
/*
if (resultType == null) {
resultType = new BaseType(Primitives.VOID);
}
if (!resultType.equals(methodDecl.getType())) {
errors.add(new TypeMismatchException("Method-Declaration " + methodDecl.getIdentifier() + " with type "
+ methodDecl.getType() + " has at least one Mismatching return Type:"
+ TypeHelper.generateLocationString(methodDecl.line, methodDecl.column, fileName)));
valid = false;
}
*/
return new TypeCheckResult(valid, resultType);
} }
@Override @Override
@ -128,4 +166,14 @@ public class SemanticAnalyzer implements SemanticVisitor {
return null; return null;
} }
@Override
public TypeCheckResult analyze(ParameterNode toCheck) {
return new TypeCheckResult(true, null);
}
@Override
public TypeCheckResult analyze(BlockNode toCheck) {
return new TypeCheckResult(true, null);
}
} }

View File

@ -2,7 +2,9 @@ package semantic;
import ast.*; import ast.*;
import ast.block.BlockNode;
import ast.member.*; import ast.member.*;
import ast.parameter.ParameterNode;
import ast.statement.*; import ast.statement.*;
import ast.statement.ifstatement.*; import ast.statement.ifstatement.*;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
@ -23,4 +25,9 @@ public interface SemanticVisitor {
TypeCheckResult analyze(WhileStatementNode toCheck); TypeCheckResult analyze(WhileStatementNode toCheck);
TypeCheckResult analyze(ParameterNode toCheck);
TypeCheckResult analyze(BlockNode toCheck);
} }

View File

@ -2,7 +2,13 @@ package semantic;
import ast.*; import ast.*;
import ast.block.BlockNode; import ast.block.BlockNode;
import ast.member.FieldNode;
import ast.member.MethodNode; import ast.member.MethodNode;
import ast.parameter.ParameterNode;
import ast.statement.StatementNode;
import ast.statement.statementexpression.NewDeclarationStatementExpressionNode;
import ast.type.AccessModifierNode;
import ast.type.TypeNode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -11,26 +17,94 @@ import static parser.generated.SimpleJavaParser.Identifier;
public class Mocker { public class Mocker {
public static ProgramNode mockCorrectClass(){ public static ASTNode mockTwoSameFields(){
ProgramNode p = new ProgramNode(); ProgramNode p = new ProgramNode();
ClassNode c = new ClassNode(); ClassNode c = new ClassNode();
c.identifier = "testClass"; c.identifier = "testClass";
MethodNode m = new MethodNode(); FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a");
BlockNode b = new BlockNode(); c.members.add(f1);
FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new TypeNode("int"), "a");
c.members.add(f2);
// b.statements.add();
m.block = b;
c.members.add(m);
p.classes.add(c); p.classes.add(c);
return p; return p;
} }
public static ASTNode mockSimpleMethod(){
ProgramNode p = new ProgramNode();
ClassNode c = new ClassNode();
MethodNode methodNode = new MethodNode();
//Parameter
ParameterNode parameterNode = new ParameterNode(new TypeNode("int"), "a");
methodNode.addParameter(parameterNode);
//Statements
//Block
methodNode.block = new BlockNode();
c.members.add(methodNode);
p.classes.add(c);
return p;
}
public static ASTNode mockTwoSameMethods(){
ProgramNode p = new ProgramNode();
ClassNode c = new ClassNode();
MethodNode methodNode = new MethodNode();
methodNode.block = new BlockNode();
methodNode.type = new TypeNode("int");
methodNode.identifier = "testMethod";
c.members.add(methodNode);
MethodNode methodNode1 = new MethodNode();
methodNode1.block = new BlockNode();
methodNode1.type = new TypeNode("int");
methodNode1.identifier = "testMethod";
c.members.add(methodNode1);
p.classes.add(c);
return p;
}
public static ASTNode mockTwoDifferentMethods(){
ProgramNode p = new ProgramNode();
ClassNode c = new ClassNode();
MethodNode methodNode = new MethodNode();
methodNode.block = new BlockNode();
methodNode.identifier = "testMethod";
c.members.add(methodNode);
MethodNode methodNode1 = new MethodNode();
methodNode1.block = new BlockNode();
methodNode1.identifier = "testMethod1";
c.members.add(methodNode1);
p.classes.add(c);
return p;
}
} }

View File

@ -1,14 +1,63 @@
package semantic; package semantic;
import ast.ASTNode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import semantic.exeptions.AlreadyDeclearedException;
import static org.junit.jupiter.api.Assertions.*;
public class SemanticTest { public class SemanticTest {
@BeforeEach
public void setup(){
SemanticAnalyzer.clearAnalyzier();
}
@Test @Test
public void correctClass(){ public void twoFieldsSameName() {
ASTNode ast = Mocker.mockTwoSameFields();
ASTNode tast = SemanticAnalyzer.generateTast(ast);
assertEquals(SemanticAnalyzer.errors.size(), 1);
assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
assertNull(tast);
} }
@Test
public void simpleMethod(){
ASTNode ast = Mocker.mockSimpleMethod();
ASTNode tast = SemanticAnalyzer.generateTast(ast);
assertEquals(SemanticAnalyzer.errors.size(), 0);
assertNotNull(tast);
}
@Test
public void twoSameMethods(){
ASTNode ast = Mocker.mockTwoSameMethods();
ASTNode tast = SemanticAnalyzer.generateTast(ast);
assertEquals(1, SemanticAnalyzer.errors.size());
assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
assertNull(tast);
}
@Test
public void twoDifferentMethods(){
ASTNode ast = Mocker.mockTwoDifferentMethods();
ASTNode tast = SemanticAnalyzer.generateTast(ast);
assertEquals(SemanticAnalyzer.errors.size(), 0);
assertNotNull(tast);
}
} }

View File

@ -1,5 +1,6 @@
package semantic.endToTAST; package semantic.endToTAST;
import ast.ASTNode;
import ast.ProgramNode; import ast.ProgramNode;
import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CharStreams;
@ -9,10 +10,13 @@ import org.junit.jupiter.api.Test;
import parser.astBuilder.ASTBuilder; import parser.astBuilder.ASTBuilder;
import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser; import parser.generated.SimpleJavaParser;
import semantic.SemanticAnalyzer;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths; import java.nio.file.Paths;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CorrectTest { public class CorrectTest {
@Test @Test
@ -36,6 +40,12 @@ public class CorrectTest {
System.out.println("Test"); System.out.println("Test");
ASTNode tast = SemanticAnalyzer.generateTast(abstractSyntaxTree);
System.out.println("Errors: " + SemanticAnalyzer.errors.size());
assertEquals(SemanticAnalyzer.errors.size(), 0);
} }
} }

View File

@ -1,7 +1,6 @@
public class Test { public class Test {
public void test(){ public boolean b;
public boolean b;
}
} }