Added Method Check
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
This commit is contained in:
parent
fd8c3b066a
commit
0ec65af9f9
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
package ast.expression;
|
||||
|
||||
public class ExpressionNode {
|
||||
import ast.ASTNode;
|
||||
|
||||
public class ExpressionNode implements ASTNode {
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -1,2 +1,6 @@
|
||||
package ast.statement;public class StatementNode {
|
||||
package ast.statement;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
public class StatementNode implements ASTNode {
|
||||
}
|
||||
|
@ -22,4 +22,10 @@ public class TypeNode {
|
||||
this.type = EnumTypeNode.IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(TypeNode o) {
|
||||
return !o.type.equals(this.type);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
public class Test {
|
||||
|
||||
public void test(){
|
||||
|
||||
}
|
||||
public boolean b;
|
||||
public boolean b;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user