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

View File

@ -1,13 +1,21 @@
package ast; package ast;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ProgramNode implements ASTNode { public class ProgramNode implements ASTNode, Visitable {
public List<ClassNode> classes = new ArrayList<>(); public List<ClassNode> classes = new ArrayList<>();
public void addClass(ClassNode classNode) { public void addClass(ClassNode classNode) {
classes.add(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.ASTNode;
import ast.statement.IStatementNode; 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.ArrayList;
import java.util.List; import java.util.List;
public class BlockNode implements ASTNode { public class BlockNode implements ASTNode, Visitable {
public List<IStatementNode> statements = new ArrayList<>(); public List<IStatementNode> statements = new ArrayList<>();
public Boolean hasReturnStatement = false;
public BlockNode() {} public BlockNode() {}
public void addStatement(IStatementNode statement) { public void addStatement(IStatementNode statement) {
statements.add(statement); statements.add(statement);
} }
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
} }

View File

@ -1,5 +1,11 @@
package ast.expression; package ast.expression;
import ast.ASTNode; 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; package ast.expression.binaryexpression;
import ast.expression.IExpressionNode; 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; package ast.expression.binaryexpression;
import ast.ASTNode; import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class CalculationExpressionNode extends BinaryExpressionNode { public class CalculationExpressionNode extends BinaryExpressionNode {
public CalculationExpressionNode calculationExpression; public CalculationExpressionNode calculationExpression;
public String operator; public EnumLineOperator operator;
public DotExpressionNode dotExpression; public DotExpressionNode dotExpression;
public CalculationExpressionNode(CalculationExpressionNode calculationExpression, String operator, DotExpressionNode dotExpression) { public CalculationExpressionNode(CalculationExpressionNode calculationExpression, String operator, DotExpressionNode dotExpression) {
this.calculationExpression = calculationExpression; this.calculationExpression = calculationExpression;
this.operator = operator; setOperator(operator);
this.dotExpression = dotExpression; this.dotExpression = dotExpression;
} }
public CalculationExpressionNode(DotExpressionNode dotExpression) { public CalculationExpressionNode(DotExpressionNode dotExpression) {
this.dotExpression = 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; package ast.expression.binaryexpression;
import ast.ASTNode; import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DotExpressionNode extends BinaryExpressionNode { public class DotExpressionNode extends BinaryExpressionNode {
public DotExpressionNode dotExpression; public DotExpressionNode dotExpression;
public String operator; public EnumDotOperator operator;
public DotSubstractionExpressionNode dotSubstractionExpression; public DotSubstractionExpressionNode dotSubstractionExpression;
public DotExpressionNode(DotExpressionNode dotExpression, String operator, DotSubstractionExpressionNode dotSubstractionExpression) { public DotExpressionNode(DotExpressionNode dotExpression, String operator, DotSubstractionExpressionNode dotSubstractionExpression) {
this.dotExpression = dotExpression; this.dotExpression = dotExpression;
this.operator = operator; setOperator(operator);
this.dotSubstractionExpression = dotSubstractionExpression; this.dotSubstractionExpression = dotSubstractionExpression;
} }
public DotExpressionNode(DotSubstractionExpressionNode dotSubstractionExpression) { public DotExpressionNode(DotSubstractionExpressionNode dotSubstractionExpression) {
this.dotSubstractionExpression = 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; package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.MemberAccessNode;
import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode; import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode;
import ast.type.type.*;
import ast.type.ValueNode; import ast.type.ValueNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DotSubstractionExpressionNode extends BinaryExpressionNode { public class DotSubstractionExpressionNode extends BinaryExpressionNode {
public ValueNode value; public ValueNode value;
@ -28,4 +30,15 @@ public class DotSubstractionExpressionNode extends BinaryExpressionNode {
this.methodCall = methodCall; this.methodCall = methodCall;
this.calculationExpression = calculationExpression; 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; package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.expression.unaryexpression.UnaryExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class NonCalculationExpressionNode extends BinaryExpressionNode { public class NonCalculationExpressionNode extends BinaryExpressionNode {
public UnaryExpressionNode unaryExpression; public UnaryExpressionNode unaryExpression;
public String operator; public EnumNonCalculationOperator operator;
public IExpressionNode expression; public IExpressionNode expression;
public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, IExpressionNode expression) { public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, IExpressionNode expression) {
this.unaryExpression = unaryExpression; this.unaryExpression = unaryExpression;
this.operator = operator; setOperator(operator);
this.expression = expression; 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) { public void addIdentifier(String identifier) {
identifiers.add(identifier); identifiers.add(identifier);
} }
} }

View File

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

View File

@ -2,7 +2,10 @@ package ast.expression.unaryexpression;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.statement.IStatementNode; import ast.statement.IStatementNode;
import ast.type.type.*;
import ast.type.ValueNode; import ast.type.ValueNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.Objects; import java.util.Objects;
@ -14,6 +17,7 @@ public class UnaryExpressionNode implements IExpressionNode {
public NotExpressionNode notExpression; public NotExpressionNode notExpression;
public IStatementNode statement; public IStatementNode statement;
public IExpressionNode expression; public IExpressionNode expression;
private ITypeNode type;
public UnaryExpressionNode(String value) { public UnaryExpressionNode(String value) {
if(Objects.equals(value, "this")) { if(Objects.equals(value, "this")) {
@ -42,4 +46,19 @@ public class UnaryExpressionNode implements IExpressionNode {
public UnaryExpressionNode(IExpressionNode expression) { public UnaryExpressionNode(IExpressionNode expression) {
this.expression = 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,11 +3,14 @@ package ast.member;
import ast.block.BlockNode; import ast.block.BlockNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode; import ast.type.AccessModifierNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ConstructorNode extends MethodNode { public class ConstructorNode extends MethodNode {
public AccessModifierNode accessType; public AccessModifierNode accessType;
public String identifier; public String identifier;
public List<ParameterNode> parameters = new ArrayList<>(); public List<ParameterNode> parameters = new ArrayList<>();

View File

@ -1,16 +1,25 @@
package ast.member; package ast.member;
import ast.type.AccessModifierNode; 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 AccessModifierNode accessTypeNode;
public TypeNode type; public ITypeNode type;
public String identifier; public String identifier;
public FieldNode(AccessModifierNode accessTypeNode, TypeNode type, String name){ public FieldNode(AccessModifierNode accessTypeNode, ITypeNode type, String name){
this.accessTypeNode = accessTypeNode; this.accessTypeNode = accessTypeNode;
this.type = type; this.type = type;
this.identifier = name; 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.block.BlockNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
public class MethodNode implements MemberNode { public class MethodNode implements MemberNode, Visitable {
public AccessModifierNode accesModifier; public AccessModifierNode accesModifier;
public TypeNode type; private ITypeNode type;
public Boolean voidType; public Boolean voidType;
public String identifier; private String identifier;
public List<ParameterNode> parameters = new ArrayList<>(); public List<ParameterNode> parameters = new ArrayList<>();
public BlockNode block; public BlockNode block;
public MethodNode() {} public MethodNode() {}
public MethodNode(BlockNode block){ public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){
this.block = block;
}
public MethodNode(String accessModifier, String type, Boolean voidType, String identifier, BlockNode block){
this.accesModifier = new AccessModifierNode(accessModifier); this.accesModifier = new AccessModifierNode(accessModifier);
this.type = new TypeNode(type); this.type = type;
this.voidType = voidType; this.voidType = voidType;
this.identifier = identifier; this.identifier = identifier;
this.block = block; this.block = block;
@ -34,21 +35,22 @@ public class MethodNode implements MemberNode {
this.parameters.add(parameter); this.parameters.add(parameter);
} }
/* public List<ParameterNode> getParameters() {
return parameters;
}
public boolean isSame(MethodNode methodNode){ public boolean isSame(MethodNode methodNode){
boolean isSame = false; if (!(Objects.equals(this.identifier, methodNode.getIdentifier())) || type.equals(methodNode.type)
if(methodNode.identifier.equals(identifier)){ || getParameters().size() != methodNode.getParameters().size()) {
if(parameters != null && methodNode.parameters != null){ return false;
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)){ for (int i = 0; i < this.getParameters().size(); i++) {
isSame = true; if (this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) {
} return false;
}
}
} }
} }
return isSame; return true;
} }
@Override @Override
@ -60,6 +62,21 @@ public class MethodNode implements MemberNode {
public void accept(MethodVisitor methodVisitor) { public void accept(MethodVisitor methodVisitor) {
methodVisitor.visit(this); 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; package ast.parameter;
import ast.ASTNode; 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 class ParameterNode implements ASTNode, Visitable {
public TypeNode type; public ITypeNode type;
public String identifier; public String identifier;
public ParameterNode(TypeNode type, String identifier) { public ParameterNode(ITypeNode type, String identifier) {
this.type = type; this.type = type;
this.identifier = identifier; this.identifier = identifier;
} }
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
} }

View File

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

View File

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

View File

@ -1,12 +1,24 @@
package ast.statement; package ast.statement;
import ast.ASTNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class ReturnStatementNode implements IStatementNode { public class ReturnStatementNode implements IStatementNode {
public IExpressionNode expression; public IExpressionNode expression;
public Boolean voidReturn = false;
public ReturnStatementNode(IExpressionNode expression) { public ReturnStatementNode(IExpressionNode expression) {
this.expression = 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.ASTNode;
import ast.block.BlockNode; import ast.block.BlockNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class WhileStatementNode implements IStatementNode { public class WhileStatementNode implements IStatementNode {
public IExpressionNode expression; public IExpressionNode expression;
@ -12,4 +14,10 @@ public class WhileStatementNode implements IStatementNode {
this.expression = expression; this.expression = expression;
this.block = block; 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.ASTNode;
import ast.block.BlockNode; import ast.block.BlockNode;
import ast.statement.IStatementNode; import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class ElseStatementNode implements IStatementNode { public class ElseStatementNode implements IStatementNode {
public BlockNode block; public BlockNode block;
@ -10,4 +12,10 @@ public class ElseStatementNode implements IStatementNode {
public ElseStatementNode(BlockNode block) { public ElseStatementNode(BlockNode block) {
this.block = 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.ASTNode;
import ast.statement.IStatementNode; import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -18,4 +20,9 @@ public class IfElseStatementNode implements IStatementNode {
elseStatements.add(elseStatement); 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.block.BlockNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.statement.IStatementNode; import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class IfStatementNode implements IStatementNode { public class IfStatementNode implements IStatementNode {
public IExpressionNode expression; public IExpressionNode expression;
@ -13,4 +15,10 @@ public class IfStatementNode implements IStatementNode {
this.expression = expression; this.expression = expression;
this.block = block; this.block = block;
} }
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
} }

View File

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

View File

@ -1,10 +1,12 @@
package ast.statement.statementexpression; package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.MemberAccessNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class AssignableExpressionNode implements IStatementExpressionNode { public class AssignableExpressionNode implements IStatementExpressionNode {
public String identifier; public String identifier;
public MemberAccessNode memberAccess; public MemberAccessNode memberAccess;
public AssignableExpressionNode(String identifier) { public AssignableExpressionNode(String identifier) {
@ -14,4 +16,10 @@ public class AssignableExpressionNode implements IStatementExpressionNode {
public AssignableExpressionNode(MemberAccessNode memberAccess) { public AssignableExpressionNode(MemberAccessNode memberAccess) {
this.memberAccess = 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.ASTNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -17,4 +19,10 @@ public class NewDeclarationStatementExpressionNode implements IStatementExpressi
public void addExpression(IExpressionNode expression) { public void addExpression(IExpressionNode expression) {
expressions.add(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.ASTNode;
import ast.statement.statementexpression.AssignableExpressionNode; import ast.statement.statementexpression.AssignableExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode; import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DecrementExpressionNode implements IStatementExpressionNode { public class DecrementExpressionNode implements IStatementExpressionNode {
public CrementType crementType; public CrementType crementType;
@ -11,4 +13,10 @@ public class DecrementExpressionNode implements IStatementExpressionNode {
public DecrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) { public DecrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) {
this.assignableExpression = 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.ASTNode;
import ast.statement.statementexpression.AssignableExpressionNode; import ast.statement.statementexpression.AssignableExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode; import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class IncrementExpressionNode implements IStatementExpressionNode { public class IncrementExpressionNode implements IStatementExpressionNode {
public CrementType crementType; public CrementType crementType;
@ -11,4 +13,10 @@ public class IncrementExpressionNode implements IStatementExpressionNode {
public IncrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) { public IncrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) {
this.assignableExpression = 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.ASTNode;
import ast.expression.IExpressionNode; import ast.expression.IExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode; import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,5 +28,9 @@ public class MethodCallStatementExpressionNode implements IStatementExpressionNo
expressions.add(expression); 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) { public void visit(ProgramNode programNode) {
for (ClassNode classDeclarationNode : programNode.classes) { for (ClassNode classDeclarationNode : programNode.classes) {
ClassCodeGen classCodeGen = new ClassCodeGen(); 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.FieldNode;
import ast.member.MemberNode; import ast.member.MemberNode;
import ast.member.MethodNode; import ast.member.MethodNode;
import ast.type.BaseTypeNode; import ast.type.type.BaseType;
import bytecode.visitor.ClassVisitor; import bytecode.visitor.ClassVisitor;
import java.io.File; import java.io.File;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -25,8 +24,8 @@ public class ClassCodeGen implements ClassVisitor {
@Override @Override
public void visit(ClassNode classNode) { public void visit(ClassNode classNode) {
classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null, // classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null,
"java/lang/Object", null); // "java/lang/Object", null);
for (MemberNode memberNode : classNode.members) { for (MemberNode memberNode : classNode.members) {
if (memberNode instanceof FieldNode) { if (memberNode instanceof FieldNode) {
@ -45,8 +44,8 @@ public class ClassCodeGen implements ClassVisitor {
@Override @Override
public void visit(FieldNode fieldNode) { public void visit(FieldNode fieldNode) {
if(fieldNode.type instanceof BaseTypeNode baseTypeNode){ if(fieldNode.type instanceof BaseType baseTypeNode){
classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null ); // classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null );
} }
classWriter.visitEnd(); classWriter.visitEnd();
} }

View File

@ -1,44 +1,41 @@
package bytecode; package bytecode;
import ast.parameter.ParameterNode;
import ast.type.*; import ast.type.*;
import org.objectweb.asm.Opcodes;
import ast.type.BaseTypeNode;
public class Mapper { public class Mapper {
public int mapAccessTypeToOpcode(AccessTypeNode type) { // public int mapAccessTypeToOpcode(AccessModifierNode type) {
switch (type.enumAccessTypeNode) { // switch (type.enumAccessTypeNode) {
case EnumAccessTypeNode.PUBLIC: // case EnumAccessTypeNode.PUBLIC:
return Opcodes.ACC_PUBLIC; // return Opcodes.ACC_PUBLIC;
case EnumAccessTypeNode.PRIVATE: // case EnumAccessTypeNode.PRIVATE:
return Opcodes.ACC_PRIVATE; // return Opcodes.ACC_PRIVATE;
} // }
return 0; // return 0;
} // }
public String generateMethodDescriptor(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) { // public String generateMethodDescriptor(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) {
String descriptor = "("; // String descriptor = "(";
for(ParameterNode parameterNode : parameterListNode.parameters) { // for(ParameterNode parameterNode : parameterListNode.parameters) {
descriptor += getTypeChar(EnumTypeNode.INT); // descriptor += getTypeChar(EnumTypeNode.INT);
} // }
descriptor += ")"; // descriptor += ")";
descriptor += getTypeChar(baseTypeNode.enumType); // descriptor += getTypeChar(baseTypeNode.enumType);
return descriptor; // return descriptor;
} // }
public String getTypeChar(EnumTypeNode enumTypeNode) { // public String getTypeChar(TypeEnum enumTypeNode) {
String typeChar = ""; // String typeChar = "";
switch (enumTypeNode) { // switch (enumTypeNode) {
case EnumTypeNode.INT: // case TypeEnum.INT:
typeChar = "I"; // typeChar = "I";
break; // break;
case EnumTypeNode.CHAR: // case TypeEnum.CHAR:
typeChar = "C"; // typeChar = "C";
break; // break;
case EnumTypeNode.BOOLEAN: // case TypeEnum.BOOLEAN:
typeChar = "Z"; // typeChar = "Z";
break; // break;
} // }
return typeChar; // return typeChar;
} // }
} }

View File

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

View File

@ -10,11 +10,9 @@ import ast.expression.binaryexpression.NonCalculationExpressionNode;
import ast.expression.unaryexpression.MemberAccessNode; import ast.expression.unaryexpression.MemberAccessNode;
import ast.expression.unaryexpression.NotExpressionNode; import ast.expression.unaryexpression.NotExpressionNode;
import ast.expression.unaryexpression.UnaryExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.member.MethodNode; import ast.member.*;
import ast.statement.ifstatement.ElseStatementNode; import ast.statement.ifstatement.ElseStatementNode;
import ast.statement.ifstatement.IfElseStatementNode; import ast.statement.ifstatement.IfElseStatementNode;
import ast.member.ConstructorNode;
import ast.member.MemberNode;
import ast.parameter.ParameterNode; import ast.parameter.ParameterNode;
import ast.statement.*; import ast.statement.*;
import ast.statement.ifstatement.IfStatementNode; 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.MethodCallStatementExpressionNode;
import ast.statement.statementexpression.methodcallstatementnexpression.TargetNode; import ast.statement.statementexpression.methodcallstatementnexpression.TargetNode;
import ast.type.*; import ast.type.*;
import ast.type.type.*;
import org.antlr.v4.runtime.tree.TerminalNode; import org.antlr.v4.runtime.tree.TerminalNode;
import parser.generated.*; import parser.generated.*;
@ -63,10 +62,10 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override @Override
public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) { public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) {
if(ctx.MainMethodDeclaration() != null) { if(ctx.MainMethodDeclaration() != null) {
return new MethodNode((BlockNode) visit(ctx.block())); return new MainMethodNode((BlockNode) visit(ctx.block()));
} else { } else {
if(ctx.type() != null) { 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()) { for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
methodNode.addParameter((ParameterNode) visit(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 @Override
public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) { 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 @Override
@ -113,7 +117,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override @Override
public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) { 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 @Override
@ -122,6 +126,9 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
for(SimpleJavaParser.StatementContext statement : ctx.statement()) { for(SimpleJavaParser.StatementContext statement : ctx.statement()) {
blockNode.addStatement((IStatementNode) visit(statement)); blockNode.addStatement((IStatementNode) visit(statement));
} }
if(!blockNode.hasReturnStatement) {
blockNode.addStatement(new ReturnStatementNode(null));
}
return blockNode; return blockNode;
} }
@ -394,4 +401,15 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
} }
return null; 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; package semantic;
import oldAst.type.TypeNode; import ast.type.type.*;
import semantic.exeptions.AlreadyDeclearedException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Stack; import java.util.Stack;
public class Scope { public class Scope {
private Stack<HashMap<String, TypeNode>> localVars; private Stack<HashMap<String, ITypeNode>> localVars;
public Scope() { 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)) { 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); 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) { public boolean contains(String name) {
for (HashMap<String, TypeNode> map : localVars) { for (HashMap<String, ITypeNode> map : localVars) {
if (map.containsKey(name)) { if (map.containsKey(name)) {
return true; return true;
} }
@ -30,7 +38,7 @@ public class Scope {
} }
public void pushScope() { public void pushScope() {
localVars.push(new HashMap<String, TypeNode>()); localVars.push(new HashMap<String, ITypeNode>());
} }
public void popScope() { public void popScope() {

View File

@ -1,40 +1,44 @@
package semantic; 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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import oldAst.type.BaseTypeNode; import ast.*;
import oldAst.type.TypeNode; 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.context.Context;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.*;
import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException;
import typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
public class SemanticAnalyzer implements SemanticVisitor { 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<>(); public static ArrayList<Exception> errors = new ArrayList<>();
private Context context; private static Context context;
private static Scope currentScope; private static Scope currentScope;
private static ClassNode currentClass; private static ClassNode currentClass;
private static ITypeNode currentNullType;
private ITypeNode currentMethodReturnType;
public static ASTNode generateTast(ASTNode node) { public static ASTNode generateTast(ASTNode node) {
SemanticAnalyzer semanticCheck = new SemanticAnalyzer(); SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
@ -50,7 +54,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
return null; return null;
} }
public static void clearAnalyzier(){ public static void clearAnalyzer() {
currentFields.clear(); currentFields.clear();
errors.clear(); errors.clear();
currentScope = null; currentScope = null;
@ -87,13 +91,10 @@ public class SemanticAnalyzer implements SemanticVisitor {
valid = valid && result.isValid(); valid = valid && result.isValid();
} else if (memberNode instanceof MethodNode methodNode) { } else if (memberNode instanceof MethodNode methodNode) {
//Methods //Methods
for(MethodNode methode : currentClass.getMethods()){ for (MethodNode methode : currentClass.getMethods()) {
if(methode.equals(methodNode)) if (methode.equals(methodNode))
break; break;
if(methode.isSame(methodNode)){
errors.add(new AlreadyDeclearedException("This method has already been declared"));
valid = false;
}
} }
var result = methodNode.accept(this); var result = methodNode.accept(this);
valid = valid && result.isValid(); valid = valid && result.isValid();
@ -106,38 +107,59 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override @Override
public TypeCheckResult analyze(MethodNode methodNode) { public TypeCheckResult analyze(MethodNode methodNode) {
var valid = true; if (methodNode instanceof ConstructorNode) {
return new TypeCheckResult(true, new BaseType(TypeEnum.VOID));
} else {
currentScope.pushScope(); var valid = true;
//Parameter for (var otherMethod : currentClass.getMethods()) {
ParameterListNode parameterListNode = methodNode.parameters; if (Objects.equals(otherMethod, methodNode))
if (parameterListNode != null) { break;
List<ParameterNode> parameters = parameterListNode.parameters; if (otherMethod.isSame(methodNode)) {
for (ParameterNode parameter : parameters) { errors.add(new AlreadyDeclearedException(
if (currentScope.contains(parameter.identifier)) { "Method " + methodNode.getIdentifier() + " is already defined in class "
errors.add(new AlreadyDeclearedException("Duplicated Parameter " + parameter.identifier)); + currentClass.identifier));
return new TypeCheckResult(false, null); valid = false;
} else {
currentScope.addLocalVar(parameter.identifier, parameter.type);
} }
} }
}
//Statements currentScope.pushScope();
List<StatementNode> statements = methodNode.statements; for (var parameter : methodNode.getParameters()) {
for (StatementNode statement : statements) { var result = parameter.accept(this);
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(); valid = valid && result.isValid();
try {
currentScope.addLocalVar(parameter.identifier, parameter.type);
} catch (AlreadyDeclearedException e) {
errors.add(new AlreadyDeclearedException(parameter.identifier));
}
} }
} // Check if this method is already declared
currentScope.popScope(); currentMethodReturnType = methodNode.getType();
return new TypeCheckResult(valid, null); currentNullType = currentMethodReturnType; // Solange nicht in einem Assign oder Methoden-Aufruf dieser Typ
ITypeNode resultType = new BaseType(TypeEnum.VOID);
// gesetzt ist, ist dieser der Rückgabewert der Methode
var result = methodNode.block.accept(this);
valid = valid && result.isValid();
currentScope.popScope();
resultType = result.getType();
if (resultType == null) {
resultType = new BaseType(TypeEnum.VOID);
}
if (!resultType.equals(methodNode.getType())) {
errors.add(new TypeMismatchException("Method-Declaration " + methodNode.getIdentifier() + " with type "
+ methodNode.getType() + " has at least one Mismatching return Type:"));
valid = false;
}
return new TypeCheckResult(valid, resultType);
}
} }
@Override @Override
@ -151,80 +173,6 @@ public class SemanticAnalyzer implements SemanticVisitor {
return new TypeCheckResult(true, null); 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 @Override
public TypeCheckResult analyze(IfStatementNode toCheck) { public TypeCheckResult analyze(IfStatementNode toCheck) {
return null; return null;
@ -232,7 +180,9 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override @Override
public TypeCheckResult analyze(ReturnStatementNode toCheck) { public TypeCheckResult analyze(ReturnStatementNode toCheck) {
return null;
var result = toCheck.expression.accept(this);
return new TypeCheckResult(true, result.getType());
} }
@Override @Override
@ -241,39 +191,175 @@ public class SemanticAnalyzer implements SemanticVisitor {
} }
@Override @Override
public TypeCheckResult analyze(LiteralNode toCheck) { public TypeCheckResult analyze(ParameterNode toCheck) {
return new TypeCheckResult(true, toCheck.getType());
return new TypeCheckResult(true, null);
} }
@Override @Override
public TypeCheckResult analyze(InstVar toCheck) { public TypeCheckResult analyze(BlockNode blockNode) {
boolean valid = true; ITypeNode blockReturnType = null;
for (IStatementNode statementNode : blockNode.statements) {
var result = toCheck.expression.accept(this); var result = statementNode.accept(this);
if(result.getType() != null){
if(result.getType() instanceof BaseTypeNode){ if(blockReturnType == null){
throw new RuntimeException("BaseType has no Methods or Fields"); blockReturnType = result.getType();
} else { } else {
//Get typ of Field errors.add(new MultipleReturnTypes("There are multiple Return types"));
}
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());
} }
} }
return new TypeCheckResult(true, blockReturnType);
}
@Override
public TypeCheckResult analyze(AssignableExpressionNode toCheck) {
return new TypeCheckResult(true, currentFields.get(toCheck.identifier));
} }
@Override @Override
public TypeCheckResult analyze(This toCheck) { public TypeCheckResult analyze(ElseStatementNode toCheck) {
return new TypeCheckResult(true, toCheck.getType()); 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; package semantic;
import ast.ClassNode; import ast.*;
import ast.expression.LiteralNode; import ast.block.BlockNode;
import ast.ProgramNode; import ast.expression.binaryexpression.*;
import ast.expression.BinaryExpressionNode;
import ast.expression.IdentifierExpressionNode;
import ast.expression.InstVar;
import ast.expression.unaryexpression.UnaryExpressionNode; import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.member.FieldNode; import ast.member.*;
import ast.member.MethodNode; import ast.parameter.ParameterNode;
import ast.statement.*; import ast.statement.*;
import ast.expression.This; import ast.statement.ifstatement.*;
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 typechecker.TypeCheckResult; import typechecker.TypeCheckResult;
public interface SemanticVisitor { public interface SemanticVisitor {
@ -25,25 +27,46 @@ public interface SemanticVisitor {
TypeCheckResult analyze(FieldNode toCheck); 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(IfStatementNode toCheck);
TypeCheckResult analyze(ReturnStatementNode toCheck); TypeCheckResult analyze(ReturnStatementNode toCheck);
TypeCheckResult analyze(WhileStatementNode 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; package semantic.context;
import oldAst.ClassNode; import ast.ClassNode;
import oldAst.member.FieldNode; import ast.member.FieldNode;
import java.util.HashMap; import java.util.HashMap;
public class ClassContext { public class ClassContext {

View File

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

View File

@ -1,20 +1,20 @@
package semantic.context; package semantic.context;
import oldAst.member.FieldNode; import ast.member.FieldNode;
import oldAst.type.AccessTypeNode; import ast.type.*;
import oldAst.type.TypeNode; import ast.type.type.*;
public class FieldContext { public class FieldContext {
private AccessTypeNode accessModifier; private AccessModifierNode accessModifier;
private TypeNode type; private ITypeNode type;
public FieldContext(FieldNode field) { public FieldContext(FieldNode field) {
accessModifier = field.accessTypeNode; accessModifier = field.accessTypeNode;
type = field.type; type = field.type;
} }
public TypeNode getType() { public ITypeNode getType() {
return type; 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; package typechecker;
import oldAst.type.TypeNode; import ast.type.type.ITypeNode;
public class TypeCheckResult { public class TypeCheckResult {
private boolean valid; 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.valid = valid;
this.type = type; this.type = type;
} }
@ -17,7 +17,7 @@ public class TypeCheckResult {
return valid; return valid;
} }
public TypeNode getType() { public ITypeNode getType() {
return type; 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; package semantic;
import oldAst.ClassNode; import ast.*;
import oldAst.expression.LiteralNode; import ast.block.BlockNode;
import oldAst.ProgramNode; import ast.member.FieldNode;
import oldAst.expression.*; import ast.member.MethodNode;
import oldAst.member.FieldNode; import ast.parameter.ParameterNode;
import oldAst.member.MemberNode; import ast.type.AccessModifierNode;
import oldAst.member.MethodNode; import ast.type.type.*;
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;
public class Mocker { public class Mocker {
public static ProgramNode mockCorrectProgrammNode(){ public static ASTNode mockTwoSameFields(){
ProgramNode p = new ProgramNode();
ProgramNode programNode = new ProgramNode(); ClassNode c = new ClassNode();
List<ClassNode> classList = new ArrayList<ClassNode>(); c.identifier = "testClass";
AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar1"); FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a");
classNode.members.add(memberNode1);
MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "objectVar"); c.members.add(f1);
classNode.members.add(memberNode2);
List<ParameterNode> parameterNodeList = new ArrayList<ParameterNode>(); FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a");
ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1");
parameterNodeList.add(parameterNode1);
ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList);
List<StatementNode> statementNodeList = new ArrayList<StatementNode>(); c.members.add(f2);
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;
p.classes.add(c);
return p;
} }
public static ProgramNode mockFieldNodeAlreadyDeclaredProgrammNode(){ public static ASTNode mockSimpleMethod(){
ProgramNode programNode = new ProgramNode(); ProgramNode p = new ProgramNode();
List<ClassNode> classList = new ArrayList<ClassNode>();
AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); ClassNode c = new ClassNode();
classNode.members.add(memberNode1);
MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar"); MethodNode methodNode = new MethodNode();
classNode.members.add(memberNode2);
classList.add(classNode); //Parameter
programNode.classes = classList; 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; package semantic;
import ast.ASTNode;
import oldAst.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import semantic.exeptions.AlreadyDeclearedException; import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.TypeMismatchException;
import java.io.File; import static org.junit.jupiter.api.Assertions.*;
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;
public class SemanticTest { public class SemanticTest {
@BeforeEach
public void init() {
SemanticAnalyzer.clearAnalyzier();
}
@Test @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 assertEquals(semanticAnalyzer.errors.size(), 1);
assertInstanceOf(AlreadyDeclearedException.class, semanticAnalyzer.errors.getFirst());
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode); assertNull(tast);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException);
assertEquals(null, typedAst);
} }
@Test @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 assertEquals(semanticAnalyzer.errors.size(), 0);
assertNotNull(tast);
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
assertNull(typedAst);
} }
@Test @Test
public void shouldWorkWithNoError() { public void twoSameMethods(){
ASTNode ast = Mocker.mockTwoSameMethods();
//Arrange SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ASTNode tast = semanticAnalyzer.generateTast(ast);
ProgramNode programNode = Mocker.mockCorrectProgrammNode();
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(0, SemanticAnalyzer.errors.size());
assertEquals(programNode, typedAst);
assertEquals(1, semanticAnalyzer.errors.size());
assertInstanceOf(AlreadyDeclearedException.class, semanticAnalyzer.errors.getFirst());
assertNull(tast);
} }
@Test @Test
public void refTypeCorrect() { public void twoDifferentMethods(){
ASTNode ast = Mocker.mockTwoDifferentMethods();
//Arrange SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ASTNode tast = semanticAnalyzer.generateTast(ast);
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);
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;
}
}