Tests, Structure, More #10
@ -1,4 +1,3 @@
|
|||||||
import ast.ASTNode;
|
|
||||||
import ast.ProgramNode;
|
import ast.ProgramNode;
|
||||||
import parser.ASTBuilder;
|
import parser.ASTBuilder;
|
||||||
import parser.generated.SimpleJavaLexer;
|
import parser.generated.SimpleJavaLexer;
|
||||||
@ -11,7 +10,7 @@ import org.antlr.v4.runtime.tree.ParseTree;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start Raupenpiler with the following commands:
|
* Start Raupenpiler with the following commands:
|
||||||
i22005 marked this conversation as resolved
Outdated
|
|||||||
@ -19,6 +18,8 @@ import java.util.List;
|
|||||||
* <p> <code> make clean compile-raupenpiler </code>
|
* <p> <code> make clean compile-raupenpiler </code>
|
||||||
*/
|
*/
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
// args[0] is the input file path
|
// args[0] is the input file path
|
||||||
@ -45,105 +46,56 @@ public class Main {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
|
|
||||||
/* ------------------------- Scanner -> tokens ------------------------- */
|
|
||||||
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
|
|
||||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
|
||||||
tokenStream.fill();
|
|
||||||
|
|
||||||
// Printing the tokens
|
|
||||||
System.out.println("-------------------- Scanner -> Tokens --------------------");
|
|
||||||
List<Token> tokens = tokenStream.getTokens();
|
|
||||||
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)); //one line representation
|
|
||||||
// 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 -> typed AST -------------------------*/
|
|
||||||
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
|
||||||
|
|
||||||
// Printing the typed AST
|
|
||||||
System.out.println("-------------------- Semantic Analyzer -> typed AST --------------------");
|
|
||||||
printAST(typedAst, 0);
|
|
||||||
System.out.println();
|
|
||||||
|
|
||||||
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
|
|
||||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath);
|
|
||||||
byteCodeGenerator.visit(typedAst);
|
|
||||||
System.out.println("Bytecode generated");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------- Printing methods ------------------------- */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used to print the parse tree in a structured format.
|
* This method is used to compile a file from a given CharStream and output the bytecode to a specified directory.
|
||||||
* It recursively traverses the tree and prints the rule names and text of the
|
* It goes through the following steps:
|
||||||
* nodes.
|
* <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.
|
||||||
* @param tree The parse tree to be printed.
|
* <p>3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST).
|
||||||
* @param parser The parser used to parse the input. It's used to get the rule
|
* <p>4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST.
|
||||||
i22011 marked this conversation as resolved
Outdated
i22005
commented
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. 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.
|
|||||||
* names.
|
* <p>5. Bytecode Generator: It uses the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory.
|
||||||
* @param indent The current indentation level. It's used to format the output.
|
*
|
||||||
*/
|
* @param inputCharStream The CharStream representing the input file to be compiled.
|
||||||
public static void printTree(ParseTree tree, Parser parser, int indent) {
|
* @param outputDirectoryPath The path of the directory where the output bytecode should be written.
|
||||||
// Create an indentation string based on the current indentation level
|
*/
|
||||||
String indentString = " ".repeat(indent * 2);
|
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
|
||||||
|
// Initialize the logger
|
||||||
|
new MyLogger();
|
||||||
|
|
||||||
// If the tree node is an instance of RuleContext (i.e., it's an internal node),
|
/* ------------------------- Scanner -> tokens ------------------------- */
|
||||||
// print the rule name
|
// Use the SimpleJavaLexer to tokenize the input CharStream
|
||||||
if (tree instanceof RuleContext) {
|
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
|
||||||
int ruleIndex = ((RuleContext) tree).getRuleIndex();
|
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||||
String ruleName = parser.getRuleNames()[ruleIndex];
|
tokenStream.fill();
|
||||||
System.out.println(indentString + ruleName);
|
// Log the tokens
|
||||||
} else {
|
MyLogger.logScanner(tokenStream);
|
||||||
i22011 marked this conversation as resolved
Outdated
i22005
commented
Same Here Same Here
|
|||||||
// 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
|
/*------------------------- Parser -> Parse tree -------------------------*/
|
||||||
// indentation level
|
// Use the SimpleJavaParser to parse the tokens and generate a ParseTree
|
||||||
for (int i = 0; i < tree.getChildCount(); i++) {
|
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
|
||||||
printTree(tree.getChild(i), parser, indent + 1);
|
ParseTree parseTree = parser.program(); // parse the input
|
||||||
}
|
// Log the ParseTree
|
||||||
}
|
MyLogger.logParser(parseTree, parser);
|
||||||
|
|
||||||
// TODO: Fix this method
|
/*------------------------- AST builder -> AST -------------------------*/
|
||||||
public static void printAST(ASTNode node, int indent) {
|
// Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST)
|
||||||
i22011 marked this conversation as resolved
Outdated
i22005
commented
Same Here Same Here
|
|||||||
if (node == null) {
|
ASTBuilder astBuilder = new ASTBuilder();
|
||||||
System.out.println("null");
|
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
|
||||||
return;
|
// Log the AST
|
||||||
}
|
MyLogger.logAST(abstractSyntaxTree);
|
||||||
String indentString = " ".repeat(indent * 2);
|
|
||||||
System.out.println(indentString + node.getClass().toString());
|
|
||||||
|
|
||||||
// for (ASTNode child : node.) {
|
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
|
||||||
// printAST(child, indent + 1);
|
// Use the SemanticAnalyzer to generate a typed AST
|
||||||
// }
|
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||||
i22011 marked this conversation as resolved
Outdated
i22005
commented
Same Here Same Here
|
|||||||
}
|
// Log the typed AST
|
||||||
|
MyLogger.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(typedAst);
|
||||||
|
// Log the bytecode generation
|
||||||
|
MyLogger.logBytecodeGenerator();
|
||||||
|
}
|
||||||
}
|
}
|
178
src/main/java/MyLogger.java
Normal file
178
src/main/java/MyLogger.java
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
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 MyLogger {
|
||||||
|
|
||||||
|
static Logger logger = Logger.getLogger("RaupenLogs");
|
||||||
|
|
||||||
|
public MyLogger() {
|
||||||
|
// ------------------------- 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 node) {
|
||||||
|
// Printing the AST
|
||||||
|
logger.info("-------------------- AST builder -> AST --------------------");
|
||||||
|
// logger.info("AST: " + ast.toString());
|
||||||
|
logAST(node, 0);
|
||||||
|
logger.info("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logSemanticAnalyzer(ASTNode node) {
|
||||||
|
// Printing the typed AST
|
||||||
|
logger.info("-------------------- Semantic Analyzer -> typed AST --------------------");
|
||||||
|
logAST(node, 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 node, int indent) {
|
||||||
|
if (node == null) {
|
||||||
|
System.out.println("null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String indentString = " ".repeat(indent * 2);
|
||||||
|
logger.info(indentString + node.getClass().toString());
|
||||||
|
|
||||||
|
// for (ASTNode child : node.) {
|
||||||
|
// printAST(child, indent + 1);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
# Makefile
|
# Makefile
|
||||||
### IntelliJs play buttons do not work. Run in "src/test" folder with "make" command to run all
|
### 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 delete" etc.
|
### Or run only parts with "make compile-javac", "make clean" etc.
|
||||||
|
|
||||||
all: compile-javac compile-raupenpiler
|
all: compile-javac compile-raupenpiler
|
||||||
|
|
||||||
@ -25,4 +25,5 @@ clean:
|
|||||||
rm -f ./resources/output/raupenpiler/*.class
|
rm -f ./resources/output/raupenpiler/*.class
|
||||||
rm -f ./java/*.class
|
rm -f ./java/*.class
|
||||||
rm -f ../main/resources/output/*.class
|
rm -f ../main/resources/output/*.class
|
||||||
|
rm -f ../main/resources/logs/*.log
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package parser;
|
package parser;
|
||||||
|
|
||||||
import ast.ProgramNode;
|
|
||||||
import org.antlr.v4.runtime.*;
|
import org.antlr.v4.runtime.*;
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -10,9 +9,7 @@ import parser.generated.SimpleJavaParser;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BooleanSupplier;
|
|
||||||
|
|
||||||
public class ParserTest {
|
public class ParserTest {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
Loading…
Reference in New Issue
Block a user
Warum muss der compiler mit einem Makefile gestartet werden? Es reicht doch wenn wir die jar mit
Java compiler fileIn fileOut ausführt.