Added logging
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
This commit is contained in:
parent
f59d7e9918
commit
102961bccc
@ -1,4 +1,3 @@
|
||||
import ast.ASTNode;
|
||||
import ast.ProgramNode;
|
||||
import parser.ASTBuilder;
|
||||
import parser.generated.SimpleJavaLexer;
|
||||
@ -11,7 +10,7 @@ import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Start Raupenpiler with the following commands:
|
||||
@ -19,6 +18,8 @@ import java.util.List;
|
||||
* <p> <code> make clean compile-raupenpiler </code>
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length > 0) {
|
||||
// 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.
|
||||
* 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);
|
||||
* This method is used to compile a file from a given CharStream and output the bytecode to a specified directory.
|
||||
* It goes through the following steps:
|
||||
* <p>1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream.
|
||||
* <p>2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree.
|
||||
* <p>3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST).
|
||||
* <p>4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST.
|
||||
* <p>5. Bytecode Generator: It uses the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory.
|
||||
*
|
||||
* @param inputCharStream The CharStream representing the input file to be compiled.
|
||||
* @param outputDirectoryPath The path of the directory where the output bytecode should be written.
|
||||
*/
|
||||
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
|
||||
// Initialize the logger
|
||||
new MyLogger();
|
||||
|
||||
// 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());
|
||||
}
|
||||
/* ------------------------- Scanner -> tokens ------------------------- */
|
||||
// Use the SimpleJavaLexer to tokenize the input CharStream
|
||||
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
tokenStream.fill();
|
||||
// Log the tokens
|
||||
MyLogger.logScanner(tokenStream);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
/*------------------------- Parser -> Parse tree -------------------------*/
|
||||
// Use the SimpleJavaParser to parse the tokens and generate a ParseTree
|
||||
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
|
||||
ParseTree parseTree = parser.program(); // parse the input
|
||||
// Log the ParseTree
|
||||
MyLogger.logParser(parseTree, parser);
|
||||
|
||||
// TODO: Fix this method
|
||||
public static void printAST(ASTNode node, int indent) {
|
||||
if (node == null) {
|
||||
System.out.println("null");
|
||||
return;
|
||||
}
|
||||
String indentString = " ".repeat(indent * 2);
|
||||
System.out.println(indentString + node.getClass().toString());
|
||||
/*------------------------- AST builder -> AST -------------------------*/
|
||||
// Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST)
|
||||
ASTBuilder astBuilder = new ASTBuilder();
|
||||
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
|
||||
// Log the AST
|
||||
MyLogger.logAST(abstractSyntaxTree);
|
||||
|
||||
// for (ASTNode child : node.) {
|
||||
// printAST(child, indent + 1);
|
||||
// }
|
||||
}
|
||||
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
|
||||
// Use the SemanticAnalyzer to generate a typed AST
|
||||
ProgramNode typedAst = (ProgramNode) SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
// 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
|
||||
### 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
|
||||
|
||||
@ -25,4 +25,5 @@ clean:
|
||||
rm -f ./resources/output/raupenpiler/*.class
|
||||
rm -f ./java/*.class
|
||||
rm -f ../main/resources/output/*.class
|
||||
rm -f ../main/resources/logs/*.log
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package parser;
|
||||
|
||||
import ast.ProgramNode;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -10,9 +9,7 @@ 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 {
|
||||
@BeforeEach
|
||||
|
Loading…
Reference in New Issue
Block a user