overhaul logging + printing ast to image

This commit is contained in:
ChUrl
2021-02-04 19:59:00 +01:00
parent a17201d10a
commit 5c27fe4cb6
16 changed files with 196 additions and 100 deletions

View File

@ -45,7 +45,7 @@ public final class StupsCompiler {
final FlowGraphGenerator gen = getFlowGraphGen(filename);
final FlowGraph graph = gen.generateGraph();
Logger.logInfoSupplier(graph::printToImage, StupsCompiler.class);
Logger.logDebugSupplier(graph::printToImage, StupsCompiler.class);
// Codegeneration + Output
final String fileExtension = filename.substring(filename.lastIndexOf('.') + 1);
@ -79,11 +79,11 @@ public final class StupsCompiler {
final FlowGraphGenerator gen = getFlowGraphGen(filename);
final FlowGraph graph = gen.generateGraph();
Logger.logInfoSupplier(graph::printToImage, StupsCompiler.class);
Logger.logDebugSupplier(graph::printToImage, StupsCompiler.class);
final DataFlowGraph dataFlowGraph = DataFlowGraph.fromFlowGraph(graph);
Logger.logInfoSupplier(dataFlowGraph::printToImage, StupsCompiler.class);
Logger.logDebugSupplier(dataFlowGraph::printToImage, StupsCompiler.class);
final LivenessAnalysis liveness = LivenessAnalysis.fromDataFlowGraph(dataFlowGraph, gen.getVarMap());
final int registers = liveness.doLivenessAnalysis();
@ -129,7 +129,10 @@ public final class StupsCompiler {
// Parsing + Typechecking of program
final SyntaxTree parseTree = stupsParser.parse(lexer.getAllTokens(), lexer.getVocabulary());
Logger.logDebugSupplier(() -> parseTree.printToImage("ParseTree"), StupsCompiler.class);
final SyntaxTree abstractSyntaxTree = SyntaxTree.toAbstractSyntaxTree(parseTree, grammar);
final Map<SyntaxTreeNode, String> nodeTable = TypeChecker.validate(abstractSyntaxTree);
return FlowGraphGenerator.fromAST(abstractSyntaxTree, nodeTable, filename);

View File

@ -98,7 +98,7 @@ public final class DataFlowGraph implements Iterable<DataFlowNode> {
public String printToImage() {
if (this.dataFlowNodes.isEmpty()) {
return "Empty Graph";
return "Can't export empty graph: DataFLowGraph.svg";
}
final StringBuilder dot = new StringBuilder();
@ -132,7 +132,7 @@ public final class DataFlowGraph implements Iterable<DataFlowNode> {
GraphvizCaller.callGraphviz(dot, "DataFlowGraph");
return "Finished.";
return "Successfully exported as image: DataFlowGraph.svg";
}
// Overrides

View File

@ -69,7 +69,7 @@ public final class InterferenceGraph implements Iterable<InterferenceNode> {
public String printToImage() {
if (this.interferenceNodes.isEmpty()) {
return "Empty Graph";
return "Can't export empty graph: Interference.svg";
}
final StringBuilder dot = new StringBuilder();
@ -100,7 +100,7 @@ public final class InterferenceGraph implements Iterable<InterferenceNode> {
GraphvizCaller.callGraphviz(dot, "InterferenceGraph");
return "Finished.";
return "Successfully exported as Image: InterferenceGraph.svg";
}
// Overrides

View File

@ -107,7 +107,7 @@ public final class LivenessAnalysis {
Logger.logDebug("Successfully colored interference-graph", LivenessAnalysis.class);
}
Logger.logInfoSupplier(this.interferenceGraph::printToImage, LivenessAnalysis.class);
Logger.logDebugSupplier(this.interferenceGraph::printToImage, LivenessAnalysis.class);
return colors;
}

View File

@ -48,13 +48,16 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
* und zu Blöcken aus der {@link #predecessorMap} hergestellt.
*/
public void addLabel(String label) {
Logger.logInfo("Adding Label: " + label, FlowGraph.class);
Logger.logInfo(" :: Adding label: \"" + label + "\"", FlowGraph.class);
final FlowBasicBlock newBlock = new FlowBasicBlock(label);
// Resolve missing successors/predecessors from jumps
if (this.predecessorMap.containsKey(label)) {
Logger.logInfo("Handling PredecessorMap Entry: " + this.predecessorMap.get(label), FlowGraph.class);
Logger.logInfo(" :: Handling predecessor-map entry:\n\t\t\t"
+ this.predecessorMap.get(label).getLabel()
+ "\n\t\t\t[...]\n\t\t\t"
+ this.predecessorMap.get(label).getLastInstruction(), FlowGraph.class);
this.predecessorMap.get(label).addSuccessorBlock(newBlock);
newBlock.addPredecessorBlock(this.predecessorMap.get(label));
@ -79,7 +82,7 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
* @param jumpInstruction Der verwendete Sprungbefehl.
*/
public void addJump(String jumpInstruction, String label) {
Logger.logInfo("Adding Jump to Label: " + label, FlowGraph.class);
Logger.logInfo(" :: Adding jump to label \"" + label + "\"", FlowGraph.class);
this.addInstruction(jumpInstruction, label);
@ -111,7 +114,9 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
// Successor doesn't exist, so wait until it does
// Current node is predecessor of label-block
Logger.logInfo("Adding Entry to PredecessorMap: " + currentBlock, FlowGraph.class);
currentBlock.ifPresent(flowBasicBlock -> Logger.logInfo(" :: Adding entry to predecessor-map: \n\t\t\t"
+ flowBasicBlock.getLabel() + "\n\t\t\t[...]\n\t\t\t"
+ flowBasicBlock.getLastInstruction(), FlowGraph.class));
currentBlock.ifPresent(flowBasicBlock -> this.predecessorMap.put(label, flowBasicBlock));
}
@ -119,7 +124,7 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
}
public void addInstruction(String instruction, String... args) {
Logger.logInfo("Adding Instruction: " + instruction, FlowGraph.class);
Logger.logInfo(" :: Adding instruction \"" + instruction + "\"", FlowGraph.class);
if (this.basicBlocks.isEmpty()) {
this.basicBlocks.add(new FlowBasicBlock("START")); // First block doesn't exist
@ -143,7 +148,7 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
// Collect removable blocks
for (FlowBasicBlock block : this.basicBlocks) {
if (block.isEmpty()) {
Logger.logInfo("Marking Block " + this.basicBlocks.indexOf(block) + " as removable.", FlowGraph.class);
Logger.logInfo(" :: Marking block nr. " + this.basicBlocks.indexOf(block) + " as removable.", FlowGraph.class);
toRemove.add(block);
}
}
@ -155,8 +160,8 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
for (FlowBasicBlock predecessor : block.getBlockPredecessorSet()) {
for (FlowBasicBlock successor : block.getBlockSuccessorSet()) {
Logger.logInfo("Rerouting Block " + this.basicBlocks.indexOf(predecessor)
+ " to Block " + this.basicBlocks.indexOf(successor), FlowGraph.class);
Logger.logInfo(" :: Rerouting block nr. " + this.basicBlocks.indexOf(predecessor)
+ " to block nr. " + this.basicBlocks.indexOf(successor), FlowGraph.class);
predecessor.addSuccessorBlock(successor);
successor.addPredecessorBlock(predecessor);
}
@ -200,7 +205,7 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
final Optional<FlowBasicBlock> currentBlock = this.getCurrentBlock();
if (this.basicBlocks.isEmpty() || currentBlock.isEmpty()) {
return "Empty Graph";
return "Can't export empty graph: FlowGraph.svg";
}
final StringBuilder dot = new StringBuilder();
@ -237,7 +242,7 @@ public class FlowGraph implements Iterable<FlowBasicBlock> {
GraphvizCaller.callGraphviz(dot, "FlowGraph");
return "Finished.";
return "Successfully exported the graph as Image: FlowGraph.svg";
}
// Overrides

View File

@ -75,9 +75,8 @@ public final class FlowGraphGenerator {
currentVarNumber++;
varMap.put(current.getChildren().get(0).getValue(), currentVarNumber);
Logger.logInfo("New local " + current.getValue() + " variable "
+ current.getChildren().get(0).getValue()
+ " assigned to slot " + currentVarNumber + ".", FlowGraphGenerator.class);
Logger.logInfo("Assign local variable \"" + current.getChildren().get(0).getValue() + "\" -> \""
+ current.getValue() + "\" to slot " + currentVarNumber, FlowGraphGenerator.class);
}
current.getChildren().forEach(stack::push);
@ -110,7 +109,6 @@ public final class FlowGraphGenerator {
this.graph.purgeEmptyBlocks();
Logger.logDebug("Source-graph generation complete", FlowGraphGenerator.class);
Logger.logInfo("\n\nSourceGraph print:\n" + "-".repeat(100) + "\n" + this.graph + "-".repeat(100), FlowGraphGenerator.class);
return this.graph;
}
@ -138,7 +136,7 @@ public final class FlowGraphGenerator {
* Erzeugt den Teilbaum für einen If-Knoten.
*/
private void condNode(SyntaxTreeNode root) {
Logger.logInfo("Generating Conditional Node", FlowGraphGenerator.class);
Logger.logInfo("Generating conditional node", FlowGraphGenerator.class);
final int currentLabel = this.labelCounter;
this.labelCounter++;
@ -169,7 +167,7 @@ public final class FlowGraphGenerator {
* Erzeugt den Teilbaum für einen While-Knoten.
*/
private void loopNode(SyntaxTreeNode root) {
Logger.logInfo("Generating Loop Node", FlowGraphGenerator.class);
Logger.logInfo("Generating loop node", FlowGraphGenerator.class);
final int currentLabel = this.labelCounter;
this.labelCounter++;
@ -196,7 +194,7 @@ public final class FlowGraphGenerator {
* Die JVM-Stacksize wird dabei um 1 verringert, da istore/astore 1 Argument konsumieren.
*/
private void assignNode(SyntaxTreeNode root) { //! Stack - 1
Logger.logInfo("Generating Assignment Node", FlowGraphGenerator.class);
Logger.logInfo("Generating assignment node", FlowGraphGenerator.class);
this.generateNode(root.getChildren().get(0));
@ -207,7 +205,7 @@ public final class FlowGraphGenerator {
default -> throw new IllegalStateException("Unexpected value: " + type);
};
Logger.logInfo("assign(): " + root.getName() + ": " + root.getValue() + " => " + inst, FlowGraphGenerator.class);
Logger.logInfo("assign(): Node \"" + root.getName() + ": " + root.getValue() + "\" => " + inst, FlowGraphGenerator.class);
this.graph.addInstruction(inst, this.varMap.get(root.getValue()).toString());
}
@ -229,7 +227,7 @@ public final class FlowGraphGenerator {
* bei binären Operatoren sinkt die Stackgröße um 1 (2 konsumiert, 1 Ergebnis).
*/
private void intExpr(SyntaxTreeNode root) {
Logger.logInfo("Generating Integer Expression Node", FlowGraphGenerator.class);
Logger.logInfo("Generating integer expression node: \"" + root.getName() + ": " + root.getValue() + "\"", FlowGraphGenerator.class);
String inst = "";
@ -259,7 +257,7 @@ public final class FlowGraphGenerator {
};
}
Logger.logInfo("intExpr(): " + root.getName() + ": " + root.getValue() + " => " + inst, FlowGraphGenerator.class);
Logger.logInfo("intExpr(): Node \"" + root.getName() + ": " + root.getValue() + "\" => " + inst, FlowGraphGenerator.class);
this.graph.addInstruction(inst);
}
@ -270,7 +268,7 @@ public final class FlowGraphGenerator {
* bei binären Operatoren sinkt die Stackgröße um 1 (2 konsumiert, 1 Ergebnis).
*/
private void boolExpr(SyntaxTreeNode node) {
Logger.logInfo("Generating Boolean Expression", FlowGraphGenerator.class);
Logger.logInfo("Generating boolean expression", FlowGraphGenerator.class);
if (node.getChildren().size() == 1) { //! Stack + 1
// Unary operator
@ -342,14 +340,14 @@ public final class FlowGraphGenerator {
// Leafs
private void intStringLiteralNode(SyntaxTreeNode node) { //! Stack + 1
Logger.logInfo("intStringLiteral(): " + node.getName() + ": " + node.getValue() + " => ldc", FlowGraphGenerator.class);
Logger.logInfo("intStringLiteral(): Node \"" + node.getName() + ": " + node.getValue() + "\" => ldc", FlowGraphGenerator.class);
// bipush only pushes 1 byte as int
this.graph.addInstruction("ldc", node.getValue());
}
private void boolLiteralNode(SyntaxTreeNode node) { //! Stack + 1
Logger.logInfo("booleanLiteral(): " + node.getName() + ": " + node.getValue() + " => ldc", FlowGraphGenerator.class);
Logger.logInfo("booleanLiteral(): Node \"" + node.getName() + ": " + node.getValue() + "\" => ldc", FlowGraphGenerator.class);
final String val = "true".equals(node.getValue()) ? "1" : "0";
@ -364,7 +362,7 @@ public final class FlowGraphGenerator {
default -> throw new IllegalStateException("Unexpected value: " + type);
};
Logger.logInfo("identifier(): " + node.getName() + ": " + node.getValue() + " => " + inst, FlowGraphGenerator.class);
Logger.logInfo("identifier(): Node \"" + node.getName() + ": " + node.getValue() + "\" => " + inst, FlowGraphGenerator.class);
this.graph.addInstruction(inst, this.varMap.get(node.getValue()).toString());
}
@ -382,7 +380,7 @@ public final class FlowGraphGenerator {
this.generateNode(expr);
Logger.logInfo("println(): " + expr.getName() + ": " + expr.getValue() + " => " + type, FlowGraphGenerator.class);
Logger.logInfo("println(): Node \"" + expr.getName() + ": " + expr.getValue() + "\" => " + type, FlowGraphGenerator.class);
this.graph.addInstruction("invokevirtual", "java/io/PrintStream/println(" + type + ")V");
}

View File

@ -49,13 +49,11 @@ public class StupsParser {
int inputPosition = 0;
Logger.logInfo("Input: " + token + "\n", StupsParser.class);
// Parsing
while (!stack.isEmpty()) {
final String top = stack.peek().getName();
Logger.logInfo("Parsing Top Symbol: " + top, StupsParser.class);
Logger.logInfo("Parsing Top Symbol: \"" + top + "\"", StupsParser.class);
final String currentTokenSym;
int currentLine = 0;
@ -76,16 +74,20 @@ public class StupsParser {
if (top.equals(Grammar.EPSILON_SYMBOL)) {
// Wenn auf dem Stack das Epsilonsymbol liegt
// Logger.logInfo(" :: Skip epsilon", StupsParser.class);
stack.pop();
} else if (top.equals(currentTokenSym)) {
// Wenn auf dem Stack ein Terminal liegt (dieses muss mit der Eingabe übereinstimmen)
// Logger.logInfo(" :: Skip terminal-symbol (Matches input)", StupsParser.class);
stack.pop();
inputPosition++;
} else if (this.parsetable.getTerminals().contains(top)) {
// Wenn das Terminal auf dem Stack nicht mit der aktuellen Eingabe übereinstimmt
Logger.logError("\nLine " + currentLine + " Syntaxerror: Expected " + top + " but found "
Logger.logError("Line " + currentLine + " Syntaxerror: Expected " + top + " but found "
+ currentTokenSym, StupsParser.class);
Logger.logError(StupsParser.printSourceLine(currentLine, token), StupsParser.class);
@ -93,7 +95,7 @@ public class StupsParser {
} else if (prod == null) {
// Wenn es für das aktuelle Terminal und das Nichtterminal auf dem Stack keine Regel gibt
Logger.logError("\nLine " + currentLine + " Syntaxerror: Didn't expect " + currentTokenSym, StupsParser.class);
Logger.logError("Line " + currentLine + " Syntaxerror: Didn't expect " + currentTokenSym, StupsParser.class);
Logger.logError(StupsParser.printSourceLine(currentLine, token), StupsParser.class);
throw new ParseException("No prod. for nonterminal " + top + ", terminal " + currentTokenSym, tree);
@ -101,7 +103,7 @@ public class StupsParser {
// Wenn das Nichtterminal auf dem Stack durch (s)eine Produktion ersetzt werden kann
// Hier wird auch der AST aufgebaut
Logger.logInfo("Used: " + top + " -> " + prod, StupsParser.class);
Logger.logInfo(" :: Used rule: \"" + top + " -> " + prod + "\"", StupsParser.class);
final SyntaxTreeNode pop = stack.pop();
final String[] split = prod.split(" ");
@ -126,7 +128,6 @@ public class StupsParser {
}
Logger.logDebug("Successfully parsed the program and built the parse-tree", StupsParser.class);
Logger.logInfo("\nParsed AST:\n" + tree, StupsParser.class);
return tree;
}

View File

@ -34,7 +34,7 @@ public final class ParseTreeCleaner {
valueToValue(parseTree, grammar);
Logger.logDebug("Successfully cleaned the parse-tree", ParseTreeCleaner.class);
Logger.logInfo("\nCleaned Tree:\n" + parseTree, ParseTreeCleaner.class);
Logger.logDebugSupplier(() -> parseTree.printToImage("ParseTreeCleaned"), ParseTreeCleaner.class);
}
/**
@ -57,8 +57,8 @@ public final class ParseTreeCleaner {
continue;
}
Logger.logInfo("Promoting " + child.getName() + " -> " + root.getName(), ParseTreeCleaner.class);
Logger.logInfo(root.toString(), ParseTreeCleaner.class);
Logger.logInfo("Promoting child \"" + child.getName() + "\" to root \"" + root.getName() + "\"\n"
+ root.nodePrint("\t\t"), ParseTreeCleaner.class);
root.setName(child.getName());
root.setValue(child.getValue());
@ -90,7 +90,7 @@ public final class ParseTreeCleaner {
continue;
}
Logger.logInfo("Removing " + child.getName(), ParseTreeCleaner.class);
Logger.logInfo("Removing node \"" + child.getName() + "\"", ParseTreeCleaner.class);
child.setValue("REMOVE"); // If both childs have the same identity both are removed, so change one
toRemove.add(child);
@ -118,7 +118,8 @@ public final class ParseTreeCleaner {
continue;
}
Logger.logInfo("Removing " + root.getName() + " -> " + child.getName(), ParseTreeCleaner.class);
Logger.logInfo("Removing child \"" + child.getName() + "\" from root \"" + root.getName() + "\"\n"
+ root.nodePrint("\t\t"), ParseTreeCleaner.class);
child.setValue("REMOVE"); // If both childs have the same identity both are removed, so change one
toRemove.add(child);
@ -144,7 +145,7 @@ public final class ParseTreeCleaner {
continue;
}
Logger.logInfo("Rename " + root.getName() + " to " + grammar.getNewName(root) + ".", ParseTreeCleaner.class);
Logger.logInfo("Renaming node \"" + root.getName() + "\" to \"" + grammar.getNewName(root) + "\"", ParseTreeCleaner.class);
root.setName(grammar.getNewName(root));
}
@ -169,8 +170,8 @@ public final class ParseTreeCleaner {
continue;
}
Logger.logInfo("Moving " + child.getName() + " to value of " + root.getName(), ParseTreeCleaner.class);
Logger.logInfo(root.toString(), ParseTreeCleaner.class);
Logger.logInfo("Moving child-name \"" + child.getName() + "\" to parent-value of node \"" + root.getName() + "\"\n"
+ root.nodePrint("\t\t"), ParseTreeCleaner.class);
root.setValue(child.getName());
@ -206,8 +207,9 @@ public final class ParseTreeCleaner {
&& root.getChildren().get(0).getName().equals(root.getChildren().get(1).getName())) {
// Case where variable is assigned another variable with the same name
Logger.logInfo("Moving " + root.getChildren().get(1).getValue() + " to value of " + root.getName(), ParseTreeCleaner.class);
Logger.logInfo(root.toString(), ParseTreeCleaner.class);
Logger.logInfo("Moving child-value \"" + root.getChildren().get(1).getValue()
+ "\" to parent-value of node \"" + root.getName() + "\"\n"
+ root.nodePrint("\t\t"), ParseTreeCleaner.class);
root.setValue(root.getChildren().get(1).getValue());
@ -217,8 +219,8 @@ public final class ParseTreeCleaner {
} else {
// Usual case where an expression is assigned
Logger.logInfo("Moving " + child.getValue() + " to value of " + root.getName(), ParseTreeCleaner.class);
Logger.logInfo(root.toString(), ParseTreeCleaner.class);
Logger.logInfo("Moving child value \"" + child.getValue() + "\" to parent-value of node \""
+ root.getName() + "\"\n" + root.nodePrint("\t\t"), ParseTreeCleaner.class);
root.setValue(child.getValue());
toRemove.add(child);

View File

@ -1,7 +1,10 @@
package parser.ast;
import parser.grammar.Grammar;
import util.GraphvizCaller;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Objects;
/**
@ -47,6 +50,52 @@ public class SyntaxTree {
return this.root.isEmpty();
}
public String printToImage(String filename) {
if (this.isEmpty()) {
return "Empty tree can't be exported to image: " + filename + ".svg";
}
final Deque<SyntaxTreeNode> stack = new ArrayDeque<>();
final StringBuilder dot = new StringBuilder();
dot.append("digraph tree {\n")
.append("node[shape=Mrecord]\n");
stack.push(this.root);
while (!stack.isEmpty()) {
final SyntaxTreeNode current = stack.pop();
dot.append("\"").append(current.getId()).append("\"")
.append(" [label=\"{<f0> ")
.append(current.getName())
.append("|<f1> ")
.append(current.getValue())
.append("}\"];\n");
current.getChildren().forEach(stack::push);
}
stack.push(this.root);
while (!stack.isEmpty()) {
final SyntaxTreeNode current = stack.pop();
for (SyntaxTreeNode child : current.getChildren()) {
dot.append("\"").append(current.getId()).append("\"")
.append(" -> ")
.append("\"").append(child.getId()).append("\"")
.append("\n");
}
current.getChildren().forEach(stack::push);
}
dot.append("}");
GraphvizCaller.callGraphviz(dot, filename);
return "Successfully generated image of syntax-tree: " + filename + ".svg";
}
// Overrides
@Override

View File

@ -5,6 +5,7 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
/**
@ -13,12 +14,14 @@ import java.util.stream.Collectors;
*/
public class SyntaxTreeNode {
private final UUID id;
private final int line;
private String name;
private String value;
private List<SyntaxTreeNode> children = new ArrayList<>();
public SyntaxTreeNode(String name, int line) {
this.id = UUID.randomUUID();
this.name = name;
this.line = line;
this.value = "";
@ -82,6 +85,10 @@ public class SyntaxTreeNode {
this.name = name;
}
public UUID getId() {
return this.id;
}
// Printing
// toString() und treePrint() von hier: https://stackoverflow.com/a/8948691
@ -104,6 +111,13 @@ public class SyntaxTreeNode {
}
}
public String nodePrint(String prefix) {
return prefix + this.name + ": " + this.value + "\n"
+ prefix + this.children.stream()
.map(child -> prefix + "└── " + child.name + ": " + child.value + "\n")
.collect(Collectors.joining()).trim();
}
// Overrides
@Override

View File

@ -70,7 +70,7 @@ public final class SyntaxTreeRebalancer {
flipCommutativeExpr(abstractSyntaxTree);
Logger.logDebug("Successfully rebalanced syntax-tree", SyntaxTreeRebalancer.class);
Logger.logInfo("AST after rebalancing:" + abstractSyntaxTree, SyntaxTreeRebalancer.class);
Logger.logDebugSupplier(() -> abstractSyntaxTree.printToImage("AbstractSyntaxTree"), SyntaxTreeRebalancer.class);
}
/**
@ -110,8 +110,8 @@ public final class SyntaxTreeRebalancer {
if (root.getChildren().size() == 2 && root.getChildren().get(0).size() < root.getChildren().get(1).size()) {
// Make the bigger subtree the left one
Logger.logInfo("Flipping " + root.getName() + ": " + root.getValue() + " for stack efficiency.", SyntaxTreeRebalancer.class);
Logger.logInfo(root.toString(), SyntaxTreeRebalancer.class);
Logger.logInfo("Flipping node \"" + root.getName() + ": " + root.getValue() + "\"\n"
+ root.nodePrint("\t\t"), SyntaxTreeRebalancer.class);
Collections.reverse(root.getChildren());
}
@ -153,8 +153,8 @@ public final class SyntaxTreeRebalancer {
* @return Es wird false zurückgegeben, sobald keine weitere Rotation mehr möglich ist.
*/
private static boolean specialLeftRotate(SyntaxTreeNode root) {
Logger.logInfo("Special-Left-Rotation around " + root.getName(), SyntaxTreeRebalancer.class);
Logger.logInfo(root.toString(), SyntaxTreeRebalancer.class);
Logger.logInfo("Special-left-rotation around node \"" + root.getName() + ": " + root.getValue() + "\"\n"
+ root.nodePrint("\t\t"), SyntaxTreeRebalancer.class);
final SyntaxTreeNode left = root.getChildren().get(0);
final SyntaxTreeNode right = root.getChildren().get(1);
@ -245,8 +245,8 @@ public final class SyntaxTreeRebalancer {
}
private static void simpleRightRotate(SyntaxTreeNode root) {
Logger.logInfo("Right-Rotation around " + root.getName() + ": " + root.getValue(), SyntaxTreeRebalancer.class);
Logger.logInfo(root.toString(), SyntaxTreeRebalancer.class);
Logger.logInfo("Simple right-rotation around node \"" + root.getName() + ": " + root.getValue() + "\"\n"
+ root.nodePrint("\t\t"), SyntaxTreeRebalancer.class);
final SyntaxTreeNode left = root.getChildren().get(0);
final SyntaxTreeNode right = root.getChildren().get(1);

View File

@ -118,15 +118,23 @@ public class Grammar {
Logger.logDebug("Beginning grammar parsing", Grammar.class);
for (String currentLine : lines) {
Logger.logInfo("Parsed: " + currentLine, Grammar.class);
Logger.logInfo("Parsing: \"" + currentLine + "\"", Grammar.class);
// Parse Keywords
if (currentLine.startsWith("TERM:")) {
terminals.addAll(Arrays.stream(currentLine.split(" ")).skip(1).collect(Collectors.toSet()));
Arrays.stream(currentLine.split(" "))
.skip(1)
.forEach(term -> Logger.logInfo(" :: Registered terminal symbol \"" + term + "\"", Grammar.class));
} else if (currentLine.startsWith("NTERM:")) {
nonterminals.addAll(Arrays.stream(currentLine.split(" ")).skip(1).collect(Collectors.toSet()));
Arrays.stream(currentLine.split(" "))
.skip(1)
.forEach(nterm -> Logger.logInfo(" :: Registered nonterminal symbol \"" + nterm + "\"", Grammar.class));
} else {
// Parse regular lines
@ -136,7 +144,10 @@ public class Grammar {
}
}
Logger.logInfo("Registered actions: " + actionMap, Grammar.class);
Logger.logInfo("Grammar terminals: " + terminals, Grammar.class);
Logger.logInfo("Grammar nonterminals: " + nonterminals, Grammar.class);
Logger.logInfo("Grammar productions: " + rules, Grammar.class);
Logger.logInfo("Grammar actions: " + actionMap, Grammar.class);
Logger.logDebug("Grammar parsed successfully", Grammar.class);
return new Grammar(terminals, nonterminals,
@ -170,8 +181,6 @@ public class Grammar {
final Set<String> actionSet = parseActionSet(leftside, open, close);
Logger.logInfo("Current Line " + currentLine + " has Actions: " + actionSet, Grammar.class);
// Validate Actions
throwOnInvalidActionSet(actionSet);
@ -230,7 +239,7 @@ public class Grammar {
Map<GrammarAction, Set<String>> actions) {
actions.get(action).add(leftside.trim());
Logger.logInfo("Registered " + flag + ": " + leftside.trim(), Grammar.class);
Logger.logInfo(" :: Registered action [" + flag + "] for \"" + leftside.trim() + "\"", Grammar.class);
}
/**
@ -246,7 +255,8 @@ public class Grammar {
final int argStart = flag.indexOf('=');
final String[] argSplit = flag.substring(argStart + 1).split(",");
Logger.logInfo("Registered " + flag + " args: " + argSplit, Grammar.class);
Arrays.stream(argSplit)
.forEach(arg -> Logger.logInfo(" :: Action has arg " + arg, Grammar.class));
switch (action) {
case DELCHILD -> delChildMappings.put(leftside, Arrays.asList(argSplit));
@ -270,7 +280,7 @@ public class Grammar {
final GrammarRule rule = new GrammarRule(leftside, prod.split(" "));
rules.add(rule);
Logger.logInfo("Registered production " + rule, Grammar.class);
Logger.logInfo(" :: Registered production \"" + rule + "\"", Grammar.class);
}
}

View File

@ -83,6 +83,7 @@ public final class GrammarAnalyzer {
for (String rightside : this.grammar.getRightsides(leftside)) {
// ...and X -> Y1 Y2 ... Yk is a production...
if (!rightside.equals(Grammar.EPSILON_SYMBOL)) {
// ...for some k >= 1...
@ -107,8 +108,9 @@ public final class GrammarAnalyzer {
final boolean changeNow = firstOut.get(leftside).addAll(firstYiNoEps);
change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "First: Added " + firstYiNoEps + " to "
+ leftside + " (All before are nullable)", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, " :: Added " + firstYiNoEps + " to \"first("
+ leftside + ")\" (All before are nullable)", GrammarAnalyzer.class);
}
if (i == split.length - 1 && allNullable.test(split)) {
@ -117,8 +119,9 @@ public final class GrammarAnalyzer {
final boolean changeNow = firstOut.get(leftside).add(Grammar.EPSILON_SYMBOL);
change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "First: Added " + Grammar.EPSILON_SYMBOL + " to "
+ leftside + " (All are nullable)", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, " :: Added [" + Grammar.EPSILON_SYMBOL + "] to \"first("
+ leftside + ")\" (All are nullable)", GrammarAnalyzer.class);
}
}
}
@ -129,15 +132,16 @@ public final class GrammarAnalyzer {
final boolean changeNow = firstOut.get(leftside).add(Grammar.EPSILON_SYMBOL);
change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "First: Added " + Grammar.EPSILON_SYMBOL + " to "
+ leftside + " (X -> EPS exists)", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, " :: Added [" + Grammar.EPSILON_SYMBOL + "] to \"first("
+ leftside + ")\" (X -> EPS exists)", GrammarAnalyzer.class);
}
}
}
} while (change);
Logger.logDebug(" :: First-set initialized successfully", GrammarAnalyzer.class);
Logger.logInfo("First Set: " + firstOut, GrammarAnalyzer.class);
Logger.logDebug(" :: First-set initialized successfully", GrammarAnalyzer.class);
return firstOut;
}
@ -192,8 +196,9 @@ public final class GrammarAnalyzer {
final boolean changeNow = followOut.get(split[i - 1]).addAll(firstXkNoEps);
change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "Follow: Added " + firstXkNoEps + " to "
+ split[i - 1] + " (Dazwischen nullable)", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, " :: Added " + firstXkNoEps + " to \"follow("
+ split[i - 1] + ")\" (All nullable inbetween)", GrammarAnalyzer.class);
}
}
@ -206,8 +211,9 @@ public final class GrammarAnalyzer {
final boolean changeNow = followOut.get(split[i - 1]).addAll(followOut.get(leftside));
change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "Follow: Added " + leftside + " to "
+ split[i - 1] + " (Dahinter nullable)", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, " :: Added " + leftside + " to \"follow("
+ split[i - 1] + ")\" (All following are nullable)", GrammarAnalyzer.class);
}
}
@ -217,16 +223,17 @@ public final class GrammarAnalyzer {
final boolean changeNow = followOut.get(split[split.length - 1]).addAll(followOut.get(leftside));
change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "Follow: Added " + followOut.get(leftside) + " to "
+ split[split.length - 1] + " (Ende der Regel)", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfoIfTrue(changeNow, " :: Added " + followOut.get(leftside) + " to \"follow("
+ split[split.length - 1] + ")\" (Last item in production)", GrammarAnalyzer.class);
}
}
}
} while (change);
Logger.logDebug(" :: Follow-set initialized successfully", GrammarAnalyzer.class);
Logger.logInfo("Follow Set: " + followOut, GrammarAnalyzer.class);
Logger.logDebug(" :: Follow-set initialized successfully", GrammarAnalyzer.class);
return followOut;
}
@ -248,9 +255,10 @@ public final class GrammarAnalyzer {
final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, sym), rightside);
Logger.logInfo("Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym
+ " in first of " + rightside + ")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, "Overwritten " + prev + "!\n", GrammarAnalyzer.class);
Logger.logInfo("Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfo(" :: Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym
+ " in \"first(" + rightside + ")\")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, " :: Overwritten " + prev + "!", GrammarAnalyzer.class);
}
final Set<String> followLeftside = this.follow(leftside);
@ -263,9 +271,10 @@ public final class GrammarAnalyzer {
final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, sym), rightside);
Logger.logInfo("Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym
+ " in follow of " + leftside + ")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, "Overwritten " + prev + "!\n", GrammarAnalyzer.class);
Logger.logInfo("Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfo(" :: Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym
+ " in \"follow(" + leftside + ")\")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, " :: Overwritten " + prev + "!", GrammarAnalyzer.class);
}
if (followLeftside.contains("$")) {
@ -273,10 +282,11 @@ public final class GrammarAnalyzer {
final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, "$"), rightside);
Logger.logInfo("Add " + rightside + " to cell (" + leftside
+ ", $) (epsilon in first of " + rightside + " and $ in follow of "
+ leftside + ")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, "Overwritten " + prev + "!\n", GrammarAnalyzer.class);
Logger.logInfo("Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
Logger.logInfo(" :: Add " + rightside + " to cell (" + leftside
+ ", $) (epsilon in \"first(" + rightside + ")\" and $ in \"follow("
+ leftside + ")\")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, " :: Overwritten " + prev + "!", GrammarAnalyzer.class);
}
}
}
@ -284,8 +294,8 @@ public final class GrammarAnalyzer {
final ParsingTable parsingTable = new ParsingTable(this.grammar, tableOut);
Logger.logInfo("ParsingTable:\n" + parsingTable, GrammarAnalyzer.class);
Logger.logDebug(" :: Parse-table initialized successfully", GrammarAnalyzer.class);
Logger.logInfo("ParsingTable: " + parsingTable, GrammarAnalyzer.class);
return parsingTable;
}

View File

@ -42,7 +42,8 @@ public final class TypeChecker {
final String literalType = getLiteralType(root.getName());
Logger.logInfo("Type " + literalType + " for Node:\n" + root, TypeChecker.class);
Logger.logInfo("Register type \"" + literalType + "\" for node \"" + root.getName() + ": "
+ root.getValue() + "\"", TypeChecker.class);
nodeTable.put(root, literalType);
return;
@ -51,7 +52,8 @@ public final class TypeChecker {
final String exprType = table.getMethodReturnType(root.getValue());
Logger.logInfo("Type " + exprType + " for Node:\n" + root, TypeChecker.class);
Logger.logInfo("Register type \"" + exprType + "\" for node \"" + root.getName() + "\"\n"
+ root.nodePrint("\t\t"), TypeChecker.class);
nodeTable.put(root, exprType);
} else if ("par_expr".equals(root.getName())) {
@ -65,7 +67,8 @@ public final class TypeChecker {
final String identifierType = table.getSymbolType(root.getValue());
Logger.logInfo("Type " + identifierType + " for Node:\n" + root, TypeChecker.class);
Logger.logInfo("Register type \"" + identifierType + "\" for node \"" + root.getName() + ": "
+ root.getValue() + "\"", TypeChecker.class);
nodeTable.put(root, identifierType);
}
@ -83,7 +86,7 @@ public final class TypeChecker {
final SyntaxTreeNode literalNode = root.getChildren().get(0);
final String literalType = nodeTable.get(literalNode);
Logger.logInfo("Validating Assignment: " + identifierType + ": " + identifier + " = " + literalType, TypeChecker.class);
Logger.logInfo("Validating assignment: \"" + identifier + "\" -> \"" + identifierType + "\" = \"" + literalType + "\"", TypeChecker.class);
if (!literalType.equals(identifierType)) {
Logger.logError("Line " + root.getLine() + " Typeerror: Can't assign [" + literalNode.getValue()
@ -96,7 +99,7 @@ public final class TypeChecker {
private static void validateExpression(SyntaxTreeNode root, TypeTable table, Map<SyntaxTreeNode, String> nodeTable) {
final String op = root.getValue();
Logger.logInfo("Validating Expression: " + root.getValue(), TypeChecker.class);
Logger.logInfo("Validating expression: \"" + root.getValue() + "\"\n" + root.nodePrint("\t\t"), TypeChecker.class);
if (root.isEmpty()) {
// Keine Kinder

View File

@ -86,7 +86,7 @@ public final class TypeTable {
if ("declaration".equals(root.getName())) {
final SyntaxTreeNode child = root.getChildren().get(0);
Logger.logInfo("Adding Entry " + child.getValue() + " -> " + root.getValue(), TypeTable.class);
Logger.logInfo("Adding Entry: \"" + child.getValue() + "\" -> \"" + root.getValue() + "\"", TypeTable.class);
final String oldEntry = table.put(child.getValue(), root.getValue());
if (oldEntry != null) {

View File

@ -8,7 +8,7 @@ public final class Logger {
private static final boolean LOG_ENABLED = true;
private static final boolean LOG_EXCEPTIONS = false;
private static final int LOG_LEVEL = 1; // 0 = ERROR, 1 = DEBUG, 2 = INFO
private static final int LOG_LEVEL = 2; // 0 = ERROR, 1 = DEBUG, 2 = INFO
private static final Map<String, Boolean> packages;
@ -21,14 +21,15 @@ public final class Logger {
Map.entry("codegen.analysis", true),
Map.entry("codegen.analysis.dataflow", true),
Map.entry("codegen.analysis.liveness", true),
Map.entry("codegen", false));
Map.entry("codegen", true));
}
private Logger() {}
private static void log(String message, Class clazz) {
if (LOG_ENABLED
&& packages.containsKey(clazz.getPackageName()) && packages.get(clazz.getPackageName()).equals(true)) {
&& (packages.containsKey(clazz.getPackageName()) && packages.get(clazz.getPackageName()).equals(true))
|| "StupsCompiler".equals(clazz.getName())) {
System.out.printf("%-75s\t(%s)%n", message, clazz.getName());
} else if (LOG_ENABLED && !packages.containsKey(clazz.getPackageName())) {