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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,10 @@
package parser.ast; package parser.ast;
import parser.grammar.Grammar; import parser.grammar.Grammar;
import util.GraphvizCaller;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Objects; import java.util.Objects;
/** /**
@ -47,6 +50,52 @@ public class SyntaxTree {
return this.root.isEmpty(); 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 // Overrides
@Override @Override

View File

@ -5,6 +5,7 @@ import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -13,12 +14,14 @@ import java.util.stream.Collectors;
*/ */
public class SyntaxTreeNode { public class SyntaxTreeNode {
private final UUID id;
private final int line; private final int line;
private String name; private String name;
private String value; private String value;
private List<SyntaxTreeNode> children = new ArrayList<>(); private List<SyntaxTreeNode> children = new ArrayList<>();
public SyntaxTreeNode(String name, int line) { public SyntaxTreeNode(String name, int line) {
this.id = UUID.randomUUID();
this.name = name; this.name = name;
this.line = line; this.line = line;
this.value = ""; this.value = "";
@ -82,6 +85,10 @@ public class SyntaxTreeNode {
this.name = name; this.name = name;
} }
public UUID getId() {
return this.id;
}
// Printing // Printing
// toString() und treePrint() von hier: https://stackoverflow.com/a/8948691 // 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 // Overrides
@Override @Override

View File

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

View File

@ -118,15 +118,23 @@ public class Grammar {
Logger.logDebug("Beginning grammar parsing", Grammar.class); Logger.logDebug("Beginning grammar parsing", Grammar.class);
for (String currentLine : lines) { for (String currentLine : lines) {
Logger.logInfo("Parsed: " + currentLine, Grammar.class); Logger.logInfo("Parsing: \"" + currentLine + "\"", Grammar.class);
// Parse Keywords // Parse Keywords
if (currentLine.startsWith("TERM:")) { if (currentLine.startsWith("TERM:")) {
terminals.addAll(Arrays.stream(currentLine.split(" ")).skip(1).collect(Collectors.toSet())); 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:")) { } else if (currentLine.startsWith("NTERM:")) {
nonterminals.addAll(Arrays.stream(currentLine.split(" ")).skip(1).collect(Collectors.toSet())); 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 { } else {
// Parse regular lines // 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); Logger.logDebug("Grammar parsed successfully", Grammar.class);
return new Grammar(terminals, nonterminals, return new Grammar(terminals, nonterminals,
@ -170,8 +181,6 @@ public class Grammar {
final Set<String> actionSet = parseActionSet(leftside, open, close); final Set<String> actionSet = parseActionSet(leftside, open, close);
Logger.logInfo("Current Line " + currentLine + " has Actions: " + actionSet, Grammar.class);
// Validate Actions // Validate Actions
throwOnInvalidActionSet(actionSet); throwOnInvalidActionSet(actionSet);
@ -230,7 +239,7 @@ public class Grammar {
Map<GrammarAction, Set<String>> actions) { Map<GrammarAction, Set<String>> actions) {
actions.get(action).add(leftside.trim()); 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 int argStart = flag.indexOf('=');
final String[] argSplit = flag.substring(argStart + 1).split(","); 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) { switch (action) {
case DELCHILD -> delChildMappings.put(leftside, Arrays.asList(argSplit)); case DELCHILD -> delChildMappings.put(leftside, Arrays.asList(argSplit));
@ -270,7 +280,7 @@ public class Grammar {
final GrammarRule rule = new GrammarRule(leftside, prod.split(" ")); final GrammarRule rule = new GrammarRule(leftside, prod.split(" "));
rules.add(rule); 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)) { for (String rightside : this.grammar.getRightsides(leftside)) {
// ...and X -> Y1 Y2 ... Yk is a production... // ...and X -> Y1 Y2 ... Yk is a production...
if (!rightside.equals(Grammar.EPSILON_SYMBOL)) { if (!rightside.equals(Grammar.EPSILON_SYMBOL)) {
// ...for some k >= 1... // ...for some k >= 1...
@ -107,8 +108,9 @@ public final class GrammarAnalyzer {
final boolean changeNow = firstOut.get(leftside).addAll(firstYiNoEps); final boolean changeNow = firstOut.get(leftside).addAll(firstYiNoEps);
change = change || changeNow; change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "First: Added " + firstYiNoEps + " to " Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ leftside + " (All before are nullable)", GrammarAnalyzer.class); Logger.logInfoIfTrue(changeNow, " :: Added " + firstYiNoEps + " to \"first("
+ leftside + ")\" (All before are nullable)", GrammarAnalyzer.class);
} }
if (i == split.length - 1 && allNullable.test(split)) { 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); final boolean changeNow = firstOut.get(leftside).add(Grammar.EPSILON_SYMBOL);
change = change || changeNow; change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "First: Added " + Grammar.EPSILON_SYMBOL + " to " Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ leftside + " (All are nullable)", 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); final boolean changeNow = firstOut.get(leftside).add(Grammar.EPSILON_SYMBOL);
change = change || changeNow; change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "First: Added " + Grammar.EPSILON_SYMBOL + " to " Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ leftside + " (X -> EPS exists)", GrammarAnalyzer.class); Logger.logInfoIfTrue(changeNow, " :: Added [" + Grammar.EPSILON_SYMBOL + "] to \"first("
+ leftside + ")\" (X -> EPS exists)", GrammarAnalyzer.class);
} }
} }
} }
} while (change); } while (change);
Logger.logDebug(" :: First-set initialized successfully", GrammarAnalyzer.class);
Logger.logInfo("First Set: " + firstOut, GrammarAnalyzer.class); Logger.logInfo("First Set: " + firstOut, GrammarAnalyzer.class);
Logger.logDebug(" :: First-set initialized successfully", GrammarAnalyzer.class);
return firstOut; return firstOut;
} }
@ -192,8 +196,9 @@ public final class GrammarAnalyzer {
final boolean changeNow = followOut.get(split[i - 1]).addAll(firstXkNoEps); final boolean changeNow = followOut.get(split[i - 1]).addAll(firstXkNoEps);
change = change || changeNow; change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "Follow: Added " + firstXkNoEps + " to " Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ split[i - 1] + " (Dazwischen nullable)", 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)); final boolean changeNow = followOut.get(split[i - 1]).addAll(followOut.get(leftside));
change = change || changeNow; change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "Follow: Added " + leftside + " to " Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ split[i - 1] + " (Dahinter nullable)", 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)); final boolean changeNow = followOut.get(split[split.length - 1]).addAll(followOut.get(leftside));
change = change || changeNow; change = change || changeNow;
Logger.logInfoIfTrue(changeNow, "Follow: Added " + followOut.get(leftside) + " to " Logger.logInfoIfTrue(changeNow, "Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ split[split.length - 1] + " (Ende der Regel)", GrammarAnalyzer.class); Logger.logInfoIfTrue(changeNow, " :: Added " + followOut.get(leftside) + " to \"follow("
+ split[split.length - 1] + ")\" (Last item in production)", GrammarAnalyzer.class);
} }
} }
} }
} while (change); } while (change);
Logger.logDebug(" :: Follow-set initialized successfully", GrammarAnalyzer.class);
Logger.logInfo("Follow Set: " + followOut, GrammarAnalyzer.class); Logger.logInfo("Follow Set: " + followOut, GrammarAnalyzer.class);
Logger.logDebug(" :: Follow-set initialized successfully", GrammarAnalyzer.class);
return followOut; return followOut;
} }
@ -248,9 +255,10 @@ public final class GrammarAnalyzer {
final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, sym), rightside); final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, sym), rightside);
Logger.logInfo("Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym Logger.logInfo("Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ " in first of " + rightside + ")", GrammarAnalyzer.class); Logger.logInfo(" :: Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym
Logger.logInfoNullable(prev, "Overwritten " + prev + "!\n", GrammarAnalyzer.class); + " in \"first(" + rightside + ")\")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, " :: Overwritten " + prev + "!", GrammarAnalyzer.class);
} }
final Set<String> followLeftside = this.follow(leftside); 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); final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, sym), rightside);
Logger.logInfo("Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym Logger.logInfo("Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ " in follow of " + leftside + ")", GrammarAnalyzer.class); Logger.logInfo(" :: Add " + rightside + " to cell (" + leftside + ", " + sym + ") (" + sym
Logger.logInfoNullable(prev, "Overwritten " + prev + "!\n", GrammarAnalyzer.class); + " in \"follow(" + leftside + ")\")", GrammarAnalyzer.class);
Logger.logInfoNullable(prev, " :: Overwritten " + prev + "!", GrammarAnalyzer.class);
} }
if (followLeftside.contains("$")) { if (followLeftside.contains("$")) {
@ -273,10 +282,11 @@ public final class GrammarAnalyzer {
final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, "$"), rightside); final String prev = tableOut.put(new AbstractMap.SimpleEntry<>(leftside, "$"), rightside);
Logger.logInfo("Add " + rightside + " to cell (" + leftside Logger.logInfo("Rule: \"" + leftside + " -> " + rightside + "\"", GrammarAnalyzer.class);
+ ", $) (epsilon in first of " + rightside + " and $ in follow of " Logger.logInfo(" :: Add " + rightside + " to cell (" + leftside
+ leftside + ")", GrammarAnalyzer.class); + ", $) (epsilon in \"first(" + rightside + ")\" and $ in \"follow("
Logger.logInfoNullable(prev, "Overwritten " + prev + "!\n", GrammarAnalyzer.class); + 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); final ParsingTable parsingTable = new ParsingTable(this.grammar, tableOut);
Logger.logInfo("ParsingTable:\n" + parsingTable, GrammarAnalyzer.class);
Logger.logDebug(" :: Parse-table initialized successfully", GrammarAnalyzer.class); Logger.logDebug(" :: Parse-table initialized successfully", GrammarAnalyzer.class);
Logger.logInfo("ParsingTable: " + parsingTable, GrammarAnalyzer.class);
return parsingTable; return parsingTable;
} }

