Merge branch 'main' into code-generator
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
This commit is contained in:
commit
fb3f822160
8
.gitignore
vendored
8
.gitignore
vendored
@ -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
32
pom.xml
@ -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>
|
@ -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);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
package ast;
|
||||
|
||||
public class IdentifierNode {
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
package ast.expression;
|
||||
|
||||
import visitor.Visitable;
|
||||
|
||||
public abstract class ExpressionNode implements Visitable {
|
||||
}
|
11
src/main/java/ast/expression/IExpressionNode.java
Normal file
11
src/main/java/ast/expression/IExpressionNode.java
Normal 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();
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package ast.expression.binaryexpression;
|
||||
|
||||
public class BinaryExpression {
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
package ast.expression.binaryexpression;
|
||||
|
||||
public enum EnumDotOperator {
|
||||
MULT, DIV, MOD
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ast.expression.binaryexpression;
|
||||
|
||||
public enum EnumLineOperator {
|
||||
PLUS, MINUS
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ast.expression.binaryexpression;
|
||||
|
||||
public enum EnumNonCalculationOperator {
|
||||
AND, OR, GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL
|
||||
}
|
@ -1,17 +1,50 @@
|
||||
package ast.expression.binaryexpression;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,4 +16,5 @@ public class MemberAccessNode implements ASTNode {
|
||||
public void addIdentifier(String identifier) {
|
||||
identifiers.add(identifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
11
src/main/java/ast/member/MainMethodNode.java
Normal file
11
src/main/java/ast/member/MainMethodNode.java
Normal file
@ -0,0 +1,11 @@
|
||||
package ast.member;
|
||||
|
||||
import ast.block.BlockNode;
|
||||
|
||||
public class MainMethodNode extends MethodNode {
|
||||
public BlockNode block;
|
||||
|
||||
public MainMethodNode(BlockNode block) {
|
||||
this.block = block;
|
||||
}
|
||||
}
|
@ -3,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
7
src/main/java/ast/statement/IStatementNode.java
Normal file
7
src/main/java/ast/statement/IStatementNode.java
Normal file
@ -0,0 +1,7 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.ASTNode;
|
||||
import visitor.Visitable;
|
||||
|
||||
public interface IStatementNode extends ASTNode, Visitable {
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import visitor.Visitable;
|
||||
|
||||
public abstract class StatementNode implements Visitable {
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
package ast.statement.statementexpression;
|
||||
|
||||
import ast.statement.IStatementNode;
|
||||
|
||||
public interface IStatementExpressionNode extends IStatementNode {}
|
@ -1,5 +0,0 @@
|
||||
package ast.statement.statementexpression;
|
||||
|
||||
public class IncrementExpression {
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -1,5 +0,0 @@
|
||||
package ast.type;
|
||||
|
||||
public enum EnumTypeNode {
|
||||
INT, BOOLEAN, CHAR, IDENTIFIER
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package ast.type;
|
||||
|
||||
public class TypeNode {
|
||||
public EnumTypeNode type;
|
||||
|
||||
public TypeNode(String type) {
|
||||
setType(type);
|
||||
}
|
||||
|
||||
private void setType(String type) {
|
||||
switch(type) {
|
||||
case "int":
|
||||
this.type = EnumTypeNode.INT;
|
||||
break;
|
||||
case "boolean":
|
||||
this.type = EnumTypeNode.BOOLEAN;
|
||||
break;
|
||||
case "char":
|
||||
this.type = EnumTypeNode.CHAR;
|
||||
break;
|
||||
default:
|
||||
this.type = EnumTypeNode.IDENTIFIER;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
30
src/main/java/ast/type/type/BaseType.java
Normal file
30
src/main/java/ast/type/type/BaseType.java
Normal file
@ -0,0 +1,30 @@
|
||||
package ast.type.type;
|
||||
|
||||
public class BaseType implements ITypeNode {
|
||||
|
||||
private TypeEnum typeEnum;
|
||||
|
||||
public BaseType(TypeEnum typeEnum) {
|
||||
this.typeEnum = typeEnum;
|
||||
}
|
||||
|
||||
public TypeEnum getTypeEnum() {
|
||||
return typeEnum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BaseType other = (BaseType) obj;
|
||||
if (typeEnum != other.typeEnum)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
5
src/main/java/ast/type/type/ITypeNode.java
Normal file
5
src/main/java/ast/type/type/ITypeNode.java
Normal file
@ -0,0 +1,5 @@
|
||||
package ast.type.type;
|
||||
|
||||
public interface ITypeNode {
|
||||
|
||||
}
|
33
src/main/java/ast/type/type/ReferenceType.java
Normal file
33
src/main/java/ast/type/type/ReferenceType.java
Normal file
@ -0,0 +1,33 @@
|
||||
package ast.type.type;
|
||||
|
||||
public class ReferenceType implements ITypeNode{
|
||||
|
||||
private String identifier;
|
||||
|
||||
public ReferenceType(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ReferenceType other = (ReferenceType) obj;
|
||||
if (identifier == null) {
|
||||
if (other.identifier != null)
|
||||
return false;
|
||||
} else if (!identifier.equals(other.identifier))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
9
src/main/java/ast/type/type/TypeEnum.java
Normal file
9
src/main/java/ast/type/type/TypeEnum.java
Normal file
@ -0,0 +1,9 @@
|
||||
package ast.type.type;
|
||||
|
||||
public enum TypeEnum {
|
||||
VOID,
|
||||
INT,
|
||||
CHAR,
|
||||
BOOL;
|
||||
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
// }
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Binary file not shown.
108
src/main/java/main/Main.java
Normal file
108
src/main/java/main/Main.java
Normal 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();
|
||||
}
|
||||
}
|
180
src/main/java/main/RaupenLogger.java
Normal file
180
src/main/java/main/RaupenLogger.java
Normal 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);
|
||||
// }
|
||||
}
|
||||
}
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
@ -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 {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package semantic.context;
|
||||
|
||||
import oldAst.ProgramNode;
|
||||
import ast.ProgramNode;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Context {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
package semantic.exeptions;
|
||||
|
||||
public class AlreadyDefinedException extends RuntimeException {
|
||||
|
||||
public AlreadyDefinedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package semantic.exeptions;
|
||||
|
||||
public class MultipleReturnTypes extends RuntimeException {
|
||||
|
||||
public MultipleReturnTypes(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
package typechecker;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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){
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
16
src/main/resources/input/CompilerInput.java
Normal file
16
src/main/resources/input/CompilerInput.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -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
29
src/test/Makefile
Normal 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
|
||||
|
@ -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
|
@ -1,3 +1,5 @@
|
||||
package main;
|
||||
|
||||
public class EmptyClassExample {
|
||||
private class Inner {
|
||||
}
|
@ -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());
|
||||
}
|
@ -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());
|
||||
}
|
45
src/test/java/main/TestCompilerOutput.java
Normal file
45
src/test/java/main/TestCompilerOutput.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
185
src/test/java/parser/ParserTest.java
Normal file
185
src/test/java/parser/ParserTest.java
Normal 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;
|
||||
}
|
||||
}
|
282
src/test/java/semantic/EndToTAST.java
Normal file
282
src/test/java/semantic/EndToTAST.java
Normal 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());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
//}
|
||||
}
|
||||
|
16
src/test/resources/input/CompilerInput.java
Normal file
16
src/test/resources/input/CompilerInput.java
Normal 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
Loading…
Reference in New Issue
Block a user