]> gitweb.ps.run Git - toc/blob - antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/ProfilingATNSimulator.cpp
add antlr source code and ReadMe
[toc] / antlr4-cpp-runtime-4.9.2-source / runtime / src / atn / ProfilingATNSimulator.cpp
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.
4  */
5
6 #include "atn/PredicateEvalInfo.h"
7 #include "atn/LookaheadEventInfo.h"
8 #include "Parser.h"
9 #include "atn/ATNConfigSet.h"
10 #include "support/CPPUtils.h"
11
12 #include "atn/ProfilingATNSimulator.h"
13
14 using namespace antlr4;
15 using namespace antlr4::atn;
16 using namespace antlr4::dfa;
17 using namespace antlrcpp;
18
19 using namespace std::chrono;
20
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));
27   }
28 }
29
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).
33   });
34
35   _sllStopIndex = -1;
36   _llStopIndex = -1;
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++;
43
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);
50   }
51
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);
59     }
60   }
61
62   return alt;
63 }
64
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();
69
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)
76       );
77     }
78   }
79
80   _currentState = existingTargetState;
81   return existingTargetState;
82 }
83
84 DFAState* ProfilingATNSimulator::computeTargetState(DFA &dfa, DFAState *previousD, size_t t) {
85   DFAState *state = ParserATNSimulator::computeTargetState(dfa, previousD, t);
86   _currentState = state;
87   return state;
88 }
89
90 std::unique_ptr<ATNConfigSet> ProfilingATNSimulator::computeReachSet(ATNConfigSet *closure, size_t t, bool fullCtx) {
91   if (fullCtx) {
92     // this method is called after each time the input position advances
93     // during full context prediction
94     _llStopIndex = (int)_input->index();
95   }
96
97   std::unique_ptr<ATNConfigSet> reachConfigs = ParserATNSimulator::computeReachSet(closure, t, fullCtx);
98   if (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));
104     }
105   } else {
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));
110     }
111   }
112   return reachConfigs;
113 }
114
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));
123   }
124
125   return result;
126 }
127
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);
132   } else {
133     conflictingAltResolvedBySLL = configs->getAlts().nextSetBit(0);
134   }
135   _decisions[_currentDecision].LL_Fallback++;
136   ParserATNSimulator::reportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex);
137 }
138
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)
144     );
145   }
146   ParserATNSimulator::reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);
147 }
148
149 void ProfilingATNSimulator::reportAmbiguity(DFA &dfa, DFAState *D, size_t startIndex, size_t stopIndex, bool exact,
150                                             const BitSet &ambigAlts, ATNConfigSet *configs) {
151   size_t prediction;
152   if (ambigAlts.count() > 0) {
153     prediction = ambigAlts.nextSetBit(0);
154   } else {
155     prediction = configs->getAlts().nextSetBit(0);
156   }
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)
165     );
166   }
167   _decisions[_currentDecision].ambiguities.push_back(
168     AmbiguityInfo(_currentDecision, configs, ambigAlts, _input, startIndex, stopIndex, configs->fullCtx)
169   );
170   ParserATNSimulator::reportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configs);
171 }
172
173 std::vector<DecisionInfo> ProfilingATNSimulator::getDecisionInfo() const {
174   return _decisions;
175 }
176
177 DFAState* ProfilingATNSimulator::getCurrentState() const {
178   return _currentState;
179 }