1 /* 2 * [The "BSD license"] 3 * Copyright (c) 2013 Terence Parr 4 * Copyright (c) 2013 Sam Harwell 5 * Copyright (c) 2017 Egbert Voigt 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 module antlr.v4.runtime.atn.ProfilingATNSimulator; 33 34 import std.conv; 35 import std.datetime; 36 import std.algorithm; 37 import antlr.v4.runtime.atn.ATNConfigSet; 38 import antlr.v4.runtime.atn.ParserATNSimulator; 39 import antlr.v4.runtime.atn.DecisionInfo; 40 import antlr.v4.runtime.atn.ErrorInfo; 41 import antlr.v4.runtime.atn.PredicateEvalInfo; 42 import antlr.v4.runtime.atn.LookaheadEventInfo; 43 import antlr.v4.runtime.dfa.DFAState; 44 import antlr.v4.runtime.dfa.DFA; 45 import antlr.v4.runtime.Parser; 46 import antlr.v4.runtime.atn.SemanticContext; 47 import antlr.v4.runtime.TokenStream; 48 import antlr.v4.runtime.ParserRuleContext; 49 50 // Class ProfilingATNSimulator 51 /** 52 * TODO add class description 53 */ 54 class ProfilingATNSimulator : ParserATNSimulator 55 { 56 57 protected DecisionInfo[] decisions; 58 59 protected int currentDecision; 60 61 protected int numDecisions; 62 63 protected int _sllStopIndex; 64 65 protected int _llStopIndex; 66 67 protected DFAState currentState; 68 69 /** 70 * we can determine whether or not a decision / input pair is context-sensitive. 71 * If LL gives a different result than SLL's predicted alternative, we have a 72 * context sensitivity for sure. The converse is not necessarily true, however. 73 * It's possible that after conflict resolution chooses minimum alternatives, 74 * SLL could get the same answer as LL. Regardless of whether or not the result indicates 75 * an ambiguity, it is not treated as a context sensitivity because LL prediction 76 * was not required in order to produce a correct prediction for this decision and input sequence. 77 * It may in fact still be a context sensitivity but we don't know by looking at the 78 * minimum alternatives for the current input. 79 */ 80 public int conflictingAltResolvedBySLL; 81 82 public this(Parser parser) 83 { 84 super(parser, 85 parser.getInterpreter().atn, 86 parser.getInterpreter().decisionToDFA, 87 parser.getInterpreter().sharedContextCache); 88 numDecisions = to!int(atn.decisionToState.length); 89 decisions = new DecisionInfo[numDecisions]; 90 for (int i=0; i<numDecisions; i++) { 91 decisions[i] = new DecisionInfo(i); 92 } 93 } 94 95 /** 96 * @uml 97 * @override 98 */ 99 public override int adaptivePredict(TokenStream input, int decision, ParserRuleContext outerContext) 100 { 101 try { 102 this._sllStopIndex = -1; 103 this._llStopIndex = -1; 104 this.currentDecision = decision; 105 auto start = MonoTime.currTime; // expensive but useful info 106 int alt = super.adaptivePredict(input, decision, outerContext); 107 auto stop = MonoTime.currTime; 108 decisions[decision].timeInPrediction += ticksToNSecs(stop.ticks - start.ticks); 109 decisions[decision].invocations++; 110 111 int SLL_k = _sllStopIndex - _startIndex + 1; 112 decisions[decision].SLL_TotalLook += SLL_k; 113 decisions[decision].SLL_MinLook = decisions[decision].SLL_MinLook==0 ? SLL_k : min(decisions[decision].SLL_MinLook, SLL_k); 114 if ( SLL_k > decisions[decision].SLL_MaxLook ) { 115 decisions[decision].SLL_MaxLook = SLL_k; 116 decisions[decision].SLL_MaxLookEvent = 117 new LookaheadEventInfo(decision, null, alt, input, _startIndex, _sllStopIndex, false); 118 } 119 120 if (_llStopIndex >= 0) { 121 int LL_k = _llStopIndex - _startIndex + 1; 122 decisions[decision].LL_TotalLook += LL_k; 123 decisions[decision].LL_MinLook = decisions[decision].LL_MinLook==0 ? LL_k : min(decisions[decision].LL_MinLook, LL_k); 124 if ( LL_k > decisions[decision].LL_MaxLook ) { 125 decisions[decision].LL_MaxLook = LL_k; 126 decisions[decision].LL_MaxLookEvent = 127 new LookaheadEventInfo(decision, null, alt, input, _startIndex, _llStopIndex, true); 128 } 129 } 130 131 return alt; 132 } 133 finally { 134 this.currentDecision = -1; 135 } 136 137 } 138 139 /** 140 * @uml 141 * @override 142 */ 143 public override DFAState getExistingTargetState(DFAState previousD, int t) 144 { 145 // this method is called after each time the input position advances 146 // during SLL prediction 147 _sllStopIndex = _input.index(); 148 149 DFAState existingTargetState = super.getExistingTargetState(previousD, t); 150 if (existingTargetState !is null) { 151 decisions[currentDecision].SLL_DFATransitions++; // count only if we transition over a DFA state 152 if ( existingTargetState==ERROR ) { 153 decisions[currentDecision].errors 154 ~= new ErrorInfo(currentDecision, previousD.configs, _input, _startIndex, _sllStopIndex, false); 155 } 156 } 157 158 currentState = existingTargetState; 159 return existingTargetState; 160 161 } 162 163 /** 164 * @uml 165 * @override 166 */ 167 protected override DFAState computeTargetState(DFA dfa, DFAState previousD, int t) 168 { 169 DFAState state = super.computeTargetState(dfa, previousD, t); 170 currentState = state; 171 return state; 172 } 173 174 /** 175 * @uml 176 * @override 177 */ 178 protected override ATNConfigSet computeReachSet(ATNConfigSet closure, int t, bool fullCtx) 179 { 180 if (fullCtx) { 181 // this method is called after each time the input position advances 182 // during full context prediction 183 _llStopIndex = _input.index(); 184 } 185 186 ATNConfigSet reachConfigs = super.computeReachSet(closure, t, fullCtx); 187 if (fullCtx) { 188 decisions[currentDecision].LL_ATNTransitions++; // count computation even if error 189 if (reachConfigs !is null) { 190 } 191 else { // no reach on current lookahead symbol. ERROR. 192 // TODO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule() 193 decisions[currentDecision].errors 194 ~= new ErrorInfo(currentDecision, closure, _input, _startIndex, _llStopIndex, true); 195 } 196 } 197 else { 198 decisions[currentDecision].SLL_ATNTransitions++; 199 if (reachConfigs !is null) { 200 } 201 else { // no reach on current lookahead symbol. ERROR. 202 decisions[currentDecision].errors 203 ~= new ErrorInfo(currentDecision, closure, _input, _startIndex, _sllStopIndex, false); 204 } 205 } 206 return reachConfigs; 207 208 } 209 210 /** 211 * @uml 212 * @override 213 */ 214 protected override bool evalSemanticContext(SemanticContext pred, ParserRuleContext parserCallStack, 215 int alt, bool fullCtx) 216 { 217 bool result = super.evalSemanticContext(pred, parserCallStack, alt, fullCtx); 218 if (pred.classinfo != SemanticContext.PrecedencePredicate.classinfo) { 219 bool fullContext = _llStopIndex >= 0; 220 int stopIndex = fullContext ? _llStopIndex : _sllStopIndex; 221 decisions[currentDecision].predicateEvals 222 ~= new PredicateEvalInfo(currentDecision, _input, _startIndex, stopIndex, pred, result, alt, fullCtx); 223 } 224 return result; 225 } 226 227 public DecisionInfo[] getDecisionInfo() 228 { 229 return decisions; 230 } 231 232 }