Compare commits
4 Commits
d2f8ea1e78
...
1d5bfdd88f
Author | SHA1 | Date | |
---|---|---|---|
1d5bfdd88f | |||
|
149caf5202 | ||
b03ea72eca | |||
|
c5bb038fc3 |
@ -1,13 +0,0 @@
|
|||||||
public class Example {
|
|
||||||
|
|
||||||
public int testVar;
|
|
||||||
|
|
||||||
public static int testMethod(char b){
|
|
||||||
|
|
||||||
int a;
|
|
||||||
int a;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -16,16 +16,20 @@ import java.nio.file.Paths;
|
|||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
if(args.length > 0) {
|
||||||
|
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/java/CompilerInput.txt"));
|
CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/CompilerInput.java"));
|
||||||
parseFile(codeCharStream);
|
parseFile(codeCharStream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Error reading the file: " + e.getMessage());
|
System.err.println("Error reading the file: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void parseFile(CharStream codeCharStream){
|
static void parseFile(CharStream codeCharStream) {
|
||||||
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
SimpleJavaParser parser = new SimpleJavaParser(tokens);
|
SimpleJavaParser parser = new SimpleJavaParser(tokens);
|
||||||
@ -38,6 +42,8 @@ public class Main {
|
|||||||
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(ast);
|
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(ast);
|
||||||
|
|
||||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
|
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
|
||||||
|
if (typedAst != null)
|
||||||
byteCodeGenerator.visit(typedAst);
|
byteCodeGenerator.visit(typedAst);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package ast;
|
|||||||
|
|
||||||
import ast.member.ConstructorNode;
|
import ast.member.ConstructorNode;
|
||||||
import ast.member.MemberNode;
|
import ast.member.MemberNode;
|
||||||
|
import ast.member.MethodNode;
|
||||||
import ast.type.AccessTypeNode;
|
import ast.type.AccessTypeNode;
|
||||||
import ast.type.EnumAccessTypeNode;
|
import ast.type.EnumAccessTypeNode;
|
||||||
|
|
||||||
@ -38,6 +39,16 @@ public class ClassNode implements ASTNode, Visitable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<MethodNode> getMethods(){
|
||||||
|
List<MethodNode> methods = new ArrayList<>();
|
||||||
|
for (MemberNode member : members) {
|
||||||
|
if (member instanceof MethodNode methodNode) {
|
||||||
|
methods.add(methodNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
|
@ -36,6 +36,22 @@ public class MethodNode implements MemberNode, Visitable {
|
|||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSame(MethodNode methodNode){
|
||||||
|
boolean isSame = false;
|
||||||
|
if(methodNode.identifier.equals(identifier)){
|
||||||
|
if(parameters != null && methodNode.parameters != null){
|
||||||
|
if(parameters.parameters.size() == methodNode.parameters.parameters.size()){
|
||||||
|
for(int i = 0; i < parameters.parameters.size(); i++){
|
||||||
|
if(parameters.parameters.get(i).identifier.equals(methodNode.parameters.parameters.get(i).identifier)){
|
||||||
|
isSame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isSame;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
|
Binary file not shown.
@ -54,7 +54,11 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
|||||||
AccessTypeNode accessType = (AccessTypeNode) visit(ctx.accessType());
|
AccessTypeNode accessType = (AccessTypeNode) visit(ctx.accessType());
|
||||||
TypeNode returnType = (TypeNode) visit(ctx.type());
|
TypeNode returnType = (TypeNode) visit(ctx.type());
|
||||||
String methodName = ctx.IDENTIFIER().getText();
|
String methodName = ctx.IDENTIFIER().getText();
|
||||||
ParameterListNode parameterListNode = (ParameterListNode) visit(ctx.parameterList());
|
|
||||||
|
ParameterListNode parameterListNode = null;
|
||||||
|
if(ctx.parameterList() != null) {
|
||||||
|
parameterListNode = (ParameterListNode) visit(ctx.parameterList());
|
||||||
|
}
|
||||||
List<StatementNode> statements = new ArrayList<>();
|
List<StatementNode> statements = new ArrayList<>();
|
||||||
for (SimpleJavaParser.StatementContext stmtCtx : ctx.statement()) {
|
for (SimpleJavaParser.StatementContext stmtCtx : ctx.statement()) {
|
||||||
statements.add((StatementNode) visit(stmtCtx));
|
statements.add((StatementNode) visit(stmtCtx));
|
||||||
|
@ -9,6 +9,10 @@ public class Scope {
|
|||||||
|
|
||||||
private Stack<HashMap<String, TypeNode>> localVars;
|
private Stack<HashMap<String, TypeNode>> localVars;
|
||||||
|
|
||||||
|
public Scope() {
|
||||||
|
localVars = new Stack<HashMap<String, TypeNode>>();
|
||||||
|
}
|
||||||
|
|
||||||
public void addLocalVar(String name, TypeNode type) {
|
public void addLocalVar(String name, TypeNode type) {
|
||||||
if (this.contains(name)) {
|
if (this.contains(name)) {
|
||||||
throw new RuntimeException("Variable " + name + " already exists in this scope");
|
throw new RuntimeException("Variable " + name + " already exists in this scope");
|
||||||
|
@ -5,39 +5,51 @@ import ast.*;
|
|||||||
import ast.expression.BinaryExpressionNode;
|
import ast.expression.BinaryExpressionNode;
|
||||||
import ast.expression.IdentifierExpressionNode;
|
import ast.expression.IdentifierExpressionNode;
|
||||||
import ast.expression.UnaryExpressionNode;
|
import ast.expression.UnaryExpressionNode;
|
||||||
|
import ast.member.ConstructorNode;
|
||||||
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.parameter.ParameterListNode;
|
||||||
|
import ast.parameter.ParameterNode;
|
||||||
import ast.statement.*;
|
import ast.statement.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import semantic.exeptions.AlreadyDeclearedException;
|
||||||
import typechecker.TypeCheckResult;
|
import typechecker.TypeCheckResult;
|
||||||
|
|
||||||
public class SemanticAnalyzer implements SemanticVisitor {
|
public class SemanticAnalyzer implements SemanticVisitor {
|
||||||
|
|
||||||
private ArrayList<String> currentFields = new ArrayList<>();
|
private ArrayList<String> currentFields = new ArrayList<>();
|
||||||
|
|
||||||
private Scope currentScope;
|
public static ArrayList<Exception> errors = new ArrayList<>();
|
||||||
|
|
||||||
public static ASTNode generateTast(ASTNode node) throws RuntimeException {
|
private Scope currentScope;
|
||||||
|
private ClassNode currentClass;
|
||||||
|
|
||||||
|
public static ASTNode generateTast(ASTNode node) {
|
||||||
SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
|
SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
|
||||||
ProgramNode programNode = (ProgramNode) node;
|
ProgramNode programNode = (ProgramNode) node;
|
||||||
var result = programNode.accept(semanticCheck);
|
var result = programNode.accept(semanticCheck);
|
||||||
if (result.isValid()) {
|
if (result.isValid()) {
|
||||||
return node;
|
return node;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Not Valid");
|
for (Exception e : errors) {
|
||||||
|
e.printStackTrace(System.out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(ProgramNode node) {
|
public TypeCheckResult analyze(ProgramNode node) {
|
||||||
|
|
||||||
var valid = true;
|
var valid = true;
|
||||||
|
|
||||||
|
currentScope = new Scope();
|
||||||
|
|
||||||
List<ClassNode> classes = node.classes;
|
List<ClassNode> classes = node.classes;
|
||||||
for (ClassNode classNode : classes) {
|
for (ClassNode classNode : classes) {
|
||||||
var result = classNode.accept(this);
|
var result = classNode.accept(this);
|
||||||
@ -49,12 +61,25 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(ClassNode classNode) {
|
public TypeCheckResult analyze(ClassNode classNode) {
|
||||||
var valid = true;
|
var valid = true;
|
||||||
|
|
||||||
|
currentClass = classNode;
|
||||||
|
|
||||||
List<MemberNode> members = classNode.members;
|
List<MemberNode> members = classNode.members;
|
||||||
for (MemberNode memberNode : members) {
|
for (MemberNode memberNode : members) {
|
||||||
if (memberNode instanceof FieldNode fieldNode) {
|
if (memberNode instanceof FieldNode fieldNode) {
|
||||||
|
//LocalFields
|
||||||
var result = fieldNode.accept(this);
|
var result = fieldNode.accept(this);
|
||||||
valid = valid && result.isValid();
|
valid = valid && result.isValid();
|
||||||
} else if (memberNode instanceof MethodNode methodNode) {
|
} else if (memberNode instanceof MethodNode methodNode) {
|
||||||
|
//Methods
|
||||||
|
for(MethodNode methode : currentClass.getMethods()){
|
||||||
|
if(methode.equals(methodNode))
|
||||||
|
break;
|
||||||
|
if(methode.isSame(methodNode)){
|
||||||
|
errors.add(new AlreadyDeclearedException("This method has already been declared"));
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
var result = methodNode.accept(this);
|
var result = methodNode.accept(this);
|
||||||
valid = valid && result.isValid();
|
valid = valid && result.isValid();
|
||||||
}
|
}
|
||||||
@ -68,8 +93,23 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
public TypeCheckResult analyze(MethodNode methodNode) {
|
public TypeCheckResult analyze(MethodNode methodNode) {
|
||||||
var valid = true;
|
var valid = true;
|
||||||
|
|
||||||
currentLocalScope.pushScope();
|
currentScope.pushScope();
|
||||||
|
|
||||||
|
//Parameter
|
||||||
|
ParameterListNode parameterListNode = methodNode.parameters;
|
||||||
|
if (parameterListNode != null) {
|
||||||
|
List<ParameterNode> parameters = parameterListNode.parameters;
|
||||||
|
for (ParameterNode parameter : parameters) {
|
||||||
|
if (currentScope.contains(parameter.identifier)) {
|
||||||
|
errors.add(new AlreadyDeclearedException("Duplicated Parameter " + parameter.identifier));
|
||||||
|
return new TypeCheckResult(false, null);
|
||||||
|
} else {
|
||||||
|
currentScope.addLocalVar(parameter.identifier, parameter.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Statements
|
||||||
List<StatementNode> statements = methodNode.statements;
|
List<StatementNode> statements = methodNode.statements;
|
||||||
for (StatementNode statement : statements) {
|
for (StatementNode statement : statements) {
|
||||||
if (statement instanceof AssignmentStatementNode assignmentStatementNode) {
|
if (statement instanceof AssignmentStatementNode assignmentStatementNode) {
|
||||||
@ -80,13 +120,16 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
valid = valid && result.isValid();
|
valid = valid && result.isValid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentScope.popScope();
|
||||||
return new TypeCheckResult(valid, null);
|
return new TypeCheckResult(valid, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(FieldNode toCheck) {
|
public TypeCheckResult analyze(FieldNode toCheck) {
|
||||||
if (currentFields.contains(toCheck.identifier)) {
|
if (currentFields.contains(toCheck.identifier)) {
|
||||||
throw new RuntimeException(toCheck.identifier + " Is Already Declared");
|
errors.add(new AlreadyDeclearedException("Already declared " + toCheck.identifier));
|
||||||
|
return new TypeCheckResult(false, null);
|
||||||
} else {
|
} else {
|
||||||
currentFields.add(toCheck.identifier);
|
currentFields.add(toCheck.identifier);
|
||||||
}
|
}
|
||||||
@ -124,7 +167,12 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(VariableDeclarationStatementNode toCheck) {
|
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);
|
return new TypeCheckResult(true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package semantic.exeptions;
|
||||||
|
|
||||||
|
public class AlreadyDeclearedException extends RuntimeException {
|
||||||
|
|
||||||
|
public AlreadyDeclearedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/main/resources/CompilerInput.java
Normal file
10
src/main/resources/CompilerInput.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
public class Example {
|
||||||
|
|
||||||
|
public int a;
|
||||||
|
|
||||||
|
public static int testMethod(char x, int a){
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user