• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Note to JL: Replaced Hashset with Dictionary.
3  *
4  * [The "BSD licence"]
5  * Copyright (c) 2005-2008 Terence Parr
6  * All rights reserved.
7  *
8  * Conversion to C#:
9  * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 namespace Antlr.Runtime.Debug {
36     using System.Collections.Generic;
37     using System.Collections.ObjectModel;
38     using Antlr.Runtime.Debug.Misc;
39 
40     using Array = System.Array;
41     using CLSCompliantAttribute = System.CLSCompliantAttribute;
42     using Console = System.Console;
43     using DateTime = System.DateTime;
44     using Environment = System.Environment;
45     using Math = System.Math;
46     using StringBuilder = System.Text.StringBuilder;
47 
48     /** <summary>Using the debug event interface, track what is happening in the parser
49      *  and record statistics about the runtime.
50      */
51     public class Profiler : BlankDebugEventListener {
52         public static readonly string DataSeparator = "\t";
53         public static readonly string NewLine = Environment.NewLine;
54 
55         internal static bool dump = false;
56 
57         /** Because I may change the stats, I need to track that for later
58          *  computations to be consistent.
59          */
60         public static readonly string Version = "3";
61         public static readonly string RuntimeStatsFilename = "runtime.stats";
62 
63         /** Ack, should not store parser; can't do remote stuff.  Well, we pass
64          *  input stream around too so I guess it's ok.
65          */
66         public DebugParser parser = null;
67 
68         // working variables
69 
70         [CLSCompliant(false)]
71         protected int ruleLevel = 0;
72         //protected int decisionLevel = 0;
73         protected IToken lastRealTokenTouchedInDecision;
74         protected Dictionary<string, string> uniqueRules = new Dictionary<string, string>();
75         protected Stack<string> currentGrammarFileName = new Stack<string>();
76         protected Stack<string> currentRuleName = new Stack<string>();
77         protected Stack<int> currentLine = new Stack<int>();
78         protected Stack<int> currentPos = new Stack<int>();
79 
80         // Vector<DecisionStats>
81         //protected Vector decisions = new Vector(200); // need setSize
82         protected DoubleKeyMap<string, int, DecisionDescriptor> decisions = new DoubleKeyMap<string, int, DecisionDescriptor>();
83 
84         // Record a DecisionData for each decision we hit while parsing
85         private List<DecisionEvent> decisionEvents = new List<DecisionEvent>();
86         protected Stack<DecisionEvent> decisionStack = new Stack<DecisionEvent>();
87 
88         protected int backtrackDepth;
89 
90         ProfileStats stats = new ProfileStats();
91 
Profiler()92         public Profiler() {
93         }
94 
Profiler(DebugParser parser)95         public Profiler(DebugParser parser) {
96             this.parser = parser;
97         }
98 
EnterRule(string grammarFileName, string ruleName)99         public override void EnterRule(string grammarFileName, string ruleName) {
100             //System.out.println("enterRule "+grammarFileName+":"+ruleName);
101             ruleLevel++;
102             stats.numRuleInvocations++;
103             uniqueRules[ruleName] = (grammarFileName + ":" + ruleName);
104             stats.maxRuleInvocationDepth = Math.Max(stats.maxRuleInvocationDepth, ruleLevel);
105             currentGrammarFileName.Push(grammarFileName);
106             currentRuleName.Push(ruleName);
107         }
108 
ExitRule(string grammarFileName, string ruleName)109         public override void ExitRule(string grammarFileName, string ruleName) {
110             ruleLevel--;
111             currentGrammarFileName.Pop();
112             currentRuleName.Pop();
113         }
114 
115         /** Track memoization; this is not part of standard debug interface
116          *  but is triggered by profiling.  Code gen inserts an override
117          *  for this method in the recognizer, which triggers this method.
118          *  Called from alreadyParsedRule().
119          */
ExamineRuleMemoization(IIntStream input, int ruleIndex, int stopIndex, string ruleName)120         public virtual void ExamineRuleMemoization(IIntStream input,
121                                            int ruleIndex,
122                                            int stopIndex, // index or MEMO_RULE_UNKNOWN...
123                                            string ruleName) {
124             if (dump)
125                 Console.WriteLine("examine memo " + ruleName + " at " + input.Index + ": " + stopIndex);
126             if (stopIndex == BaseRecognizer.MemoRuleUnknown) {
127                 //System.out.println("rule "+ruleIndex+" missed @ "+input.index());
128                 stats.numMemoizationCacheMisses++;
129                 stats.numGuessingRuleInvocations++; // we'll have to enter
130                 CurrentDecision().numMemoizationCacheMisses++;
131             } else {
132                 // regardless of rule success/failure, if in cache, we have a cache hit
133                 //System.out.println("rule "+ruleIndex+" hit @ "+input.index());
134                 stats.numMemoizationCacheHits++;
135                 CurrentDecision().numMemoizationCacheHits++;
136             }
137         }
138 
139         /** Warning: doesn't track success/failure, just unique recording event */
Memoize(IIntStream input, int ruleIndex, int ruleStartIndex, string ruleName)140         public virtual void Memoize(IIntStream input,
141                             int ruleIndex,
142                             int ruleStartIndex,
143                             string ruleName) {
144             // count how many entries go into table
145             if (dump)
146                 Console.WriteLine("memoize " + ruleName);
147             stats.numMemoizationCacheEntries++;
148         }
149 
Location(int line, int pos)150         public override void Location(int line, int pos) {
151             currentLine.Push(line);
152             currentPos.Push(pos);
153         }
154 
EnterDecision(int decisionNumber, bool couldBacktrack)155         public override void EnterDecision(int decisionNumber, bool couldBacktrack) {
156             lastRealTokenTouchedInDecision = null;
157             stats.numDecisionEvents++;
158             int startingLookaheadIndex = parser.TokenStream.Index;
159             ITokenStream input = parser.TokenStream;
160             if (dump) {
161                 Console.WriteLine("enterDecision canBacktrack=" + couldBacktrack + " " + decisionNumber +
162                       " backtrack depth " + backtrackDepth +
163                       " @ " + input.Get(input.Index) +
164                       " rule " + LocationDescription());
165             }
166             string g = currentGrammarFileName.Peek();
167             DecisionDescriptor descriptor = decisions.Get(g, decisionNumber);
168             if (descriptor == null) {
169                 descriptor = new DecisionDescriptor();
170                 decisions.Put(g, decisionNumber, descriptor);
171                 descriptor.decision = decisionNumber;
172                 descriptor.fileName = currentGrammarFileName.Peek();
173                 descriptor.ruleName = currentRuleName.Peek();
174                 descriptor.line = currentLine.Peek();
175                 descriptor.pos = currentPos.Peek();
176                 descriptor.couldBacktrack = couldBacktrack;
177             }
178             descriptor.n++;
179 
180             DecisionEvent d = new DecisionEvent();
181             decisionStack.Push(d);
182             d.decision = descriptor;
183             d.startTime = DateTime.Now;
184             d.startIndex = startingLookaheadIndex;
185         }
186 
ExitDecision(int decisionNumber)187         public override void ExitDecision(int decisionNumber) {
188             DecisionEvent d = decisionStack.Pop();
189             d.stopTime = DateTime.Now;
190 
191             int lastTokenIndex = lastRealTokenTouchedInDecision.TokenIndex;
192             int numHidden = GetNumberOfHiddenTokens(d.startIndex, lastTokenIndex);
193             int depth = lastTokenIndex - d.startIndex - numHidden + 1; // +1 counts consuming start token as 1
194             d.k = depth;
195             d.decision.maxk = Math.Max(d.decision.maxk, depth);
196 
197             if (dump) {
198                 Console.WriteLine("exitDecision " + decisionNumber + " in " + d.decision.ruleName +
199                                    " lookahead " + d.k + " max token " + lastRealTokenTouchedInDecision);
200             }
201 
202             decisionEvents.Add(d); // done with decision; track all
203         }
204 
ConsumeToken(IToken token)205         public override void ConsumeToken(IToken token) {
206             if (dump)
207                 Console.WriteLine("consume token " + token);
208 
209             if (!InDecision) {
210                 stats.numTokens++;
211                 return;
212             }
213 
214             if (lastRealTokenTouchedInDecision == null ||
215                  lastRealTokenTouchedInDecision.TokenIndex < token.TokenIndex) {
216                 lastRealTokenTouchedInDecision = token;
217             }
218             DecisionEvent d = CurrentDecision();
219             // compute lookahead depth
220             int thisRefIndex = token.TokenIndex;
221             int numHidden = GetNumberOfHiddenTokens(d.startIndex, thisRefIndex);
222             int depth = thisRefIndex - d.startIndex - numHidden + 1; // +1 counts consuming start token as 1
223             //d.maxk = Math.max(d.maxk, depth);
224             if (dump) {
225                 Console.WriteLine("consume " + thisRefIndex + " " + depth + " tokens ahead in " +
226                                    d.decision.ruleName + "-" + d.decision.decision + " start index " + d.startIndex);
227             }
228         }
229 
230         /** The parser is in a decision if the decision depth > 0.  This
231          *  works for backtracking also, which can have nested decisions.
232          */
233         public virtual bool InDecision {
234             get {
235                 return decisionStack.Count > 0;
236             }
237         }
238 
ConsumeHiddenToken(IToken token)239         public override void ConsumeHiddenToken(IToken token) {
240             //System.out.println("consume hidden token "+token);
241             if (!InDecision)
242                 stats.numHiddenTokens++;
243         }
244 
245         /** Track refs to lookahead if in a fixed/nonfixed decision.
246          */
LT(int i, IToken t)247         public override void LT(int i, IToken t) {
248             if (InDecision && i > 0) {
249                 DecisionEvent d = CurrentDecision();
250                 if (dump) {
251                     Console.WriteLine("LT(" + i + ")=" + t + " index " + t.TokenIndex + " relative to " + d.decision.ruleName + "-" +
252                              d.decision.decision + " start index " + d.startIndex);
253                 }
254 
255                 if (lastRealTokenTouchedInDecision == null ||
256                      lastRealTokenTouchedInDecision.TokenIndex < t.TokenIndex) {
257                     lastRealTokenTouchedInDecision = t;
258                     if (dump)
259                         Console.WriteLine("set last token " + lastRealTokenTouchedInDecision);
260                 }
261                 // get starting index off stack
262                 //			int stackTop = lookaheadStack.size()-1;
263                 //			Integer startingIndex = (Integer)lookaheadStack.get(stackTop);
264                 //			// compute lookahead depth
265                 //			int thisRefIndex = parser.getTokenStream().index();
266                 //			int numHidden =
267                 //				getNumberOfHiddenTokens(startingIndex.intValue(), thisRefIndex);
268                 //			int depth = i + thisRefIndex - startingIndex.intValue() - numHidden;
269                 //			/*
270                 //			System.out.println("LT("+i+") @ index "+thisRefIndex+" is depth "+depth+
271                 //				" max is "+maxLookaheadInCurrentDecision);
272                 //			*/
273                 //			if ( depth>maxLookaheadInCurrentDecision ) {
274                 //				maxLookaheadInCurrentDecision = depth;
275                 //			}
276                 //			d.maxk = currentDecision()/
277             }
278         }
279 
280         /** Track backtracking decisions.  You'll see a fixed or cyclic decision
281          *  and then a backtrack.
282          *
283          * 		enter rule
284          * 		...
285          * 		enter decision
286          * 		LA and possibly consumes (for cyclic DFAs)
287          * 		begin backtrack level
288          * 		mark m
289          * 		rewind m
290          * 		end backtrack level, success
291          * 		exit decision
292          * 		...
293          * 		exit rule
294          */
BeginBacktrack(int level)295         public override void BeginBacktrack(int level) {
296             if (dump)
297                 Console.WriteLine("enter backtrack " + level);
298             backtrackDepth++;
299             DecisionEvent e = CurrentDecision();
300             if (e.decision.couldBacktrack) {
301                 stats.numBacktrackOccurrences++;
302                 e.decision.numBacktrackOccurrences++;
303                 e.backtracks = true;
304             }
305         }
306 
307         /** Successful or not, track how much lookahead synpreds use */
EndBacktrack(int level, bool successful)308         public override void EndBacktrack(int level, bool successful) {
309             if (dump)
310                 Console.WriteLine("exit backtrack " + level + ": " + successful);
311             backtrackDepth--;
312         }
313 
Mark(int i)314         public override void Mark(int i) {
315             if (dump)
316                 Console.WriteLine("mark " + i);
317         }
318 
Rewind(int i)319         public override void Rewind(int i) {
320             if (dump)
321                 Console.WriteLine("rewind " + i);
322         }
323 
Rewind()324         public override void Rewind() {
325             if (dump)
326                 Console.WriteLine("rewind");
327         }
328 
CurrentDecision()329         protected virtual DecisionEvent CurrentDecision() {
330             return decisionStack.Peek();
331         }
332 
RecognitionException(RecognitionException e)333         public override void RecognitionException(RecognitionException e) {
334             stats.numReportedErrors++;
335         }
336 
SemanticPredicate(bool result, string predicate)337         public override void SemanticPredicate(bool result, string predicate) {
338             stats.numSemanticPredicates++;
339             if (InDecision) {
340                 DecisionEvent d = CurrentDecision();
341                 d.evalSemPred = true;
342                 d.decision.numSemPredEvals++;
343                 if (dump) {
344                     Console.WriteLine("eval " + predicate + " in " + d.decision.ruleName + "-" +
345                                        d.decision.decision);
346                 }
347             }
348         }
349 
Terminate()350         public override void Terminate() {
351             foreach (DecisionEvent e in decisionEvents) {
352                 //System.out.println("decision "+e.decision.decision+": k="+e.k);
353                 e.decision.avgk += e.k;
354                 stats.avgkPerDecisionEvent += e.k;
355                 if (e.backtracks) { // doesn't count gated syn preds on DFA edges
356                     stats.avgkPerBacktrackingDecisionEvent += e.k;
357                 }
358             }
359             stats.averageDecisionPercentBacktracks = 0.0f;
360             foreach (DecisionDescriptor d in decisions.Values()) {
361                 stats.numDecisionsCovered++;
362                 d.avgk /= (float)d.n;
363                 if (d.couldBacktrack) {
364                     stats.numDecisionsThatPotentiallyBacktrack++;
365                     float percentBacktracks = d.numBacktrackOccurrences / (float)d.n;
366                     //System.out.println("dec "+d.decision+" backtracks "+percentBacktracks*100+"%");
367                     stats.averageDecisionPercentBacktracks += percentBacktracks;
368                 }
369                 // ignore rules that backtrack along gated DFA edges
370                 if (d.numBacktrackOccurrences > 0) {
371                     stats.numDecisionsThatDoBacktrack++;
372                 }
373             }
374             stats.averageDecisionPercentBacktracks /= stats.numDecisionsThatPotentiallyBacktrack;
375             stats.averageDecisionPercentBacktracks *= 100; // it's a percentage
376             stats.avgkPerDecisionEvent /= stats.numDecisionEvents;
377             stats.avgkPerBacktrackingDecisionEvent /= (float)stats.numBacktrackOccurrences;
378 
379             Console.Error.WriteLine(ToString());
380             Console.Error.WriteLine(GetDecisionStatsDump());
381 
382             //		String stats = toNotifyString();
383             //		try {
384             //			Stats.writeReport(RUNTIME_STATS_FILENAME,stats);
385             //		}
386             //		catch (IOException ioe) {
387             //			System.err.println(ioe);
388             //			ioe.printStackTrace(System.err);
389             //		}
390         }
391 
SetParser(DebugParser parser)392         public virtual void SetParser(DebugParser parser) {
393             this.parser = parser;
394         }
395 
396         // R E P O R T I N G
397 
ToNotifyString()398         public virtual string ToNotifyString() {
399             StringBuilder buf = new StringBuilder();
400             buf.Append(Version);
401             buf.Append('\t');
402             buf.Append(parser.GetType().Name);
403             //		buf.Append('\t');
404             //		buf.Append(numRuleInvocations);
405             //		buf.Append('\t');
406             //		buf.Append(maxRuleInvocationDepth);
407             //		buf.Append('\t');
408             //		buf.Append(numFixedDecisions);
409             //		buf.Append('\t');
410             //		buf.Append(Stats.min(decisionMaxFixedLookaheads));
411             //		buf.Append('\t');
412             //		buf.Append(Stats.max(decisionMaxFixedLookaheads));
413             //		buf.Append('\t');
414             //		buf.Append(Stats.avg(decisionMaxFixedLookaheads));
415             //		buf.Append('\t');
416             //		buf.Append(Stats.stddev(decisionMaxFixedLookaheads));
417             //		buf.Append('\t');
418             //		buf.Append(numCyclicDecisions);
419             //		buf.Append('\t');
420             //		buf.Append(Stats.min(decisionMaxCyclicLookaheads));
421             //		buf.Append('\t');
422             //		buf.Append(Stats.max(decisionMaxCyclicLookaheads));
423             //		buf.Append('\t');
424             //		buf.Append(Stats.avg(decisionMaxCyclicLookaheads));
425             //		buf.Append('\t');
426             //		buf.Append(Stats.stddev(decisionMaxCyclicLookaheads));
427             //		buf.Append('\t');
428             //		buf.Append(numBacktrackDecisions);
429             //		buf.Append('\t');
430             //		buf.Append(Stats.min(toArray(decisionMaxSynPredLookaheads)));
431             //		buf.Append('\t');
432             //		buf.Append(Stats.max(toArray(decisionMaxSynPredLookaheads)));
433             //		buf.Append('\t');
434             //		buf.Append(Stats.avg(toArray(decisionMaxSynPredLookaheads)));
435             //		buf.Append('\t');
436             //		buf.Append(Stats.stddev(toArray(decisionMaxSynPredLookaheads)));
437             //		buf.Append('\t');
438             //		buf.Append(numSemanticPredicates);
439             //		buf.Append('\t');
440             //		buf.Append(parser.getTokenStream().size());
441             //		buf.Append('\t');
442             //		buf.Append(numHiddenTokens);
443             //		buf.Append('\t');
444             //		buf.Append(numCharsMatched);
445             //		buf.Append('\t');
446             //		buf.Append(numHiddenCharsMatched);
447             //		buf.Append('\t');
448             //		buf.Append(numberReportedErrors);
449             //		buf.Append('\t');
450             //		buf.Append(numMemoizationCacheHits);
451             //		buf.Append('\t');
452             //		buf.Append(numMemoizationCacheMisses);
453             //		buf.Append('\t');
454             //		buf.Append(numGuessingRuleInvocations);
455             //		buf.Append('\t');
456             //		buf.Append(numMemoizationCacheEntries);
457             return buf.ToString();
458         }
459 
ToString()460         public override string ToString() {
461             return ToString(GetReport());
462         }
463 
GetReport()464         public virtual ProfileStats GetReport() {
465             //ITokenStream input = parser.TokenStream;
466             //for (int i = 0; i < input.Count && lastRealTokenTouchedInDecision != null && i <= lastRealTokenTouchedInDecision.TokenIndex; i++)
467             //{
468             //    IToken t = input.Get(i);
469             //    if (t.Channel != TokenChannels.Default)
470             //    {
471             //        stats.numHiddenTokens++;
472             //        stats.numHiddenCharsMatched += t.Text.Length;
473             //    }
474             //}
475             stats.Version = Version;
476             stats.name = parser.GetType().Name;
477             stats.numUniqueRulesInvoked = uniqueRules.Count;
478             //stats.numCharsMatched = lastTokenConsumed.getStopIndex() + 1;
479             return stats;
480         }
481 
GetDecisionStats()482         public virtual DoubleKeyMap<string, int, DecisionDescriptor> GetDecisionStats() {
483             return decisions;
484         }
485 
486         public virtual ReadOnlyCollection<DecisionEvent> DecisionEvents {
487             get {
488                 return decisionEvents.AsReadOnly();
489             }
490         }
491 
ToString(ProfileStats stats)492         public static string ToString(ProfileStats stats) {
493             StringBuilder buf = new StringBuilder();
494             buf.Append("ANTLR Runtime Report; Profile Version ");
495             buf.Append(stats.Version);
496             buf.Append(NewLine);
497             buf.Append("parser name ");
498             buf.Append(stats.name);
499             buf.Append(NewLine);
500             buf.Append("Number of rule invocations ");
501             buf.Append(stats.numRuleInvocations);
502             buf.Append(NewLine);
503             buf.Append("Number of unique rules visited ");
504             buf.Append(stats.numUniqueRulesInvoked);
505             buf.Append(NewLine);
506             buf.Append("Number of decision events ");
507             buf.Append(stats.numDecisionEvents);
508             buf.Append(NewLine);
509             buf.Append("Number of rule invocations while backtracking ");
510             buf.Append(stats.numGuessingRuleInvocations);
511             buf.Append(NewLine);
512             buf.Append("max rule invocation nesting depth ");
513             buf.Append(stats.maxRuleInvocationDepth);
514             buf.Append(NewLine);
515             //		buf.Append("number of fixed lookahead decisions ");
516             //		buf.Append();
517             //		buf.Append(newline);
518             //		buf.Append("min lookahead used in a fixed lookahead decision ");
519             //		buf.Append();
520             //		buf.Append(newline);
521             //		buf.Append("max lookahead used in a fixed lookahead decision ");
522             //		buf.Append();
523             //		buf.Append(newline);
524             //		buf.Append("average lookahead depth used in fixed lookahead decisions ");
525             //		buf.Append();
526             //		buf.Append(newline);
527             //		buf.Append("standard deviation of depth used in fixed lookahead decisions ");
528             //		buf.Append();
529             //		buf.Append(newline);
530             //		buf.Append("number of arbitrary lookahead decisions ");
531             //		buf.Append();
532             //		buf.Append(newline);
533             //		buf.Append("min lookahead used in an arbitrary lookahead decision ");
534             //		buf.Append();
535             //		buf.Append(newline);
536             //		buf.Append("max lookahead used in an arbitrary lookahead decision ");
537             //		buf.Append();
538             //		buf.Append(newline);
539             //		buf.Append("average lookahead depth used in arbitrary lookahead decisions ");
540             //		buf.Append();
541             //		buf.Append(newline);
542             //		buf.Append("standard deviation of depth used in arbitrary lookahead decisions ");
543             //		buf.Append();
544             //		buf.Append(newline);
545             //		buf.Append("number of evaluated syntactic predicates ");
546             //		buf.Append();
547             //		buf.Append(newline);
548             //		buf.Append("min lookahead used in a syntactic predicate ");
549             //		buf.Append();
550             //		buf.Append(newline);
551             //		buf.Append("max lookahead used in a syntactic predicate ");
552             //		buf.Append();
553             //		buf.Append(newline);
554             //		buf.Append("average lookahead depth used in syntactic predicates ");
555             //		buf.Append();
556             //		buf.Append(newline);
557             //		buf.Append("standard deviation of depth used in syntactic predicates ");
558             //		buf.Append();
559             //		buf.Append(newline);
560             buf.Append("rule memoization cache size ");
561             buf.Append(stats.numMemoizationCacheEntries);
562             buf.Append(NewLine);
563             buf.Append("number of rule memoization cache hits ");
564             buf.Append(stats.numMemoizationCacheHits);
565             buf.Append(NewLine);
566             buf.Append("number of rule memoization cache misses ");
567             buf.Append(stats.numMemoizationCacheMisses);
568             buf.Append(NewLine);
569             //		buf.Append("number of evaluated semantic predicates ");
570             //		buf.Append();
571             //		buf.Append(newline);
572             buf.Append("number of tokens ");
573             buf.Append(stats.numTokens);
574             buf.Append(NewLine);
575             buf.Append("number of hidden tokens ");
576             buf.Append(stats.numHiddenTokens);
577             buf.Append(NewLine);
578             buf.Append("number of char ");
579             buf.Append(stats.numCharsMatched);
580             buf.Append(NewLine);
581             buf.Append("number of hidden char ");
582             buf.Append(stats.numHiddenCharsMatched);
583             buf.Append(NewLine);
584             buf.Append("number of syntax errors ");
585             buf.Append(stats.numReportedErrors);
586             buf.Append(NewLine);
587             return buf.ToString();
588         }
589 
GetDecisionStatsDump()590         public virtual string GetDecisionStatsDump() {
591             StringBuilder buf = new StringBuilder();
592             buf.Append("location");
593             buf.Append(DataSeparator);
594             buf.Append("n");
595             buf.Append(DataSeparator);
596             buf.Append("avgk");
597             buf.Append(DataSeparator);
598             buf.Append("maxk");
599             buf.Append(DataSeparator);
600             buf.Append("synpred");
601             buf.Append(DataSeparator);
602             buf.Append("sempred");
603             buf.Append(DataSeparator);
604             buf.Append("canbacktrack");
605             buf.Append("\n");
606             foreach (string fileName in decisions.KeySet()) {
607                 foreach (int d in decisions.KeySet(fileName)) {
608                     DecisionDescriptor s = decisions.Get(fileName, d);
609                     buf.Append(s.decision);
610                     buf.Append("@");
611                     buf.Append(LocationDescription(s.fileName, s.ruleName, s.line, s.pos)); // decision number
612                     buf.Append(DataSeparator);
613                     buf.Append(s.n);
614                     buf.Append(DataSeparator);
615                     buf.Append(string.Format("{0}", s.avgk));
616                     buf.Append(DataSeparator);
617                     buf.Append(s.maxk);
618                     buf.Append(DataSeparator);
619                     buf.Append(s.numBacktrackOccurrences);
620                     buf.Append(DataSeparator);
621                     buf.Append(s.numSemPredEvals);
622                     buf.Append(DataSeparator);
623                     buf.Append(s.couldBacktrack ? "1" : "0");
624                     buf.Append(NewLine);
625                 }
626             }
627             return buf.ToString();
628         }
629 
Trim(int[] X, int n)630         protected virtual int[] Trim(int[] X, int n) {
631             if (n < X.Length) {
632                 int[] trimmed = new int[n];
633                 Array.Copy(X, 0, trimmed, 0, n);
634                 X = trimmed;
635             }
636             return X;
637         }
638 
639         /** Get num hidden tokens between i..j inclusive */
GetNumberOfHiddenTokens(int i, int j)640         public virtual int GetNumberOfHiddenTokens(int i, int j) {
641             int n = 0;
642             ITokenStream input = parser.TokenStream;
643             for (int ti = i; ti < input.Count && ti <= j; ti++) {
644                 IToken t = input.Get(ti);
645                 if (t.Channel != TokenChannels.Default) {
646                     n++;
647                 }
648             }
649             return n;
650         }
651 
LocationDescription()652         protected virtual string LocationDescription() {
653             return LocationDescription(
654                 currentGrammarFileName.Peek(),
655                 currentRuleName.Peek(),
656                 currentLine.Peek(),
657                 currentPos.Peek());
658         }
659 
LocationDescription(string file, string rule, int line, int pos)660         protected virtual string LocationDescription(string file, string rule, int line, int pos) {
661             return file + ":" + line + ":" + pos + "(" + rule + ")";
662         }
663 
664         public class ProfileStats {
665             public string Version;
666             public string name;
667             public int numRuleInvocations;
668             public int numUniqueRulesInvoked;
669             public int numDecisionEvents;
670             public int numDecisionsCovered;
671             public int numDecisionsThatPotentiallyBacktrack;
672             public int numDecisionsThatDoBacktrack;
673             public int maxRuleInvocationDepth;
674             public float avgkPerDecisionEvent;
675             public float avgkPerBacktrackingDecisionEvent;
676             public float averageDecisionPercentBacktracks;
677             public int numBacktrackOccurrences; // doesn't count gated DFA edges
678 
679             public int numFixedDecisions;
680             public int minDecisionMaxFixedLookaheads;
681             public int maxDecisionMaxFixedLookaheads;
682             public int avgDecisionMaxFixedLookaheads;
683             public int stddevDecisionMaxFixedLookaheads;
684             public int numCyclicDecisions;
685             public int minDecisionMaxCyclicLookaheads;
686             public int maxDecisionMaxCyclicLookaheads;
687             public int avgDecisionMaxCyclicLookaheads;
688             public int stddevDecisionMaxCyclicLookaheads;
689             //		int Stats.min(toArray(decisionMaxSynPredLookaheads);
690             //		int Stats.max(toArray(decisionMaxSynPredLookaheads);
691             //		int Stats.avg(toArray(decisionMaxSynPredLookaheads);
692             //		int Stats.stddev(toArray(decisionMaxSynPredLookaheads);
693             public int numSemanticPredicates;
694             public int numTokens;
695             public int numHiddenTokens;
696             public int numCharsMatched;
697             public int numHiddenCharsMatched;
698             public int numReportedErrors;
699             public int numMemoizationCacheHits;
700             public int numMemoizationCacheMisses;
701             public int numGuessingRuleInvocations;
702             public int numMemoizationCacheEntries;
703         }
704 
705         public class DecisionDescriptor {
706             public int decision;
707             public string fileName;
708             public string ruleName;
709             public int line;
710             public int pos;
711             public bool couldBacktrack;
712 
713             public int n;
714             public float avgk; // avg across all decision events
715             public int maxk;
716             public int numBacktrackOccurrences;
717             public int numSemPredEvals;
718         }
719 
720         // all about a specific exec of a single decision
721         public class DecisionEvent {
722             public DecisionDescriptor decision;
723             public int startIndex;
724             public int k;
725             public bool backtracks; // doesn't count gated DFA edges
726             public bool evalSemPred;
727             public DateTime startTime;
728             public DateTime stopTime;
729             public int numMemoizationCacheHits;
730             public int numMemoizationCacheMisses;
731         }
732     }
733 }
734