aboutsummaryrefslogtreecommitdiff
path: root/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/debug/Profiler.java
diff options
context:
space:
mode:
Diffstat (limited to 'antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/debug/Profiler.java')
-rw-r--r--antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/debug/Profiler.java734
1 files changed, 734 insertions, 0 deletions
diff --git a/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/debug/Profiler.java b/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/debug/Profiler.java
new file mode 100644
index 0000000..aea9a17
--- /dev/null
+++ b/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/debug/Profiler.java
@@ -0,0 +1,734 @@
+/*
+ [The "BSD license"]
+ Copyright (c) 2005-2009 Terence Parr
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.antlr.runtime.debug;
+
+import org.antlr.runtime.*;
+import org.antlr.runtime.misc.DoubleKeyMap;
+
+import java.util.*;
+
+/** Using the debug event interface, track what is happening in the parser
+ * and record statistics about the runtime.
+ */
+public class Profiler extends BlankDebugEventListener {
+ public static final String DATA_SEP = "\t";
+ public static final String newline = System.getProperty("line.separator");
+
+ static boolean dump = false;
+
+ public static class ProfileStats {
+ public String Version;
+ public String name;
+ public int numRuleInvocations;
+ public int numUniqueRulesInvoked;
+ public int numDecisionEvents;
+ public int numDecisionsCovered;
+ public int numDecisionsThatPotentiallyBacktrack;
+ public int numDecisionsThatDoBacktrack;
+ public int maxRuleInvocationDepth;
+ public float avgkPerDecisionEvent;
+ public float avgkPerBacktrackingDecisionEvent;
+ public float averageDecisionPercentBacktracks;
+ public int numBacktrackOccurrences; // doesn't count gated DFA edges
+
+ public int numFixedDecisions;
+ public int minDecisionMaxFixedLookaheads;
+ public int maxDecisionMaxFixedLookaheads;
+ public int avgDecisionMaxFixedLookaheads;
+ public int stddevDecisionMaxFixedLookaheads;
+ public int numCyclicDecisions;
+ public int minDecisionMaxCyclicLookaheads;
+ public int maxDecisionMaxCyclicLookaheads;
+ public int avgDecisionMaxCyclicLookaheads;
+ public int stddevDecisionMaxCyclicLookaheads;
+// int Stats.min(toArray(decisionMaxSynPredLookaheads);
+// int Stats.max(toArray(decisionMaxSynPredLookaheads);
+// int Stats.avg(toArray(decisionMaxSynPredLookaheads);
+// int Stats.stddev(toArray(decisionMaxSynPredLookaheads);
+ public int numSemanticPredicates;
+ public int numTokens;
+ public int numHiddenTokens;
+ public int numCharsMatched;
+ public int numHiddenCharsMatched;
+ public int numReportedErrors;
+ public int numMemoizationCacheHits;
+ public int numMemoizationCacheMisses;
+ public int numGuessingRuleInvocations;
+ public int numMemoizationCacheEntries;
+ }
+
+ public static class DecisionDescriptor {
+ public int decision;
+ public String fileName;
+ public String ruleName;
+ public int line;
+ public int pos;
+ public boolean couldBacktrack;
+
+ public int n;
+ public float avgk; // avg across all decision events
+ public int maxk;
+ public int numBacktrackOccurrences;
+ public int numSemPredEvals;
+ }
+
+ // all about a specific exec of a single decision
+ public static class DecisionEvent {
+ public DecisionDescriptor decision;
+ public int startIndex;
+ public int k;
+ public boolean backtracks; // doesn't count gated DFA edges
+ public boolean evalSemPred;
+ public long startTime;
+ public long stopTime;
+ public int numMemoizationCacheHits;
+ public int numMemoizationCacheMisses;
+ }
+
+ /** Because I may change the stats, I need to track that for later
+ * computations to be consistent.
+ */
+ public static final String Version = "3";
+ public static final String RUNTIME_STATS_FILENAME = "runtime.stats";
+
+ /** Ack, should not store parser; can't do remote stuff. Well, we pass
+ * input stream around too so I guess it's ok.
+ */
+ public DebugParser parser = null;
+
+ // working variables
+
+ protected int ruleLevel = 0;
+ //protected int decisionLevel = 0;
+ protected Token lastRealTokenTouchedInDecision;
+ protected Set<String> uniqueRules = new HashSet<String>();
+ protected Stack<String> currentGrammarFileName = new Stack();
+ protected Stack<String> currentRuleName = new Stack();
+ protected Stack<Integer> currentLine = new Stack();
+ protected Stack<Integer> currentPos = new Stack();
+
+ // Vector<DecisionStats>
+ //protected Vector decisions = new Vector(200); // need setSize
+ protected DoubleKeyMap<String,Integer, DecisionDescriptor> decisions =
+ new DoubleKeyMap<String,Integer, DecisionDescriptor>();
+
+ // Record a DecisionData for each decision we hit while parsing
+ protected List<DecisionEvent> decisionEvents = new ArrayList<DecisionEvent>();
+ protected Stack<DecisionEvent> decisionStack = new Stack<DecisionEvent>();
+
+ protected int backtrackDepth;
+
+ ProfileStats stats = new ProfileStats();
+
+ public Profiler() {
+ }
+
+ public Profiler(DebugParser parser) {
+ this.parser = parser;
+ }
+
+ public void enterRule(String grammarFileName, String ruleName) {
+// System.out.println("enterRule "+grammarFileName+":"+ruleName);
+ ruleLevel++;
+ stats.numRuleInvocations++;
+ uniqueRules.add(grammarFileName+":"+ruleName);
+ stats.maxRuleInvocationDepth = Math.max(stats.maxRuleInvocationDepth, ruleLevel);
+ currentGrammarFileName.push( grammarFileName );
+ currentRuleName.push( ruleName );
+ }
+
+ public void exitRule(String grammarFileName, String ruleName) {
+ ruleLevel--;
+ currentGrammarFileName.pop();
+ currentRuleName.pop();
+ }
+
+ /** Track memoization; this is not part of standard debug interface
+ * but is triggered by profiling. Code gen inserts an override
+ * for this method in the recognizer, which triggers this method.
+ * Called from alreadyParsedRule().
+ */
+ public void examineRuleMemoization(IntStream input,
+ int ruleIndex,
+ int stopIndex, // index or MEMO_RULE_UNKNOWN...
+ String ruleName)
+ {
+ if (dump) System.out.println("examine memo "+ruleName+" at "+input.index()+": "+stopIndex);
+ if ( stopIndex==BaseRecognizer.MEMO_RULE_UNKNOWN ) {
+ //System.out.println("rule "+ruleIndex+" missed @ "+input.index());
+ stats.numMemoizationCacheMisses++;
+ stats.numGuessingRuleInvocations++; // we'll have to enter
+ currentDecision().numMemoizationCacheMisses++;
+ }
+ else {
+ // regardless of rule success/failure, if in cache, we have a cache hit
+ //System.out.println("rule "+ruleIndex+" hit @ "+input.index());
+ stats.numMemoizationCacheHits++;
+ currentDecision().numMemoizationCacheHits++;
+ }
+ }
+
+ /** Warning: doesn't track success/failure, just unique recording event */
+ public void memoize(IntStream input,
+ int ruleIndex,
+ int ruleStartIndex,
+ String ruleName)
+ {
+ // count how many entries go into table
+ if (dump) System.out.println("memoize "+ruleName);
+ stats.numMemoizationCacheEntries++;
+ }
+
+ @Override
+ public void location(int line, int pos) {
+ currentLine.push(line);
+ currentPos.push(pos);
+ }
+
+ public void enterDecision(int decisionNumber, boolean couldBacktrack) {
+ lastRealTokenTouchedInDecision = null;
+ stats.numDecisionEvents++;
+ int startingLookaheadIndex = parser.getTokenStream().index();
+ TokenStream input = parser.getTokenStream();
+ if ( dump ) System.out.println("enterDecision canBacktrack="+couldBacktrack+" "+ decisionNumber +
+ " backtrack depth " + backtrackDepth +
+ " @ " + input.get(input.index()) +
+ " rule " +locationDescription());
+ String g = (String) currentGrammarFileName.peek();
+ DecisionDescriptor descriptor = decisions.get(g, decisionNumber);
+ if ( descriptor == null ) {
+ descriptor = new DecisionDescriptor();
+ decisions.put(g, decisionNumber, descriptor);
+ descriptor.decision = decisionNumber;
+ descriptor.fileName = (String)currentGrammarFileName.peek();
+ descriptor.ruleName = (String)currentRuleName.peek();
+ descriptor.line = (Integer)currentLine.peek();
+ descriptor.pos = (Integer)currentPos.peek();
+ descriptor.couldBacktrack = couldBacktrack;
+ }
+ descriptor.n++;
+
+ DecisionEvent d = new DecisionEvent();
+ decisionStack.push(d);
+ d.decision = descriptor;
+ d.startTime = System.currentTimeMillis();
+ d.startIndex = startingLookaheadIndex;
+ }
+
+ public void exitDecision(int decisionNumber) {
+ DecisionEvent d = decisionStack.pop();
+ d.stopTime = System.currentTimeMillis();
+
+ int lastTokenIndex = lastRealTokenTouchedInDecision.getTokenIndex();
+ int numHidden = getNumberOfHiddenTokens(d.startIndex, lastTokenIndex);
+ int depth = lastTokenIndex - d.startIndex - numHidden + 1; // +1 counts consuming start token as 1
+ d.k = depth;
+ d.decision.maxk = Math.max(d.decision.maxk, depth);
+
+ if (dump) System.out.println("exitDecision "+decisionNumber+" in "+d.decision.ruleName+
+ " lookahead "+d.k +" max token "+lastRealTokenTouchedInDecision);
+ decisionEvents.add(d); // done with decision; track all
+ }
+
+ public void consumeToken(Token token) {
+ if (dump) System.out.println("consume token "+token);
+ if ( !inDecision() ) {
+ stats.numTokens++;
+ return;
+ }
+ if ( lastRealTokenTouchedInDecision==null ||
+ lastRealTokenTouchedInDecision.getTokenIndex() < token.getTokenIndex() )
+ {
+ lastRealTokenTouchedInDecision = token;
+ }
+ DecisionEvent d = currentDecision();
+ // compute lookahead depth
+ int thisRefIndex = token.getTokenIndex();
+ int numHidden = getNumberOfHiddenTokens(d.startIndex, thisRefIndex);
+ int depth = thisRefIndex - d.startIndex - numHidden + 1; // +1 counts consuming start token as 1
+ //d.maxk = Math.max(d.maxk, depth);
+ if (dump) System.out.println("consume "+thisRefIndex+" "+depth+" tokens ahead in "+
+ d.decision.ruleName+"-"+d.decision.decision+" start index "+d.startIndex);
+ }
+
+ /** The parser is in a decision if the decision depth > 0. This
+ * works for backtracking also, which can have nested decisions.
+ */
+ public boolean inDecision() {
+ return decisionStack.size()>0;
+ }
+
+ public void consumeHiddenToken(Token token) {
+ //System.out.println("consume hidden token "+token);
+ if ( !inDecision() ) stats.numHiddenTokens++;
+ }
+
+ /** Track refs to lookahead if in a fixed/nonfixed decision.
+ */
+ public void LT(int i, Token t) {
+ if ( inDecision() && i>0 ) {
+ DecisionEvent d = currentDecision();
+ if (dump) System.out.println("LT("+i+")="+t+" index "+t.getTokenIndex()+" relative to "+d.decision.ruleName+"-"+
+ d.decision.decision+" start index "+d.startIndex);
+ if ( lastRealTokenTouchedInDecision==null ||
+ lastRealTokenTouchedInDecision.getTokenIndex() < t.getTokenIndex() )
+ {
+ lastRealTokenTouchedInDecision = t;
+ if (dump) System.out.println("set last token "+lastRealTokenTouchedInDecision);
+ }
+ // get starting index off stack
+// int stackTop = lookaheadStack.size()-1;
+// Integer startingIndex = (Integer)lookaheadStack.get(stackTop);
+// // compute lookahead depth
+// int thisRefIndex = parser.getTokenStream().index();
+// int numHidden =
+// getNumberOfHiddenTokens(startingIndex.intValue(), thisRefIndex);
+// int depth = i + thisRefIndex - startingIndex.intValue() - numHidden;
+// /*
+// System.out.println("LT("+i+") @ index "+thisRefIndex+" is depth "+depth+
+// " max is "+maxLookaheadInCurrentDecision);
+// */
+// if ( depth>maxLookaheadInCurrentDecision ) {
+// maxLookaheadInCurrentDecision = depth;
+// }
+// d.maxk = currentDecision()/
+ }
+ }
+
+ /** Track backtracking decisions. You'll see a fixed or cyclic decision
+ * and then a backtrack.
+ *
+ * enter rule
+ * ...
+ * enter decision
+ * LA and possibly consumes (for cyclic DFAs)
+ * begin backtrack level
+ * mark m
+ * rewind m
+ * end backtrack level, success
+ * exit decision
+ * ...
+ * exit rule
+ */
+ public void beginBacktrack(int level) {
+ if (dump) System.out.println("enter backtrack "+level);
+ backtrackDepth++;
+ DecisionEvent e = currentDecision();
+ if ( e.decision.couldBacktrack ) {
+ stats.numBacktrackOccurrences++;
+ e.decision.numBacktrackOccurrences++;
+ e.backtracks = true;
+ }
+ }
+
+ /** Successful or not, track how much lookahead synpreds use */
+ public void endBacktrack(int level, boolean successful) {
+ if (dump) System.out.println("exit backtrack "+level+": "+successful);
+ backtrackDepth--;
+ }
+
+ @Override
+ public void mark(int i) {
+ if (dump) System.out.println("mark "+i);
+ }
+
+ @Override
+ public void rewind(int i) {
+ if (dump) System.out.println("rewind "+i);
+ }
+
+ @Override
+ public void rewind() {
+ if (dump) System.out.println("rewind");
+ }
+
+
+
+ protected DecisionEvent currentDecision() {
+ return decisionStack.peek();
+ }
+
+ public void recognitionException(RecognitionException e) {
+ stats.numReportedErrors++;
+ }
+
+ public void semanticPredicate(boolean result, String predicate) {
+ stats.numSemanticPredicates++;
+ if ( inDecision() ) {
+ DecisionEvent d = currentDecision();
+ d.evalSemPred = true;
+ d.decision.numSemPredEvals++;
+ if (dump) System.out.println("eval "+predicate+" in "+d.decision.ruleName+"-"+
+ d.decision.decision);
+ }
+ }
+
+ public void terminate() {
+ for (DecisionEvent e : decisionEvents) {
+ //System.out.println("decision "+e.decision.decision+": k="+e.k);
+ e.decision.avgk += e.k;
+ stats.avgkPerDecisionEvent += e.k;
+ if ( e.backtracks ) { // doesn't count gated syn preds on DFA edges
+ stats.avgkPerBacktrackingDecisionEvent += e.k;
+ }
+ }
+ stats.averageDecisionPercentBacktracks = 0.0f;
+ for (DecisionDescriptor d : decisions.values()) {
+ stats.numDecisionsCovered++;
+ d.avgk /= (double)d.n;
+ if ( d.couldBacktrack ) {
+ stats.numDecisionsThatPotentiallyBacktrack++;
+ float percentBacktracks = d.numBacktrackOccurrences / (float)d.n;
+ //System.out.println("dec "+d.decision+" backtracks "+percentBacktracks*100+"%");
+ stats.averageDecisionPercentBacktracks += percentBacktracks;
+ }
+ // ignore rules that backtrack along gated DFA edges
+ if ( d.numBacktrackOccurrences > 0 ) {
+ stats.numDecisionsThatDoBacktrack++;
+ }
+ }
+ stats.averageDecisionPercentBacktracks /= stats.numDecisionsThatPotentiallyBacktrack;
+ stats.averageDecisionPercentBacktracks *= 100; // it's a percentage
+ stats.avgkPerDecisionEvent /= stats.numDecisionEvents;
+ stats.avgkPerBacktrackingDecisionEvent /= (double)stats.numBacktrackOccurrences;
+
+ System.err.println(toString());
+ System.err.println(getDecisionStatsDump());
+
+// String stats = toNotifyString();
+// try {
+// Stats.writeReport(RUNTIME_STATS_FILENAME,stats);
+// }
+// catch (IOException ioe) {
+// System.err.println(ioe);
+// ioe.printStackTrace(System.err);
+// }
+ }
+
+ public void setParser(DebugParser parser) {
+ this.parser = parser;
+ }
+
+ // R E P O R T I N G
+
+ public String toNotifyString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(Version);
+ buf.append('\t');
+ buf.append(parser.getClass().getName());
+// buf.append('\t');
+// buf.append(numRuleInvocations);
+// buf.append('\t');
+// buf.append(maxRuleInvocationDepth);
+// buf.append('\t');
+// buf.append(numFixedDecisions);
+// buf.append('\t');
+// buf.append(Stats.min(decisionMaxFixedLookaheads));
+// buf.append('\t');
+// buf.append(Stats.max(decisionMaxFixedLookaheads));
+// buf.append('\t');
+// buf.append(Stats.avg(decisionMaxFixedLookaheads));
+// buf.append('\t');
+// buf.append(Stats.stddev(decisionMaxFixedLookaheads));
+// buf.append('\t');
+// buf.append(numCyclicDecisions);
+// buf.append('\t');
+// buf.append(Stats.min(decisionMaxCyclicLookaheads));
+// buf.append('\t');
+// buf.append(Stats.max(decisionMaxCyclicLookaheads));
+// buf.append('\t');
+// buf.append(Stats.avg(decisionMaxCyclicLookaheads));
+// buf.append('\t');
+// buf.append(Stats.stddev(decisionMaxCyclicLookaheads));
+// buf.append('\t');
+// buf.append(numBacktrackDecisions);
+// buf.append('\t');
+// buf.append(Stats.min(toArray(decisionMaxSynPredLookaheads)));
+// buf.append('\t');
+// buf.append(Stats.max(toArray(decisionMaxSynPredLookaheads)));
+// buf.append('\t');
+// buf.append(Stats.avg(toArray(decisionMaxSynPredLookaheads)));
+// buf.append('\t');
+// buf.append(Stats.stddev(toArray(decisionMaxSynPredLookaheads)));
+// buf.append('\t');
+// buf.append(numSemanticPredicates);
+// buf.append('\t');
+// buf.append(parser.getTokenStream().size());
+// buf.append('\t');
+// buf.append(numHiddenTokens);
+// buf.append('\t');
+// buf.append(numCharsMatched);
+// buf.append('\t');
+// buf.append(numHiddenCharsMatched);
+// buf.append('\t');
+// buf.append(numberReportedErrors);
+// buf.append('\t');
+// buf.append(numMemoizationCacheHits);
+// buf.append('\t');
+// buf.append(numMemoizationCacheMisses);
+// buf.append('\t');
+// buf.append(numGuessingRuleInvocations);
+// buf.append('\t');
+// buf.append(numMemoizationCacheEntries);
+ return buf.toString();
+ }
+
+ public String toString() {
+ return toString(getReport());
+ }
+
+ public ProfileStats getReport() {
+// TokenStream input = parser.getTokenStream();
+// for (int i=0; i<input.size()&& lastRealTokenTouchedInDecision !=null&&i<= lastRealTokenTouchedInDecision.getTokenIndex(); i++) {
+// Token t = input.get(i);
+// if ( t.getChannel()!=Token.DEFAULT_CHANNEL ) {
+// stats.numHiddenTokens++;
+// stats.numHiddenCharsMatched += t.getText().length();
+// }
+// }
+ stats.Version = Version;
+ stats.name = parser.getClass().getName();
+ stats.numUniqueRulesInvoked = uniqueRules.size();
+ //stats.numCharsMatched = lastTokenConsumed.getStopIndex() + 1;
+ return stats;
+ }
+
+ public DoubleKeyMap getDecisionStats() {
+ return decisions;
+ }
+
+ public List getDecisionEvents() {
+ return decisionEvents;
+ }
+
+ public static String toString(ProfileStats stats) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("ANTLR Runtime Report; Profile Version ");
+ buf.append(stats.Version);
+ buf.append(newline);
+ buf.append("parser name ");
+ buf.append(stats.name);
+ buf.append(newline);
+ buf.append("Number of rule invocations ");
+ buf.append(stats.numRuleInvocations);
+ buf.append(newline);
+ buf.append("Number of unique rules visited ");
+ buf.append(stats.numUniqueRulesInvoked);
+ buf.append(newline);
+ buf.append("Number of decision events ");
+ buf.append(stats.numDecisionEvents);
+ buf.append(newline);
+ buf.append("Overall average k per decision event ");
+ buf.append(stats.avgkPerDecisionEvent);
+ buf.append(newline);
+ buf.append("Number of backtracking occurrences (can be multiple per decision) ");
+ buf.append(stats.numBacktrackOccurrences);
+ buf.append(newline);
+ buf.append("Overall average k per decision event that backtracks ");
+ buf.append(stats.avgkPerBacktrackingDecisionEvent);
+ buf.append(newline);
+ buf.append("Number of rule invocations while backtracking ");
+ buf.append(stats.numGuessingRuleInvocations);
+ buf.append(newline);
+ buf.append("num decisions that potentially backtrack ");
+ buf.append(stats.numDecisionsThatPotentiallyBacktrack);
+ buf.append(newline);
+ buf.append("num decisions that do backtrack ");
+ buf.append(stats.numDecisionsThatDoBacktrack);
+ buf.append(newline);
+ buf.append("num decisions that potentially backtrack but don't ");
+ buf.append(stats.numDecisionsThatPotentiallyBacktrack - stats.numDecisionsThatDoBacktrack);
+ buf.append(newline);
+ buf.append("average % of time a potentially backtracking decision backtracks ");
+ buf.append(stats.averageDecisionPercentBacktracks);
+ buf.append(newline);
+ buf.append("num unique decisions covered ");
+ buf.append(stats.numDecisionsCovered);
+ buf.append(newline);
+ buf.append("max rule invocation nesting depth ");
+ buf.append(stats.maxRuleInvocationDepth);
+ buf.append(newline);
+
+// buf.append("number of fixed lookahead decisions ");
+// buf.append();
+// buf.append('\n');
+// buf.append("min lookahead used in a fixed lookahead decision ");
+// buf.append();
+// buf.append('\n');
+// buf.append("max lookahead used in a fixed lookahead decision ");
+// buf.append();
+// buf.append('\n');
+// buf.append("average lookahead depth used in fixed lookahead decisions ");
+// buf.append();
+// buf.append('\n');
+// buf.append("standard deviation of depth used in fixed lookahead decisions ");
+// buf.append();
+// buf.append('\n');
+// buf.append("number of arbitrary lookahead decisions ");
+// buf.append();
+// buf.append('\n');
+// buf.append("min lookahead used in an arbitrary lookahead decision ");
+// buf.append();
+// buf.append('\n');
+// buf.append("max lookahead used in an arbitrary lookahead decision ");
+// buf.append();
+// buf.append('\n');
+// buf.append("average lookahead depth used in arbitrary lookahead decisions ");
+// buf.append();
+// buf.append('\n');
+// buf.append("standard deviation of depth used in arbitrary lookahead decisions ");
+// buf.append();
+// buf.append('\n');
+// buf.append("number of evaluated syntactic predicates ");
+// buf.append();
+// buf.append('\n');
+// buf.append("min lookahead used in a syntactic predicate ");
+// buf.append();
+// buf.append('\n');
+// buf.append("max lookahead used in a syntactic predicate ");
+// buf.append();
+// buf.append('\n');
+// buf.append("average lookahead depth used in syntactic predicates ");
+// buf.append();
+// buf.append('\n');
+// buf.append("standard deviation of depth used in syntactic predicates ");
+// buf.append();
+// buf.append('\n');
+ buf.append("rule memoization cache size ");
+ buf.append(stats.numMemoizationCacheEntries);
+ buf.append(newline);
+ buf.append("number of rule memoization cache hits ");
+ buf.append(stats.numMemoizationCacheHits);
+ buf.append(newline);
+ buf.append("number of rule memoization cache misses ");
+ buf.append(stats.numMemoizationCacheMisses);
+ buf.append(newline);
+// buf.append("number of evaluated semantic predicates ");
+// buf.append();
+// buf.append(newline);
+ buf.append("number of tokens ");
+ buf.append(stats.numTokens);
+ buf.append(newline);
+ buf.append("number of hidden tokens ");
+ buf.append(stats.numHiddenTokens);
+ buf.append(newline);
+ buf.append("number of char ");
+ buf.append(stats.numCharsMatched);
+ buf.append(newline);
+ buf.append("number of hidden char ");
+ buf.append(stats.numHiddenCharsMatched);
+ buf.append(newline);
+ buf.append("number of syntax errors ");
+ buf.append(stats.numReportedErrors);
+ buf.append(newline);
+ return buf.toString();
+ }
+
+ public String getDecisionStatsDump() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("location");
+ buf.append(DATA_SEP);
+ buf.append("n");
+ buf.append(DATA_SEP);
+ buf.append("avgk");
+ buf.append(DATA_SEP);
+ buf.append("maxk");
+ buf.append(DATA_SEP);
+ buf.append("synpred");
+ buf.append(DATA_SEP);
+ buf.append("sempred");
+ buf.append(DATA_SEP);
+ buf.append("canbacktrack");
+ buf.append("\n");
+ for (String fileName : decisions.keySet()) {
+ for (int d : decisions.keySet(fileName)) {
+ DecisionDescriptor s = decisions.get(fileName, d);
+ buf.append(s.decision);
+ buf.append("@");
+ buf.append(locationDescription(s.fileName,s.ruleName,s.line,s.pos)); // decision number
+ buf.append(DATA_SEP);
+ buf.append(s.n);
+ buf.append(DATA_SEP);
+ buf.append(String.format("%.2f",s.avgk));
+ buf.append(DATA_SEP);
+ buf.append(s.maxk);
+ buf.append(DATA_SEP);
+ buf.append(s.numBacktrackOccurrences);
+ buf.append(DATA_SEP);
+ buf.append(s.numSemPredEvals);
+ buf.append(DATA_SEP);
+ buf.append(s.couldBacktrack ?"1":"0");
+ buf.append(newline);
+ }
+ }
+ return buf.toString();
+ }
+
+ protected int[] trim(int[] X, int n) {
+ if ( n<X.length ) {
+ int[] trimmed = new int[n];
+ System.arraycopy(X,0,trimmed,0,n);
+ X = trimmed;
+ }
+ return X;
+ }
+
+ protected int[] toArray(List a) {
+ int[] x = new int[a.size()];
+ for (int i = 0; i < a.size(); i++) {
+ Integer I = (Integer) a.get(i);
+ x[i] = I.intValue();
+ }
+ return x;
+ }
+
+ /** Get num hidden tokens between i..j inclusive */
+ public int getNumberOfHiddenTokens(int i, int j) {
+ int n = 0;
+ TokenStream input = parser.getTokenStream();
+ for (int ti = i; ti<input.size() && ti <= j; ti++) {
+ Token t = input.get(ti);
+ if ( t.getChannel()!=Token.DEFAULT_CHANNEL ) {
+ n++;
+ }
+ }
+ return n;
+ }
+
+ protected String locationDescription() {
+ return locationDescription(
+ currentGrammarFileName.peek(),
+ currentRuleName.peek(),
+ currentLine.peek(),
+ currentPos.peek());
+ }
+
+ protected String locationDescription(String file, String rule, int line, int pos) {
+ return file+":"+line+":"+pos+"(" + rule + ")";
+ }
+}