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 /** 51 * TODO add class description 52 */ 53 class ProfilingATNSimulator : ParserATNSimulator 54 { 55 56 protected DecisionInfo[] decisions; 57 58 protected int currentDecision; 59 60 protected int numDecisions; 61 62 protected int _sllStopIndex; 63 64 protected int _llStopIndex; 65 66 protected DFAState currentState; 67 68 /** 69 * we can determine whether or not a decision / input pair is context-sensitive. 70 * If LL gives a different result than SLL's predicted alternative, we have a 71 * context sensitivity for sure. The converse is not necessarily true, however. 72 * It's possible that after conflict resolution chooses minimum alternatives, 73 * SLL could get the same answer as LL. Regardless of whether or not the result indicates 74 * an ambiguity, it is not treated as a context sensitivity because LL prediction 75 * was not required in order to produce a correct prediction for this decision and input sequence. 76 * It may in fact still be a context sensitivity but we don't know by looking at the 77 * minimum alternatives for the current input. 78 */ 79 public int conflictingAltResolvedBySLL; 80 81 public this(Parser parser) 82 { 83 super(parser, 84 parser.getInterpreter().atn, 85 parser.getInterpreter().decisionToDFA, 86 parser.getInterpreter().sharedContextCache); 87 numDecisions = to!int(atn.decisionToState.length); 88 decisions = new DecisionInfo[numDecisions]; 89 for (int i=0; i<numDecisions; i++) { 90 decisions[i] = new DecisionInfo(i); 91 } 92 } 93 94 /** 95 * @uml 96 * @override 97 */ 98 public override int adaptivePredict(TokenStream input, int decision, ParserRuleContext outerContext) 99 { 100 try { 101 this._sllStopIndex = -1; 102 this._llStopIndex = -1; 103 this.currentDecision = decision; 104 auto start = MonoTime.currTime; // expensive but useful info 105 int alt = super.adaptivePredict(input, decision, outerContext); 106 auto stop = MonoTime.currTime; 107 decisions[decision].timeInPrediction += ticksToNSecs(stop.ticks - start.ticks); 108 decisions[decision].invocations++; 109 110 int SLL_k = _sllStopIndex - _startIndex + 1; 111 decisions[decision].SLL_TotalLook += SLL_k; 112 decisions[decision].SLL_MinLook = decisions[decision].SLL_MinLook==0 ? SLL_k : min(decisions[decision].SLL_MinLook, SLL_k); 113 if ( SLL_k > decisions[decision].SLL_MaxLook ) { 114 decisions[decision].SLL_MaxLook = SLL_k; 115 decisions[decision].SLL_MaxLookEvent = 116 new LookaheadEventInfo(decision, null, alt, input, _startIndex, _sllStopIndex, false); 117 } 118 119 if (_llStopIndex >= 0) { 120 int LL_k = _llStopIndex - _startIndex + 1; 121 decisions[decision].LL_TotalLook += LL_k; 122 decisions[decision].LL_MinLook = decisions[decision].LL_MinLook==0 ? LL_k : min(decisions[decision].LL_MinLook, LL_k); 123 if ( LL_k > decisions[decision].LL_MaxLook ) { 124 decisions[decision].LL_MaxLook = LL_k; 125 decisions[decision].LL_MaxLookEvent = 126 new LookaheadEventInfo(decision, null, alt, input, _startIndex, _llStopIndex, true); 127 } 128 } 129 130 return alt; 131 } 132 finally { 133 this.currentDecision = -1; 134 } 135 136 } 137 138 /** 139 * @uml 140 * @override 141 */ 142 public override DFAState getExistingTargetState(DFAState previousD, int t) 143 { 144 // this method is called after each time the input position advances 145 // during SLL prediction 146 _sllStopIndex = _input.index(); 147 148 DFAState existingTargetState = super.getExistingTargetState(previousD, t); 149 if (existingTargetState !is null) { 150 decisions[currentDecision].SLL_DFATransitions++; // count only if we transition over a DFA state 151 if ( existingTargetState==ERROR ) { 152 decisions[currentDecision].errors 153 ~= new ErrorInfo(currentDecision, previousD.configs, _input, _startIndex, _sllStopIndex, false); 154 } 155 } 156 157 currentState = existingTargetState; 158 return existingTargetState; 159 160 } 161 162 /** 163 * @uml 164 * @override 165 */ 166 protected override DFAState computeTargetState(DFA dfa, DFAState previousD, int t) 167 { 168 DFAState state = super.computeTargetState(dfa, previousD, t); 169 currentState = state; 170 return state; 171 } 172 173 /** 174 * @uml 175 * @override 176 */ 177 protected override ATNConfigSet computeReachSet(ATNConfigSet closure, int t, bool fullCtx) 178 { 179 if (fullCtx) { 180 // this method is called after each time the input position advances 181 // during full context prediction 182 _llStopIndex = _input.index(); 183 } 184 185 ATNConfigSet reachConfigs = super.computeReachSet(closure, t, fullCtx); 186 if (fullCtx) { 187 decisions[currentDecision].LL_ATNTransitions++; // count computation even if error 188 if (reachConfigs !is null) { 189 } 190 else { // no reach on current lookahead symbol. ERROR. 191 // TODO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule() 192 decisions[currentDecision].errors 193 ~= new ErrorInfo(currentDecision, closure, _input, _startIndex, _llStopIndex, true); 194 } 195 } 196 else { 197 decisions[currentDecision].SLL_ATNTransitions++; 198 if (reachConfigs !is null) { 199 } 200 else { // no reach on current lookahead symbol. ERROR. 201 decisions[currentDecision].errors 202 ~= new ErrorInfo(currentDecision, closure, _input, _startIndex, _sllStopIndex, false); 203 } 204 } 205 return reachConfigs; 206 207 } 208 209 /** 210 * @uml 211 * @override 212 */ 213 protected override bool evalSemanticContext(SemanticContext pred, ParserRuleContext parserCallStack, 214 int alt, bool fullCtx) 215 { 216 bool result = super.evalSemanticContext(pred, parserCallStack, alt, fullCtx); 217 if (pred.classinfo != SemanticContext.PrecedencePredicate.classinfo) { 218 bool fullContext = _llStopIndex >= 0; 219 int stopIndex = fullContext ? _llStopIndex : _sllStopIndex; 220 decisions[currentDecision].predicateEvals 221 ~= new PredicateEvalInfo(currentDecision, _input, _startIndex, stopIndex, pred, result, alt, fullCtx); 222 } 223 return result; 224 } 225 226 public DecisionInfo[] getDecisionInfo() 227 { 228 return decisions; 229 } 230 231 }