package org.rascalmpl.parser.uptr.debug;
import java.io.PrintWriter;
import org.rascalmpl.parser.gtd.debug.IDebugListener;
import org.rascalmpl.parser.gtd.location.PositionStore;
import org.rascalmpl.parser.gtd.result.AbstractNode;
import org.rascalmpl.parser.gtd.result.struct.Link;
import org.rascalmpl.parser.gtd.stack.AbstractStackNode;
import org.rascalmpl.parser.gtd.stack.edge.EdgesSet;
import org.rascalmpl.parser.gtd.util.ArrayList;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.values.uptr.ProductionAdapter;
public class DebugLogger implements IDebugListener<IConstructor>{
private final PrintWriter out;
private final boolean verbose;
public DebugLogger(PrintWriter out, boolean verbose){
super();
this.out = out;
this.verbose = verbose;
}
public DebugLogger(PrintWriter out){
this(out, false);
}
private static void collectProductions(AbstractStackNode<IConstructor> node, ArrayList<IConstructor> productions){
AbstractStackNode<IConstructor>[] production = node.getProduction();
if(production == null) return; // Can happen, but can't remember why.
int dot = node.getDot();
if(node.isEndNode()){
IConstructor parentProduction = node.getParentProduction();
productions.add(parentProduction);
if(ProductionAdapter.isList(parentProduction)) return; // Don't follow productions in lists productions, since they are 'cyclic'.
}
for(int i = dot + 1; i < production.length; ++i){
AbstractStackNode<IConstructor> currentNode = production[i];
if(currentNode.isEndNode()){
productions.add(currentNode.getParentProduction());
}
AbstractStackNode<IConstructor>[][] alternateProductions = currentNode.getAlternateProductions();
if(alternateProductions != null){
for(int j = alternateProductions.length - 1; j >= 0; --j){
collectProductions(alternateProductions[j][i], productions);
}
}
}
}
private void printProductions(AbstractStackNode<IConstructor> node, boolean indent){
ArrayList<IConstructor> productions = new ArrayList<IConstructor>();
collectProductions(node, productions);
for(int i = productions.size() - 1; i >= 0; --i){
if(indent) out.print('\t');
out.println(productions.get(i));
}
}
public void shifting(int offset, int[] input, PositionStore positionStore){
int line = positionStore.findLine(offset);
int column = positionStore.getColumn(offset, line);
out.println(String.format("Shifting to offset: %d (line: %d, column: %d)", offset, line, column));
}
public void iterating(){
out.println("Iterating");
}
public void matched(AbstractStackNode<IConstructor> node, AbstractNode result){
out.println(String.format("Matched: %s", node));
}
public void failedToMatch(AbstractStackNode<IConstructor> node){
out.println(String.format("Failed to match: %s", node));
}
public void expanding(AbstractStackNode<IConstructor> node){
out.println(String.format("Expanding: %s", node));
if(verbose){
out.println("\tPart of the following production(s):");
printProductions(node, true);
}
}
public void expanded(AbstractStackNode<IConstructor> node, AbstractStackNode<IConstructor> child){
out.println(String.format("Expanded: %s", node));
}
public void foundIterationCachedNullableResult(AbstractStackNode<IConstructor> node){
out.println(String.format("Found cached nullable result for: %s", node));
}
public void moving(AbstractStackNode<IConstructor> node, AbstractNode result){
out.println(String.format("Moving: %s", node));
if(verbose){
out.println("\tPart of the following production(s):");
printProductions(node, true);
}
}
public void progressed(AbstractStackNode<IConstructor> node, AbstractNode result, AbstractStackNode<IConstructor> next){
out.println(String.format("Progressed: %s to %s", node, next));
if(verbose){
out.println("\tPart of the following production(s):");
printProductions(next, true);
}
}
public void propagated(AbstractStackNode<IConstructor> node, AbstractNode nodeResult, AbstractStackNode<IConstructor> next){
out.println(String.format("Propagated prefixes from %s to %s", node, next));
if(verbose){
out.println("\tPart of the following production(s):");
printProductions(next, true);
}
}
public void reducing(AbstractStackNode<IConstructor> node, Link resultLink, EdgesSet<IConstructor> edges){
out.println(String.format("Reducing: %s, start location: %d", node.getParentProduction(), edges.get(0).getStartLocation()));
}
public void reduced(AbstractStackNode<IConstructor> parent){
out.println(String.format("Reduced to: %s", parent));
if(verbose){
out.println(String.format("\tPart of the following production(s) (Dot position: %d):", parent.getDot()));
printProductions(parent, true);
}
}
public void filteredByNestingRestriction(AbstractStackNode<IConstructor> parent){
out.println(String.format("Filtered by nesting restriction: %s (parent)", parent));
}
public void filteredByEnterFilter(AbstractStackNode<IConstructor> node){
out.println(String.format("Filtered by enter filter restriction: %s", node));
}
public void filteredByCompletionFilter(AbstractStackNode<IConstructor> node, AbstractNode result){
out.println(String.format("Filtered by completion filter: %s", node));
}
}