View File

@ -42,7 +42,8 @@ public final class TypeChecker {
final String literalType = getLiteralType(root.getName()); 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); nodeTable.put(root, literalType);
return; return;
@ -51,7 +52,8 @@ public final class TypeChecker {
final String exprType = table.getMethodReturnType(root.getValue()); 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); nodeTable.put(root, exprType);
} else if ("par_expr".equals(root.getName())) { } else if ("par_expr".equals(root.getName())) {
@ -65,7 +67,8 @@ public final class TypeChecker {
final String identifierType = table.getSymbolType(root.getValue()); 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); nodeTable.put(root, identifierType);
} }
@ -83,7 +86,7 @@ public final class TypeChecker {
final SyntaxTreeNode literalNode = root.getChildren().get(0); final SyntaxTreeNode literalNode = root.getChildren().get(0);
final String literalType = nodeTable.get(literalNode); 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)) { if (!literalType.equals(identifierType)) {
Logger.logError("Line " + root.getLine() + " Typeerror: Can't assign [" + literalNode.getValue() 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) { private static void validateExpression(SyntaxTreeNode root, TypeTable table, Map<SyntaxTreeNode, String> nodeTable) {
final String op = root.getValue(); 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()) { if (root.isEmpty()) {
// Keine Kinder // Keine Kinder

View File

@ -86,7 +86,7 @@ public final class TypeTable {
if ("declaration".equals(root.getName())) { if ("declaration".equals(root.getName())) {
final SyntaxTreeNode child = root.getChildren().get(0); 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()); final String oldEntry = table.put(child.getValue(), root.getValue());
if (oldEntry != null) { 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_ENABLED = true;
private static final boolean LOG_EXCEPTIONS = false; 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; private static final Map<String, Boolean> packages;
@ -21,14 +21,15 @@ public final class Logger {
Map.entry("codegen.analysis", true), Map.entry("codegen.analysis", true),
Map.entry("codegen.analysis.dataflow", true), Map.entry("codegen.analysis.dataflow", true),
Map.entry("codegen.analysis.liveness", true), Map.entry("codegen.analysis.liveness", true),
Map.entry("codegen", false)); Map.entry("codegen", true));
} }
private Logger() {} private Logger() {}
private static void log(String message, Class clazz) { private static void log(String message, Class clazz) {
if (LOG_ENABLED 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()); System.out.printf("%-75s\t(%s)%n", message, clazz.getName());
} else if (LOG_ENABLED && !packages.containsKey(clazz.getPackageName())) { } else if (LOG_ENABLED && !packages.containsKey(clazz.getPackageName())) {