Compare commits
7 Commits
50a52a1e87
...
6d36eb109c
Author | SHA1 | Date | |
---|---|---|---|
6d36eb109c | |||
|
7b41c45cd5 | ||
|
cf41babcb7 | ||
|
b9ada16dd1 | ||
|
b5738034b0 | ||
|
0ec65af9f9 | ||
|
fd8c3b066a |
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package ast.expression.binaryexpression;
|
||||||
|
|
||||||
|
public enum EnumDotOperator {
|
||||||
|
MULT, DIV, MOD
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package ast.expression.binaryexpression;
|
||||||
|
|
||||||
|
public enum EnumLineOperator {
|
||||||
|
PLUS, MINUS
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package ast.expression.binaryexpression;
|
||||||
|
|
||||||
|
public enum EnumNonCalculationOperator {
|
||||||
|
AND, OR, GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,5 @@ public class NotExpressionNode implements ASTNode {
|
|||||||
public NotExpressionNode(IExpressionNode expression) {
|
public NotExpressionNode(IExpressionNode expression) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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<>();
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
11
src/main/java/ast/member/MainMethodNode.java
Normal file
11
src/main/java/ast/member/MainMethodNode.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package ast.type;
|
|
||||||
|
|
||||||
public enum EnumTypeNode {
|
|
||||||
INT, BOOLEAN, CHAR, IDENTIFIER
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
30
src/main/java/ast/type/type/BaseType.java
Normal file
30
src/main/java/ast/type/type/BaseType.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
5
src/main/java/ast/type/type/ITypeNode.java
Normal file
5
src/main/java/ast/type/type/ITypeNode.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package ast.type.type;
|
||||||
|
|
||||||
|
public interface ITypeNode {
|
||||||
|
|
||||||
|
}
|
33
src/main/java/ast/type/type/ReferenceType.java
Normal file
33
src/main/java/ast/type/type/ReferenceType.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
9
src/main/java/ast/type/type/TypeEnum.java
Normal file
9
src/main/java/ast/type/type/TypeEnum.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package ast.type.type;
|
||||||
|
|
||||||
|
public enum TypeEnum {
|
||||||
|
VOID,
|
||||||
|
INT,
|
||||||
|
CHAR,
|
||||||
|
BOOL;
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
|
||||||
}
|
}
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package semantic.exeptions;
|
||||||
|
|
||||||
|
public class AlreadyDefinedException extends RuntimeException {
|
||||||
|
|
||||||
|
public AlreadyDefinedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package semantic.exeptions;
|
||||||
|
|
||||||
|
public class MultipleReturnTypes extends RuntimeException {
|
||||||
|
|
||||||
|
public MultipleReturnTypes(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
257
src/test/java/semantic/EndToTAST.java
Normal file
257
src/test/java/semantic/EndToTAST.java
Normal 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());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public static int testMethod(int x){
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
src/test/resources/semantic/endToTAST/CorrectTest.java
Normal file
11
src/test/resources/semantic/endToTAST/CorrectTest.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public int a;
|
||||||
|
|
||||||
|
public static int testMethod(int b){
|
||||||
|
a = b;
|
||||||
|
return a;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public int a;
|
||||||
|
public int a;
|
||||||
|
|
||||||
|
public static int testMethod(char a){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public static int testMethod(int x, char c){
|
||||||
|
return x;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
src/test/resources/semantic/endToTAST/NotDecleared.java
Normal file
6
src/test/resources/semantic/endToTAST/NotDecleared.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
public class Test {
|
||||||
|
public static int testMethod(int x){
|
||||||
|
int a = b;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public static int testMethod(char a, int a){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
public class Test {
|
||||||
|
|
||||||
|
public boolean b;
|
||||||
|
|
||||||
|
public static int testMethod(int a){
|
||||||
|
|
||||||
|
b = a;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public static int testMethod(char x){
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user