Merge branch 'main' into code-generator
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled

This commit is contained in:
i22007 2024-06-21 19:25:35 -04:00
commit fb3f822160
115 changed files with 2176 additions and 897 deletions

8
.gitignore vendored
View File

@ -76,4 +76,10 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
/target
/target
src/main/resources/logs/RaupenLog.log
src/main/resources/output/CompilerInput.class
src/test/resources/output/javac/CompilerInput$Test.class
src/test/resources/output/javac/CompilerInput.class
src/test/resources/output/raupenpiler/CompilerInput.class
src/test/resources/output/raupenpiler/CompilerInput$Test.class

32
pom.xml
View File

@ -4,13 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<groupId>de.dhbw-stuttgart</groupId>
<artifactId>JavaCompiler</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.0</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<java.version>22</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@ -53,7 +54,28 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version> <!-- Change the version as needed -->
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>main.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,132 +0,0 @@
import oldAst.ASTNode;
import org.antlr.v4.runtime.*;
import oldAst.ProgramNode;
import bytecode.ByteCodeGenerator;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.CommonTokenStream;
import parser.astBuilder.ASTBuilder;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
import semantic.SemanticAnalyzer;
import java.io.IOException;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) throws Exception {
if(args.length > 0) {
} else {
try {
CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/CompilerInput.java"));
parseFile(codeCharStream);
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}
}
}
static void parseFile(CharStream codeCharStream) {
/* ------------------------- Scanner -> tokens ------------------------- */
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
// Printing the tokens
// tokenStream.fill();
// List<Token> tokens = tokenStream.getTokens();
// System.out.println("-------------------- Scanner -> tokens --------------------");
// for (Token token : tokens) {
// String tokenType = SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType());
// String tokenText = token.getText();
// // System.out.println("Token Type: " + tokenType + ", Token Text: " +
// // tokenText);
// System.out.println(tokenType + " " + tokenText);
// }
// System.out.println();
/* ------------------------- Parser -> Parsetree ------------------------- */
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program(); // parse the input
// Printing the parse tree
// System.out.println("-------------------- Parser -> Parsetree --------------------");
// System.out.println(parseTree.toStringTree(parser));
// printTree(parseTree, parser, 0);
// System.out.println();
/* ------------------------- AST builder -> AST ------------------------- */
ASTBuilder astBuilder = new ASTBuilder();
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
// Printing the AST
// System.out.println("-------------------- AST builder -> AST --------------------");
// // System.out.println("AST: " + ast.toString());
// printAST(abstractSyntaxTree, 0);
// System.out.println();
/*
* ------------------------- Semantic Analyzer -> Tast -------------------------
*/
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
ProgramNode typedAst = (ProgramNode) semanticAnalyzer.generateTast(abstractSyntaxTree);
// Printing the Tast
System.out.println("Tast generated");
/*
* ------------------------- Bytecode Generator -> Bytecode
* -------------------------
*/
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
//byteCodeGenerator.generateByteCode(abstractSyntaxTree);
byteCodeGenerator.visit(typedAst);
System.out.println("Bytecode generated");
}
/**
* This method is used to print the parse tree in a structured format.
* It recursively traverses the tree and prints the rule names and text of the
* nodes.
*
* @param tree The parse tree to be printed.
* @param parser The parser used to parse the input. It's used to get the rule
* names.
* @param indent The current indentation level. It's used to format the output.
*/
public static void printTree(ParseTree tree, Parser parser, int indent) {
// Create an indentation string based on the current indentation level
String indentString = " ".repeat(indent * 2);
// If the tree node is an instance of RuleContext (i.e., it's an internal node),
// print the rule name
if (tree instanceof RuleContext) {
int ruleIndex = ((RuleContext) tree).getRuleIndex();
String ruleName = parser.getRuleNames()[ruleIndex];
System.out.println(indentString + ruleName);
} else {
// If the tree node is not an instance of RuleContext (i.e., it's a leaf node),
// print the text of the node
System.out.println(indentString + tree.getText());
}
// Recursively print the children of the current node, increasing the
// indentation level
for (int i = 0; i < tree.getChildCount(); i++) {
printTree(tree.getChild(i), parser, indent + 1);
}
}
public static void printAST(ASTNode node, int indent) {
String indentString = " ".repeat(indent * 2);
System.out.println(indentString + node.getClass().toString());
// for (ASTNode child : node.) {
// printAST(child, indent + 1);
// }
}
}

View File

@ -1,8 +1,6 @@
package ast;
import ast.type.AccessModifierNode;
import ast.type.EnumAccessModifierNode;
import bytecode.visitor.ClassVisitor;
import ast.member.ConstructorNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
@ -56,8 +54,4 @@ public class ClassNode implements ASTNode, Visitable {
return visitor.analyze(this);
}
@Override
public void accept(ClassVisitor classVisitor) {
classVisitor.visit(this);
}
}

View File

@ -1,4 +0,0 @@
package ast;
public class IdentifierNode {
}

View File

@ -1,6 +1,5 @@
package ast;
import bytecode.visitor.ProgramVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
@ -19,9 +18,4 @@ public class ProgramNode implements ASTNode, Visitable {
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public void accept(ProgramVisitor programVisitor) {
programVisitor.visit(this);
}
}

View File

