Compare commits

..

4 Commits

Author SHA1 Message Date
1d5bfdd88f Merge pull request 'johns-branch' (#7) from johns-branch into main
Reviewed-on: #7
Reviewed-by: i22007 <i22007@hb.dhbw-stuttgart.de>
2024-05-14 13:35:21 +00:00
Bruder John
149caf5202 Merge branch 'main' into johns-branch 2024-05-14 15:35:03 +02:00
b03ea72eca Merge pull request 'code-generator' (#8) from code-generator into main
Reviewed-on: #8
Reviewed-by: Johannes Ehlert <i22005@hb.dhbw-stuttgart.de>
2024-05-14 13:34:51 +00:00
Bruder John
c5bb038fc3 added same Method Declaration 2024-05-14 15:31:02 +02:00
10 changed files with 122 additions and 27 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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