Compare commits
14 Commits
1d5bfdd88f
...
1c77a99f54
Author | SHA1 | Date | |
---|---|---|---|
1c77a99f54 | |||
|
c483babaf5 | ||
|
403ab70655 | ||
|
d91e3ad819 | ||
|
8b9b70b9ee | ||
|
7906a38cdd | ||
|
dd424cda99 | ||
|
f781d8eeb6 | ||
|
8b6189ea33 | ||
|
1d9d7e1f00 | ||
|
e4d0b93880 | ||
|
584dcc6beb | ||
|
275eceb80a | ||
|
9d6717a9ce |
15
.gitea/workflows/test.yml
Normal file
15
.gitea/workflows/test.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
name: Gitea Actions Demo
|
||||||
|
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Explore-Gitea-Actions:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Run the Maven verify phase
|
||||||
|
run: mvn --batch-mode --update-snapshots verify
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -40,7 +40,7 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="openjdk-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,18 +1,21 @@
|
|||||||
import ast.ASTNode;
|
import ast.ASTNode;
|
||||||
import ast.ClassNode;
|
import org.antlr.v4.runtime.*;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
import ast.ProgramNode;
|
import ast.ProgramNode;
|
||||||
import bytecode.ByteCodeGenerator;
|
import bytecode.ByteCodeGenerator;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
import parser.ASTBuilder;
|
import parser.ASTBuilder;
|
||||||
import parser.generated.SimpleJavaLexer;
|
import parser.generated.SimpleJavaLexer;
|
||||||
import parser.generated.SimpleJavaParser;
|
import parser.generated.SimpleJavaParser;
|
||||||
import semantic.SemanticAnalyzer;
|
import semantic.SemanticAnalyzer;
|
||||||
|
import bytecode.ByteCodeGenerator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
@ -30,20 +33,103 @@ public class Main {
|
|||||||
|
|
||||||
|
|
||||||
static void parseFile(CharStream codeCharStream) {
|
static void parseFile(CharStream codeCharStream) {
|
||||||
|
/* ------------------------- Scanner -> tokens ------------------------- */
|
||||||
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||||
SimpleJavaParser parser = new SimpleJavaParser(tokens);
|
|
||||||
|
|
||||||
ParseTree tree = parser.program(); // parse the input
|
// 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();
|
||||||
|
|
||||||
ASTBuilder builder = new ASTBuilder();
|
/* ------------------------- Parser -> Parsetree ------------------------- */
|
||||||
ProgramNode ast = (ProgramNode) builder.visit(tree); // build the AST
|
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
|
||||||
|
ParseTree parseTree = parser.program(); // parse the input
|
||||||
|
|
||||||
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(ast);
|
// 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 byteCodeGenerator = new ByteCodeGenerator();
|
||||||
if (typedAst != null)
|
//byteCodeGenerator.generateByteCode(abstractSyntaxTree);
|
||||||
byteCodeGenerator.visit(typedAst);
|
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,7 +1,12 @@
|
|||||||
package ast;
|
package ast;
|
||||||
|
|
||||||
public interface ASTNode {
|
//import java.util.List;
|
||||||
|
|
||||||
|
public interface ASTNode {
|
||||||
|
/**
|
||||||
|
* Please implement this method to return a list of children of each node.
|
||||||
|
*/
|
||||||
|
// public List<ASTNode> getChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
package ast;
|
|
||||||
|
|
||||||
import semantic.SemanticVisitor;
|
|
||||||
import typechecker.TypeCheckResult;
|
|
||||||
import visitor.Visitable;
|
|
||||||
|
|
||||||
public class VarNode implements ASTNode, Visitable {
|
|
||||||
|
|
||||||
private String identifier;
|
|
||||||
private String type;
|
|
||||||
|
|
||||||
public VarNode(String type, String identifier){
|
|
||||||
this.type = type;
|
|
||||||
this.identifier = identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType(){
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentifier(){
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
|
||||||
return visitor.analyze(this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,9 +7,9 @@ import visitor.Visitable;
|
|||||||
public class BinaryExpressionNode implements ExpressionNode, Visitable {
|
public class BinaryExpressionNode implements ExpressionNode, Visitable {
|
||||||
public ExpressionNode left;
|
public ExpressionNode left;
|
||||||
public ExpressionNode right;
|
public ExpressionNode right;
|
||||||
public String operator; // Stores the operator as a string (e.g., "+", "-", "&&")
|
public ExpresssionOperator operator; // Stores the operator as a string (e.g., "+", "-", "&&")
|
||||||
|
|
||||||
public BinaryExpressionNode(ExpressionNode left, ExpressionNode right, String operator) {
|
public BinaryExpressionNode(ExpressionNode left, ExpressionNode right, ExpresssionOperator operator) {
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
|
14
src/main/java/ast/expression/ExpresssionOperator.java
Normal file
14
src/main/java/ast/expression/ExpresssionOperator.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package ast.expression;
|
||||||
|
|
||||||
|
public enum ExpresssionOperator {
|
||||||
|
DOT, // .
|
||||||
|
PLUS, // +
|
||||||
|
MINUS, // -
|
||||||
|
MULTIPLY, // *
|
||||||
|
DIVIDE, // /
|
||||||
|
NOT, // !
|
||||||
|
ASSIGNMENT, // =
|
||||||
|
EQUALS, // ==
|
||||||
|
UNEQUALS, // !=
|
||||||
|
ERROR //TODO: Remove This
|
||||||
|
}
|
@ -18,3 +18,5 @@ public class UnaryExpressionNode implements ExpressionNode, Visitable {
|
|||||||
return visitor.analyze(this);
|
return visitor.analyze(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package ast.statement;
|
package ast.statement;
|
||||||
|
|
||||||
import ast.VarNode;
|
import ast.expression.BinaryExpressionNode;
|
||||||
import ast.expression.ExpressionNode;
|
|
||||||
import semantic.SemanticVisitor;
|
import semantic.SemanticVisitor;
|
||||||
import typechecker.TypeCheckResult;
|
import typechecker.TypeCheckResult;
|
||||||
import visitor.Visitable;
|
import visitor.Visitable;
|
||||||
|
|
||||||
public class AssignmentStatementNode extends StatementNode implements Visitable {
|
public class AssignmentStatementNode extends StatementNode implements Visitable {
|
||||||
public VarNode varNode;
|
public BinaryExpressionNode expression;
|
||||||
public ExpressionNode expression;
|
|
||||||
|
|
||||||
public AssignmentStatementNode(VarNode varNode, ExpressionNode expression) {
|
public AssignmentStatementNode(BinaryExpressionNode expression) {
|
||||||
this.varNode = varNode;
|
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -3,6 +3,7 @@ package parser;
|
|||||||
import ast.*;
|
import ast.*;
|
||||||
import ast.expression.BinaryExpressionNode;
|
import ast.expression.BinaryExpressionNode;
|
||||||
import ast.expression.ExpressionNode;
|
import ast.expression.ExpressionNode;
|
||||||
|
import ast.expression.ExpresssionOperator;
|
||||||
import ast.expression.IdentifierExpressionNode;
|
import ast.expression.IdentifierExpressionNode;
|
||||||
import ast.expression.UnaryExpressionNode;
|
import ast.expression.UnaryExpressionNode;
|
||||||
import ast.member.FieldNode;
|
import ast.member.FieldNode;
|
||||||
@ -137,14 +138,14 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ASTNode visitAssignmentStatement(SimpleJavaParser.AssignmentStatementContext ctx) {
|
public ASTNode visitAssignmentStatement(SimpleJavaParser.AssignmentStatementContext ctx) {
|
||||||
VarNode varNode = (VarNode) visit(ctx.var());
|
|
||||||
ExpressionNode expression = (ExpressionNode) visit(ctx.expression());
|
BinaryExpressionNode expression = (BinaryExpressionNode) visit(ctx.expression());
|
||||||
return new AssignmentStatementNode(varNode, expression);
|
return new AssignmentStatementNode(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ASTNode visitVar(SimpleJavaParser.VarContext ctx) {
|
public ASTNode visitVar(SimpleJavaParser.VarContext ctx) {
|
||||||
return new VarNode("int", ctx.getText());
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -180,8 +181,7 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
|||||||
if (ctx.getChildCount() == 3 && ctx.getChild(1) instanceof TerminalNode) {
|
if (ctx.getChildCount() == 3 && ctx.getChild(1) instanceof TerminalNode) {
|
||||||
ExpressionNode left = (ExpressionNode) visit(ctx.expression(0));
|
ExpressionNode left = (ExpressionNode) visit(ctx.expression(0));
|
||||||
ExpressionNode right = (ExpressionNode) visit(ctx.expression(1));
|
ExpressionNode right = (ExpressionNode) visit(ctx.expression(1));
|
||||||
String operator = ctx.getChild(1).getText();
|
return new BinaryExpressionNode(left, right, ExpresssionOperator.ERROR);
|
||||||
return new BinaryExpressionNode(left, right, operator);
|
|
||||||
}
|
}
|
||||||
// Handle unary operations
|
// Handle unary operations
|
||||||
else if (ctx.getChildCount() == 2) {
|
else if (ctx.getChildCount() == 2) {
|
||||||
|
@ -22,12 +22,12 @@ import typechecker.TypeCheckResult;
|
|||||||
|
|
||||||
public class SemanticAnalyzer implements SemanticVisitor {
|
public class SemanticAnalyzer implements SemanticVisitor {
|
||||||
|
|
||||||
private ArrayList<String> currentFields = new ArrayList<>();
|
private static ArrayList<String> currentFields = new ArrayList<>();
|
||||||
|
|
||||||
public static ArrayList<Exception> errors = new ArrayList<>();
|
public static ArrayList<Exception> errors = new ArrayList<>();
|
||||||
|
|
||||||
private Scope currentScope;
|
private static Scope currentScope;
|
||||||
private ClassNode currentClass;
|
private static ClassNode currentClass;
|
||||||
|
|
||||||
public static ASTNode generateTast(ASTNode node) {
|
public static ASTNode generateTast(ASTNode node) {
|
||||||
SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
|
SemanticAnalyzer semanticCheck = new SemanticAnalyzer();
|
||||||
@ -43,6 +43,13 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void clearAnalyzier(){
|
||||||
|
currentFields.clear();
|
||||||
|
errors.clear();
|
||||||
|
currentScope = null;
|
||||||
|
currentClass = null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(ProgramNode node) {
|
public TypeCheckResult analyze(ProgramNode node) {
|
||||||
|
|
||||||
@ -138,21 +145,17 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(AssignmentStatementNode assignmentStatementNode) {
|
public TypeCheckResult analyze(AssignmentStatementNode assignmentStatementNode) {
|
||||||
if (assignmentStatementNode.expression instanceof LiteralNode literalNode) {
|
boolean valid = true;
|
||||||
TypeCheckResult varResult = assignmentStatementNode.varNode.accept(this);
|
BinaryExpressionNode binaryExpressionNode = assignmentStatementNode.expression;
|
||||||
TypeCheckResult expressionResult = assignmentStatementNode.expression.accept(this);
|
var result = binaryExpressionNode.accept(this);
|
||||||
}
|
valid = valid && result.isValid();
|
||||||
return new TypeCheckResult(true, null);
|
return new TypeCheckResult(valid, null);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult analyze(VarNode toCheck) {
|
|
||||||
return new TypeCheckResult(true, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult analyze(BinaryExpressionNode toCheck) {
|
public TypeCheckResult analyze(BinaryExpressionNode toCheck) {
|
||||||
return null;
|
boolean valid = true;
|
||||||
|
return new TypeCheckResult(valid, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,7 +3,6 @@ package semantic;
|
|||||||
|
|
||||||
import ast.ClassNode;
|
import ast.ClassNode;
|
||||||
import ast.ProgramNode;
|
import ast.ProgramNode;
|
||||||
import ast.VarNode;
|
|
||||||
import ast.expression.BinaryExpressionNode;
|
import ast.expression.BinaryExpressionNode;
|
||||||
import ast.expression.IdentifierExpressionNode;
|
import ast.expression.IdentifierExpressionNode;
|
||||||
import ast.expression.UnaryExpressionNode;
|
import ast.expression.UnaryExpressionNode;
|
||||||
@ -24,8 +23,6 @@ public interface SemanticVisitor {
|
|||||||
|
|
||||||
TypeCheckResult analyze(AssignmentStatementNode toCheck);
|
TypeCheckResult analyze(AssignmentStatementNode toCheck);
|
||||||
|
|
||||||
TypeCheckResult analyze(VarNode toCheck);
|
|
||||||
|
|
||||||
TypeCheckResult analyze(BinaryExpressionNode toCheck);
|
TypeCheckResult analyze(BinaryExpressionNode toCheck);
|
||||||
|
|
||||||
TypeCheckResult analyze(IdentifierExpressionNode toCheck);
|
TypeCheckResult analyze(IdentifierExpressionNode toCheck);
|
||||||
|
@ -2,9 +2,17 @@ public class Example {
|
|||||||
|
|
||||||
public int a;
|
public int a;
|
||||||
|
|
||||||
public static int testMethod(char x, int a){
|
public static int testMethod(char x){
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
public static int testMethod(char x, int a){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,6 +17,12 @@
|
|||||||
## Scanner Output
|
## Scanner Output
|
||||||
### Beispiel 1: Empty Class
|
### 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]
|
[TokPublic,TokClass,TokIdentifier "Name",TokLeftBrace,TokRightBrace]
|
||||||
|
|
||||||
### Beispiel 2: Filled Class
|
### Beispiel 2: Filled Class
|
BIN
src/main/test/java/EmptyClassExample.class
Normal file
BIN
src/main/test/java/EmptyClassExample.class
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
public class EmptyClassExample {
|
public class EmptyClassExample {
|
||||||
private class Inner {
|
private class Inner {
|
||||||
}
|
}
|
||||||
}
|
} // -o für outout
|
72
src/main/test/java/FailureTest.java
Normal file
72
src/main/test/java/FailureTest.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
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"
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test method checks if invalid Java files fail to compile as expected.
|
||||||
|
* It uses the JavaCompiler from the ToolProvider to compile the files.
|
||||||
|
* The test passes if all the files fail to compile.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void invalidJavaFilesTest() {
|
||||||
|
// Get the system Java compiler
|
||||||
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
|
||||||
|
// Assert that the compiler is available
|
||||||
|
assertNotNull(compiler, "Java Compiler is not available");
|
||||||
|
|
||||||
|
// Iterate over the test files
|
||||||
|
for (String fileName : TEST_FILES) {
|
||||||
|
// Create a File object for the current file
|
||||||
|
File file = new File(fileName);
|
||||||
|
|
||||||
|
// Try to compile the file and get the result
|
||||||
|
// The run method returns 0 if the compilation was successful, and non-zero otherwise
|
||||||
|
int result = compiler.run(null, null, null, file.getPath());
|
||||||
|
|
||||||
|
// Assert that the compilation failed (i.e., the result is non-zero)
|
||||||
|
assertTrue(result != 0, "Expected compilation failure for " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// schmeißt John Fehler, wenn namen doppelt sind?
|
||||||
|
// Input: ParseTree mit genanntem Fehler
|
||||||
|
// Output: Fehlermeldung
|
||||||
|
@Test
|
||||||
|
void typedASTTest() throws IOException {
|
||||||
|
CharStream codeCharStream = null;
|
||||||
|
try {
|
||||||
|
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java"));
|
||||||
|
Main.parsefile(codeCharStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error reading the file: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ public class MainTest {
|
|||||||
void testEmptyClass() {
|
void testEmptyClass() {
|
||||||
CharStream codeCharStream = null;
|
CharStream codeCharStream = null;
|
||||||
try {
|
try {
|
||||||
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/java/EmptyClassExample.java"));
|
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/EmptyClassExample.java"));
|
||||||
Main.parsefile(codeCharStream);
|
Main.parsefile(codeCharStream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Error reading the file: " + e.getMessage());
|
System.err.println("Error reading the file: " + e.getMessage());
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
public class Tester {
|
public class Tester {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new EmptyClassExample();
|
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
|
0
src/main/test/java/make.md
Normal file
0
src/main/test/java/make.md
Normal file
@ -1,3 +1,5 @@
|
|||||||
|
package resources;
|
||||||
|
|
||||||
public class AllFeaturesClassExample {
|
public class AllFeaturesClassExample {
|
||||||
int a;
|
int a;
|
||||||
boolean b;
|
boolean b;
|
25
src/main/test/resources/CombinedExample.java
Normal file
25
src/main/test/resources/CombinedExample.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package resources;
|
||||||
|
|
||||||
|
public class CombinedExample {
|
||||||
|
int number;
|
||||||
|
boolean flag;
|
||||||
|
char letter;
|
||||||
|
|
||||||
|
public CombinedExample(int number, boolean flag, char letter) {
|
||||||
|
this.number = number;
|
||||||
|
this.flag = flag;
|
||||||
|
this.letter = letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void displayValues() {
|
||||||
|
System.out.println("Number: " + number);
|
||||||
|
System.out.println("Flag: " + flag);
|
||||||
|
System.out.println("Letter: " + letter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CombinedExample obj = new CombinedExample(10, true, 'X');
|
||||||
|
obj.displayValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
|||||||
|
package resources;
|
||||||
|
|
||||||
public class MoreFeaturesClassExample {
|
public class MoreFeaturesClassExample {
|
||||||
int hallo;
|
int hallo;
|
||||||
private class Inner {
|
private class Inner {
|
6
src/main/test/resources/failureTests/TestClass1.java
Normal file
6
src/main/test/resources/failureTests/TestClass1.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Syntax Error: Missing semicolon
|
||||||
|
public class TestClass1 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!") // Missing semicolon here
|
||||||
|
}
|
||||||
|
}
|
10
src/main/test/resources/failureTests/TestClass10.java
Normal file
10
src/main/test/resources/failureTests/TestClass10.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Semantic Error: Non-static method called from static context
|
||||||
|
public class TestClass10 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
greet(); // Non-static method 'greet' cannot be referenced from a static context
|
||||||
|
}
|
||||||
|
|
||||||
|
public void greet() {
|
||||||
|
System.out.println("Hi!");
|
||||||
|
}
|
||||||
|
}
|
10
src/main/test/resources/failureTests/TestClass11.java
Normal file
10
src/main/test/resources/failureTests/TestClass11.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//Compile error: (4, 9) java: variable number is already defined in method main(java.lang.String[])
|
||||||
|
public class TestClass10 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Declare and initialize an integer variable named 'number' with the value 12
|
||||||
|
int number = 12;
|
||||||
|
|
||||||
|
// This line will cause a compile-time error because 'number' is already defined in this scope
|
||||||
|
int number =13;
|
||||||
|
}
|
||||||
|
}
|
6
src/main/test/resources/failureTests/TestClass2.java
Normal file
6
src/main/test/resources/failureTests/TestClass2.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Syntax Error: Unclosed string literal
|
||||||
|
public class TestClass2 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!); // Unclosed string literal
|
||||||
|
}
|
||||||
|
}
|
10
src/main/test/resources/failureTests/TestClass3.java
Normal file
10
src/main/test/resources/failureTests/TestClass3.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Syntax Error: Missing parentheses in method declaration
|
||||||
|
public class TestClass3 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void greet { // Missing parentheses
|
||||||
|
System.out.println("Hi!");
|
||||||
|
}
|
||||||
|
}
|
4
src/main/test/resources/failureTests/TestClass4.java
Normal file
4
src/main/test/resources/failureTests/TestClass4.java
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Syntax Error: Missing class body
|
||||||
|
public class TestClass4 {-
|
||||||
|
// Missing class body
|
||||||
|
}
|
7
src/main/test/resources/failureTests/TestClass5.java
Normal file
7
src/main/test/resources/failureTests/TestClass5.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Semantic Error: Variable used before declaration
|
||||||
|
public class TestClass5 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(number); // Variable 'number' used before declaration
|
||||||
|
int number = 10;
|
||||||
|
}
|
||||||
|
}
|
10
src/main/test/resources/failureTests/TestClass6.java
Normal file
10
src/main/test/resources/failureTests/TestClass6.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Semantic Error: Method with wrong return type
|
||||||
|
public class TestClass6 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int greet() { // Method should return int, but no return statement is provided
|
||||||
|
System.out.println("Hi!");
|
||||||
|
}
|
||||||
|
}
|
5
src/main/test/resources/failureTests/TestClass7.java
Normal file
5
src/main/test/resources/failureTests/TestClass7.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Syntax Error: Unmatched braces
|
||||||
|
public class TestClass7 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!");
|
||||||
|
// Missing closing brace for the class
|
14
src/main/test/resources/failureTests/TestClass8.java
Normal file
14
src/main/test/resources/failureTests/TestClass8.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Semantic Error: Duplicate method definition
|
||||||
|
public class TestClass8 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void greet() {
|
||||||
|
System.out.println("Hi!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void greet() { // Duplicate method definition
|
||||||
|
System.out.println("Hello!");
|
||||||
|
}
|
||||||
|
}
|
6
src/main/test/resources/failureTests/TestClass9.java
Normal file
6
src/main/test/resources/failureTests/TestClass9.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Syntax Error: Incompatible types
|
||||||
|
public class TestClass9 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int number = "Hello"; // Incompatible types: String cannot be converted to int
|
||||||
|
}
|
||||||
|
}
|
24
src/main/test/resources/featureTests/BooleanOperations.java
Normal file
24
src/main/test/resources/featureTests/BooleanOperations.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package resources.featureTests;
|
||||||
|
|
||||||
|
public class BooleanOperations {
|
||||||
|
boolean flag;
|
||||||
|
|
||||||
|
public BooleanOperations(boolean flag) {
|
||||||
|
this.flag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFlag() {
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleFlag() {
|
||||||
|
flag = !flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BooleanOperations obj = new BooleanOperations(true);
|
||||||
|
System.out.println(obj.isFlag());
|
||||||
|
obj.toggleFlag();
|
||||||
|
System.out.println(obj.isFlag());
|
||||||
|
}
|
||||||
|
}
|
24
src/main/test/resources/featureTests/CharManipulation.java
Normal file
24
src/main/test/resources/featureTests/CharManipulation.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package resources.featureTests;
|
||||||
|
|
||||||
|
public class CharManipulation {
|
||||||
|
char letter;
|
||||||
|
|
||||||
|
public CharManipulation(char letter) {
|
||||||
|
this.letter = letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getLetter() {
|
||||||
|
return letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLetter(char letter) {
|
||||||
|
this.letter = letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CharManipulation obj = new CharManipulation('A');
|
||||||
|
System.out.println(obj.getLetter());
|
||||||
|
obj.setLetter('B');
|
||||||
|
System.out.println(obj.getLetter());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package resources.featureTests;
|
||||||
|
|
||||||
|
public class ConditionalStatements {
|
||||||
|
int number;
|
||||||
|
|
||||||
|
public ConditionalStatements(int number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkNumber() {
|
||||||
|
if (number > 0) {
|
||||||
|
System.out.println("The number is positive.");
|
||||||
|
} else if (number < 0) {
|
||||||
|
System.out.println("The number is negative.");
|
||||||
|
} else {
|
||||||
|
System.out.println("The number is zero.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ConditionalStatements obj1 = new ConditionalStatements(5);
|
||||||
|
ConditionalStatements obj2 = new ConditionalStatements(-3);
|
||||||
|
ConditionalStatements obj3 = new ConditionalStatements(0);
|
||||||
|
|
||||||
|
obj1.checkNumber();
|
||||||
|
obj2.checkNumber();
|
||||||
|
obj3.checkNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
18
src/main/test/resources/featureTests/LoopExamples.java
Normal file
18
src/main/test/resources/featureTests/LoopExamples.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package resources.featureTests;
|
||||||
|
|
||||||
|
public class LoopExamples {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// For loop example
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
System.out.println("For loop iteration: " + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// While loop example
|
||||||
|
int j = 0;
|
||||||
|
while (j < 5) {
|
||||||
|
System.out.println("While loop iteration: " + j);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
18
src/main/test/resources/featureTests/MethodOverloading.java
Normal file
18
src/main/test/resources/featureTests/MethodOverloading.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package resources.featureTests;
|
||||||
|
|
||||||
|
public class MethodOverloading {
|
||||||
|
public int add(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int add(int a, int b, int c) {
|
||||||
|
return a + b + c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
MethodOverloading obj = new MethodOverloading();
|
||||||
|
System.out.println("Sum of 2 and 3: " + obj.add(2, 3));
|
||||||
|
System.out.println("Sum of 1, 2, and 3: " + obj.add(1, 2, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
107
src/test/java/semantic/SemanticTest.java
Normal file
107
src/test/java/semantic/SemanticTest.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package semantic;
|
||||||
|
|
||||||
|
|
||||||
|
import ast.*;
|
||||||
|
import ast.expression.BinaryExpressionNode;
|
||||||
|
import ast.expression.ExpressionNode;
|
||||||
|
import ast.expression.ExpresssionOperator;
|
||||||
|
import ast.expression.IdentifierExpressionNode;
|
||||||
|
import ast.member.FieldNode;
|
||||||
|
import ast.member.MemberNode;
|
||||||
|
import ast.member.MethodNode;
|
||||||
|
import ast.parameter.ParameterListNode;
|
||||||
|
import ast.parameter.ParameterNode;
|
||||||
|
import ast.statement.AssignmentStatementNode;
|
||||||
|
import ast.statement.StatementNode;
|
||||||
|
import ast.type.AccessTypeNode;
|
||||||
|
import ast.type.BaseTypeNode;
|
||||||
|
import ast.type.EnumAccessTypeNode;
|
||||||
|
import ast.type.EnumTypeNode;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import semantic.exeptions.AlreadyDeclearedException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class SemanticTest {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void init() {
|
||||||
|
SemanticAnalyzer.clearAnalyzier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void alreadyDeclaredLocalFieldVar(){
|
||||||
|
|
||||||
|
ProgramNode programNode = new ProgramNode();
|
||||||
|
List<ClassNode> classList = new ArrayList<ClassNode>();
|
||||||
|
AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
|
||||||
|
ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
|
||||||
|
|
||||||
|
MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar");
|
||||||
|
classNode.members.add(memberNode1);
|
||||||
|
|
||||||
|
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());
|
||||||
|
assertEquals(true, SemanticAnalyzer.errors.get(0) instanceof AlreadyDeclearedException);
|
||||||
|
assertEquals(null, typedAst);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldWorkWithNoError(){
|
||||||
|
|
||||||
|
ProgramNode programNode = new ProgramNode();
|
||||||
|
List<ClassNode> classList = new ArrayList<ClassNode>();
|
||||||
|
AccessTypeNode accessTypeNode = new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
|
||||||
|
ClassNode classNode = new ClassNode(accessTypeNode, "testClass");
|
||||||
|
|
||||||
|
MemberNode memberNode1 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar1");
|
||||||
|
classNode.members.add(memberNode1);
|
||||||
|
|
||||||
|
MemberNode memberNode2 = new FieldNode(accessTypeNode, new BaseTypeNode(EnumTypeNode.INT), "testVar2");
|
||||||
|
classNode.members.add(memberNode2);
|
||||||
|
|
||||||
|
List<ParameterNode> parameterNodeList = new ArrayList<ParameterNode>();
|
||||||
|
ParameterNode parameterNode1 = new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "param1");
|
||||||
|
parameterNodeList.add(parameterNode1);
|
||||||
|
ParameterListNode parameterListNode = new ParameterListNode(parameterNodeList);
|
||||||
|
|
||||||
|
List<StatementNode> statementNodeList = new ArrayList<StatementNode>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
StatementNode statementNode1 = new AssignmentStatementNode(expressionNode);
|
||||||
|
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;
|
||||||
|
|
||||||
|
ASTNode typedAst = SemanticAnalyzer.generateTast(programNode);
|
||||||
|
|
||||||
|
assertEquals(0, SemanticAnalyzer.errors.size());
|
||||||
|
assertEquals(programNode, typedAst);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user