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 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:
|
||||||
@ -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.
|
||||||
* 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);
|
||||||
// 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)
|
||||||
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);
|
||||||
}
|
// 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