Added Method Check
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Bruder John 2024-06-20 16:53:31 +02:00
parent fd8c3b066a
commit 0ec65af9f9
15 changed files with 261 additions and 44 deletions

View File

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

View File

@ -1,4 +1,6 @@
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;
public class UnaryExpressionNode implements ASTNode {
public class UnaryExpressionNode extends ExpressionNode {
String thisExp;
String identifier;
MemberAccessNode memberAccess;

View File

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

View File

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

View File

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

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;
}
}
public boolean equals(TypeNode o) {
return !o.type.equals(this.type);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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