diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9ee63e3..d81162c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,13 +27,22 @@
antlr4-runtime
4.13.1
-
org.ow2.asm
asm
9.7
-
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.16.0
+
+
+ org.assertj
+ assertj-core
+ 3.26.0
+ test
+
diff --git a/src/main/java/ast/ClassNode.java b/src/main/java/ast/ClassNode.java
index f1f5a4c..26310f8 100644
--- a/src/main/java/ast/ClassNode.java
+++ b/src/main/java/ast/ClassNode.java
@@ -20,6 +20,8 @@ public class ClassNode implements ASTNode, Visitable {
public List members = new ArrayList<>();
public boolean hasConstructor = false;
+ public ClassNode() {}
+
public ClassNode(AccessTypeNode accessType, String identifier){
this.accessType = accessType;
this.identifier = identifier;
diff --git a/src/main/java/ast/expression/ExpressionNode.java b/src/main/java/ast/expression/ExpressionNode.java
index e790795..42be180 100644
--- a/src/main/java/ast/expression/ExpressionNode.java
+++ b/src/main/java/ast/expression/ExpressionNode.java
@@ -1,8 +1,25 @@
package ast.expression;
import ast.ASTNode;
+import ast.statement.AssignmentStatementNode;
+import ast.statement.IfStatementNode;
+import ast.statement.VariableDeclarationStatementNode;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
import visitor.Visitable;
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = BinaryExpressionNode.class, name = "Binary"),
+ @JsonSubTypes.Type(value = This.class, name = "This"),
+ @JsonSubTypes.Type(value = InstVar.class, name = "InstVar"),
+ @JsonSubTypes.Type(value = IdentifierExpressionNode.class, name = "Identifier"),
+ @JsonSubTypes.Type(value = LiteralNode.class, name = "Literal"),
+ @JsonSubTypes.Type(value = UnaryExpressionNode.class, name = "Unary")}
+)
+
public interface ExpressionNode extends ASTNode, Visitable {
}
diff --git a/src/main/java/ast/expression/InstVar.java b/src/main/java/ast/expression/InstVar.java
index 51c7629..6ffbba3 100644
--- a/src/main/java/ast/expression/InstVar.java
+++ b/src/main/java/ast/expression/InstVar.java
@@ -10,6 +10,7 @@ public class InstVar implements ExpressionNode, Visitable {
public ExpressionNode expression;
public TypeNode type;
+ public InstVar(){}
public InstVar(ExpressionNode expression, String identifier) {
this.identifier = identifier;
diff --git a/src/main/java/ast/LiteralNode.java b/src/main/java/ast/expression/LiteralNode.java
similarity index 68%
rename from src/main/java/ast/LiteralNode.java
rename to src/main/java/ast/expression/LiteralNode.java
index 4e7c466..d97f7df 100644
--- a/src/main/java/ast/LiteralNode.java
+++ b/src/main/java/ast/expression/LiteralNode.java
@@ -1,23 +1,25 @@
-package ast;
+package ast.expression;
-import ast.expression.ExpressionNode;
+import ast.type.TypeNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class LiteralNode implements ExpressionNode {
int value;
- private String type;
+ private TypeNode type;
+
+ public LiteralNode(){}
public LiteralNode(int value) {
this.value = value;
}
- public String getType() {
+ public TypeNode getType() {
return type;
}
- public void setType(String type) {
+ public void setType(TypeNode type) {
this.type = type;
}
diff --git a/src/main/java/ast/expression/This.java b/src/main/java/ast/expression/This.java
new file mode 100644
index 0000000..29fc827
--- /dev/null
+++ b/src/main/java/ast/expression/This.java
@@ -0,0 +1,26 @@
+package ast.expression;
+
+import ast.ASTNode;
+import ast.type.ReferenceTypeNode;
+import ast.type.TypeNode;
+import semantic.SemanticVisitor;
+import typechecker.TypeCheckResult;
+
+public class This implements ASTNode, ExpressionNode {
+ private TypeNode type;
+
+ public This(){}
+
+ public This(String className) {
+ type = new ReferenceTypeNode(className);
+ }
+
+ @Override
+ public TypeCheckResult accept(SemanticVisitor visitor) {
+ return visitor.analyze(this);
+ }
+
+ public TypeNode getType() {
+ return type;
+ }
+}
diff --git a/src/main/java/ast/member/FieldNode.java b/src/main/java/ast/member/FieldNode.java
index 60c5411..7273f6b 100644
--- a/src/main/java/ast/member/FieldNode.java
+++ b/src/main/java/ast/member/FieldNode.java
@@ -12,6 +12,8 @@ public class FieldNode implements MemberNode, Visitable {
public TypeNode type;
public String identifier;
+ public FieldNode(){}
+
public FieldNode(AccessTypeNode accessTypeNode, TypeNode type, String name){
this.accessTypeNode = accessTypeNode;
this.type = type;
diff --git a/src/main/java/ast/member/MemberNode.java b/src/main/java/ast/member/MemberNode.java
index f186835..ace0d6d 100644
--- a/src/main/java/ast/member/MemberNode.java
+++ b/src/main/java/ast/member/MemberNode.java
@@ -1,6 +1,18 @@
package ast.member;
import ast.ASTNode;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = MethodNode.class, name = "Method"),
+
+ @JsonSubTypes.Type(value = FieldNode.class, name = "Field") }
+)
public interface MemberNode extends ASTNode {
+
}
diff --git a/src/main/java/ast/member/MethodNode.java b/src/main/java/ast/member/MethodNode.java
index bd67bc4..f3cba60 100644
--- a/src/main/java/ast/member/MethodNode.java
+++ b/src/main/java/ast/member/MethodNode.java
@@ -22,6 +22,8 @@ public class MethodNode implements MemberNode, Visitable {
public List statements = new ArrayList<>();
+ public MethodNode(){}
+
public MethodNode(AccessTypeNode visibility, TypeNode type, String identifier, ParameterListNode parameters,
List statements){
this.visibility = visibility;
diff --git a/src/main/java/ast/parameter/ParameterListNode.java b/src/main/java/ast/parameter/ParameterListNode.java
index ff1c58d..76a39fb 100644
--- a/src/main/java/ast/parameter/ParameterListNode.java
+++ b/src/main/java/ast/parameter/ParameterListNode.java
@@ -8,6 +8,8 @@ import java.util.List;
public class ParameterListNode implements ASTNode {
public List parameters = new ArrayList<>();
+ public ParameterListNode() {}
+
public ParameterListNode(List parameters){
this.parameters = parameters;
}
diff --git a/src/main/java/ast/parameter/ParameterNode.java b/src/main/java/ast/parameter/ParameterNode.java
index f3f5193..176e987 100644
--- a/src/main/java/ast/parameter/ParameterNode.java
+++ b/src/main/java/ast/parameter/ParameterNode.java
@@ -7,6 +7,8 @@ public class ParameterNode implements ASTNode {
public TypeNode type;
public String identifier;
+ public ParameterNode(){}
+
public ParameterNode(TypeNode type, String identifier) {
this.type = type;
this.identifier = identifier;
diff --git a/src/main/java/ast/statement/AssignmentStatementNode.java b/src/main/java/ast/statement/AssignmentStatementNode.java
index d76cc85..abd00a5 100644
--- a/src/main/java/ast/statement/AssignmentStatementNode.java
+++ b/src/main/java/ast/statement/AssignmentStatementNode.java
@@ -10,7 +10,9 @@ import visitor.Visitable;
public class AssignmentStatementNode extends StatementNode implements Visitable {
public ExpressionNode expressionLeft;
public ExpressionNode expressionRight;
- public TypeNode type;
+// public TypeNode type;
+
+ public AssignmentStatementNode(){}
public AssignmentStatementNode(ExpressionNode expressionLeft, ExpressionNode expressionRight) {
this.expressionLeft = expressionLeft;
diff --git a/src/main/java/ast/statement/StatementNode.java b/src/main/java/ast/statement/StatementNode.java
index eff1804..5a96ee5 100644
--- a/src/main/java/ast/statement/StatementNode.java
+++ b/src/main/java/ast/statement/StatementNode.java
@@ -1,8 +1,22 @@
package ast.statement;
import ast.ASTNode;
+import ast.type.BaseTypeNode;
+import ast.type.ReferenceTypeNode;
import visitor.Visitable;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = IfStatementNode.class, name = "IF"),
+ @JsonSubTypes.Type(value = AssignmentStatementNode.class, name = "Assignment"),
+ @JsonSubTypes.Type(value = VariableDeclarationStatementNode.class, name = "VariableDeclaration") }
+)
+
public abstract class StatementNode implements ASTNode, Visitable {
}
diff --git a/src/main/java/ast/statement/VariableDeclarationStatementNode.java b/src/main/java/ast/statement/VariableDeclarationStatementNode.java
index 4302177..9feb086 100644
--- a/src/main/java/ast/statement/VariableDeclarationStatementNode.java
+++ b/src/main/java/ast/statement/VariableDeclarationStatementNode.java
@@ -9,6 +9,9 @@ public class VariableDeclarationStatementNode extends StatementNode {
public TypeNode type;
public String identifier;
public ExpressionNode expression;
+
+ public VariableDeclarationStatementNode(){}
+
public VariableDeclarationStatementNode(TypeNode type, String identifier, ExpressionNode expression) {
this.type = type;
this.identifier = identifier;
diff --git a/src/main/java/ast/type/AccessTypeNode.java b/src/main/java/ast/type/AccessTypeNode.java
index ba156c1..4e0db89 100644
--- a/src/main/java/ast/type/AccessTypeNode.java
+++ b/src/main/java/ast/type/AccessTypeNode.java
@@ -5,6 +5,8 @@ import ast.ASTNode;
public class AccessTypeNode implements ASTNode {
public EnumAccessTypeNode enumAccessTypeNode;
+ public AccessTypeNode(){}
+
public AccessTypeNode(EnumAccessTypeNode enumAccessTypeNode) {
this.enumAccessTypeNode = enumAccessTypeNode;
}
diff --git a/src/main/java/ast/type/BaseTypeNode.java b/src/main/java/ast/type/BaseTypeNode.java
index eb9537c..8a9a4a6 100644
--- a/src/main/java/ast/type/BaseTypeNode.java
+++ b/src/main/java/ast/type/BaseTypeNode.java
@@ -6,6 +6,8 @@ public class BaseTypeNode implements ASTNode, TypeNode {
public EnumTypeNode enumType;
+ public BaseTypeNode(){}
+
public BaseTypeNode(EnumTypeNode enumType) {
this.enumType = enumType;
}
diff --git a/src/main/java/ast/type/ReferenceTypeNode.java b/src/main/java/ast/type/ReferenceTypeNode.java
index 88225f3..91da6bc 100644
--- a/src/main/java/ast/type/ReferenceTypeNode.java
+++ b/src/main/java/ast/type/ReferenceTypeNode.java
@@ -3,4 +3,34 @@ package ast.type;
import ast.ASTNode;
public class ReferenceTypeNode implements ASTNode, TypeNode {
+
+ private String identifier;
+
+ public ReferenceTypeNode() {}
+
+ public ReferenceTypeNode(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;
+ ReferenceTypeNode other = (ReferenceTypeNode) obj;
+ if (identifier == null) {
+ if (other.identifier != null)
+ return false;
+ } else if (!identifier.equals(other.identifier))
+ return false;
+ return true;
+ }
+
}
diff --git a/src/main/java/ast/type/This.java b/src/main/java/ast/type/This.java
deleted file mode 100644
index 4972ac8..0000000
--- a/src/main/java/ast/type/This.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package ast.type;
-
-import ast.ASTNode;
-import ast.expression.ExpressionNode;
-import semantic.SemanticVisitor;
-import typechecker.TypeCheckResult;
-
-public class This implements ASTNode, ExpressionNode {
- @Override
- public TypeCheckResult accept(SemanticVisitor visitor) {
- return null;
- }
-}
diff --git a/src/main/java/ast/type/TypeNode.java b/src/main/java/ast/type/TypeNode.java
index 79be9c9..a855f09 100644
--- a/src/main/java/ast/type/TypeNode.java
+++ b/src/main/java/ast/type/TypeNode.java
@@ -2,5 +2,17 @@ package ast.type;
import ast.ASTNode;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = BaseTypeNode.class, name = "Base"),
+
+ @JsonSubTypes.Type(value = ReferenceTypeNode.class, name = "Reference") }
+)
+
public interface TypeNode extends ASTNode {
}
\ No newline at end of file
diff --git a/src/main/java/parser/ASTBuilder.java b/src/main/java/parser/ASTBuilder.java
index c8dec84..9110f2c 100644
--- a/src/main/java/parser/ASTBuilder.java
+++ b/src/main/java/parser/ASTBuilder.java
@@ -1,11 +1,7 @@
package parser;
import ast.*;
-import ast.expression.BinaryExpressionNode;
-import ast.expression.ExpressionNode;
-import ast.expression.ExpresssionOperator;
-import ast.expression.IdentifierExpressionNode;
-import ast.expression.UnaryExpressionNode;
+import ast.expression.*;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
@@ -210,7 +206,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor {
int intValue = Integer.parseInt(literalContext.getText());
LiteralNode literalNode = new LiteralNode(intValue);
- literalNode.setType("int");
+ literalNode.setType(new BaseTypeNode(EnumTypeNode.INT));
return literalNode;
} catch (NumberFormatException ignored) {}
diff --git a/src/main/java/semantic/SemanticAnalyzer.java b/src/main/java/semantic/SemanticAnalyzer.java
index ab1051b..2d95119 100644
--- a/src/main/java/semantic/SemanticAnalyzer.java
+++ b/src/main/java/semantic/SemanticAnalyzer.java
@@ -10,6 +10,9 @@ import ast.member.MethodNode;
import ast.parameter.ParameterListNode;
import ast.parameter.ParameterNode;
import ast.statement.*;
+import ast.type.ReferenceTypeNode;
+import ast.expression.This;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -17,8 +20,8 @@ import java.util.Objects;
import ast.type.BaseTypeNode;
import ast.type.EnumTypeNode;
-import ast.type.This;
import ast.type.TypeNode;
+import semantic.context.Context;
import semantic.exeptions.AlreadyDeclearedException;
import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException;
@@ -30,6 +33,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
public static ArrayList errors = new ArrayList<>();
+ private Context context;
private static Scope currentScope;
private static ClassNode currentClass;
@@ -60,6 +64,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
var valid = true;
currentScope = new Scope();
+ context = new Context(node);
List classes = node.classes;
for (ClassNode classNode : classes) {
@@ -74,7 +79,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
var valid = true;
currentClass = classNode;
-
+ currentFields.clear();
List members = classNode.members;
for (MemberNode memberNode : members) {
if (memberNode instanceof FieldNode fieldNode) {
@@ -238,23 +243,38 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
public TypeCheckResult analyze(LiteralNode toCheck) {
- return new TypeCheckResult(true, new BaseTypeNode(EnumTypeNode.INT));
+ return new TypeCheckResult(true, toCheck.getType());
}
@Override
public TypeCheckResult analyze(InstVar toCheck) {
boolean valid = true;
- if(toCheck.expression instanceof This){
- if(currentFields.get(toCheck.identifier) == null){
- errors.add(new NotDeclearedException("Not declared " + toCheck.identifier + " in this scope"));
- valid = false;
+ var result = toCheck.expression.accept(this);
+
+ if(result.getType() instanceof BaseTypeNode){
+ throw new RuntimeException("BaseType has no Methods or Fields");
+ } else {
+ //Get typ of Field
+
+ var type = (ReferenceTypeNode)result.getType();
+ var classContext = context.getClass(type.getIdentifier());
+
+ if(classContext == null){
+ errors.add(new NotDeclearedException("Not declared " + type.getIdentifier() + " in this scope"));
+ return new TypeCheckResult(false, null);
} else {
- TypeNode typeNode = currentFields.get(toCheck.identifier);
- return new TypeCheckResult(valid, typeNode);
+ var field = classContext.getField(toCheck.identifier);
+
+ return new TypeCheckResult(valid, field.getType());
}
}
- return new TypeCheckResult(valid, null);
+
+ }
+
+ @Override
+ public TypeCheckResult analyze(This toCheck) {
+ return new TypeCheckResult(true, toCheck.getType());
}
}
\ No newline at end of file
diff --git a/src/main/java/semantic/SemanticVisitor.java b/src/main/java/semantic/SemanticVisitor.java
index fd69518..b66ea75 100644
--- a/src/main/java/semantic/SemanticVisitor.java
+++ b/src/main/java/semantic/SemanticVisitor.java
@@ -2,7 +2,7 @@ package semantic;
import ast.ClassNode;
-import ast.LiteralNode;
+import ast.expression.LiteralNode;
import ast.ProgramNode;
import ast.expression.BinaryExpressionNode;
import ast.expression.IdentifierExpressionNode;
@@ -11,6 +11,7 @@ import ast.expression.UnaryExpressionNode;
import ast.member.FieldNode;
import ast.member.MethodNode;
import ast.statement.*;
+import ast.expression.This;
import typechecker.TypeCheckResult;
public interface SemanticVisitor {
@@ -42,4 +43,6 @@ public interface SemanticVisitor {
TypeCheckResult analyze(LiteralNode toCheck);
TypeCheckResult analyze(InstVar toCheck);
+
+ TypeCheckResult analyze(This toCheck);
}
\ No newline at end of file
diff --git a/src/main/java/semantic/context/ClassContext.java b/src/main/java/semantic/context/ClassContext.java
new file mode 100644
index 0000000..982866f
--- /dev/null
+++ b/src/main/java/semantic/context/ClassContext.java
@@ -0,0 +1,27 @@
+package semantic.context;
+
+import ast.ClassNode;
+import ast.member.FieldNode;
+import java.util.HashMap;
+
+public class ClassContext {
+
+ private HashMap fields;
+
+ public ClassContext(ClassNode classNode) {
+
+ fields = new HashMap<>();
+
+ classNode.members.forEach(member -> {
+ if(member instanceof FieldNode fieldNode) {
+ fields.put(fieldNode.identifier, new FieldContext(fieldNode));
+ }
+ });
+
+ }
+
+ public FieldContext getField(String name) {
+ return fields.get(name);
+ }
+
+}
diff --git a/src/main/java/semantic/context/Context.java b/src/main/java/semantic/context/Context.java
new file mode 100644
index 0000000..7006e65
--- /dev/null
+++ b/src/main/java/semantic/context/Context.java
@@ -0,0 +1,25 @@
+package semantic.context;
+
+import ast.ClassNode;
+import ast.ProgramNode;
+import java.util.HashMap;
+
+public class Context {
+
+ private HashMap classes;
+
+ public Context(ProgramNode programNode) {
+ classes = new HashMap<>();
+
+ programNode.classes.forEach(classNode -> {
+ ClassContext classContext = new ClassContext(classNode);
+ classes.put(classNode.identifier, classContext);
+ });
+
+ }
+
+ public ClassContext getClass(String identifier) {
+ return classes.get(identifier);
+ }
+
+}
diff --git a/src/main/java/semantic/context/FieldContext.java b/src/main/java/semantic/context/FieldContext.java
new file mode 100644
index 0000000..447aa4e
--- /dev/null
+++ b/src/main/java/semantic/context/FieldContext.java
@@ -0,0 +1,22 @@
+package semantic.context;
+
+import ast.member.FieldNode;
+import ast.type.AccessTypeNode;
+import ast.type.EnumAccessTypeNode;
+import ast.type.TypeNode;
+
+public class FieldContext {
+
+ private AccessTypeNode accessModifier;
+ private TypeNode type;
+
+ public FieldContext(FieldNode field) {
+ accessModifier = field.accessTypeNode;
+ type = field.type;
+ }
+
+ public TypeNode getType() {
+ return type;
+ }
+
+}
diff --git a/src/test/java/semantic/Mocker.java b/src/test/java/semantic/Mocker.java
index 433d0ab..4c303d8 100644
--- a/src/test/java/semantic/Mocker.java
+++ b/src/test/java/semantic/Mocker.java
@@ -1,7 +1,7 @@
package semantic;
import ast.ClassNode;
-import ast.LiteralNode;
+import ast.expression.LiteralNode;
import ast.ProgramNode;
import ast.expression.*;
import ast.member.FieldNode;
@@ -39,16 +39,14 @@ public class Mocker {
List statementNodeList = new ArrayList();
- ExpressionNode expressionNodeLeft = new InstVar(new This(), "objectVar");
+ ExpressionNode expressionNodeLeft = new InstVar(new This("testClass"), "objectVar");
- ExpressionNode expressionNodeRight = new LiteralNode(1);
+ LiteralNode expressionNodeRight = new LiteralNode();
+ expressionNodeRight.setType(new BaseTypeNode(EnumTypeNode.INT));
StatementNode statementNode1 = new AssignmentStatementNode(expressionNodeLeft, expressionNodeRight);
statementNodeList.add(statementNode1);
- StatementNode statementNode2 = new VariableDeclarationStatementNode(new BaseTypeNode(EnumTypeNode.CHAR), "objectVar", new LiteralNode(1));
- statementNodeList.add(statementNode2);
-
MemberNode memberNode3 = new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2",parameterListNode, statementNodeList );
classNode.members.add(memberNode3);
@@ -76,5 +74,4 @@ public class Mocker {
return programNode;
}
-
}
diff --git a/src/test/java/semantic/SemanticTest.java b/src/test/java/semantic/SemanticTest.java
index c5990de..71604ee 100644
--- a/src/test/java/semantic/SemanticTest.java
+++ b/src/test/java/semantic/SemanticTest.java
@@ -2,20 +2,19 @@ package semantic;
import ast.*;
-import ast.member.FieldNode;
-import ast.member.MemberNode;
-import ast.type.AccessTypeNode;
-import ast.type.BaseTypeNode;
-import ast.type.EnumAccessTypeNode;
-import ast.type.EnumTypeNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.assertj.core.api.MatcherAssert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import semantic.exeptions.AlreadyDeclearedException;
+import semantic.exeptions.TypeMismatchException;
-import java.util.ArrayList;
-import java.util.List;
+import java.io.File;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class SemanticTest {
@@ -25,7 +24,7 @@ public class SemanticTest {
}
@Test
- public void alreadyDeclaredLocalFieldVar(){
+ public void alreadyDeclaredLocalFieldVar() {
//Arrange
@@ -44,7 +43,7 @@ public class SemanticTest {
}
@Test
- public void typeMismatch(){
+ public void alreadyDecleared() {
//Arrange
@@ -57,13 +56,13 @@ public class SemanticTest {
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
- assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException);
- assertEquals(null, typedAst);
+ assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
+ assertNull(typedAst);
}
@Test
- public void shouldWorkWithNoError(){
+ public void shouldWorkWithNoError() {
//Arrange
@@ -80,4 +79,85 @@ public class SemanticTest {
}
+ @Test
+ public void refTypeCorrect() {
+
+ //Arrange
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ ProgramNode programNode = null;
+ try{
+ programNode = objectMapper.readValue(new File("src/test/resources/semantic/correctRefType.json"), ProgramNode.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ //Act
+
+ ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
+
+ //Assert
+
+ assertEquals(0, SemanticAnalyzer.errors.size());
+ assertEquals(programNode, typedAst);
+
+ }
+
+ @Test
+ public void jsonWriteTest() {
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ //Arrange
+
+ ProgramNode programNode = Mocker.mockCorrectProgrammNode();
+ try{
+ objectMapper.writeValue(new File("src/test/resources/semantic/test.json"), programNode);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ @Test
+ public void jsonReadTest() {
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ ProgramNode programNode1 = null;
+ try{
+ programNode1 = objectMapper.readValue(new File("src/test/resources/semantic/test.json"), ProgramNode.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ ProgramNode programNode2 = Mocker.mockCorrectProgrammNode();
+
+ }
+
+ @Test
+ public void typeMismatch() {
+
+ //Arrange
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ ProgramNode programNode = null;
+ try{
+ programNode = objectMapper.readValue(new File("src/test/resources/semantic/refTypeMismatch.json"), ProgramNode.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ //Act
+
+ ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
+
+ //Assert
+
+ assertEquals(1, SemanticAnalyzer.errors.size());
+ assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
+ assertNull(typedAst);
+
+ }
+
}
diff --git a/src/test/resources/semantic/correctRefType.json b/src/test/resources/semantic/correctRefType.json
new file mode 100644
index 0000000..7e67bbc
--- /dev/null
+++ b/src/test/resources/semantic/correctRefType.json
@@ -0,0 +1,70 @@
+{
+ "classes": [
+ {
+ "identifier": "testClass1",
+ "accessType": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "members": [
+ {
+ "@type": "Field",
+ "accessTypeNode": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "testVar1"
+ },
+ {
+ "@type": "Method",
+ "visibility": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "testMethod",
+ "parameters": {
+ "parameters": [
+ {
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "param1"
+ }
+ ]
+ },
+ "statements": [
+ {
+ "@type": "Assignment",
+ "expressionLeft": {
+ "@type": "InstVar",
+ "identifier": "testVar1",
+ "expression": {
+ "@type": "This",
+ "type": {
+ "@type": "Reference",
+ "identifier": "testClass1"
+ }
+ },
+ "type": null
+ },
+ "expressionRight": {
+ "@type": "Literal",
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "hasConstructor": false
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/test/resources/semantic/refTypeMismatch.json b/src/test/resources/semantic/refTypeMismatch.json
new file mode 100644
index 0000000..e5ebcd3
--- /dev/null
+++ b/src/test/resources/semantic/refTypeMismatch.json
@@ -0,0 +1,133 @@
+{
+ "classes": [
+ {
+ "identifier": "testClass1",
+ "accessType": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "members": [
+ {
+ "@type": "Field",
+ "accessTypeNode": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "testVar1"
+ },
+ {
+ "@type": "Method",
+ "visibility": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "testMethod",
+ "parameters": {
+ "parameters": [
+ {
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "param1"
+ }
+ ]
+ },
+ "statements": [
+ {
+ "@type": "Assignment",
+ "expressionLeft": {
+ "@type": "InstVar",
+ "identifier": "testVar1",
+ "expression": {
+ "@type": "This",
+ "type": {
+ "@type": "Reference",
+ "identifier": "testClass1"
+ }
+ },
+ "type": null
+ },
+ "expressionRight": {
+ "@type": "Literal",
+ "type": {
+ "@type": "Base",
+ "enumType": "BOOLEAN"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "hasConstructor": false,
+ "methods": [
+ {
+ "@type": "Method",
+ "visibility": {
+ "enumAccessTypeNode": "PUBLIC"
+ },
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "testMethod",
+ "parameters": {
+ "parameters": [
+ {
+ "type": {
+ "@type": "Base",
+ "enumType": "INT"
+ },
+ "identifier": "param1"
+ }
+ ]
+ },
+ "statements": [
+ {
+ "@type": "Assignment",
+ "expressionLeft": {
+ "@type": "InstVar",
+ "identifier": "testVar",
+ "expression": {
+ "@type": "InstVar",
+ "identifier": "testVar",
+ "expression": {
+ "@type": "This",
+ "type": {
+ "@type": "Reference",
+ "identifier": "testClass2"
+ }
+ },
+ "type": null
+ },
+ "type": null
+ },
+ "expressionRight": {
+ "@type": "Literal",
+ "type": null
+ },
+ "type": null
+ },
+ {
+ "@type": "VariableDeclaration",
+ "type": {
+ "@type": "Base",
+ "enumType": "CHAR"
+ },
+ "identifier": "objectVar",
+ "expression": {
+ "@type": "Literal",
+ "type": null
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/test/resources/semantic/test.json b/src/test/resources/semantic/test.json
new file mode 100644
index 0000000..7acc30f
--- /dev/null
+++ b/src/test/resources/semantic/test.json
@@ -0,0 +1 @@
+{"classes":[{"identifier":"testClass","accessType":{"enumAccessTypeNode":"PUBLIC"},"members":[{"@type":"Field","accessTypeNode":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"testVar1"},{"@type":"Field","accessTypeNode":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"objectVar"},{"@type":"Method","visibility":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"testVar2","parameters":{"parameters":[{"type":{"@type":"Base","enumType":"INT"},"identifier":"param1"}]},"statements":[{"@type":"Assignment","expressionLeft":{"@type":"InstVar","identifier":"objectVar","expression":{"@type":"This","type":{"@type":"Reference","identifier":"testClass"}},"type":null},"expressionRight":{"@type":"Literal","type":{"@type":"Base","enumType":"INT"}}}]}],"hasConstructor":false,"methods":[{"@type":"Method","visibility":{"enumAccessTypeNode":"PUBLIC"},"type":{"@type":"Base","enumType":"INT"},"identifier":"testVar2","parameters":{"parameters":[{"type":{"@type":"Base","enumType":"INT"},"identifier":"param1"}]},"statements":[{"@type":"Assignment","expressionLeft":{"@type":"InstVar","identifier":"objectVar","expression":{"@type":"This","type":{"@type":"Reference","identifier":"testClass"}},"type":null},"expressionRight":{"@type":"Literal","type":{"@type":"Base","enumType":"INT"}}}]}]}]}
\ No newline at end of file