Merge branch 'NewParser' into johns-branch
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
Bruder John 2024-07-01 09:35:01 +02:00
commit 7b1e6fced4
33 changed files with 498 additions and 93 deletions

View File

@ -15,30 +15,20 @@ public class ClassNode implements ASTNode, Visitable {
public AccessModifierNode accessType; public AccessModifierNode accessType;
public String identifier; public String identifier;
public List<MemberNode> members = new ArrayList<>(); public List<MemberNode> members = new ArrayList<>();
public boolean hasConstructor;
public ClassNode() {} public ClassNode(){
}
public ClassNode(String accessType, String identifier){ public ClassNode(String accessType, String identifier){
this.accessType = new AccessModifierNode(accessType); this.accessType = new AccessModifierNode(accessType);
this.identifier = identifier; this.identifier = identifier;
hasConstructor = false;
} }
public void addMember(MemberNode member) { public void addMember(MemberNode member) {
if (member instanceof ConstructorNode) {
this.hasConstructor = true;
}
members.add(member); members.add(member);
} }
public void ensureConstructor(){
if(!hasConstructor) {
ConstructorNode constructor = new ConstructorNode(new AccessModifierNode("public"), identifier);
members.addFirst(constructor);
}
}
public List<MethodNode> getMethods(){ public List<MethodNode> getMethods(){
List<MethodNode> methods = new ArrayList<>(); List<MethodNode> methods = new ArrayList<>();
for (MemberNode member : members) { for (MemberNode member : members) {

View File

@ -13,11 +13,6 @@ public class ConstructorNode extends MethodNode {
public List<ParameterNode> parameters = new ArrayList<>(); public List<ParameterNode> parameters = new ArrayList<>();
public BlockNode block; public BlockNode block;
public ConstructorNode(AccessModifierNode accessType, String identifier) {
this.accessType = accessType;
this.identifier = identifier;
}
public ConstructorNode(String accessType, String identifier, BlockNode block) { public ConstructorNode(String accessType, String identifier, BlockNode block) {
this.accessType = new AccessModifierNode(accessType); this.accessType = new AccessModifierNode(accessType);
this.identifier = identifier; this.identifier = identifier;

View File

@ -44,11 +44,30 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override @Override
public ASTNode visitClassDeclaration(SimpleJavaParser.ClassDeclarationContext ctx) { public ASTNode visitClassDeclaration(SimpleJavaParser.ClassDeclarationContext ctx) {
ClassNode classNode = new ClassNode(ctx.AccessModifier().getText(), ctx.Identifier().getText()); ClassNode classNode;
for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) { if(ctx.AccessModifier() != null){
classNode.addMember((MemberNode) visit(member)); classNode = new ClassNode(ctx.AccessModifier().getText(), ctx.Identifier().getText());
} }
classNode.ensureConstructor(); else{
classNode = new ClassNode("public", ctx.Identifier().getText());
}
boolean hasConstructor = false;
for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) {
MemberNode memberNode = (MemberNode) visit(member);
if(memberNode instanceof ConstructorNode){
hasConstructor = true;
}
classNode.addMember(memberNode);
}
if(!hasConstructor){
BlockNode blockNode = new BlockNode();
blockNode.addStatement(new ReturnNode(null));
classNode.members.addFirst(new ConstructorNode("public", ctx.Identifier().getText(), blockNode));
}
return classNode; return classNode;
} }
@ -94,7 +113,11 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
@Override @Override
public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) { public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) {
return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText()); if(ctx.AccessModifier() != null) {
return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
} else {
return new FieldNode(null, createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
}
} }
@Override @Override
@ -184,10 +207,17 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
crement = (IStatementNode) visit(ctx.statementExpression(i)); crement = (IStatementNode) visit(ctx.statementExpression(i));
} }
BlockNode forBlock = (BlockNode) visit(ctx.blockStatement()); BlockNode forBlock = new BlockNode();
BlockNode forStatements = (BlockNode) visit(ctx.blockStatement());
if(forStatements != null) {
forBlock.addStatement((IStatementNode) forStatements);
}
if(crement != null){ if(crement != null){
forBlock.addStatement((crement)); BlockNode forCrement = new BlockNode();
forCrement.addStatement((crement));
forBlock.addStatement(forCrement);
} }
WhileNode While = new WhileNode(condition, forBlock); WhileNode While = new WhileNode(condition, forBlock);

View File

@ -1,4 +1,4 @@
// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 // Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1
package parser.generated; package parser.generated;
import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.ParserRuleContext;

View File

@ -1,4 +1,4 @@
// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 // Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1
package parser.generated; package parser.generated;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;

View File

@ -1,4 +1,4 @@
// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 // Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1
package parser.generated; package parser.generated;
import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStream;

View File

@ -1,4 +1,4 @@
// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 // Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1
package parser.generated; package parser.generated;
import org.antlr.v4.runtime.tree.ParseTreeListener; import org.antlr.v4.runtime.tree.ParseTreeListener;

View File

@ -1,4 +1,4 @@
// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 // Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1
package parser.generated; package parser.generated;
import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;

View File

@ -1,4 +1,4 @@
// Generated from C:/Users/Maxi/Documents/DHBW/Compilerbau/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1 // Generated from C:/Users/janni/Desktop/NichtHaskell2.0/src/main/java/parser/grammar/SimpleJava.g4 by ANTLR 4.13.1
package parser.generated; package parser.generated;
import org.antlr.v4.runtime.tree.ParseTreeVisitor; import org.antlr.v4.runtime.tree.ParseTreeVisitor;

View File

@ -1,57 +1,217 @@
package parser; package parser;
import ast.ASTNode;
import ast.ClassNode; import ast.ClassNode;
import ast.ProgramNode; import ast.ProgramNode;
import ast.members.ConstructorNode;
import ast.members.FieldNode;
import ast.members.MemberNode;
import ast.type.AccessModifierNode;
import ast.type.type.BaseType;
import ast.type.type.TypeEnum;
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.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import parser.astBuilder.ASTBuilder; import parser.astBuilder.ASTBuilder;
import parser.generated.SimpleJavaLexer; import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser; import parser.generated.SimpleJavaParser;
import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException;
public class AstBuilderTest { import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("Untyped Abstract Syntax Tree")
class AstBuilderTest {
@Test @Test
public void astBuilderTest() { @DisplayName("Empty Class Test")
// ---------------- Leere Klasse nachgebaut ---------------- public void emptyClassTest(){
ClassNode emptyClass = Helper.generateEmptyClass("TestClass");
ProgramNode expected = new ProgramNode();
expected.addClass(emptyClass);
ProgramNode expectedASTEmptyClass = new ProgramNode(); ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/EmptyClass.java");
assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
// public class Name {} @Test
ClassNode nameClass = new ClassNode("public", "Name"); @DisplayName("Multiple Empty Classes Test")
public void multipleEmptyClassesTest() {
ClassNode classNode1 = Helper.generateEmptyClass("TestClass1");
ClassNode classNode2 = Helper.generateEmptyClass("TestClass2");
ProgramNode expected = new ProgramNode();
expected.addClass(classNode1);
expected.addClass(classNode2);
expectedASTEmptyClass.addClass(nameClass); ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/MultipleClasses.java");
assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Empty Class Test with Constructor")
public void emptyClassWithConstructorTest() {
ClassNode classNode = Helper.generateEmptyClass("TestClass");
ProgramNode expected = new ProgramNode();
expected.addClass(classNode);
// ---------------- Leere Klasse erzeugt ---------------- ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/EmptyClassWithConstructor.java");
assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
// init @Test
CharStream inputCharStream = CharStreams.fromString("public class Name {}"); @DisplayName("Field Test")
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream); public void fieldTest() {
CommonTokenStream tokenStream = new CommonTokenStream(lexer); ClassNode classNode = Helper.generateEmptyClass("TestClass");
tokenStream.fill(); classNode.addMember(new FieldNode(null, new BaseType(TypeEnum.INT), "a"));
/* Parser -> Parsetree */ ProgramNode expected = new ProgramNode();
SimpleJavaParser parser = new SimpleJavaParser(tokenStream); expected.addClass(classNode);
ParseTree parseTreeEmptyClass = parser.program(); // parse the input
/* AST builder -> AST */ ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Field.java");
ASTBuilder astBuilder = new ASTBuilder(); assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
ProgramNode actualASTEmptyClass = (ProgramNode) new ASTBuilder().visit(parseTreeEmptyClass); }
@Test
@DisplayName("Field Test with Accessmodifier")
public void fieldTestWithModifier() {
ClassNode classNode = Helper.generateEmptyClass("TestClass");
classNode.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
// ---------------- Vergleichen ---------------- ProgramNode expected = new ProgramNode();
expected.addClass(classNode);
String expectedASTasString = expectedASTEmptyClass.toString(); ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/FieldWithAccessModifier.java");
String actualASTasString = new ASTBuilder().visit(parseTreeEmptyClass).toString(); assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
// Wie vergleiche ich das? @Test
assertEquals(expectedASTasString, actualASTasString); @DisplayName("Commments Ignore Test")
assertEquals(expectedASTEmptyClass, actualASTEmptyClass); public void commmentsIgnoreTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Constructor Paramerter Test")
public void constructorParameterTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("This Dot Test")
public void thisDotTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Constructor This Dot Test")
public void constructorThisDotTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Void Methoden Test")
public void voidMethodenTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Constructor Method call Test")
public void constructorMethodCallTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Constructor Method call Parameters Test")
public void constructorMethodCallParametersTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Char Test")
public void charTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Null Test")
public void nullTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Self Reference Test")
public void selfReferneceTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Variable Compare Test")
public void variableCompareTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Variable Calculation Test")
public void variableCalculationTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Main Method Test")
public void mainMethodTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("While Test")
public void whileTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("Do While Test")
public void doWhileTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
@Test
@DisplayName("For Test")
public void forTest(){
//assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
}
//Noch nicht speziell Increment nur zum Development Testen per Debug
@Test
@DisplayName("Increment Test")
public void incrementTest(){
ClassNode classNode = Helper.generateEmptyClass("TestClass");
classNode.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
ProgramNode expected = new ProgramNode();
expected.addClass(classNode);
ASTNode actual = Helper.generateAST("src/test/resources/input/javaCases/Increment.java");
assertThat(actual).isEqualToComparingFieldByFieldRecursively(expected);
} }
@ -65,39 +225,4 @@ public class AstBuilderTest {
// ---------------- Alter CompilerInput nachgebaut ----------------
// ProgramNode startNode = new ProgramNode();
// public class CompilerInput {}
// ClassNode compilerInputClass = new ClassNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), "CompilerInput");
// public int a;
// compilerInputClass.addMember(new FieldNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), new BaseTypeNode(EnumTypeNode.INT), "a"));
// public static int testMethod(char x) { return 0; }
/* compilerInputClass.addMember(
new MethodNode(
new AccessTypeNode(EnumAccessTypeNode.PUBLIC),
new BaseTypeNode(EnumTypeNode.INT),
"testMethod",
new ParameterListNode(List.of(new ParameterNode(new BaseTypeNode(EnumTypeNode.CHAR), "x"))),
List.of(new ReturnStatementNode(new LiteralNode(0)))
));
ClassNode testClass = new ClassNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), "Test");
testClass.addMember(
new MethodNode(
new AccessTypeNode(EnumAccessTypeNode.PUBLIC),
new BaseTypeNode(EnumTypeNode.INT),
"testMethod",
new ParameterListNode(List.of(new ParameterNode(new BaseTypeNode(EnumTypeNode.CHAR), "x"), new ParameterNode(new BaseTypeNode(EnumTypeNode.INT), "a"))),
List.of(new ReturnStatementNode(new LiteralNode(0)))
)
);
*/
//compilerInputClass.addClass(testClass);
// startNode.addClass(compilerInputClass);
// startNode.addClass(testClass);
} }

View File

@ -0,0 +1,47 @@
package parser;
import ast.ASTNode;
import ast.ClassNode;
import ast.ProgramNode;
import ast.members.ConstructorNode;
import ast.members.MemberNode;
import ast.statements.BlockNode;
import ast.statements.ReturnNode;
import ast.type.AccessModifierNode;
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.ASTBuilder;
import parser.generated.SimpleJavaLexer;
import parser.generated.SimpleJavaParser;
import java.io.IOException;
public class Helper {
public static ASTNode generateAST(String filePath) {
CharStream testFile = null;
try {
testFile = CharStreams.fromFileName(filePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
SimpleJavaLexer lexer = new SimpleJavaLexer(testFile);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
tokenStream.fill();
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
ParseTree parseTree = parser.program();
ASTBuilder astBuilder = new ASTBuilder();
return astBuilder.visit(parseTree);
}
public static ClassNode generateEmptyClass(String className) {
BlockNode blockNode = new BlockNode();
blockNode.addStatement(new ReturnNode(null));
MemberNode constructor = new ConstructorNode("public",className, blockNode);
ClassNode classNode = new ClassNode("public", className);
classNode.addMember(constructor);
return classNode;
}
}

View File

@ -0,0 +1,12 @@
class TestClass{
char a;
public TestClass(char a){
this.a = testMethod(a);
}
char testMethod(char a){
return a;
}
}

View File

@ -0,0 +1,8 @@
/*
Mutliple Line Comment. Ignore
*/
class TestClass{
private int a; // Ignore
}

View File

@ -0,0 +1,12 @@
class TestClass {
int a;
public TestClass(int a){
this.a = testMethod(a);
}
int testMethod(int a){
return a;
}
}

View File

@ -0,0 +1,12 @@
class TestClass {
int a;
public TestClass(){
this.a = testMethod();
}
int testMethod(){
return 1;
}
}

View File

@ -0,0 +1,5 @@
class TestClass {
public TestClass(int a, int b){
}
}

View File

@ -0,0 +1,8 @@
class TestClass{
private int a;
public TestClass(int a){
this.a = a;
}
}

View File

@ -0,0 +1,10 @@
class TestClass{
public TestClass(){
int i = 0;
do{
i++
}while(i < 10);
}
}

View File

@ -0,0 +1 @@
class TestClass {}

View File

@ -0,0 +1,5 @@
public class TestClass {
public TestClass() {
}
}

View File

@ -0,0 +1,3 @@
public class TestClass {
int a;
}

View File

@ -0,0 +1,3 @@
public class TestClass {
public int a;
}

View File

@ -0,0 +1,8 @@
class TestClass{
public TestClass(){
for(int i = 0; i < 10; i++){
int a;
}
}
}

View File

@ -0,0 +1,12 @@
public class Increment {
public int test;
public void increment(int p) {
test = p++;
for(int i = 1; i<=10, i++) {
int a = 5;
}
}
}

View File

@ -0,0 +1,5 @@
class TestClass{
public static void main(String[] args) {
}
}

View File

@ -0,0 +1,3 @@
class TestClass1 {}
class TestClass2{}

View File

@ -0,0 +1,8 @@
class TestClass{
int a;
public TestClass(){
this.a = null;
}
}

View File

@ -0,0 +1,18 @@
class TestClass{
TestClass testClass;
int testMethod1() {
return this.testMethod2()
}
int testMethod2() {
return 1;
}
int testMehtod3(){
TestClass testClass1 = new TestClass();
return testClass1.testClass.testMethod1();
}
}

View File

@ -0,0 +1,8 @@
class TestClass{
public int a;
public TestClass{
this.a = 1;
}
}

View File

@ -0,0 +1,3 @@
class TestClass{
void test(){}
}

View File

@ -0,0 +1,10 @@
class TestClass{
public TestClass(){
int i = 10;
while ( i > 0){
i--;
}
}
}

View File

@ -0,0 +1,34 @@
class TestClass{
int aPlusB(int a, int b){
return a + b;
}
int aMinusB(int a, int b){
return a - b;
}
int aTimeB(int a, int b){
return a * b;
}
int aDivB(int a, int b){
return a / b;
}
int colmplexCalc (int a, int b){
return a * (b / 1);
}
boolean aSmallerB (int a, int b){
return a < b;
}
boolean aGreaterB (int a, int b){
return a > b;
}
boolean aEqualsB (int a, int b){
return a == b;
}
}

View File

@ -0,0 +1,30 @@
class TestClass{
boolean true(){
return true;
}
boolean false(){
return false();
}
boolean trueAndTrue(){
return true && true;
}
boolean trueAndFalse(){
return true && true;
}
boolean falseAndFalse(){
return false && false;
}
boolean trueOrFalse(){
return true || false;
}
boolean falseOrFalse(){
return false || false;
}
}