Tests, Structure, More #10
@ -49,17 +49,16 @@ public class Main {
|
|||||||
/* ------------------------- Scanner -> tokens ------------------------- */
|
/* ------------------------- Scanner -> tokens ------------------------- */
|
||||||
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
|
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
|
||||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||||
|
tokenStream.fill();
|
||||||
|
|
||||||
// Printing the tokens
|
// Printing the tokens
|
||||||
tokenStream.fill();
|
System.out.println("-------------------- Scanner -> Tokens --------------------");
|
||||||
i22011 marked this conversation as resolved
Outdated
|
|||||||
List<Token> tokens = tokenStream.getTokens();
|
List<Token> tokens = tokenStream.getTokens();
|
||||||
System.out.println("-------------------- Scanner -> tokens --------------------");
|
|
||||||
for (Token token : tokens) {
|
for (Token token : tokens) {
|
||||||
String tokenType =
|
String tokenType =
|
||||||
SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType());
|
SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType());
|
||||||
String tokenText = token.getText();
|
String tokenText = token.getText();
|
||||||
// System.out.println("Token Type: " + tokenType + ", Token Text: " +
|
// System.out.println("Token Type: " + tokenType + ", Token Text: " + tokenText);
|
||||||
// tokenText);
|
|
||||||
System.out.println(tokenType + " " + tokenText);
|
System.out.println(tokenType + " " + tokenText);
|
||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
@ -70,8 +69,8 @@ public class Main {
|
|||||||
|
|
||||||
// Printing the parse tree
|
// Printing the parse tree
|
||||||
System.out.println("-------------------- Parser -> Parsetree --------------------");
|
System.out.println("-------------------- Parser -> Parsetree --------------------");
|
||||||
i22011 marked this conversation as resolved
Outdated
i22005
commented
Same Here Same Here
|
|||||||
System.out.println(parseTree.toStringTree(parser));
|
System.out.println(parseTree.toStringTree(parser)); //one line representation
|
||||||
printTree(parseTree, parser, 0);
|
// printTree(parseTree, parser, 0);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
/*------------------------- AST builder -> AST -------------------------*/
|
/*------------------------- AST builder -> AST -------------------------*/
|
||||||
|
@ -14,11 +14,11 @@ compile-raupenpiler:
|
|||||||
test: test-javac test-raupenpiler
|
test: test-javac test-raupenpiler
|
||||||
|
|
||||||
test-javac:
|
test-javac:
|
||||||
compile-javac
|
#compile-javac
|
||||||
java -cp .\resources\output\javac CompilerInput
|
#java -cp .\resources\output\javac CompilerInput
|
||||||
|
|
||||||
test-raupenpiler:
|
test-raupenpiler:
|
||||||
java -cp .\resources\output\raupenpiler CompilerInput
|
#java -cp .\resources\output\raupenpiler CompilerInput
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f ./resources/output/javac/*.class
|
rm -f ./resources/output/javac/*.class
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
## Scanner Output
|
## Scanner Output
|
||||||
|
|
||||||
|
CommonTokenStream
|
||||||
|
|
||||||
### Beispiel 1: Empty Class
|
### Beispiel 1: Empty Class
|
||||||
|
|
||||||
Token Type; Token Text
|
Token Type; Token Text
|
||||||
@ -28,26 +30,20 @@ Type gibts nur bei Terminalen, Text bei allen
|
|||||||
Bsp von Ihm mal:
|
Bsp von Ihm mal:
|
||||||
[TokPublic,TokClass,TokIdentifier "Name",TokLeftBrace,TokRightBrace]
|
[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
|
||||||
|
|
||||||
## Parser Input
|
## Parser Input
|
||||||
|
|
||||||
|
CommonTokenStream
|
||||||
(Scanner Output)
|
(Scanner Output)
|
||||||
|
|
||||||
## Parser Output (AST)
|
## Parser Output (AST)
|
||||||
|
|
||||||
### Beispiel 1: Empty Class
|
(program (classDeclaration (accessType public) class Name { }))
|
||||||
|
|
||||||
### Beispiel 2: Filled Class
|
ParseTree
|
||||||
|
|
||||||
|
### Beispiel 1: Empty Class
|
||||||
|
|
||||||
# Semantische Analyse / Typcheck
|
# Semantische Analyse / Typcheck
|
||||||
|
|
||||||
@ -59,8 +55,6 @@ Type gibts nur bei Terminalen, Text bei allen
|
|||||||
|
|
||||||
### Beispiel 1: Empty Class
|
### Beispiel 1: Empty Class
|
||||||
|
|
||||||
### Beispiel 2: Filled Class
|
|
||||||
|
|
||||||
# Bytecodegenerierung
|
# Bytecodegenerierung
|
||||||
|
|
||||||
## Bytecodegenerierung Input
|
## Bytecodegenerierung Input
|
||||||
@ -76,8 +70,6 @@ Compiled Classfile
|
|||||||
public class javaFileInput.Example {
|
public class javaFileInput.Example {
|
||||||
}
|
}
|
||||||
|
|
||||||
### Beispiel 2: Filled Class
|
|
||||||
|
|
||||||
## E2E Tests:
|
## E2E Tests:
|
||||||
|
|
||||||
- Testdatei mit Main ausführen/kompilieren
|
- Testdatei mit Main ausführen/kompilieren
|
||||||
@ -85,13 +77,14 @@ Compiled Classfile
|
|||||||
- -> Dateien mit javap vergleichen
|
- -> Dateien mit javap vergleichen
|
||||||
|
|
||||||
wenn beides erfolgreich
|
wenn beides erfolgreich
|
||||||
|
|
||||||
- Ergebnis vom eigenen Compiler mithilfe von TestCompilerOutput ausführen
|
- Ergebnis vom eigenen Compiler mithilfe von TestCompilerOutput ausführen
|
||||||
- (Ergebnis von javac mithilfe von TestCompilerOutput ausführen)
|
- (Ergebnis von javac mithilfe von TestCompilerOutput ausführen)
|
||||||
|
|
||||||
|
|
||||||
### Andis Tipps:
|
### Andis Tipps:
|
||||||
|
|
||||||
- cp mitgeben
|
- cp mitgeben
|
||||||
- makefile
|
- makefile
|
||||||
- java -jar pfadtocompiler.jar EmptyClass.java
|
- java -jar pfadtocompiler.jar EmptyClass.java
|
||||||
- mvn package
|
- mvn package
|
||||||
- javac tester // tester compilen
|
- javac tester // tester compilen
|
||||||
|
@ -15,17 +15,17 @@ import java.util.List;
|
|||||||
|
|
||||||
public class FailureTest {
|
public class FailureTest {
|
||||||
private static final List<String> TEST_FILES = Arrays.asList(
|
private static final List<String> TEST_FILES = Arrays.asList(
|
||||||
"src/main/test/resources/failureTests/TestClass1.java",
|
"src/main/test/resources/input/failureTests/TestClass1.java",
|
||||||
"src/main/test/resources/failureTests/TestClass2.java",
|
"src/main/test/resources/input/failureTests/TestClass2.java",
|
||||||
"src/main/test/resources/failureTests/TestClass3.java",
|
"src/main/test/resources/input/failureTests/TestClass3.java",
|
||||||
"src/main/test/resources/failureTests/TestClass4.java",
|
"src/main/test/resources/input/failureTests/TestClass4.java",
|
||||||
"src/main/test/resources/failureTests/TestClass5.java",
|
"src/main/test/resources/input/failureTests/TestClass5.java",
|
||||||
"src/main/test/resources/failureTests/TestClass6.java",
|
"src/main/test/resources/input/failureTests/TestClass6.java",
|
||||||
"src/main/test/resources/failureTests/TestClass7.java",
|
"src/main/test/resources/input/failureTests/TestClass7.java",
|
||||||
"src/main/test/resources/failureTests/TestClass8.java",
|
"src/main/test/resources/input/failureTests/TestClass8.java",
|
||||||
"src/main/test/resources/failureTests/TestClass9.java",
|
"src/main/test/resources/input/failureTests/TestClass9.java",
|
||||||
"src/main/test/resources/failureTests/TestClass10.java",
|
"src/main/test/resources/input/failureTests/TestClass10.java",
|
||||||
"src/main/test/resources/failureTests/TestClass11.java"
|
"src/main/test/resources/input/failureTests/TestClass11.java"
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,187 @@
|
|||||||
package parser;
|
package parser;
|
||||||
|
|
||||||
|
import ast.ProgramNode;
|
||||||
|
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.generated.SimpleJavaLexer;
|
||||||
|
import parser.generated.SimpleJavaParser;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
public class ParserTest {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user
Können wir die ganze Ausgabe in ne extra Klasse auzslagern? Des macht die Main Klasse bissle arg unübersichtlich. Außerdem gehört des nacher nicht in den Endgültigen Compiler.