@ -1,17 +1,29 @@
package ast.block;
import ast.ASTNode;
import ast.statement.StatementNode;
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.List;
public class BlockNode implements ASTNode {
public List<StatementNode> statements = new ArrayList<>();
public class BlockNode implements ASTNode, Visitable {
public List<IStatementNode> statements = new ArrayList<>();
public Boolean hasReturnStatement = false;
public BlockNode() {}
public void addStatement(StatementNode statement) {
public void addStatement(IStatementNode statement) {
statements.add(statement);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,6 +0,0 @@
package ast.expression;
import visitor.Visitable;
public abstract class ExpressionNode implements Visitable {
}

View File

@ -0,0 +1,11 @@
package ast.expression;
import ast.ASTNode;
import ast.type.type.ITypeNode;
import visitor.Visitable;
public interface IExpressionNode extends ASTNode, Visitable {
ITypeNode getType();
}

View File

@ -1,4 +0,0 @@
package ast.expression.binaryexpression;
public class BinaryExpression {
}

View File

@ -0,0 +1,19 @@
package ast.expression.binaryexpression;
import ast.expression.IExpressionNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class BinaryExpressionNode implements IExpressionNode {
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -1,19 +1,40 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class CalculationExpressionNode implements ASTNode {
CalculationExpressionNode calculationExpression;
String operator;
DotExpressionNode dotExpression;
public class CalculationExpressionNode extends BinaryExpressionNode {
public CalculationExpressionNode calculationExpression;
public EnumLineOperator operator;
public DotExpressionNode dotExpression;
public CalculationExpressionNode(CalculationExpressionNode calculationExpression, String operator, DotExpressionNode dotExpression) {
this.calculationExpression = calculationExpression;
this.operator = operator;
setOperator(operator);
this.dotExpression = dotExpression;
}
public CalculationExpressionNode(DotExpressionNode dotExpression) {
this.dotExpression = dotExpression;
}
private void setOperator(String operator) {
if(operator.equals("+")) {
this.operator = EnumLineOperator.PLUS;
} else if(operator.equals("-")) {
this.operator = EnumLineOperator.MINUS;
}
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -1,19 +1,42 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DotExpressionNode implements ASTNode {
DotExpressionNode dotExpression;
String operator;
DotSubstractionExpressionNode dotSubstractionExpression;
public class DotExpressionNode extends BinaryExpressionNode {
public DotExpressionNode dotExpression;
public EnumDotOperator operator;
public DotSubstractionExpressionNode dotSubstractionExpression;
public DotExpressionNode(DotExpressionNode dotExpression, String operator, DotSubstractionExpressionNode dotSubstractionExpression) {
this.dotExpression = dotExpression;
this.operator = operator;
setOperator(operator);
this.dotSubstractionExpression = dotSubstractionExpression;
}
public DotExpressionNode(DotSubstractionExpressionNode dotSubstractionExpression) {
this.dotSubstractionExpression = dotSubstractionExpression;
}
private void setOperator(String operator) {
if(operator.equals("*")) {
this.operator = EnumDotOperator.MULT;
} else if(operator.equals("/")) {
this.operator = EnumDotOperator.DIV;
} else if(operator.equals("%")) {
this.operator = EnumDotOperator.MOD;
}
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -1,16 +1,18 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.expression.unaryexpression.MemberAccessNode;
import ast.statement.statementexpression.methodcallstatementnexpression.MethodCallStatementExpressionNode;
import ast.type.type.*;
import ast.type.ValueNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DotSubstractionExpressionNode implements ASTNode {
ValueNode value;
String identifier;
MemberAccessNode memberAccess;
MethodCallStatementExpressionNode methodCall;
CalculationExpressionNode calculationExpression;
public class DotSubstractionExpressionNode extends BinaryExpressionNode {
public ValueNode value;
public String identifier;
public MemberAccessNode memberAccess;
public MethodCallStatementExpressionNode methodCall;
public CalculationExpressionNode calculationExpression;
public DotSubstractionExpressionNode(ValueNode value) {
this.value = value;
@ -28,4 +30,15 @@ public class DotSubstractionExpressionNode implements ASTNode {
this.methodCall = methodCall;
this.calculationExpression = calculationExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -0,0 +1,5 @@
package ast.expression.binaryexpression;
public enum EnumDotOperator {
MULT, DIV, MOD
}

View File

@ -0,0 +1,5 @@
package ast.expression.binaryexpression;
public enum EnumLineOperator {
PLUS, MINUS
}

View File

@ -0,0 +1,5 @@
package ast.expression.binaryexpression;
public enum EnumNonCalculationOperator {
AND, OR, GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL
}

View File

@ -1,17 +1,50 @@
package ast.expression.binaryexpression;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class NonCalculationExpressionNode implements ASTNode {
UnaryExpressionNode unaryExpression;
String operator;
ExpressionNode expression;
public class NonCalculationExpressionNode extends BinaryExpressionNode {
public UnaryExpressionNode unaryExpression;
public EnumNonCalculationOperator operator;
public IExpressionNode expression;
public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, ExpressionNode expression) {
public NonCalculationExpressionNode(UnaryExpressionNode unaryExpression, String operator, IExpressionNode expression) {
this.unaryExpression = unaryExpression;
this.operator = operator;
setOperator(operator);
this.expression = expression;
}
private void setOperator(String operator) {
if(operator.equals("&&")) {
this.operator = EnumNonCalculationOperator.AND;
} else if(operator.equals("||")) {
this.operator = EnumNonCalculationOperator.OR;
} else if(operator.equals(">")) {
this.operator = EnumNonCalculationOperator.GREATER;
} else if(operator.equals("<")) {
this.operator = EnumNonCalculationOperator.LESS;
} else if(operator.equals(">=")) {
this.operator = EnumNonCalculationOperator.GREATER_EQUAL;
} else if(operator.equals("<=")) {
this.operator = EnumNonCalculationOperator.LESS_EQUAL;
} else if(operator.equals("==")) {
this.operator = EnumNonCalculationOperator.EQUAL;
} else if(operator.equals("!=")) {
this.operator = EnumNonCalculationOperator.NOT_EQUAL;
}
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return null;
}
}

View File

@ -16,4 +16,5 @@ public class MemberAccessNode implements ASTNode {
public void addIdentifier(String identifier) {
identifiers.add(identifier);
}
}

View File

@ -1,12 +1,13 @@
package ast.expression.unaryexpression;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
public class NotExpressionNode implements ASTNode {
ExpressionNode expression;
public IExpressionNode expression;
public NotExpressionNode(ExpressionNode expression) {
public NotExpressionNode(IExpressionNode expression) {
this.expression = expression;
}
}

View File

@ -1,20 +1,23 @@
package ast.expression.unaryexpression;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.statement.StatementNode;
import ast.expression.IExpressionNode;
import ast.statement.IStatementNode;
import ast.type.type.*;
import ast.type.ValueNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.Objects;
public class UnaryExpressionNode implements ASTNode {
String thisExp;
String identifier;
MemberAccessNode memberAccess;
ValueNode value;
NotExpressionNode notExpression;
StatementNode statement;
ExpressionNode expression;
public class UnaryExpressionNode implements IExpressionNode {
public String thisExp;
public String identifier;
public MemberAccessNode memberAccess;
public ValueNode value;
public NotExpressionNode notExpression;
public IStatementNode statement;
public IExpressionNode expression;
private ITypeNode type;
public UnaryExpressionNode(String value) {
if(Objects.equals(value, "this")) {
@ -36,11 +39,26 @@ public class UnaryExpressionNode implements ASTNode {
this.notExpression = notExpression;
}
public UnaryExpressionNode(StatementNode statement) {
public UnaryExpressionNode(IStatementNode statement) {
this.statement = statement;
}
public UnaryExpressionNode(ExpressionNode expression) {
public UnaryExpressionNode(IExpressionNode expression) {
this.expression = expression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
@Override
public ITypeNode getType() {
return type;
}
public void setType(ITypeNode type) {
this.type = type;
}
}

View File

@ -3,7 +3,8 @@ package ast.member;
import ast.block.BlockNode;
import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode;
import bytecode.visitor.MethodVisitor;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList;
@ -20,8 +21,8 @@ public class ConstructorNode extends MethodNode implements Visitable {
this.identifier = identifier;
}
public ConstructorNode(AccessModifierNode accessType, String identifier, BlockNode body) {
this.accessType = accessType;
public ConstructorNode(String accessType, String identifier, BlockNode body) {
this.accessType = new AccessModifierNode(accessType);
this.identifier = identifier;
this.body = body;
}

View File

@ -1,18 +1,17 @@
package ast.member;
import ast.type.AccessModifierNode;
import ast.type.TypeNode;
import bytecode.visitor.ClassVisitor;
import ast.type.type.ITypeNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
public class FieldNode implements MemberNode, Visitable {
public AccessModifierNode accessTypeNode;
public TypeNode type;
public ITypeNode type;
public String identifier;
public FieldNode(AccessModifierNode accessTypeNode, TypeNode type, String name){
public FieldNode(AccessModifierNode accessTypeNode, ITypeNode type, String name){
this.accessTypeNode = accessTypeNode;
this.type = type;
this.identifier = name;
@ -23,8 +22,4 @@ public class FieldNode implements MemberNode, Visitable {
return visitor.analyze(this);
}
@Override
public void accept(ClassVisitor classVisitor) {
classVisitor.visit(this);
}
}

View File

@ -0,0 +1,11 @@
package ast.member;
import ast.block.BlockNode;
public class MainMethodNode extends MethodNode {
public BlockNode block;
public MainMethodNode(BlockNode block) {
this.block = block;
}
}

View File

@ -3,31 +3,28 @@ package ast.member;
import ast.block.BlockNode;
import ast.parameter.ParameterNode;
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.List;
import java.util.Objects;
public class MethodNode implements MemberNode, Visitable {
public AccessModifierNode accesModifier;
public TypeNode type;
private ITypeNode type;
public Boolean voidType;
public String identifier;
public List<ParameterNode> parameters;
private String identifier;
public List<ParameterNode> parameters = new ArrayList<>();
public BlockNode block;
public MethodNode() {
}
public MethodNode(BlockNode block) {
this.block = block;
}
public MethodNode(AccessModifierNode accessModifier, TypeNode type, Boolean voidType, String identifier, BlockNode block) {
this.accesModifier = accessModifier;
public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){
this.accesModifier = new AccessModifierNode(accessModifier);
this.type = type;
this.voidType = voidType;
this.identifier = identifier;
@ -38,23 +35,24 @@ public class MethodNode implements MemberNode, Visitable {
this.parameters.add(parameter);
}
/*
public List<ParameterNode> getParameters() {
return parameters;
}
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;
}
}
}
if (!(Objects.equals(this.identifier, methodNode.getIdentifier())) || type.equals(methodNode.type)
|| getParameters().size() != methodNode.getParameters().size()) {
return false;
}
for (int i = 0; i < this.getParameters().size(); i++) {
if (this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) {
return false;
}
}
return isSame;
return true;
}
*/
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
@ -65,5 +63,20 @@ public class MethodNode implements MemberNode, Visitable {
methodVisitor.visit(this);
}
public String getIdentifier() {
return identifier;
}
public ITypeNode getType() {
return type;
}
public void setType(ITypeNode type) {
this.type = type;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
}

View File

@ -1,14 +1,23 @@
package ast.parameter;
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 TypeNode type;
public String identifier;
public ParameterNode(TypeNode type, String identifier) {
public ParameterNode(ITypeNode type, String identifier) {
this.type = type;
this.identifier = identifier;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,23 +1,31 @@
package ast.statement;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class ForStatementNode implements ASTNode {
ExpressionNode statementExpressionInit;
StatementNode localVariableDeclarationInit;
ExpressionNode expression;
ExpressionNode statementExpression;
public class ForStatementNode implements IStatementNode {
public IExpressionNode statementExpressionInit;
public IStatementNode localVariableDeclarationInit;
public IExpressionNode expression;
public IExpressionNode statementExpression;
public ForStatementNode(ExpressionNode statementExpressionInit, ExpressionNode expression, ExpressionNode statementExpression) {
public ForStatementNode(IExpressionNode statementExpressionInit, IExpressionNode expression, IExpressionNode statementExpression) {
this.statementExpressionInit = statementExpressionInit;
this.expression = expression;
this.statementExpression = statementExpression;
}
public ForStatementNode(StatementNode localVariableDeclarationInit, ExpressionNode expression, ExpressionNode statementExpression) {
public ForStatementNode(IStatementNode localVariableDeclarationInit, IExpressionNode expression, IExpressionNode statementExpression) {
this.localVariableDeclarationInit = localVariableDeclarationInit;
this.expression = expression;
this.statementExpression = statementExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -0,0 +1,7 @@
package ast.statement;
import ast.ASTNode;
import visitor.Visitable;
public interface IStatementNode extends ASTNode, Visitable {
}

View File

@ -1,19 +1,26 @@
package ast.statement;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.type.TypeNode;
import ast.expression.IExpressionNode;
import ast.type.type.*;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class LocalVariableDeclarationNode implements ASTNode {
public TypeNode type;
public class LocalVariableDeclarationNode implements IStatementNode {
public ITypeNode type;
public String identifier;
public String assign;
public ExpressionNode expression;
public IExpressionNode expression;
public LocalVariableDeclarationNode(TypeNode type, String identifier, String assign, ExpressionNode expression) {
public LocalVariableDeclarationNode(ITypeNode type, String identifier, String assign, IExpressionNode expression) {
this.type = type;
this.identifier = identifier;
this.assign = assign;
this.expression = expression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,30 +1,24 @@
package ast.statement;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.type.TypeNode;
import bytecode.visitor.MethodVisitor;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import visitor.Visitable;
import java.util.ArrayList;
import java.util.List;
public class ReturnStatementNode implements IStatementNode {
public IExpressionNode expression;
public Boolean voidReturn = false;
public class ReturnStatementNode implements ASTNode, Visitable {
public ExpressionNode expression;
public ReturnStatementNode(ExpressionNode expression) {
this.expression = expression;
}
@Override
public void accept(MethodVisitor methodVisitor) {
methodVisitor.visit(this);
public ReturnStatementNode(IExpressionNode expression) {
if(expression != null) {
this.expression = expression;
} else {
voidReturn = true;
}
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return null;
return visitor.analyze(this);
}
}

View File

@ -1,6 +0,0 @@
package ast.statement;
import visitor.Visitable;
public abstract class StatementNode implements Visitable {
}

View File

@ -2,14 +2,22 @@ package ast.statement;
import ast.ASTNode;
import ast.block.BlockNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class WhileStatementNode implements ASTNode {
ExpressionNode expression;
BlockNode block;
public class WhileStatementNode implements IStatementNode {
public IExpressionNode expression;
public BlockNode block;
public WhileStatementNode(ExpressionNode expression, BlockNode block) {
public WhileStatementNode(IExpressionNode expression, BlockNode block) {
this.expression = expression;
this.block = block;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,11 +2,20 @@ package ast.statement.ifstatement;
import ast.ASTNode;
import ast.block.BlockNode;
import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class ElseStatementNode implements ASTNode {
BlockNode block;
public class ElseStatementNode implements IStatementNode {
public BlockNode block;
public ElseStatementNode(BlockNode block) {
this.block = block;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,13 +1,16 @@
package ast.statement.ifstatement;
import ast.ASTNode;
import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList;
import java.util.List;
public class IfElseStatementNode implements ASTNode {
IfStatementNode ifStatement;
List<ElseStatementNode> elseStatements = new ArrayList<>();
public class IfElseStatementNode implements IStatementNode {
public IfStatementNode ifStatement;
public List<ElseStatementNode> elseStatements = new ArrayList<>();
public IfElseStatementNode(IfStatementNode ifStatement) {
this.ifStatement = ifStatement;
@ -17,4 +20,9 @@ public class IfElseStatementNode implements ASTNode {
elseStatements.add(elseStatement);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,14 +2,23 @@ package ast.statement.ifstatement;
import ast.ASTNode;
import ast.block.BlockNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import ast.statement.IStatementNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class IfStatementNode implements ASTNode {
ExpressionNode expression;
BlockNode block;
public class IfStatementNode implements IStatementNode {
public IExpressionNode expression;
public BlockNode block;
public IfStatementNode(ExpressionNode expression, BlockNode block) {
public IfStatementNode(IExpressionNode expression, BlockNode block) {
this.expression = expression;
this.block = block;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

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

View File

@ -1,10 +1,12 @@
package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.unaryexpression.MemberAccessNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class AssignableExpressionNode implements ASTNode {
public class AssignableExpressionNode implements IStatementExpressionNode {
public String identifier;
public MemberAccessNode memberAccess;
public AssignableExpressionNode(String identifier) {
@ -14,4 +16,10 @@ public class AssignableExpressionNode implements ASTNode {
public AssignableExpressionNode(MemberAccessNode memberAccess) {
this.memberAccess = memberAccess;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -0,0 +1,5 @@
package ast.statement.statementexpression;
import ast.statement.IStatementNode;
public interface IStatementExpressionNode extends IStatementNode {}

View File

@ -1,5 +0,0 @@
package ast.statement.statementexpression;
public class IncrementExpression {
}

View File

@ -1,20 +1,28 @@
package ast.statement.statementexpression;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList;
import java.util.List;
public class NewDeclarationStatementExpressionNode implements ASTNode {
String identifier;
List<ExpressionNode> expressions = new ArrayList<>();
public class NewDeclarationStatementExpressionNode implements IStatementExpressionNode {
public String identifier;
public List<IExpressionNode> expressions = new ArrayList<>();
public NewDeclarationStatementExpressionNode(String identifier) {
this.identifier = identifier;
}
public void addExpression(ExpressionNode expression) {
public void addExpression(IExpressionNode expression) {
expressions.add(expression);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,12 +2,21 @@ package ast.statement.statementexpression.crementExpression;
import ast.ASTNode;
import ast.statement.statementexpression.AssignableExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class DecrementExpressionNode implements ASTNode {
CrementType crementType;
AssignableExpressionNode assignableExpression;
public class DecrementExpressionNode implements IStatementExpressionNode {
public CrementType crementType;
public AssignableExpressionNode assignableExpression;
public DecrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) {
this.assignableExpression = assignableExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -2,12 +2,21 @@ package ast.statement.statementexpression.crementExpression;
import ast.ASTNode;
import ast.statement.statementexpression.AssignableExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
public class IncrementExpressionNode implements ASTNode {
CrementType crementType;
AssignableExpressionNode assignableExpression;
public class IncrementExpressionNode implements IStatementExpressionNode {
public CrementType crementType;
public AssignableExpressionNode assignableExpression;
public IncrementExpressionNode(CrementType crementType, AssignableExpressionNode assignableExpression) {
this.assignableExpression = assignableExpression;
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -1,20 +1,20 @@
package ast.statement.statementexpression.methodcallstatementnexpression;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import java.util.ArrayList;
import java.util.List;
public class ChainedMethodNode implements ASTNode {
String identifier;
List<ExpressionNode> expressions = new ArrayList<>();
public String identifier;
public List<IExpressionNode> expressions = new ArrayList<>();
public ChainedMethodNode(String identifier) {
this.identifier = identifier;
}
public void addExpression(ExpressionNode expression) {
public void addExpression(IExpressionNode expression) {
expressions.add(expression);
}
}

View File

@ -1,16 +1,19 @@
package ast.statement.statementexpression.methodcallstatementnexpression;
import ast.ASTNode;
import ast.expression.ExpressionNode;
import ast.expression.IExpressionNode;
import ast.statement.statementexpression.IStatementExpressionNode;
import semantic.SemanticVisitor;
import typechecker.TypeCheckResult;
import java.util.ArrayList;
import java.util.List;
public class MethodCallStatementExpressionNode implements ASTNode {
TargetNode target;
List<ChainedMethodNode> chainedMethods = new ArrayList<>();
String identifier;
List<ExpressionNode> expressions = new ArrayList<>();
public class MethodCallStatementExpressionNode implements IStatementExpressionNode {
public TargetNode target;
public List<ChainedMethodNode> chainedMethods = new ArrayList<>();
public String identifier;
public List<IExpressionNode> expressions = new ArrayList<>();
public MethodCallStatementExpressionNode(TargetNode target, String identifier) {
this.target = target;
@ -21,9 +24,13 @@ public class MethodCallStatementExpressionNode implements ASTNode {
chainedMethods.add(chainedMethode);
}
public void addExpression(ExpressionNode expression) {
public void addExpression(IExpressionNode expression) {
expressions.add(expression);
}
@Override
public TypeCheckResult accept(SemanticVisitor visitor) {
return visitor.analyze(this);
}
}

View File

@ -5,10 +5,10 @@ import ast.expression.unaryexpression.MemberAccessNode;
import ast.statement.statementexpression.NewDeclarationStatementExpressionNode;
public class TargetNode implements ASTNode {
Boolean thisTar;
MemberAccessNode memberAccess;
NewDeclarationStatementExpressionNode newDeclaration;
String identifier;
public Boolean thisTar;
public MemberAccessNode memberAccess;
public NewDeclarationStatementExpressionNode newDeclaration;
public String identifier;
public TargetNode(Boolean thisTar) {
this.thisTar = thisTar;

View File

@ -1,5 +0,0 @@
package ast.type;
public enum EnumTypeNode {
INT, BOOLEAN, CHAR, IDENTIFIER
}

View File

@ -1,25 +0,0 @@
package ast.type;
public class TypeNode {
public EnumTypeNode type;
public TypeNode(String type) {
setType(type);
}
private void setType(String type) {
switch(type) {
case "int":
this.type = EnumTypeNode.INT;
break;
case "boolean":
this.type = EnumTypeNode.BOOLEAN;
break;
case "char":
this.type = EnumTypeNode.CHAR;
break;
default:
this.type = EnumTypeNode.IDENTIFIER;
}
}
}

View File

@ -3,8 +3,8 @@ package ast.type;
import ast.ASTNode;
public class ValueNode implements ASTNode {
EnumValueNode valueType;
String value;
public EnumValueNode valueType;
public String value;
public ValueNode(EnumValueNode valueType, String value) {
this.valueType = valueType;

View File

@ -0,0 +1,30 @@
package ast.type.type;
public class BaseType implements ITypeNode {
private TypeEnum typeEnum;
public BaseType(TypeEnum typeEnum) {
this.typeEnum = typeEnum;
}
public TypeEnum getTypeEnum() {
return typeEnum;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseType other = (BaseType) obj;
if (typeEnum != other.typeEnum)
return false;
return true;
}
}

View File

@ -0,0 +1,5 @@
package ast.type.type;
public interface ITypeNode {
}

View File

@ -0,0 +1,33 @@
package ast.type.type;
public class ReferenceType implements ITypeNode{
private String identifier;
public ReferenceType(String identifier) {
this.identifier = identifier;
}
public String getIdentifier() {
return identifier;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReferenceType other = (ReferenceType) obj;
if (identifier == null) {
if (other.identifier != null)
return false;
} else if (!identifier.equals(other.identifier))
return false;
return true;
}
}

View File

@ -0,0 +1,9 @@
package ast.type.type;
public enum TypeEnum {
VOID,
INT,
CHAR,
BOOL;
}

View File

@ -9,7 +9,6 @@ import bytecode.visitor.ClassVisitor;
import java.io.File;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import java.io.FileOutputStream;
import java.io.IOException;
@ -30,8 +29,8 @@ public class ClassCodeGen implements ClassVisitor {
@Override
public void visit(ClassNode classNode) {
classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null,
"java/lang/Object", null);
// classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null,
// "java/lang/Object", null);
for (MemberNode memberNode : classNode.members) {
if (memberNode instanceof FieldNode) {
@ -62,7 +61,7 @@ public class ClassCodeGen implements ClassVisitor {
directory.mkdirs();
}
String filePath = directoryPath + "/" + name + ".class";
String filePath = outputDirectoryPath + "/" + name + ".class";
try {
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write(byteCode);

View File

@ -1,6 +1,5 @@
package bytecode;
import ast.parameter.ParameterNode;
import ast.type.*;
import org.objectweb.asm.Opcodes;
@ -31,19 +30,19 @@ public class Mapper {
return descriptor;
}
public String getTypeChar(EnumTypeNode enumTypeNode) {
String typeChar = "";
switch (enumTypeNode) {
case EnumTypeNode.INT:
typeChar = "I";
break;
case EnumTypeNode.CHAR:
typeChar = "C";
break;
case EnumTypeNode.BOOLEAN:
typeChar = "Z";
break;
}
return typeChar;
}
// public String getTypeChar(TypeEnum enumTypeNode) {
// String typeChar = "";
// switch (enumTypeNode) {
// case TypeEnum.INT:
// typeChar = "I";
// break;
// case TypeEnum.CHAR:
// typeChar = "C";
// break;
// case TypeEnum.BOOLEAN:
// typeChar = "Z";
// break;
// }
// return typeChar;
// }
}

View File

@ -4,6 +4,7 @@ import ast.ClassNode;
import ast.member.FieldNode;
public interface ClassVisitor {
void visit(ClassNode classNode);
void visit(FieldNode fieldNode);
void visit(ClassNode classNode);
void visit(FieldNode fieldNode);
}

View File

@ -0,0 +1,108 @@
package main;
import ast.ASTNode;
import ast.ProgramNode;
import parser.astBuilder.ASTBuilder;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
import semantic.SemanticAnalyzer;
import bytecode.ByteCodeGenerator;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import java.io.IOException;
import java.nio.file.Paths;
/**
* Start Raupenpiler using make:
* <p> <code> cd .\src\test\ </code>
* <p> <code> make clean compile-raupenpiler </code>
* <p> Start Raupenpiler using jar:
* <p> <code> java.exe -jar path_to_jar\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory' </code>
* <p> Example (jar needs to be in the target directory, compile with make or mvn package first):
* <code> java.exe -jar .\target\JavaCompiler-1.0-SNAPSHOT-jar-with-dependencies.jar 'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' </code>
*/
public class Main {
public static void main(String[] args) throws Exception {
if (args.length == 2) {
// args[0] is the input file path
// args[1] is the output directory path
String inputFilePath = args[0];
String outputDirectoryPath = args[1];
System.out.println("Compiling file: " + inputFilePath);
try {
CharStream inputCharStream = CharStreams.fromPath(Paths.get(inputFilePath));
compileFile(inputCharStream, outputDirectoryPath);
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}
}
/* !!! Else Branch (main ohne args starten) ist nicht zur Verwendung vorgesehen, immer mit args starten !!!
else {
try {
CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java"));
compileFile(codeCharStream);
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}
}
*/
}
/**
* This method is used to compile a file from a given CharStream and output the bytecode to a specified directory.
* It goes through the following steps:
* <p>1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream.
* <p>2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree.
* <p>3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST).
* <p>4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST.
* <p>5. Bytecode Generator: It uses the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory.
*
* @param inputCharStream The CharStream representing the input file to be compiled.
* @param outputDirectoryPath The path of the directory where the output bytecode should be written.
*/
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
// Initialize the logger
new RaupenLogger();
/* ------------------------- Scanner -> tokens ------------------------- */
// Use the SimpleJavaLexer to tokenize the input CharStream
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
tokenStream.fill();
// Log the tokens
RaupenLogger.logScanner(tokenStream);
/*------------------------- Parser -> Parsetree -------------------------*/
// Use the SimpleJavaParser to parse the tokens and generate a ParseTree
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program(); // parse the input
// Log the ParseTree
RaupenLogger.logParser(parseTree, parser);
/*------------------------- AST builder -> AST -------------------------*/
// Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST)
ASTBuilder astBuilder = new ASTBuilder();
ASTNode abstractSyntaxTree = astBuilder.visit(parseTree);
// Log the AST
RaupenLogger.logAST(abstractSyntaxTree);
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
// Use the SemanticAnalyzer to generate a typed AST
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
// Log the typed AST
RaupenLogger.logSemanticAnalyzer(typedAst);
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
// Use the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath);
assert typedAst != null;
byteCodeGenerator.visit((ProgramNode) typedAst);
// Log the bytecode generation
RaupenLogger.logBytecodeGenerator();
}
}

View File

@ -0,0 +1,180 @@
package main;
import ast.ASTNode;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.*;
/**
Beispiel für Logging-Arten:
<p><code>logger.severe("Schwerwiegender Fehler");</code>
<p><code>logger.warning("Warnung");</code>
<p><code>logger.info("Information");</code>
<p><code>logger.config("Konfigurationshinweis");</code>
<p><code>logger.fine("Fein");</code>
<p><code>logger.finer("Feiner");</code>
<p><code>logger.finest("Am feinsten");</code>
<p>You may toggle the logging level of the console and file handlers by
changing the level ALL/OFF/etc. in the constructor.
<code>consoleHandler.setLevel(Level.OFF);</code>
<code>fileHandler.setLevel(Level.ALL);</code>
*/
public class RaupenLogger {
static Logger logger = Logger.getLogger("RaupenLogs");
public RaupenLogger() {
// ------------------------- Logging -------------------------
logger.setLevel(Level.ALL);
logger.getParent().getHandlers()[0].setLevel(Level.ALL);
logger.setUseParentHandlers(false);
// Custom formatter class
class CustomFormatter extends Formatter {
private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss dd-MM-yyyy");
@Override
public String format(LogRecord record) {
return formatMessage(record) + System.lineSeparator();
}
@Override
public String getHead(Handler h) {
Date now = new Date();
String dateTime = dateFormat.format(now);
return "Log Start Time: " + dateTime + "\n"
+ "Logger Name: " + h.getFormatter().getClass().getName() + "\n\n";
}
}
try {
// Configure console handler
Handler consoleHandler = new ConsoleHandler();
// Toggle console logging on/off
consoleHandler.setLevel(Level.OFF);
consoleHandler.setFormatter(new CustomFormatter());
logger.addHandler(consoleHandler);
// Configure file handler
Handler fileHandler = new FileHandler("src/main/resources/logs/RaupenLog.log");
// Toggle file logging on/off
fileHandler.setLevel(Level.ALL);
fileHandler.setFormatter(new CustomFormatter());
logger.addHandler(fileHandler);
} catch (SecurityException | IOException e) {
e.printStackTrace();
}
}
public static void logScanner(CommonTokenStream tokenStream) {
// Printing the tokens
logger.info("-------------------- Scanner -> Tokens --------------------");
List<Token> tokens = tokenStream.getTokens();
for (Token token : tokens) {
String tokenType =
SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType());
String tokenText = token.getText();
// logger.info("Token Type: " + tokenType + ", Token Text: " + tokenText);
logger.info(tokenType + " " + tokenText);
}
logger.info("\n");
}
public static void logParser(ParseTree parseTree, SimpleJavaParser parser) {
// Printing the parse tree
logger.info("-------------------- Parser -> Parsetree --------------------");
logger.info(parseTree.toStringTree(parser)); //one line representation
logTree(parseTree, parser, 0);
logger.info("\n");
}
public static void logAST(ASTNode abstractSyntaxTree) {
// Printing the AST
logger.info("-------------------- AST builder -> AST --------------------");
// logger.info("AST: " + ast.toString());
logAST(abstractSyntaxTree, 0);
logger.info("\n");
}
public static void logSemanticAnalyzer(ASTNode typedAst) {
// Printing the typed AST
logger.info("-------------------- Semantic Analyzer -> typed AST --------------------");
logAST(typedAst, 0);
logger.info("\n");
}
public static void logBytecodeGenerator() {
// Printing the bytecode
logger.info("-------------------- Bytecode Generator -> Bytecode --------------------");
logger.info("Bytecode generated");
logger.info("\n");
}
/* ------------------------- Printing methods ------------------------- */
/**
* This method is used to print the parse tree in a structured format.
* It recursively traverses the tree and prints the rule names and text of the
* nodes.
*
* @param tree The parse tree to be printed.
* @param parser The parser used to parse the input. It's used to get the rule
* names.
* @param indent The current indentation level. It's used to format the output.
*/
public static void logTree(ParseTree tree, Parser parser, int indent) {
// Create an indentation string based on the current indentation level
String indentString = " ".repeat(indent * 2);
// If the tree node is an instance of RuleContext (i.e., it's an internal node),
// print the rule name
if (tree instanceof RuleContext) {
int ruleIndex = ((RuleContext) tree).getRuleIndex();
String ruleName = parser.getRuleNames()[ruleIndex];
logger.info(indentString + ruleName);
} else {
// If the tree node is not an instance of RuleContext (i.e., it's a leaf node),
// print the text of the node
logger.info(indentString + tree.getText());
}
// Recursively print the children of the current node, increasing the
// indentation level
for (int i = 0; i < tree.getChildCount(); i++) {
logTree(tree.getChild(i), parser, indent + 1);
}
}
// TODO: Fix this method
public static void logAST(ASTNode abstractSyntaxTree, int indent) {
if (abstractSyntaxTree == null) {
logger.severe("AST is null !!!");
return;
}
String indentString = " ".repeat(indent * 2);
logger.info(indentString + abstractSyntaxTree.getClass());
// for (ASTNode child : node.) {
// printAST(child, indent + 1);
// }
}
}

View File

@ -10,11 +10,9 @@ import ast.expression.binaryexpression.NonCalculationExpressionNode;
import ast.expression.unaryexpression.MemberAccessNode;
import ast.expression.unaryexpression.NotExpressionNode;
import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.member.MethodNode;
import ast.member.*;
import ast.statement.ifstatement.ElseStatementNode;
import ast.statement.ifstatement.IfElseStatementNode;
import ast.member.ConstructorNode;
import ast.member.MemberNode;
import ast.parameter.ParameterNode;
import ast.statement.*;
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.TargetNode;
import ast.type.*;
import ast.type.type.*;
import org.antlr.v4.runtime.tree.TerminalNode;
import parser.generated.*;
@ -53,7 +52,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitConstructorDeclaration(SimpleJavaParser.ConstructorDeclarationContext ctx) {
ConstructorNode constructorNode = new ConstructorNode((AccessModifierNode) visit(ctx.AccessModifier()), ctx.Identifier().getText(), (BlockNode) visit(ctx.block()));
ConstructorNode constructorNode = new ConstructorNode(ctx.AccessModifier().getText(), ctx.Identifier().getText(), (BlockNode) visit(ctx.block()));
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
constructorNode.addParameter((ParameterNode) visit(parameter));
}
@ -63,16 +62,16 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) {
if(ctx.MainMethodDeclaration() != null) {
return new MethodNode((BlockNode) visit(ctx.block()));
return new MainMethodNode((BlockNode) visit(ctx.block()));
} else {
if(ctx.type() != null) {
MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), (TypeNode) visit(ctx.type()), 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()) {
methodNode.addParameter((ParameterNode) visit(parameter));
}
return methodNode;
} else {
MethodNode methodNode = new MethodNode((AccessModifierNode) visit(ctx.AccessModifier()), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block()));
MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.block()));
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().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
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
@ -108,34 +112,37 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitReturnStatement(SimpleJavaParser.ReturnStatementContext ctx) {
return new ReturnStatementNode((ExpressionNode) visit(ctx.expression()));
return new ReturnStatementNode((IExpressionNode) visit(ctx.expression()));
}
@Override
public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) {
return new LocalVariableDeclarationNode(new TypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (ExpressionNode) visit(ctx.expression()));
return new LocalVariableDeclarationNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression()));
}
@Override
public ASTNode visitBlock(SimpleJavaParser.BlockContext ctx) {
BlockNode blockNode = new BlockNode();
for(SimpleJavaParser.StatementContext statement : ctx.statement()) {
blockNode.addStatement((StatementNode) visit(statement));
blockNode.addStatement((IStatementNode) visit(statement));
}
if(!blockNode.hasReturnStatement) {
blockNode.addStatement(new ReturnStatementNode(null));
}
return blockNode;
}
@Override
public ASTNode visitWhileStatement(SimpleJavaParser.WhileStatementContext ctx) {
return new WhileStatementNode((ExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block()));
return new WhileStatementNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block()));
}
@Override
public ASTNode visitForStatement(SimpleJavaParser.ForStatementContext ctx) {
if(ctx.statementExpression(0) != null) {
return new ForStatementNode((ExpressionNode) visit(ctx.statementExpression(0)), (ExpressionNode) visit(ctx.expression()), (ExpressionNode) visit(ctx.statementExpression(1)));
return new ForStatementNode((IExpressionNode) visit(ctx.statementExpression(0)), (IExpressionNode) visit(ctx.expression()), (IExpressionNode) visit(ctx.statementExpression(1)));
} else if(ctx.localVariableDeclaration() != null) {
return new ForStatementNode((StatementNode) visit(ctx.localVariableDeclaration()), (ExpressionNode) visit(ctx.expression()), (ExpressionNode) visit(ctx.statementExpression(1)));
return new ForStatementNode((IStatementNode) visit(ctx.localVariableDeclaration()), (IExpressionNode) visit(ctx.expression()), (IExpressionNode) visit(ctx.statementExpression(1)));
}
return null;
}
@ -151,7 +158,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitIfStatement(SimpleJavaParser.IfStatementContext ctx) {
return new IfStatementNode((ExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block()));
return new IfStatementNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.block()));
}
@Override
@ -175,14 +182,14 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitAssign(SimpleJavaParser.AssignContext ctx) {
return new AssignStatementExpressionNode((AssignableExpressionNode) visit(ctx.assignableExpression()), (ExpressionNode) visit(ctx.expression()));
return new AssignStatementExpressionNode((AssignableExpressionNode) visit(ctx.assignableExpression()), (IExpressionNode) visit(ctx.expression()));
}
@Override
public ASTNode visitNewDeclaration(SimpleJavaParser.NewDeclarationContext ctx) {
NewDeclarationStatementExpressionNode newDeclarationStatementExpressionNode = new NewDeclarationStatementExpressionNode(ctx.Identifier().getText());
for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) {
newDeclarationStatementExpressionNode.addExpression((ExpressionNode) visit(expression));
newDeclarationStatementExpressionNode.addExpression((IExpressionNode) visit(expression));
}
return newDeclarationStatementExpressionNode;
}
@ -194,7 +201,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
methodCallStatementExpressionNode.addChainedMethod((ChainedMethodNode) visit(chainedMethod));
}
for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) {
methodCallStatementExpressionNode.addExpression((ExpressionNode) visit(expression));
methodCallStatementExpressionNode.addExpression((IExpressionNode) visit(expression));
}
return methodCallStatementExpressionNode;
}
@ -217,7 +224,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
public ASTNode visitChainedMethod(SimpleJavaParser.ChainedMethodContext ctx) {
ChainedMethodNode chainedMethodNode = new ChainedMethodNode(ctx.Identifier().getText());
for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) {
chainedMethodNode.addExpression((ExpressionNode) visit(expression));
chainedMethodNode.addExpression((IExpressionNode) visit(expression));
}
return chainedMethodNode;
}
@ -295,9 +302,9 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
} else if(ctx.notExpression() != null) {
return new UnaryExpressionNode((NotExpressionNode) visitNotExpression(ctx.notExpression()));
} else if(ctx.statementExpression() != null) {
return new UnaryExpressionNode((StatementNode) visitStatementExpression(ctx.statementExpression()));
return new UnaryExpressionNode((IStatementNode) visitStatementExpression(ctx.statementExpression()));
} else if(ctx.expression() != null) {
return new UnaryExpressionNode((ExpressionNode) visitExpression(ctx.expression()));
return new UnaryExpressionNode((IExpressionNode) visitExpression(ctx.expression()));
}
return null;
}
@ -332,7 +339,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitNotExpression(SimpleJavaParser.NotExpressionContext ctx) {
return new NotExpressionNode((ExpressionNode) visitExpression(ctx.expression()));
return new NotExpressionNode((IExpressionNode) visitExpression(ctx.expression()));
}
@ -382,7 +389,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override
public ASTNode visitNonCalculationExpression(SimpleJavaParser.NonCalculationExpressionContext ctx) {
return new NonCalculationExpressionNode((UnaryExpressionNode) visit(ctx.unaryExpression()), ctx.nonCalculationOperator().getText(), (ExpressionNode) visit(ctx.expression()));
return new NonCalculationExpressionNode((UnaryExpressionNode) visit(ctx.unaryExpression()), ctx.nonCalculationOperator().getText(), (IExpressionNode) visit(ctx.expression()));
}
@Override
@ -394,4 +401,15 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
}
return null;
}
public ITypeNode createTypeNode(String identifier){
return switch (identifier) {
case "int" -> new BaseType(TypeEnum.INT);
case "boolean" -> new BaseType(TypeEnum.BOOL);
case "char" -> new BaseType(TypeEnum.CHAR);
case "void" -> new BaseType(TypeEnum.VOID);
default -> new ReferenceType(identifier);
};
}
}

View File

@ -1,27 +1,35 @@
package semantic;
import oldAst.type.TypeNode;
import ast.type.type.*;
import semantic.exeptions.AlreadyDeclearedException;
import java.util.HashMap;
import java.util.Stack;
public class Scope {
private Stack<HashMap<String, TypeNode>> localVars;
private Stack<HashMap<String, ITypeNode>> localVars;
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)) {
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);
}
public ITypeNode getLocalVar(String name) {
for (HashMap<String, ITypeNode> map : localVars) {
return map.get(name);
}
return null;
}
public boolean contains(String name) {
for (HashMap<String, TypeNode> map : localVars) {
for (HashMap<String, ITypeNode> map : localVars) {
if (map.containsKey(name)) {
return true;
}
@ -30,7 +38,7 @@ public class Scope {
}
public void pushScope() {
localVars.push(new HashMap<String, TypeNode>());
localVars.push(new HashMap<String, ITypeNode>());
}
public void popScope() {

View File

@ -1,40 +1,44 @@
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.HashMap;
import java.util.List;
import java.util.Objects;
import oldAst.type.BaseTypeNode;
import oldAst.type.TypeNode;
import ast.*;
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.exeptions.AlreadyDeclearedException;
import semantic.exeptions.NotDeclearedException;
import semantic.exeptions.TypeMismatchException;
import semantic.exeptions.*;
import typechecker.TypeCheckResult;
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<>();
private Context context;
private static Context context;
private static Scope currentScope;
private static ClassNode currentClass;
private static ITypeNode currentNullType;
private ITypeNode currentMethodReturnType;
public static ASTNode generateTast(ASTNode node) {
SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
@ -50,7 +54,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
return null;
}
public static void clearAnalyzier(){
public static void clearAnalyzer() {
currentFields.clear();
errors.clear();
currentScope = null;
@ -87,13 +91,10 @@ public class SemanticAnalyzer implements SemanticVisitor {
valid = valid && result.isValid();
} else if (memberNode instanceof MethodNode methodNode) {
//Methods
for(MethodNode methode : currentClass.getMethods()){
if(methode.equals(methodNode))
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);
valid = valid && result.isValid();
@ -106,38 +107,59 @@ public class SemanticAnalyzer implements SemanticVisitor {
@Override
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
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);
for (var otherMethod : currentClass.getMethods()) {
if (Objects.equals(otherMethod, methodNode))
break;
if (otherMethod.isSame(methodNode)) {
errors.add(new AlreadyDeclearedException(
"Method " + methodNode.getIdentifier() + " is already defined in class "
+ currentClass.identifier));
valid = false;
}
}
}
//Statements
List<StatementNode> statements = methodNode.statements;
for (StatementNode statement : statements) {
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);
currentScope.pushScope();
for (var parameter : methodNode.getParameters()) {
var result = parameter.accept(this);
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();
return new TypeCheckResult(valid, null);
currentMethodReturnType = methodNode.getType();
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
@ -152,87 +174,20 @@ public class SemanticAnalyzer implements SemanticVisitor {
}
@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);
}
public TypeCheckResult analyze(IfStatementNode toCheck) {
return new TypeCheckResult(true, null);
}
@Override
public TypeCheckResult analyze(IfStatementNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(ReturnStatementNode toCheck) {
return null;
if(toCheck.expression != null){
var result = toCheck.expression.accept(this);
return new TypeCheckResult(true, result.getType());
} else {
return new TypeCheckResult(false, null);
}
}
@Override
@ -241,39 +196,175 @@ public class SemanticAnalyzer implements SemanticVisitor {
}
@Override
public TypeCheckResult analyze(LiteralNode toCheck) {
return new TypeCheckResult(true, toCheck.getType());
public TypeCheckResult analyze(ParameterNode toCheck) {
return new TypeCheckResult(true, null);
}
@Override
public TypeCheckResult analyze(InstVar toCheck) {
boolean valid = true;
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 {
var field = classContext.getField(toCheck.identifier);
return new TypeCheckResult(valid, field.getType());
public TypeCheckResult analyze(BlockNode blockNode) {
ITypeNode blockReturnType = null;
for (IStatementNode statementNode : blockNode.statements) {
var result = statementNode.accept(this);
if(result.getType() != null){
if(blockReturnType == null){
blockReturnType = result.getType();
} else {
errors.add(new MultipleReturnTypes("There are multiple Return types"));
}
}
}
return new TypeCheckResult(true, blockReturnType);
}
@Override
public TypeCheckResult analyze(AssignableExpressionNode toCheck) {
return new TypeCheckResult(true, currentFields.get(toCheck.identifier));
}
@Override
public TypeCheckResult analyze(This toCheck) {
return new TypeCheckResult(true, toCheck.getType());
public TypeCheckResult analyze(ElseStatementNode toCheck) {
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 new TypeCheckResult(true, null);
}
@Override
public TypeCheckResult analyze(MethodCallStatementExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(LocalVariableDeclarationNode localVarDecl) {
var valid = true;
if (localVarDecl.expression != null) {
TypeCheckResult result = localVarDecl.expression.accept(this);
var resultType = localVarDecl.expression.getType();
valid = result.isValid() && valid;
if (!Objects.equals(resultType, localVarDecl.type)) {
errors.add(new TypeMismatchException(
"Type mismatch: cannot convert from " + resultType + " to " + localVarDecl.type));
valid = false;
}
}
try {
currentScope.addLocalVar(localVarDecl.identifier, localVarDecl.type);
} catch (AlreadyDefinedException e) {
errors.add(new AlreadyDefinedException(e.getMessage()));
valid = false;
}
return new TypeCheckResult(valid, null);
}
@Override
public TypeCheckResult analyze(NewDeclarationStatementExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(IncrementExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(BinaryExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(CalculationExpressionNode calcNode) {
if (calcNode.calculationExpression != null) {
calcNode.calculationExpression.accept(this);
}
return null;
}
@Override
public TypeCheckResult analyze(DotExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(DotSubstractionExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(NonCalculationExpressionNode toCheck) {
return null;
}
@Override
public TypeCheckResult analyze(UnaryExpressionNode unary) {
var valid = true;
if (currentScope.contains(unary.identifier)) {
return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier));
} else if(currentFields.get(unary.identifier) != null) {
return new TypeCheckResult(valid, currentFields.get(unary.identifier));
} else {
errors.add(new NotDeclearedException("Var is not Decleared"));
}
return new TypeCheckResult(valid, null);
}
}

View File

@ -1,18 +1,20 @@
package semantic;
import ast.ClassNode;
import ast.expression.LiteralNode;
import ast.ProgramNode;
import ast.expression.BinaryExpressionNode;
import ast.expression.IdentifierExpressionNode;
import ast.expression.InstVar;
import ast.*;
import ast.block.BlockNode;
import ast.expression.binaryexpression.*;
import ast.expression.unaryexpression.UnaryExpressionNode;
import ast.member.FieldNode;
import ast.member.MethodNode;
import ast.member.*;
import ast.parameter.ParameterNode;
import ast.statement.*;
import ast.expression.This;
import ast.statement.ifstatement.IfStatementNode;
import ast.statement.ifstatement.*;
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;
public interface SemanticVisitor {
@ -25,25 +27,46 @@ public interface SemanticVisitor {
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(ReturnStatementNode toCheck);
TypeCheckResult analyze(WhileStatementNode toCheck);
TypeCheckResult analyze(LiteralNode toCheck);
TypeCheckResult analyze(ParameterNode toCheck);
TypeCheckResult analyze(InstVar toCheck);
TypeCheckResult analyze(BlockNode toCheck);
TypeCheckResult analyze(AssignableExpressionNode toCheck);
TypeCheckResult analyze(ElseStatementNode toCheck);
TypeCheckResult analyze(ForStatementNode toCheck);
TypeCheckResult analyze(AssignStatementExpressionNode toCheck);
TypeCheckResult analyze(DecrementExpressionNode toCheck);
TypeCheckResult analyze(IfElseStatementNode toCheck);
TypeCheckResult analyze(MethodCallStatementExpressionNode toCheck);
TypeCheckResult analyze(LocalVariableDeclarationNode toCheck);
TypeCheckResult analyze(NewDeclarationStatementExpressionNode toCheck);
TypeCheckResult analyze(IncrementExpressionNode toCheck);
TypeCheckResult analyze(BinaryExpressionNode toCheck);
TypeCheckResult analyze(CalculationExpressionNode toCheck);
TypeCheckResult analyze(DotExpressionNode toCheck);
TypeCheckResult analyze(DotSubstractionExpressionNode toCheck);
TypeCheckResult analyze(NonCalculationExpressionNode toCheck);
TypeCheckResult analyze(UnaryExpressionNode toCheck);
TypeCheckResult analyze(This toCheck);
}

View File

@ -1,7 +1,7 @@
package semantic.context;
import oldAst.ClassNode;
import oldAst.member.FieldNode;
import ast.ClassNode;
import ast.member.FieldNode;
import java.util.HashMap;
public class ClassContext {

View File

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

View File

@ -1,20 +1,20 @@
package semantic.context;
import oldAst.member.FieldNode;
import oldAst.type.AccessTypeNode;
import oldAst.type.TypeNode;
import ast.member.FieldNode;
import ast.type.*;
import ast.type.type.*;
public class FieldContext {
private AccessTypeNode accessModifier;
private TypeNode type;
private AccessModifierNode accessModifier;
private ITypeNode type;
public FieldContext(FieldNode field) {
accessModifier = field.accessTypeNode;
type = field.type;
}
public TypeNode getType() {
public ITypeNode getType() {
return type;
}

View File

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

View File

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

View File

@ -1,14 +1,14 @@
package typechecker;
import oldAst.type.TypeNode;
import ast.type.type.ITypeNode;
public class TypeCheckResult {
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.type = type;
}
@ -17,7 +17,7 @@ public class TypeCheckResult {
return valid;
}
public TypeNode getType() {
public ITypeNode getType() {
return type;
}
}

View File

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

View File

@ -0,0 +1,16 @@
public class CompilerInput {
public int a;
public static int testMethod(char x){
return 0;
}
public class Test {
public static int testMethod(char x, int a){
return 0;
}
}
}

View File

@ -1,11 +0,0 @@
public class Tester {
public static void main(String[] args) {
new EmptyClassExample();
// cp mitgeben
}
}
// java -jar pfadtocompiler.jar EmptyClass.java
//mit bash scipt ode rmakefile test automatisieren
//mvn package
// javac tester // tester compilen
// java tester // tester ausführen

29
src/test/Makefile Normal file
View File

@ -0,0 +1,29 @@
# Makefile
### IntelliJs play buttons do not work. Run in "src/test" folder with "make" command to run all
### Or run only parts with "make compile-javac", "make clean" etc.
all: compile-javac compile-raupenpiler
compile-javac:
javac -d .\resources\output\javac .\resources\input\CompilerInput.java
compile-raupenpiler:
cd ../.. ; mvn -DskipTests install
cd ../.. ; mvn exec:java -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' "
test: test-javac test-raupenpiler
test-javac:
#compile-javac
#java -cp .\resources\output\javac CompilerInput
test-raupenpiler:
#java -cp .\resources\output\raupenpiler CompilerInput
clean:
rm -f ./resources/output/javac/*.class
rm -f ./resources/output/raupenpiler/*.class
rm -f ./java/*.class
rm -f ../main/resources/output/*.class
rm -f ../main/resources/logs/*.log

View File

@ -1,5 +1,7 @@
# Scanner
## Scanner Input
### Beispiel 1: Empty Class
String empty class = "public class Name {}";
@ -15,64 +17,76 @@
"}"
## Scanner Output
CommonTokenStream
### Beispiel 1: Empty Class
Token Type; Token Text
Type gibts nur bei Terminalen, Text bei allen
[null "public", null "class", IDENTIFIER "Name", null "{", null "}", EOF "<EOF>"]
Bsp von Ihm mal:
[TokPublic,TokClass,TokIdentifier "Name",TokLeftBrace,TokRightBrace]
### Beispiel 2: Filled Class
[TokClass,TokIdentifier "javaFileInput.Example",TokLeftBrace]
[TokIf,TokLeftParen,TokIdentifier "x",TokLessThan,TokNumber 5,TokRightParen,TokLeftBrace]
[TokFor,TokLeftParen,TokIdentifier "int",TokIdentifier "i",TokAssign,TokNumber 0,TokSemicolon,TokIdentifier "i",TokLessThan,TokNumber 10,TokSemicolon,TokIdentifier "i",TokPlus,TokPlus,TokRightParen,TokLeftBrace]
[TokWhile,TokLeftParen,TokIdentifier "true",TokRightParen,TokLeftBrace]
[TokIdentifier "x",TokAssign,TokNumber 5,TokSemicolon]
[TokRightBrace]
# Parser
## Parser Input
## Parser Input
CommonTokenStream
(Scanner Output)
## Parser Output (AST)
(program (classDeclaration (accessType public) class Name { }))
ParseTree
### Beispiel 1: Empty Class
### Beispiel 2: Filled Class
# Semantische Analyse / Typcheck
## Typcheck Input
## Typcheck Input
(Parser Output = AST)
## Typcheck Output
### Beispiel 1: Empty Class
### Beispiel 2: Filled Class
# Bytecodegenerierung
## Bytecodegenerierung Input
## Bytecodegenerierung Input
(Typcheck Output = vom Typcheck eventuell manipulierter AST)
## Bytecodegenerierung Output
### Beispiel 1: Empty Class
Compiled Classfile
public class javaFileInput.Example {
}
## E2E Tests:
- Testdatei mit Main ausführen/kompilieren
- Testdatei mit "javac -d output .\CompilerInput.java" kompilieren
- -> Dateien mit javap vergleichen
### Beispiel 2: Filled Class
wenn beides erfolgreich
- Ergebnis vom eigenen Compiler mithilfe von main.TestCompilerOutput ausführen
- (Ergebnis von javac mithilfe von main.TestCompilerOutput ausführen)
### Andis Tipps:
- cp mitgeben
- makefile
- java -jar pfadtocompiler.jar EmptyClass.java
- mvn package
- javac tester // tester compilen
- java tester // tester ausführen
- -> tester ist in unserem Fall main.TestCompilerOutput.java

View File

@ -1,3 +1,5 @@
package main;
public class EmptyClassExample {
private class Inner {
}

View File

@ -1,3 +1,5 @@
package main;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -15,17 +17,17 @@ import java.util.List;
public class FailureTest {
private static final List<String> TEST_FILES = Arrays.asList(
"src/main/test/resources/failureTests/TestClass1.java",
"src/main/test/resources/failureTests/TestClass2.java",
"src/main/test/resources/failureTests/TestClass3.java",
"src/main/test/resources/failureTests/TestClass4.java",
"src/main/test/resources/failureTests/TestClass5.java",
"src/main/test/resources/failureTests/TestClass6.java",
"src/main/test/resources/failureTests/TestClass7.java",
"src/main/test/resources/failureTests/TestClass8.java",
"src/main/test/resources/failureTests/TestClass9.java",
"src/main/test/resources/failureTests/TestClass10.java",
"src/main/test/resources/failureTests/TestClass11.java"
"src/main/test/resources/input/failureTests/TestClass1.java",
"src/main/test/resources/input/failureTests/TestClass2.java",
"src/main/test/resources/input/failureTests/TestClass3.java",
"src/main/test/resources/input/failureTests/TestClass4.java",
"src/main/test/resources/input/failureTests/TestClass5.java",
"src/main/test/resources/input/failureTests/TestClass6.java",
"src/main/test/resources/input/failureTests/TestClass7.java",
"src/main/test/resources/input/failureTests/TestClass8.java",
"src/main/test/resources/input/failureTests/TestClass9.java",
"src/main/test/resources/input/failureTests/TestClass10.java",
"src/main/test/resources/input/failureTests/TestClass11.java"
);
/**
@ -62,8 +64,8 @@ public class FailureTest {
void typedASTTest() throws IOException {
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java"));
Main.parsefile(codeCharStream);
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/main/EmptyClassExample.java"));
Main.compileFile(codeCharStream, "src/main/test/resources/output");
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}

View File

@ -1,12 +1,8 @@
package main;
import org.junit.jupiter.api.Test;
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 parser.ASTBuilder;
import oldAst.ClassNode;
import oldAst.ProgramNode;
import bytecode.ByteCodeGenerator;
import java.io.IOException;
import java.nio.file.Paths;
@ -21,8 +17,8 @@ public class MainTest {
void testEmptyClass() {
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java"));
Main.parsefile(codeCharStream);
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.java"));
Main.compileFile(codeCharStream, "src/main/test/resources/output");
} catch (IOException e) {
System.err.println("Error reading the file: " + e.getMessage());
}

View File

@ -0,0 +1,45 @@
package main;
/**
* This class is used to test the output of the compiler.
*
* <p>Im gleichen Ordner wie diese Datei (main.TestCompilerOutput.java) muss die selbst kompilierte CompilerInput.class Datei sein.
* <br><strong>Hinweis:</strong> Diese muss man also vom Ordner <code> main/resources/output </code> in diesen Ordner hier (test/java) rein kopieren. (bis es eine bessere Lösung gibt)</p>
*
* <p>Die selbst kompilierte .class Datei wird dann hier drin geladen und eine Instanz von ihr erstellt, es können auch Methoden aufgerufen werden.
* <p>Diese main.TestCompilerOutput.java Datei wird dann in <code> \src\test\java> </code> mit <code>javac .\main.TestCompilerOutput.java</code> kompiliert und mit <code>java main.TestCompilerOutput</code> ausgeführt.
* Wenn unser Compiler funktioniert, sollten keine Errors kommen (sondern nur die Ausgaben, die wir in der CompilerInput.java Datei gemacht haben,
* oder Methoden, die wir hier aufrufen).</p>
*
* <p><strong>PROBLEM:</strong> Hier kommen Errors, was eigentlich heißt, dass der Compiler nicht funktioniert, der Test sollte eigentlich passen.
* <br><strong>DENN:</strong> Wenn ich statt unserem CompilerInput.class die CompilerInput.class von javac verwende (aus <code> src/test/resources/output/javac </code>), dann funktioniert es.</p>
*/
public class TestCompilerOutput {
public static void main(String[] args) {
try {
// Try to load the class named "CompilerInput"
Class<?> cls = Class.forName("CompilerInput");
// Print a success message if the class is loaded successfully
System.out.println("Class loaded successfully: " + cls.getName());
// Try to create an instance of the loaded class
Object instance = cls.getDeclaredConstructor().newInstance();
// Print a success message if the instance is created successfully
System.out.println("Instance created: " + instance);
// If the class has a main method, you can invoke it
// cls.getMethod("main", String[].class).invoke(null, (Object) new String[]{});
// If the class has other methods, you can invoke them as well
// Example: cls.getMethod("someMethod").invoke(instance);
} catch (ClassNotFoundException e) {
// Print an error message if the class is not found
System.err.println("Class not found: " + e.getMessage());
} catch (Exception e) {
// Print an error message if any other exception occurs during class loading or instance creation
System.err.println("Error during class loading or execution: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,185 @@
package parser;
import org.antlr.v4.runtime.*;
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 static org.junit.jupiter.api.Assertions.*;
import java.util.*;
public class ParserTest {
@BeforeEach
public void init() { // noch nicht benötigt
String inputFilePath = "src/main/resources/input/CompilerInput.java";
String outputDirectoryPath = "src/main/resources/output";
}
/**
* This test method is used to test the scanner functionality of the SimpleJavaLexer.
* It creates a CharStream from a string representing a simple Java class declaration,
* and uses the SimpleJavaLexer to tokenize this input.
* It then compares the actual tokens and their types produced by the lexer to the expected tokens and their types.
*/
@Test
public void scannerTest() {
// Create a CharStream from a string representing a simple Java class declaration
CharStream inputCharStream = CharStreams.fromString("public class Name {}");
// Use the SimpleJavaLexer to tokenize the input
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
tokenStream.fill();
// Prepare the expected results
List<Token> actualTokens = tokenStream.getTokens();
List<String> expectedTokens = Arrays.asList("public", "class", "Name", "{", "}", "<EOF>");
List<String> expectedTokenTypes = Arrays.asList(null, null, "IDENTIFIER", null, null, "EOF");
// Compare the actual tokens and their types to the expected tokens and their types
assertEquals(expectedTokens.size(), actualTokens.size());
for (int i = 0; i < expectedTokens.size(); i++) {
assertEquals(expectedTokens.get(i), actualTokens.get(i).getText());
assertEquals(expectedTokenTypes.get(i), SimpleJavaLexer.VOCABULARY.getSymbolicName(actualTokens.get(i).getType()));
}
}
@Test
public void parserTest() {
// init
CharStream inputCharStream = CharStreams.fromString("public class Name {}");
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
tokenStream.fill();
/* Parser -> Parsetree */
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program(); // parse the input
//Variante 1 (geht)
String actualParseTreeAsString = parseTree.toStringTree(parser);
String expectedParseTreeAsString = "(program (classDeclaration (accessType public) class Name { }))";
assertEquals(actualParseTreeAsString, expectedParseTreeAsString);
//Variante 2 (geht nicht)
// - Sollte es gehen und es liegt am Parser? (keine Ahnung) -> Bitte Fehler (actual und expected) durchlesen
Map<String, Object> actualTreeStructure = buildTreeStructure(parseTree, parser);
Map<String, Object> expectedTreeStructure = parseStringToTree(expectedParseTreeAsString);
assertEquals(actualTreeStructure, expectedTreeStructure);
}
@Test
public void astBuilderTest() {
// TODO: Implement this test method
/* AST builder -> AST */
ASTBuilder astBuilder = new ASTBuilder();
// ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
//String actualASTasString = new ASTBuilder().visit(parseTree).toString();
// ProgramNode actualAST = new ASTBuilder().visit(parseTree);
// ProgramNode expectedAST = new ProgramNode();
// expectedAST.add(new ProgramNode.ClassNode("Name", new ProgramNode()));
}
// Helpers Variante 2.1
public static Map<String, Object> buildTreeStructure(ParseTree tree, Parser parser) {
return buildTree(tree, parser, 0);
}
private static Map<String, Object> buildTree(ParseTree tree, Parser parser, int indent) {
Map<String, Object> node = new HashMap<>();
if (tree instanceof RuleContext) {
int ruleIndex = ((RuleContext) tree).getRuleIndex();
String ruleName = parser.getRuleNames()[ruleIndex];
node.put("rule", ruleName);
} else {
node.put("text", tree.getText());
}
List<Map<String, Object>> children = new ArrayList<>();
for (int i = 0; i < tree.getChildCount(); i++) {
children.add(buildTree(tree.getChild(i), parser, indent + 1));
}
if (!children.isEmpty()) {
node.put("children", children);
}
return node;
}
// Helpers Variante 2.2
public static Map<String, Object> parseStringToTree(String input) {
input = input.trim();
if (input.startsWith("(") && input.endsWith(")")) {
input = input.substring(1, input.length() - 1).trim();
}
return parse(input);
}
private static Map<String, Object> parse(String input) {
Map<String, Object> node = new HashMap<>();
StringBuilder currentToken = new StringBuilder();
List<Map<String, Object>> children = new ArrayList<>();
int depth = 0;
boolean inToken = false;
for (char ch : input.toCharArray()) {
if (ch == '(') {
if (depth == 0) {
if (currentToken.length() > 0) {
node.put("node", currentToken.toString().trim());
currentToken.setLength(0);
}
} else {
currentToken.append(ch);
}
depth++;
} else if (ch == ')') {
depth--;
if (depth == 0) {
children.add(parse(currentToken.toString().trim()));
currentToken.setLength(0);
} else {
currentToken.append(ch);
}
} else if (Character.isWhitespace(ch) && depth == 0) {
if (currentToken.length() > 0) {
node.put("node", currentToken.toString().trim());
currentToken.setLength(0);
}
} else {
currentToken.append(ch);
}
}
if (currentToken.length() > 0) {
node.put("node", currentToken.toString().trim());
}
if (!children.isEmpty()) {
node.put("children", children);
}
return node;
}
}

View File

@ -0,0 +1,282 @@
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());
}
@Test
public void wrongTypeInIfClause(){
CharStream codeCharStream = null;
try {
codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/semantic/endToTAST/WrongIfClause.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());
}
}

View File

@ -1,76 +1,103 @@
package semantic;
import oldAst.ClassNode;
import oldAst.expression.LiteralNode;
import oldAst.ProgramNode;
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.AssignmentStatementNode;
import oldAst.statement.StatementNode;
import oldAst.type.*;
import java.util.ArrayList;
import java.util.List;
import ast.*;
import ast.block.BlockNode;
import ast.member.FieldNode;
import ast.member.MethodNode;
import ast.parameter.ParameterNode;
import ast.type.AccessModifierNode;
import ast.type.type.*;
public class Mocker {
public static ProgramNode mockCorrectProgrammNode(){
public static ASTNode mockTwoSameFields(){
ProgramNode p = new ProgramNode();
ProgramNode programNode = new ProgramNode();
List<ClassNode> classList = new ArrayList<ClassNode>();
AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
ClassNode c = new ClassNode();
c.identifier = "testClass";
MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar1");
classNode.members.add(memberNode1);
FieldNode f1 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a");
MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "objectVar");
classNode.members.add(memberNode2);
c.members.add(f1);
List<ParameterNode> parameterNodeList = new ArrayList<ParameterNode>();
ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1");
parameterNodeList.add(parameterNode1);
ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList);
FieldNode f2 = new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a");
List<StatementNode> statementNodeList = new ArrayList<StatementNode>();
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;
c.members.add(f2);
p.classes.add(c);
return p;
}
public static ProgramNode mockFieldNodeAlreadyDeclaredProgrammNode(){
ProgramNode programNode = new ProgramNode();
List<ClassNode> classList = new ArrayList<ClassNode>();
AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
public static ASTNode mockSimpleMethod(){
ProgramNode p = new ProgramNode();
MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar");
classNode.members.add(memberNode1);
ClassNode c = new ClassNode();
MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar");
classNode.members.add(memberNode2);
MethodNode methodNode = new MethodNode();
classList.add(classNode);
programNode.classes = classList;
//Parameter
ParameterNode parameterNode = new ParameterNode(new BaseType(TypeEnum.INT), "a");
return programNode;
methodNode.addParameter(parameterNode);
//Statements
//Block
methodNode.block = new BlockNode();
c.members.add(methodNode);
p.classes.add(c);
return p;
}
public static ASTNode mockTwoSameMethods(){
ProgramNode p = new ProgramNode();
ClassNode c = new ClassNode();
MethodNode methodNode = new MethodNode();
methodNode.block = new BlockNode();
methodNode.setType(new BaseType(TypeEnum.INT));
methodNode.setIdentifier("testMethod");
c.members.add(methodNode);
MethodNode methodNode1 = new MethodNode();
methodNode1.block = new BlockNode();
methodNode1.setType(new BaseType(TypeEnum.INT));
methodNode1.setIdentifier("testMethod");
c.members.add(methodNode1);
p.classes.add(c);
return p;
}
public static ASTNode mockTwoDifferentMethods(){
ProgramNode p = new ProgramNode();
ClassNode c = new ClassNode();
MethodNode methodNode = new MethodNode();
methodNode.block = new BlockNode();
methodNode.setIdentifier("testMethod");
c.members.add(methodNode);
MethodNode methodNode1 = new MethodNode();
methodNode1.block = new BlockNode();
methodNode1.setIdentifier("testMethod1");
c.members.add(methodNode1);
p.classes.add(c);
return p;
}
}

View File

@ -1,162 +1,114 @@
package semantic;
import ast.*;
import ast.member.FieldNode;
import ast.member.MemberNode;
import ast.member.MethodNode;
import ast.parameter.ParameterNode;
import oldAst.*;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
import static org.junit.jupiter.api.Assertions.*;
public class SemanticTest {
@BeforeEach
public void init() {
SemanticAnalyzer.clearAnalyzier();
}
@Test
public void alreadyDeclaredLocalFieldVar() {
//Arrange
ProgramNode programNode = Mocker.mockFieldNodeAlreadyDeclaredProgrammNode();
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException);
assertEquals(null, typedAst);
}
@Test
public void alreadyDecleared() {
//Arrange
ProgramNode programNode = Mocker.mockFieldNodeAlreadyDeclaredProgrammNode();
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(1, SemanticAnalyzer.errors.size());
assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
assertNull(typedAst);
}
@Test
public void shouldWorkWithNoError() {
//Arrange
ProgramNode programNode = Mocker.mockCorrectProgrammNode();
//Act
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//Assert
assertEquals(0, SemanticAnalyzer.errors.size());
assertEquals(programNode, typedAst);
}
@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);
}
// @Test
// public void alreadyDeclaredLocalFieldVar() {
// ProgramNode programNode = new ProgramNode();
// List<ClassNode> classList = new ArrayList<>();
// AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
// ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
//
// SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
// ASTNode tast = semanticAnalyzer.generateTast(ast);
//
// MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar");
// classNode.members.add(memberNode2);
//
// classList.add(classNode);
// programNode.classes = classList;
//
// ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//
// assertEquals(1, SemanticAnalyzer.errors.size());
// assertInstanceOf(AlreadyDeclearedException.class, SemanticAnalyzer.errors.getFirst());
// assertNull(typedAst);
// }
//
// @Test
// public void shouldWorkWithNoError() {
// ProgramNode programNode = new ProgramNode();
// List<ClassNode> classList = new ArrayList<>();
// AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
// ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
//
// SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
// ASTNode tast = semanticAnalyzer.generateTast(ast);
//
// assertEquals(semanticAnalyzer.errors.size(), 0);
// assertNotNull(tast);
//
// MemberNode memberNode3 = getMemberNode(accessTypeNode);
// classNode.members.add(memberNode3);
//
// classList.add(classNode);
// programNode.classes = classList;
//
// ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
//
// assertEquals(0, SemanticAnalyzer.errors.size());
// assertEquals(programNode, typedAst);
// }
//
// /**
// * This method is used to create a MemberNode representing a method.
// * It first creates a list of ParameterNodes and adds a ParameterNode to it.
// * Then, it creates a ParameterListNode using the list of ParameterNodes.
// * After that, it creates a list of StatementNodes and adds a StatementNode to it by calling the getStatementNode method.
// * Finally, it creates a MethodNode using the provided AccessTypeNode, a BaseTypeNode representing the return type of the method,
// * the method name, the ParameterListNode, and the list of StatementNodes, and returns this MethodNode.
// *
// * @param accessTypeNode The AccessTypeNode representing the access type of the method.
// * @return The created MemberNode representing the method.
// */
//private static MemberNode getMemberNode(AccessTypeNode accessTypeNode) {
// List<ParameterNode> parameterNodeList = new ArrayList<>();
// ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1");
// parameterNodeList.add(parameterNode1);
// ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList);
//
// List<StatementNode> statementNodeList = new ArrayList<>();
//
// StatementNode statementNode1 = getStatementNode();
// statementNodeList.add(statementNode1);
//
// return new MethodNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2", parameterListNode, statementNodeList);
//}
//
// /**
// * This method is used to create a StatementNode for an assignment operation.
// * It first creates two IdentifierExpressionNodes for 'this' and 'objectVar'.
// * Then, it creates a BinaryExpressionNode to represent the operation 'this.objectVar'.
// * After that, it creates a LiteralNode to represent the integer value 1.
// * Finally, it creates another BinaryExpressionNode to represent the assignment operation 'this.objectVar = 1',
// * and wraps this expression in an AssignmentStatementNode.
// *
// * @return The created AssignmentStatementNode representing the assignment operation 'this.objectVar = 1'.
// */
//private static StatementNode getStatementNode() {
// ExpressionNode expressionNodeObjectVariableLeft = new IdentifierExpressionNode("this");
// ExpressionNode expressionNodeObjectVariableRight = new IdentifierExpressionNode("objectVar");
//
// ExpressionNode expressionNodeLeft = new BinaryExpressionNode(expressionNodeObjectVariableLeft, expressionNodeObjectVariableRight, ExpresssionOperator.DOT);
//
// ExpressionNode expressionNodeRight = new LiteralNode(1);
//
// BinaryExpressionNode expressionNode = new BinaryExpressionNode(expressionNodeLeft, expressionNodeRight, ExpresssionOperator.ASSIGNMENT);
//
// return new AssignmentStatementNode(expressionNode);
//}
}

View File

@ -0,0 +1,16 @@
public class CompilerInput {
public int a;
public static int testMethod(char x){
return 0;
}
public class Test {
public static int testMethod(char x, int a){
return 0;
}
}
}

Some files were not shown because too many files have changed in this diff Show More