Compare commits

..

7 Commits

Author SHA1 Message Date
6d36eb109c Added Enums for Operators and MainMethodNode
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
2024-06-21 18:02:29 +02:00
Bruder John
7b41c45cd5 Fixed all Tests
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2024-06-21 17:03:49 +02:00
Bruder John
cf41babcb7 Added BaseType And refferenz Type
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2024-06-21 16:42:27 +02:00
Bruder John
b9ada16dd1 Fixed SemanticCheck for new AST and added Some Test
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2024-06-21 15:23:48 +02:00
Bruder John
b5738034b0 Merge branch 'NewParser' into johns-branch
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2024-06-21 10:47:54 +02:00
Bruder John
0ec65af9f9 Added Method Check
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2024-06-20 16:53:31 +02:00
Bruder John
fd8c3b066a Trying to change to new AST
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2024-06-20 11:43:58 +02:00
66 changed files with 1347 additions and 562 deletions

View File

@ -4,11 +4,14 @@ import ast.type.AccessModifierNode;
import ast.member.ConstructorNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList;
import java.util.List;
public class ClassNode implements ASTNode {
public class ClassNode implements ASTNode, Visitable {
public AccessModifierNode accessType;
public String identifier;
public List<MemberNode> members = new ArrayList<>();
@ -45,4 +48,10 @@ public class ClassNode implements ASTNode {
}
return methods;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,13 +1,21 @@
package ast;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList;
import java.util.List;
public class ProgramNode implements ASTNode {
public class ProgramNode implements ASTNode, Visitable {
public List<ClassNode> classes = new ArrayList<>();
public void addClass(ClassNode classNode) {
classes.add(classNode);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,16 +2,28 @@ package ast.block;
import ast.ASTNode;
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 class BlockNode implements ASTNode, Visitable {
public List<IStatementNode> statements = new ArrayList<>();
public Boolean hasReturnStatement = false;
public BlockNode() {}
public void addStatement(IStatementNode statement) {
statements.add(statement);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,5 +1,11 @@
package ast.expression;
import ast.ASTNode;
import ast.type.type.ITypeNode;
import visitor.Visitable;
public interface IExpressionNode extends ASTNode {}
public interface IExpressionNode extends ASTNode, Visitable {
ITypeNode getType();
}

View File

@ -1,7 +1,19 @@
package ast.expression.binaryexpression;
import ast.expression.IExpressionNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.beans.Expression;
public class BinaryExpressionNode implements IExpressionNode {
public class BinaryExpressionNode implements IExpressionNode {}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -1,19 +1,40 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class CalculationExpressionNode extends BinaryExpressionNode {
public CalculationExpressionNode calculationExpression;
public String operator;
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;
}
}

View File

@ -1,19 +1,42 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DotExpressionNode extends BinaryExpressionNode {
public DotExpressionNode dotExpression;
public String operator;
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;
}
}

View File

@ -1,9 +1,11 @@
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 extends BinaryExpressionNode {
public ValueNode value;
@ -28,4 +30,15 @@ public class DotSubstractionExpressionNode extends BinaryExpressionNode {
this.methodCall = methodCall;
this.calculationExpression = calculationExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -0,0 +1,5 @@
package ast.expression.binaryexpression;
public enum EnumDotOperator {
MULT, DIV, MOD
}

View File

@ -0,0 +1,5 @@
package ast.expression.binaryexpression;
public enum EnumLineOperator {
PLUS, MINUS
}

View File

@ -0,0 +1,5 @@
package ast.expression.binaryexpression;
public enum EnumNonCalculationOperator {
AND, OR, GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL
}

View File

@ -1,17 +1,50 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class NonCalculationExpressionNode extends BinaryExpressionNode {
public UnaryExpressionNode unaryExpression;
public String operator;
public EnumNonCalculationOperator operator;
public IExpressionNode 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;
}
}

View File

@ -16,4 +16,5 @@ public class MemberAccessNode implements ASTNode {
public void addIdentifier(String identifier) {
identifiers.add(identifier);
}
}

View File

@ -9,4 +9,5 @@ public class NotExpressionNode implements ASTNode {
public NotExpressionNode(IExpressionNode expression) {
this.expression = expression;
}
}

View File

@ -2,7 +2,10 @@ package ast.expression.unaryexpression;
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;
@ -14,6 +17,7 @@ public class UnaryExpressionNode implements IExpressionNode {
public NotExpressionNode notExpression;
public IStatementNode statement;
public IExpressionNode expression;
private ITypeNode type;
public UnaryExpressionNode(String value) {
if(Objects.equals(value, "this")) {
@ -42,4 +46,19 @@ public class UnaryExpressionNode implements IExpressionNode {
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;
}
}

View File

@ -3,6 +3,9 @@ package ast.member;
import ast.block.BlockNode;
import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,16 +1,25 @@
package ast.member;
import ast.type.AccessModifierNode;
import ast.type.TypeNode;
import ast.type.type.ITypeNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
public class FieldNode implements MemberNode {
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;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -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;
}
}

View File

@ -3,28 +3,29 @@ 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.ArrayList;
import java.util.List;
import java.util.Objects;
public class MethodNode implements MemberNode {
public class MethodNode implements MemberNode, Visitable {
public AccessModifierNode accesModifier;
public TypeNode type;
private ITypeNode type;
public Boolean voidType;
public String identifier;
private String identifier;
public List<ParameterNode> parameters = new ArrayList<>();
public BlockNode block;
public MethodNode() {}
public MethodNode(BlockNode block){
this.block = block;
}
public MethodNode(String accessModifier, String type, Boolean voidType, String identifier, BlockNode block){
public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){
this.accesModifier = new AccessModifierNode(accessModifier);
this.type = new TypeNode(type);
this.type = type;
this.voidType = voidType;
this.identifier = identifier;
this.block = block;
@ -34,21 +35,22 @@ public class MethodNode implements MemberNode {
this.parameters.add(parameter);
}
/*
public List<ParameterNode> 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
@ -60,6 +62,21 @@ public class MethodNode implements MemberNode {
public void accept(MethodVisitor methodVisitor) {
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;
}
}

View File

@ -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 class ParameterNode implements ASTNode, Visitable {
public ITypeNode 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);
}
}

View File

@ -2,6 +2,8 @@ package ast.statement;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class ForStatementNode implements IStatementNode {
public IExpressionNode statementExpressionInit;
@ -20,4 +22,10 @@ public class ForStatementNode implements IStatementNode {
this.expression = expression;
this.statementExpression = statementExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,6 +1,7 @@
package ast.statement;
import ast.ASTNode;
import visitor.Visitable;
public interface IStatementNode extends ASTNode {
public interface IStatementNode extends ASTNode, Visitable {
}

View File

@ -1,19 +1,26 @@
package ast.statement;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import ast.type.TypeNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class LocalVariableDeclarationNode implements IStatementNode {
public TypeNode type;
public ITypeNode type;
public String identifier;
public String assign;
public IExpressionNode expression;
public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, IExpressionNode 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);
}
}

View File

@ -1,12 +1,24 @@
package ast.statement;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class ReturnStatementNode implements IStatementNode {
public IExpressionNode expression;
public Boolean voidReturn = false;
public ReturnStatementNode(IExpressionNode expression) {
if(expression != null) {
this.expression = expression;
} else {
voidReturn = true;
}
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -3,6 +3,8 @@ package ast.statement;
import ast.ASTNode;
import ast.block.BlockNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class WhileStatementNode implements IStatementNode {
public IExpressionNode expression;
@ -12,4 +14,10 @@ public class WhileStatementNode implements IStatementNode {
this.expression = expression;
this.block = block;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -3,6 +3,8 @@ 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 IStatementNode {
public BlockNode block;
@ -10,4 +12,10 @@ public class ElseStatementNode implements IStatementNode {
public ElseStatementNode(BlockNode block) {
this.block = block;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,6 +2,8 @@ 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;
@ -18,4 +20,9 @@ public class IfElseStatementNode implements IStatementNode {
elseStatements.add(elseStatement);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -4,6 +4,8 @@ import ast.ASTNode;
import ast.block.BlockNode;
import ast.expression.IExpressionNode;
import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class IfStatementNode implements IStatementNode {
public IExpressionNode expression;
@ -13,4 +15,10 @@ public class IfStatementNode implements IStatementNode {
this.expression = expression;
this.block = block;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,7 +1,8 @@
package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class AssignStatementExpressionNode implements IStatementExpressionNode {
public AssignableExpressionNode assignable;
@ -11,4 +12,10 @@ public class AssignStatementExpressionNode implements IStatementExpressionNode {
this.assignable = assignable;
this.expression = expression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -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 IStatementExpressionNode {
public String identifier;
public MemberAccessNode memberAccess;
public AssignableExpressionNode(String identifier) {
@ -14,4 +16,10 @@ public class AssignableExpressionNode implements IStatementExpressionNode {
public AssignableExpressionNode(MemberAccessNode memberAccess) {
this.memberAccess = memberAccess;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,6 +2,8 @@ package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList;
import java.util.List;
@ -17,4 +19,10 @@ public class NewDeclarationStatementExpressionNode implements IStatementExpressi
public void addExpression(IExpressionNode expression) {
expressions.add(expression);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -3,6 +3,8 @@ 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 IStatementExpressionNode {
public CrementType crementType;
@ -11,4 +13,10 @@ public class DecrementExpressionNode implements IStatementExpressionNode {
public DecrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) {
this.assignableExpression = assignableExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -3,6 +3,8 @@ 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 IStatementExpressionNode {
public CrementType crementType;
@ -11,4 +13,10 @@ public class IncrementExpressionNode implements IStatementExpressionNode {
public IncrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) {
this.assignableExpression = assignableExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -3,6 +3,8 @@ package ast.statement.statementexpression.methodcallstatementnexpression;
import ast.ASTNode;
import ast.expression.IExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList;
import java.util.List;
@ -26,5 +28,9 @@ public class MethodCallStatementExpressionNode implements IStatementExpressionNo
expressions.add(expression);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,5 +0,0 @@
package ast.type;
public enum EnumTypeNode {
INT, BOOLEAN, CHAR, IDENTIFIER
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
package ast.type.type;
public interface ITypeNode {
}

View File

@ -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;
}
}

View File

@ -0,0 +1,9 @@
package ast.type.type;
public enum TypeEnum {
VOID,
INT,
CHAR,
BOOL;
}

View File

@ -10,7 +10,7 @@ public class ByteCodeGenerator implements ProgramVisitor {
public void visit(ProgramNode programNode) {
for (ClassNode classDeclarationNode : programNode.classes) {
ClassCodeGen classCodeGen = new ClassCodeGen();
classDeclarationNode.accept(classCodeGen);
// classDeclarationNode.accept(classCodeGen);
}
}
}

View File

@ -4,11 +4,10 @@ import ast.ClassNode;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
import ast.type.BaseTypeNode;
import ast.type.type.BaseType;
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;
@ -25,8 +24,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) {
@ -45,8 +44,8 @@ public class ClassCodeGen implements ClassVisitor {
@Override
public void visit(FieldNode fieldNode) {
if(fieldNode.type instanceof BaseTypeNode baseTypeNode){
classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null );
if(fieldNode.type instanceof BaseType baseTypeNode){
// classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null );
}
classWriter.visitEnd();
}

View File

@ -1,44 +1,41 @@
package bytecode;
import ast.parameter.ParameterNode;
import ast.type.*;
import org.objectweb.asm.Opcodes;
import ast.type.BaseTypeNode;
public class Mapper {
public int mapAccessTypeToOpcode(AccessTypeNode type) {
switch (type.enumAccessTypeNode) {
case EnumAccessTypeNode.PUBLIC:
return Opcodes.ACC_PUBLIC;
case EnumAccessTypeNode.PRIVATE:
return Opcodes.ACC_PRIVATE;
}
return 0;
}
// public int mapAccessTypeToOpcode(AccessModifierNode type) {
// switch (type.enumAccessTypeNode) {
// case EnumAccessTypeNode.PUBLIC:
// return Opcodes.ACC_PUBLIC;
// case EnumAccessTypeNode.PRIVATE:
// return Opcodes.ACC_PRIVATE;
// }
// return 0;
// }
public String generateMethodDescriptor(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) {
String descriptor = "(";
for(ParameterNode parameterNode : parameterListNode.parameters) {
descriptor += getTypeChar(EnumTypeNode.INT);
}
descriptor += ")";
descriptor += getTypeChar(baseTypeNode.enumType);
return descriptor;
}
// public String generateMethodDescriptor(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) {
// String descriptor = "(";
// for(ParameterNode parameterNode : parameterListNode.parameters) {
// descriptor += getTypeChar(EnumTypeNode.INT);
// }
// descriptor += ")";
// descriptor += getTypeChar(baseTypeNode.enumType);
// 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;
// }
}

View File

@ -2,12 +2,8 @@ package bytecode;
import ast.member.ConstructorNode;
import ast.member.MethodNode;
import ast.parameter.ParameterNode;
import ast.type.BaseTypeNode;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
@ -31,12 +27,12 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
@Override
public void visit(ConstructorNode constructorNode) {
methodVisitor =
classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.visibility),
"<init>",
"()V",
null,
null);
// methodVisitor =
// classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.visibility),
// "<init>",
// "()V",
// null,
// null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
@ -47,52 +43,52 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
@Override
public void visit(MethodNode methodNode) {
if (methodNode.type instanceof BaseTypeNode baseTypeNode) {
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility),
methodNode.identifier,
mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters),
null,
null);
// if (methodNode.type instanceof BaseTypeNode baseTypeNode) {
// methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility),
// methodNode.identifier,
// mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters),
// null,
// null);
methodVisitor.visitCode();
localVaribales.add("this");
for (ParameterNode parameterNode : methodNode.parameters.parameters) {
localVaribales.add(parameterNode.identifier);
}
// for (ParameterNode parameterNode : methodNode.parameters.parameters) {
// localVaribales.add(parameterNode.identifier);
// }
//test();
methodVisitor.visitMaxs(1, localVaribales.size());
methodVisitor.visitEnd();
}
// }
}
public void test() {
Label start = new Label();
Label loop = new Label();
Label end = new Label();
methodVisitor.visitLabel(start);
//methodVisitor.visitVarInsn(Opcodes.ICONST_M1, 99);
//methodVisitor.visitInsn(Opcodes.ICONST_5);
methodVisitor.visitLdcInsn(99);
// methodVisitor.visitInsn(Opcodes.ICONST_0);
//methodVisitor.visitVarInsn(Opcodes.ILOAD, 2);
methodVisitor.visitVarInsn(Opcodes.ISTORE, 1);
methodVisitor.visitLabel(loop);
methodVisitor.visitVarInsn(Opcodes.ILOAD, 1);
methodVisitor.visitInsn(Opcodes.ICONST_5);
methodVisitor.visitJumpInsn(Opcodes.IF_ICMPGE, end);
methodVisitor.visitFieldInsn(Opcodes.GETSTATIC,
"java/lang/System", "out",
"Ljava/io/PrintStream;");
methodVisitor.visitLdcInsn("Bytecode");
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/io/PrintStream", "println",
"(Ljava/lang/String;)V", false);
methodVisitor.visitIincInsn(1, 1);
methodVisitor.visitJumpInsn(Opcodes.GOTO, loop);
methodVisitor.visitLabel(end);
methodVisitor.visitVarInsn(Opcodes.ILOAD, 1);
methodVisitor.visitInsn(Opcodes.IRETURN);
methodVisitor.visitEnd();
}
// public void test() {
// Label start = new Label();
// Label loop = new Label();
// Label end = new Label();
// methodVisitor.visitLabel(start);
// //methodVisitor.visitVarInsn(Opcodes.ICONST_M1, 99);
// //methodVisitor.visitInsn(Opcodes.ICONST_5);
// methodVisitor.visitLdcInsn(99);
// // methodVisitor.visitInsn(Opcodes.ICONST_0);
// //methodVisitor.visitVarInsn(Opcodes.ILOAD, 2);
// methodVisitor.visitVarInsn(Opcodes.ISTORE, 1);
// methodVisitor.visitLabel(loop);
// methodVisitor.visitVarInsn(Opcodes.ILOAD, 1);
// methodVisitor.visitInsn(Opcodes.ICONST_5);
// methodVisitor.visitJumpInsn(Opcodes.IF_ICMPGE, end);
// methodVisitor.visitFieldInsn(Opcodes.GETSTATIC,
// "java/lang/System", "out",
// "Ljava/io/PrintStream;");
// methodVisitor.visitLdcInsn("Bytecode");
// methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
// "java/io/PrintStream", "println",
// "(Ljava/lang/String;)V", false);
// methodVisitor.visitIincInsn(1, 1);
// methodVisitor.visitJumpInsn(Opcodes.GOTO, loop);
// methodVisitor.visitLabel(end);
// methodVisitor.visitVarInsn(Opcodes.ILOAD, 1);
// methodVisitor.visitInsn(Opcodes.IRETURN);
// methodVisitor.visitEnd();
// }
}

View File

@ -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.*;
@ -63,10 +62,10 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@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(ctx.AccessModifier().getText(), ctx.type().getText(), 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));
}
@ -81,9 +80,14 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
}
}
@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
@ -113,7 +117,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) {
return new LocalVariableDeclarationNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression()));
return new LocalVariableDeclarationNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression()));
}
@Override
@ -122,6 +126,9 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
for(SimpleJavaParser.StatementContext statement : ctx.statement()) {
blockNode.addStatement((IStatementNode) visit(statement));
}
if(!blockNode.hasReturnStatement) {
blockNode.addStatement(new ReturnStatementNode(null));
}
return blockNode;
}
@ -394,4 +401,15 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
}
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);
};
}
}

View File

@ -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<HashMap<String, TypeNode>> localVars;
private Stack<HashMap<String, ITypeNode>> localVars;
public Scope() {
localVars = new Stack<HashMap<String, TypeNode>>();
localVars = new Stack<HashMap<String, ITypeNode>>();
}
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<String, ITypeNode> map : localVars) {
return map.get(name);
}
return null;
}
public boolean contains(String name) {
for (HashMap<String, TypeNode> map : localVars) {
for (HashMap<String, ITypeNode> map : localVars) {
if (map.containsKey(name)) {
return true;
}
@ -30,7 +38,7 @@ public class Scope {
}
public void pushScope() {
localVars.push(new HashMap<String, TypeNode>());
localVars.push(new HashMap<String, ITypeNode>());
}
public void popScope() {

View File

@ -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<String, TypeNode> currentFields = new HashMap<>();
private static HashMap<String, ITypeNode> currentFields = new HashMap<>();
public static ArrayList<Exception> 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) {
if (methodNode instanceof ConstructorNode) {
return new TypeCheckResult(true, new BaseType(TypeEnum.VOID));
} else {
var valid = true;
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;
}
}
currentScope.pushScope();
//Parameter
ParameterListNode parameterListNode = methodNode.parameters;
if (parameterListNode != null) {
List<ParameterNode> 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 {
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));
}
//Statements
List<StatementNode> 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);
valid = valid && result.isValid();
}
}
// Check if this method is already declared
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();
return new TypeCheckResult(valid, null);
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
@ -151,80 +173,6 @@ public class SemanticAnalyzer implements SemanticVisitor {
return new TypeCheckResult(true, null);
}
@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);
}
return new TypeCheckResult(true, null);
}
@Override
public TypeCheckResult analyze(IfStatementNode toCheck) {
return null;
@ -232,7 +180,9 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(ReturnStatementNode toCheck) {
return null;
var result = toCheck.expression.accept(this);
return new TypeCheckResult(true, result.getType());
}
@Override
@ -241,39 +191,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");
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 {
//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());
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 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);
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -1,6 +1,6 @@
package semantic.context;
import oldAst.ProgramNode;
import ast.ProgramNode;
import java.util.HashMap;
public class Context {

View File

@ -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;
}

View File

@ -0,0 +1,9 @@
package semantic.exeptions;
public class AlreadyDefinedException extends RuntimeException {
public AlreadyDefinedException(String message) {
super(message);
}
}

View File

@ -0,0 +1,9 @@
package semantic.exeptions;
public class MultipleReturnTypes extends RuntimeException {
public MultipleReturnTypes(String message) {
super(message);
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,257 @@
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());
}
}

View File

@ -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<ClassNode> classList = new ArrayList<ClassNode>();
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<ParameterNode> parameterNodeList = new ArrayList<ParameterNode>();
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<StatementNode> statementNodeList = new ArrayList<StatementNode>();
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<ClassNode> classList = new ArrayList<ClassNode>();
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;
}
}

View File

@ -1,162 +1,63 @@
package semantic;
import oldAst.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import ast.ASTNode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.TypeMismatchException;
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() {
public void twoFieldsSameName() {
//Arrange
ASTNode ast = Mocker.mockTwoSameFields();
ProgramNode programNode = Mocker.mockFieldNodeAlreadyDeclaredProgrammNode();
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ASTNode tast = semanticAnalyzer.generateTast(ast);
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException);
assertEquals(null, typedAst);
assertEquals(semanticAnalyzer.errors.size(), 1);
assertInstanceOf(AlreadyDeclearedException.class, semanticAnalyzer.errors.getFirst());
assertNull(tast);
}
@Test
public void alreadyDecleared() {
public void simpleMethod(){
//Arrange
ASTNode ast = Mocker.mockSimpleMethod();
ProgramNode programNode = Mocker.mockFieldNodeAlreadyDeclaredProgrammNode();
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ASTNode tast = semanticAnalyzer.generateTast(ast);
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
assertNull(typedAst);
assertEquals(semanticAnalyzer.errors.size(), 0);
assertNotNull(tast);
}
@Test
public void shouldWorkWithNoError() {
public void twoSameMethods(){
ASTNode ast = Mocker.mockTwoSameMethods();
//Arrange
ProgramNode programNode = Mocker.mockCorrectProgrammNode();
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(0, SemanticAnalyzer.errors.size());
assertEquals(programNode, typedAst);
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ASTNode tast = semanticAnalyzer.generateTast(ast);
assertEquals(1, semanticAnalyzer.errors.size());
assertInstanceOf(AlreadyDeclearedException.class, semanticAnalyzer.errors.getFirst());
assertNull(tast);
}
@Test
public void refTypeCorrect() {
public void twoDifferentMethods(){
ASTNode ast = Mocker.mockTwoDifferentMethods();
//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);
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ASTNode tast = semanticAnalyzer.generateTast(ast);
assertEquals(semanticAnalyzer.errors.size(), 0);
assertNotNull(tast);
}
}

View File

@ -0,0 +1,7 @@
public class Example {
public static int testMethod(int x){
return x;
}
}

View File

@ -0,0 +1,11 @@
public class Example {
public int a;
public static int testMethod(int b){
a = b;
return a;
}
}

View File

@ -0,0 +1,10 @@
public class Example {
public int a;
public int a;
public static int testMethod(char a){
}
}

View File

@ -0,0 +1,8 @@
public class Example {
public static int testMethod(int x, char c){
return x;
return c;
}
}

View File

@ -0,0 +1,6 @@
public class Test {
public static int testMethod(int x){
int a = b;
return x;
}
}

View File

@ -0,0 +1,7 @@
public class Example {
public static int testMethod(char a, int a){
}
}

View File

@ -0,0 +1,10 @@
public class Test {
public boolean b;
public static int testMethod(int a){
b = a;
}
}

View File

@ -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;
}

View File

@ -0,0 +1,7 @@
public class Example {
public static int testMethod(char x){
return x;
}
}