1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2 * Use of this file is governed by the BSD 3-clause license that
3 * can be found in the LICENSE.txt file in the project root.
6 #include "atn/PredicateEvalInfo.h"
7 #include "atn/LookaheadEventInfo.h"
9 #include "atn/ATNConfigSet.h"
10 #include "support/CPPUtils.h"
12 #include "atn/ProfilingATNSimulator.h"
14 using namespace antlr4;
15 using namespace antlr4::atn;
16 using namespace antlr4::dfa;
17 using namespace antlrcpp;
19 using namespace std::chrono;
21 ProfilingATNSimulator::ProfilingATNSimulator(Parser *parser)
22 : ParserATNSimulator(parser, parser->getInterpreter<ParserATNSimulator>()->atn,
23 parser->getInterpreter<ParserATNSimulator>()->decisionToDFA,
24 parser->getInterpreter<ParserATNSimulator>()->getSharedContextCache()) {
25 for (size_t i = 0; i < atn.decisionToState.size(); i++) {
26 _decisions.push_back(DecisionInfo(i));
30 size_t ProfilingATNSimulator::adaptivePredict(TokenStream *input, size_t decision, ParserRuleContext *outerContext) {
31 auto onExit = finally([this](){
32 _currentDecision = 0; // Originally -1, but that makes no sense (index into a vector and init value is also 0).
37 _currentDecision = decision;
38 high_resolution_clock::time_point start = high_resolution_clock::now();
39 size_t alt = ParserATNSimulator::adaptivePredict(input, decision, outerContext);
40 high_resolution_clock::time_point stop = high_resolution_clock::now();
41 _decisions[decision].timeInPrediction += duration_cast<nanoseconds>(stop - start).count();
42 _decisions[decision].invocations++;
44 long long SLL_k = _sllStopIndex - _startIndex + 1;
45 _decisions[decision].SLL_TotalLook += SLL_k;
46 _decisions[decision].SLL_MinLook = _decisions[decision].SLL_MinLook == 0 ? SLL_k : std::min(_decisions[decision].SLL_MinLook, SLL_k);
47 if (SLL_k > _decisions[decision].SLL_MaxLook) {
48 _decisions[decision].SLL_MaxLook = SLL_k;
49 _decisions[decision].SLL_MaxLookEvent = std::make_shared<LookaheadEventInfo>(decision, nullptr, alt, input, _startIndex, _sllStopIndex, false);
52 if (_llStopIndex >= 0) {
53 long long LL_k = _llStopIndex - _startIndex + 1;
54 _decisions[decision].LL_TotalLook += LL_k;
55 _decisions[decision].LL_MinLook = _decisions[decision].LL_MinLook == 0 ? LL_k : std::min(_decisions[decision].LL_MinLook, LL_k);
56 if (LL_k > _decisions[decision].LL_MaxLook) {
57 _decisions[decision].LL_MaxLook = LL_k;
58 _decisions[decision].LL_MaxLookEvent = std::make_shared<LookaheadEventInfo>(decision, nullptr, alt, input, _startIndex, _llStopIndex, true);
65 DFAState* ProfilingATNSimulator::getExistingTargetState(DFAState *previousD, size_t t) {
66 // this method is called after each time the input position advances
67 // during SLL prediction
68 _sllStopIndex = (int)_input->index();
70 DFAState *existingTargetState = ParserATNSimulator::getExistingTargetState(previousD, t);
71 if (existingTargetState != nullptr) {
72 _decisions[_currentDecision].SLL_DFATransitions++; // count only if we transition over a DFA state
73 if (existingTargetState == ERROR.get()) {
74 _decisions[_currentDecision].errors.push_back(
75 ErrorInfo(_currentDecision, previousD->configs.get(), _input, _startIndex, _sllStopIndex, false)
80 _currentState = existingTargetState;
81 return existingTargetState;
84 DFAState* ProfilingATNSimulator::computeTargetState(DFA &dfa, DFAState *previousD, size_t t) {
85 DFAState *state = ParserATNSimulator::computeTargetState(dfa, previousD, t);
86 _currentState = state;
90 std::unique_ptr<ATNConfigSet> ProfilingATNSimulator::computeReachSet(ATNConfigSet *closure, size_t t, bool fullCtx) {
92 // this method is called after each time the input position advances
93 // during full context prediction
94 _llStopIndex = (int)_input->index();
97 std::unique_ptr<ATNConfigSet> reachConfigs = ParserATNSimulator::computeReachSet(closure, t, fullCtx);
99 _decisions[_currentDecision].LL_ATNTransitions++; // count computation even if error
100 if (reachConfigs != nullptr) {
101 } else { // no reach on current lookahead symbol. ERROR.
102 // TODO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule()
103 _decisions[_currentDecision].errors.push_back(ErrorInfo(_currentDecision, closure, _input, _startIndex, _llStopIndex, true));
106 ++_decisions[_currentDecision].SLL_ATNTransitions;
107 if (reachConfigs != nullptr) {
108 } else { // no reach on current lookahead symbol. ERROR.
109 _decisions[_currentDecision].errors.push_back(ErrorInfo(_currentDecision, closure, _input, _startIndex, _sllStopIndex, false));
115 bool ProfilingATNSimulator::evalSemanticContext(Ref<SemanticContext> const& pred, ParserRuleContext *parserCallStack,
116 size_t alt, bool fullCtx) {
117 bool result = ParserATNSimulator::evalSemanticContext(pred, parserCallStack, alt, fullCtx);
118 if (!(std::dynamic_pointer_cast<SemanticContext::PrecedencePredicate>(pred) != nullptr)) {
119 bool fullContext = _llStopIndex >= 0;
120 int stopIndex = fullContext ? _llStopIndex : _sllStopIndex;
121 _decisions[_currentDecision].predicateEvals.push_back(
122 PredicateEvalInfo(_currentDecision, _input, _startIndex, stopIndex, pred, result, alt, fullCtx));
128 void ProfilingATNSimulator::reportAttemptingFullContext(DFA &dfa, const BitSet &conflictingAlts, ATNConfigSet *configs,
129 size_t startIndex, size_t stopIndex) {
130 if (conflictingAlts.count() > 0) {
131 conflictingAltResolvedBySLL = conflictingAlts.nextSetBit(0);
133 conflictingAltResolvedBySLL = configs->getAlts().nextSetBit(0);
135 _decisions[_currentDecision].LL_Fallback++;
136 ParserATNSimulator::reportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex);
139 void ProfilingATNSimulator::reportContextSensitivity(DFA &dfa, size_t prediction, ATNConfigSet *configs,
140 size_t startIndex, size_t stopIndex) {
141 if (prediction != conflictingAltResolvedBySLL) {
142 _decisions[_currentDecision].contextSensitivities.push_back(
143 ContextSensitivityInfo(_currentDecision, configs, _input, startIndex, stopIndex)
146 ParserATNSimulator::reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);
149 void ProfilingATNSimulator::reportAmbiguity(DFA &dfa, DFAState *D, size_t startIndex, size_t stopIndex, bool exact,
150 const BitSet &ambigAlts, ATNConfigSet *configs) {
152 if (ambigAlts.count() > 0) {
153 prediction = ambigAlts.nextSetBit(0);
155 prediction = configs->getAlts().nextSetBit(0);
157 if (configs->fullCtx && prediction != conflictingAltResolvedBySLL) {
158 // Even though this is an ambiguity we are reporting, we can
159 // still detect some context sensitivities. Both SLL and LL
160 // are showing a conflict, hence an ambiguity, but if they resolve
161 // to different minimum alternatives we have also identified a
162 // context sensitivity.
163 _decisions[_currentDecision].contextSensitivities.push_back(
164 ContextSensitivityInfo(_currentDecision, configs, _input, startIndex, stopIndex)
167 _decisions[_currentDecision].ambiguities.push_back(
168 AmbiguityInfo(_currentDecision, configs, ambigAlts, _input, startIndex, stopIndex, configs->fullCtx)
170 ParserATNSimulator::reportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configs);
173 std::vector<DecisionInfo> ProfilingATNSimulator::getDecisionInfo() const {
177 DFAState* ProfilingATNSimulator::getCurrentState() const {
178 return _currentState;