-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
I've been looking at the three Java grammars, and tested each of them on 40k+ Java files (it took weeks to run). In order to figure out where some of the performance problems are, I decided to turn on the Parser.Profile option to get some diagnostics. Unfortunately, the parse crashed on a null ptr deref. I traced it down to a version skew between the Java runtime and the C# runtime. It looks like the last time the C# code was generated from the Java code by Sharpen was prior to 2014, and it seemed to have included this problem. I updated the C# runtime to correspond to what the Java runtime code is currently, and Profile=true works great now.
Here are the diffs. The file ProfilingATNSimulator.cs had evil tabs in it, so I converted them to spaces, which git diff doesn't diff very well. I'm going to make a pull request for this change.
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/AmbiguityInfo.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/AmbiguityInfo.cs
index fbe0bd7e8..7433c6d52 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/AmbiguityInfo.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/AmbiguityInfo.cs
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+/* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
@@ -41,6 +41,9 @@ namespace Antlr4.Runtime.Atn
/// <since>4.3</since>
public class AmbiguityInfo : DecisionEventInfo
{
+ /** The set of alternative numbers for this decision event that lead to a valid parse. */
+ public BitSet ambigAlts;
+
/// <summary>
/// Constructs a new instance of the
/// <see cref="AmbiguityInfo"/>
@@ -48,19 +51,31 @@ namespace Antlr4.Runtime.Atn
/// specified detailed ambiguity information.
/// </summary>
/// <param name="decision">The decision number</param>
- /// <param name="state">
- /// The final simulator state identifying the ambiguous
+ /// <param name="configs">The final configuration set identifying the ambiguous
/// alternatives for the current input
/// </param>
+ /// <param name="ambigAlts">The set of alternatives in the decision that lead to a valid parse.
+ /// </param>
+ /// The predicted alt is the min(ambigAlts)
+ /// </param>
/// <param name="input">The input token stream</param>
/// <param name="startIndex">The start index for the current prediction</param>
/// <param name="stopIndex">
/// The index at which the ambiguity was identified during
/// prediction
/// </param>
- public AmbiguityInfo(int decision, SimulatorState state, ITokenStream input, int startIndex, int stopIndex)
- : base(decision, state, input, startIndex, stopIndex, state.useContext)
+ /// <param name="fullCtx">@code true} if the ambiguity was identified during LL
+ /// prediction; otherwise, {@code false} if the ambiguity was identified
+ /// during SLL prediction
+ /// </param>
+ public AmbiguityInfo(int decision,
+ ATNConfigSet configs,
+ BitSet ambigAlts,
+ ITokenStream input, int startIndex, int stopIndex,
+ bool fullCtx)
+ : base(decision, configs, input, startIndex, stopIndex, fullCtx)
{
+ this.ambigAlts = ambigAlts;
}
}
}
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ContextSensitivityInfo.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ContextSensitivityInfo.cs
index b978c6786..454a72ef5 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ContextSensitivityInfo.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ContextSensitivityInfo.cs
@@ -35,9 +35,8 @@ namespace Antlr4.Runtime.Atn
/// with the specified detailed context sensitivity information.
/// </summary>
/// <param name="decision">The decision number</param>
- /// <param name="state">
- /// The final simulator state containing the unique
- /// alternative identified by full-context prediction
+ /// <param name="configs">The final configuration set identifying the ambiguous
+ /// alternatives for the current input
/// </param>
/// <param name="input">The input token stream</param>
/// <param name="startIndex">The start index for the current prediction</param>
@@ -45,8 +44,8 @@ namespace Antlr4.Runtime.Atn
/// The index at which the context sensitivity was
/// identified during full-context prediction
/// </param>
- public ContextSensitivityInfo(int decision, SimulatorState state, ITokenStream input, int startIndex, int stopIndex)
- : base(decision, state, input, startIndex, stopIndex, true)
+ public ContextSensitivityInfo(int decision, ATNConfigSet configs, ITokenStream input, int startIndex, int stopIndex)
+ : base(decision, configs, input, startIndex, stopIndex, true)
{
}
}
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/DecisionEventInfo.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/DecisionEventInfo.cs
index ee2098cb7..c77629dd1 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/DecisionEventInfo.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/DecisionEventInfo.cs
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+/* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
@@ -25,15 +25,13 @@ namespace Antlr4.Runtime.Atn
/// <seealso cref="ATN.decisionToState"/>
public readonly int decision;
- /// <summary>
- /// The simulator state containing additional information relevant to the
- /// prediction state when the current event occurred, or
- /// <see langword="null"/>
- /// if no
- /// additional information is relevant or available.
- /// </summary>
- [Nullable]
- public readonly SimulatorState state;
+ /// <summary>The configuration set containing additional information relevant to the
+ /// prediction state when the current event occurred, or {@code null} if no
+ /// additional information is relevant or available.</summary>
+ /// <remarks>The configuration set containing additional information relevant to the
+ /// prediction state when the current event occurred, or {@code null} if no
+ /// additional information is relevant or available.</remarks>
+ public readonly ATNConfigSet configs;
/// <summary>The input token stream which is being parsed.</summary>
/// <remarks>The input token stream which is being parsed.</remarks>
@@ -63,14 +61,17 @@ namespace Antlr4.Runtime.Atn
/// </summary>
public readonly bool fullCtx;
- public DecisionEventInfo(int decision, SimulatorState state, ITokenStream input, int startIndex, int stopIndex, bool fullCtx)
+ public DecisionEventInfo(int decision,
+ ATNConfigSet configs,
+ ITokenStream input, int startIndex, int stopIndex,
+ bool fullCtx)
{
this.decision = decision;
this.fullCtx = fullCtx;
this.stopIndex = stopIndex;
this.input = input;
this.startIndex = startIndex;
- this.state = state;
+ this.configs = configs;
}
}
}
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ErrorInfo.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ErrorInfo.cs
index 91466fa55..ce8bdfcd3 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ErrorInfo.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ErrorInfo.cs
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+/* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
@@ -30,17 +30,18 @@ namespace Antlr4.Runtime.Atn
/// specified detailed syntax error information.
/// </summary>
/// <param name="decision">The decision number</param>
- /// <param name="state">
- /// The final simulator state reached during prediction
- /// prior to reaching the
- /// <see cref="ATNSimulator.ERROR"/>
- /// state
+ /// <param name="configs">The final configuration set reached during prediction
+ /// prior to reaching the {@link ATNSimulator#ERROR} state
/// </param>
/// <param name="input">The input token stream</param>
/// <param name="startIndex">The start index for the current prediction</param>
/// <param name="stopIndex">The index at which the syntax error was identified</param>
- public ErrorInfo(int decision, SimulatorState state, ITokenStream input, int startIndex, int stopIndex)
- : base(decision, state, input, startIndex, stopIndex, state.useContext)
+ /// <param name="fullCtx">{@code true} if the syntax error was identified during LL
+ /// prediction; otherwise, {@code false} if the syntax error was identified
+ /// during SLL prediction
+ /// </param>
+ public ErrorInfo(int decision, ATNConfigSet configs, ITokenStream input, int startIndex, int stopIndex, bool fullCtx)
+ : base(decision, configs, input, startIndex, stopIndex, fullCtx)
{
}
}
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/LookaheadEventInfo.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/LookaheadEventInfo.cs
index 2b5e3f30a..a77b017aa 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/LookaheadEventInfo.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/LookaheadEventInfo.cs
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+/* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
@@ -19,6 +19,13 @@ namespace Antlr4.Runtime.Atn
/// <since>4.3</since>
public class LookaheadEventInfo : DecisionEventInfo
{
+ /// <summary>The alternative chosen by adaptivePredict(), not necessarily
+ /// the outermost alt shown for a rule; left-recursive rules have
+ /// user-level alts that differ from the rewritten rule with a (...) block
+ /// and a (..)* loop.
+ /// </summary>
+ public int predictedAlt;
+
/// <summary>
/// Constructs a new instance of the
/// <see cref="LookaheadEventInfo"/>
@@ -26,18 +33,14 @@ namespace Antlr4.Runtime.Atn
/// the specified detailed lookahead information.
/// </summary>
/// <param name="decision">The decision number</param>
- /// <param name="state">
- /// The final simulator state containing the necessary
- /// information to determine the result of a prediction, or
- /// <see langword="null"/>
- /// if
- /// the final state is not available
+ /// <param name="configs">The final configuration set containing the necessary
+ /// information to determine the result of a prediction, or {@code null} if
+ /// the final configuration set is not available
/// </param>
/// <param name="input">The input token stream</param>
/// <param name="startIndex">The start index for the current prediction</param>
/// <param name="stopIndex">The index at which the prediction was finally made</param>
/// <param name="fullCtx">
- ///
/// <see langword="true"/>
/// if the current lookahead is part of an LL
/// prediction; otherwise,
@@ -45,9 +48,10 @@ namespace Antlr4.Runtime.Atn
/// if the current lookahead is part of
/// an SLL prediction
/// </param>
- public LookaheadEventInfo(int decision, SimulatorState state, ITokenStream input, int startIndex, int stopIndex, bool fullCtx)
- : base(decision, state, input, startIndex, stopIndex, fullCtx)
+ public LookaheadEventInfo(int decision, ATNConfigSet configs, int predictedAlt, ITokenStream input, int startIndex, int stopIndex, bool fullCtx)
+ : base(decision, configs, input, startIndex, stopIndex, fullCtx)
{
+ this.predictedAlt = predictedAlt;
}
}
}
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/PredicateEvalInfo.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/PredicateEvalInfo.cs
index 467ac40f2..52889f30c 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/PredicateEvalInfo.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/PredicateEvalInfo.cs
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+/* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
@@ -49,7 +49,6 @@ namespace Antlr4.Runtime.Atn
/// class with the
/// specified detailed predicate evaluation information.
/// </summary>
- /// <param name="state">The simulator state</param>
/// <param name="decision">The decision number</param>
/// <param name="input">The input token stream</param>
/// <param name="startIndex">The start index for the current prediction</param>
@@ -68,10 +67,15 @@ namespace Antlr4.Runtime.Atn
/// <see cref="predictedAlt"/>
/// for more information.
/// </param>
+ /// <param name="fullCtx">{@code true} if the semantic context was
+ /// evaluated during LL prediction; otherwise, {@code false} if the semantic
+ /// context was evaluated during SLL prediction
+ /// </param>
+ ///
/// <seealso cref="ParserATNSimulator.EvalSemanticContext(SemanticContext, ParserRuleContext, int, bool)"/>
/// <seealso cref="SemanticContext.Eval"/>
- public PredicateEvalInfo(SimulatorState state, int decision, ITokenStream input, int startIndex, int stopIndex, SemanticContext semctx, bool evalResult, int predictedAlt)
- : base(decision, state, input, startIndex, stopIndex, state.useContext)
+ public PredicateEvalInfo(int decision, ITokenStream input, int startIndex, int stopIndex, SemanticContext semctx, bool evalResult, int predictedAlt, bool fullCtx)
+ : base(decision, new ATNConfigSet(), input, startIndex, stopIndex, fullCtx)
{
this.semctx = semctx;
this.evalResult = evalResult;
diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ProfilingATNSimulator.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ProfilingATNSimulator.cs
index 8c5ac6b99..9184a2dc6 100644
--- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ProfilingATNSimulator.cs
+++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ProfilingATNSimulator.cs
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+/* Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
@@ -9,234 +9,234 @@ using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Atn
{
- /**
- * @since 4.3
- */
- public class ProfilingATNSimulator : ParserATNSimulator
- {
- protected readonly DecisionInfo[] decisions;
- protected int numDecisions;
-
- protected int sllStopIndex;
- protected int llStopIndex;
-
- protected int currentDecision;
- protected DFAState currentState;
-
- /** At the point of LL failover, we record how SLL would resolve the conflict so that
- * we can determine whether or not a decision / input pair is context-sensitive.
- * If LL gives a different result than SLL's predicted alternative, we have a
- * context sensitivity for sure. The converse is not necessarily true, however.
- * It's possible that after conflict resolution chooses minimum alternatives,
- * SLL could get the same answer as LL. Regardless of whether or not the result indicates
- * an ambiguity, it is not treated as a context sensitivity because LL prediction
- * was not required in order to produce a correct prediction for this decision and input sequence.
- * It may in fact still be a context sensitivity but we don't know by looking at the
- * minimum alternatives for the current input.
- */
- protected int conflictingAltResolvedBySLL;
-
- public ProfilingATNSimulator(Parser parser)
-
- : base(parser,
- parser.Interpreter.atn,
- parser.Interpreter.decisionToDFA,
- parser.Interpreter.getSharedContextCache())
- {
- numDecisions = atn.decisionToState.Count;
- decisions = new DecisionInfo[numDecisions];
- for (int i = 0; i < numDecisions; i++)
- {
- decisions[i] = new DecisionInfo(i);
- }
- }
-
- public override int AdaptivePredict(ITokenStream input, int decision, ParserRuleContext outerContext)
- {
- try
- {
- this.sllStopIndex = -1;
- this.llStopIndex = -1;
- this.currentDecision = decision;
- long start = DateTime.Now.ToFileTime(); // expensive but useful info
- int alt = base.AdaptivePredict(input, decision, outerContext);
- long stop = DateTime.Now.ToFileTime();
- decisions[decision].timeInPrediction += (stop - start);
- decisions[decision].invocations++;
-
- int SLL_k = sllStopIndex - startIndex + 1;
- decisions[decision].SLL_TotalLook += SLL_k;
- decisions[decision].SLL_MinLook = decisions[decision].SLL_MinLook == 0 ? SLL_k : Math.Min(decisions[decision].SLL_MinLook, SLL_k);
- if (SLL_k > decisions[decision].SLL_MaxLook)
- {
- decisions[decision].SLL_MaxLook = SLL_k;
- decisions[decision].SLL_MaxLookEvent =
- new LookaheadEventInfo(decision, null/*, alt*/, input, startIndex, sllStopIndex, false);
- }
-
- if (llStopIndex >= 0)
- {
- int LL_k = llStopIndex - startIndex + 1;
- decisions[decision].LL_TotalLook += LL_k;
- decisions[decision].LL_MinLook = decisions[decision].LL_MinLook == 0 ? LL_k : Math.Min(decisions[decision].LL_MinLook, LL_k);
- if (LL_k > decisions[decision].LL_MaxLook)
- {
- decisions[decision].LL_MaxLook = LL_k;
- decisions[decision].LL_MaxLookEvent =
- new LookaheadEventInfo(decision, null/*, alt*/, input, startIndex, llStopIndex, true);
- }
- }
-
- return alt;
- }
- finally
- {
- this.currentDecision = -1;
- }
- }
-
- protected override DFAState GetExistingTargetState(DFAState previousD, int t)
- {
- // this method is called after each time the input position advances
- // during SLL prediction
- sllStopIndex = input.Index;
-
- DFAState existingTargetState = base.GetExistingTargetState(previousD, t);
- if (existingTargetState != null)
- {
- decisions[currentDecision].SLL_DFATransitions++; // count only if we transition over a DFA state
- if (existingTargetState == ERROR)
- {
- decisions[currentDecision].errors.Add(
- new ErrorInfo(currentDecision, null /*previousD.configs*/, input, startIndex, sllStopIndex)
- );
- }
- }
-
- currentState = existingTargetState;
- return existingTargetState;
- }
-
- protected override DFAState ComputeTargetState(DFA dfa, DFAState previousD, int t)
- {
- DFAState state = base.ComputeTargetState(dfa, previousD, t);
- currentState = state;
- return state;
- }
-
- protected override ATNConfigSet ComputeReachSet(ATNConfigSet closure, int t, bool fullCtx)
- {
- if (fullCtx)
- {
- // this method is called after each time the input position advances
- // during full context prediction
- llStopIndex = input.Index;
- }
-
- ATNConfigSet reachConfigs = base.ComputeReachSet(closure, t, fullCtx);
- if (fullCtx)
- {
- decisions[currentDecision].LL_ATNTransitions++; // count computation even if error
- if (reachConfigs != null)
- {
- }
- else { // no reach on current lookahead symbol. ERROR.
- // TODO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule()
- decisions[currentDecision].errors.Add(
- new ErrorInfo(currentDecision, null /*closure*/, input, startIndex, llStopIndex)
- );
- }
- }
- else {
- decisions[currentDecision].SLL_ATNTransitions++;
- if (reachConfigs != null)
- {
- }
- else { // no reach on current lookahead symbol. ERROR.
- decisions[currentDecision].errors.Add(
- new ErrorInfo(currentDecision, null /*closure*/, input, startIndex, sllStopIndex)
- );
- }
- }
- return reachConfigs;
- }
-
- protected override bool EvalSemanticContext(SemanticContext pred, ParserRuleContext parserCallStack, int alt, bool fullCtx)
- {
- bool result = base.EvalSemanticContext(pred, parserCallStack, alt, fullCtx);
- if (!(pred is SemanticContext.PrecedencePredicate)) {
- bool fullContext = llStopIndex >= 0;
- int stopIndex = fullContext ? llStopIndex : sllStopIndex;
- decisions[currentDecision].predicateEvals.Add(
- new PredicateEvalInfo(null , currentDecision, input, startIndex, stopIndex, pred, result, alt/*, fullCtx*/)
- );
- }
-
- return result;
- }
-
- protected override void ReportAttemptingFullContext(DFA dfa, BitSet conflictingAlts, ATNConfigSet configs, int startIndex, int stopIndex)
- {
- if (conflictingAlts != null)
- {
- conflictingAltResolvedBySLL = conflictingAlts.NextSetBit(0);
- }
- else {
- conflictingAltResolvedBySLL = configs.GetAlts().NextSetBit(0);
- }
- decisions[currentDecision].LL_Fallback++;
- base.ReportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex);
- }
-
- protected override void ReportContextSensitivity(DFA dfa, int prediction, ATNConfigSet configs, int startIndex, int stopIndex)
- {
- if (prediction != conflictingAltResolvedBySLL)
- {
- decisions[currentDecision].contextSensitivities.Add(
- new ContextSensitivityInfo(currentDecision, null /*configs*/, input, startIndex, stopIndex)
- );
- }
- base.ReportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);
- }
-
- protected override void ReportAmbiguity(DFA dfa, DFAState D, int startIndex, int stopIndex, bool exact,
- BitSet ambigAlts, ATNConfigSet configSet)
- {
- int prediction;
- if (ambigAlts != null)
- {
- prediction = ambigAlts.NextSetBit(0);
- }
- else {
- prediction = configSet.GetAlts().NextSetBit(0);
- }
- if (configSet.fullCtx && prediction != conflictingAltResolvedBySLL)
- {
- // Even though this is an ambiguity we are reporting, we can
- // still detect some context sensitivities. Both SLL and LL
- // are showing a conflict, hence an ambiguity, but if they resolve
- // to different minimum alternatives we have also identified a
- // context sensitivity.
- decisions[currentDecision].contextSensitivities.Add( new ContextSensitivityInfo(currentDecision, null /*configs*/, input, startIndex, stopIndex) );
- }
- decisions[currentDecision].ambiguities.Add(
- new AmbiguityInfo(currentDecision, null /*configs, ambigAlts*/,
- input, startIndex, stopIndex/*, configs.IsFullContext*/)
- );
- base.ReportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configSet);
- }
-
- // ---------------------------------------------------------------------
-
- public DecisionInfo[] getDecisionInfo()
- {
- return decisions;
- }
-
- public DFAState getCurrentState()
- {
- return currentState;
- }
+ /**
+ * @since 4.3
+ */
+ public class ProfilingATNSimulator : ParserATNSimulator
+ {
+ protected readonly DecisionInfo[] decisions;
+ protected int numDecisions;
+
+ protected int sllStopIndex;
+ protected int llStopIndex;
+
+ protected int currentDecision;
+ protected DFAState currentState;
+
+ /** At the point of LL failover, we record how SLL would resolve the conflict so that
+ * we can determine whether or not a decision / input pair is context-sensitive.
+ * If LL gives a different result than SLL's predicted alternative, we have a
+ * context sensitivity for sure. The converse is not necessarily true, however.
+ * It's possible that after conflict resolution chooses minimum alternatives,
+ * SLL could get the same answer as LL. Regardless of whether or not the result indicates
+ * an ambiguity, it is not treated as a context sensitivity because LL prediction
+ * was not required in order to produce a correct prediction for this decision and input sequence.
+ * It may in fact still be a context sensitivity but we don't know by looking at the
+ * minimum alternatives for the current input.
+ */
+ protected int conflictingAltResolvedBySLL;
+
+ public ProfilingATNSimulator(Parser parser)
+
+ : base(parser,
+ parser.Interpreter.atn,
+ parser.Interpreter.decisionToDFA,
+ parser.Interpreter.getSharedContextCache())
+ {
+ numDecisions = atn.decisionToState.Count;
+ decisions = new DecisionInfo[numDecisions];
+ for (int i = 0; i < numDecisions; i++)
+ {
+ decisions[i] = new DecisionInfo(i);
+ }
+ }
+
+ public override int AdaptivePredict(ITokenStream input, int decision, ParserRuleContext outerContext)
+ {
+ try
+ {
+ this.sllStopIndex = -1;
+ this.llStopIndex = -1;
+ this.currentDecision = decision;
+ long start = DateTime.Now.ToFileTime(); // expensive but useful info
+ int alt = base.AdaptivePredict(input, decision, outerContext);
+ long stop = DateTime.Now.ToFileTime();
+ decisions[decision].timeInPrediction += (stop - start);
+ decisions[decision].invocations++;
+
+ int SLL_k = sllStopIndex - startIndex + 1;
+ decisions[decision].SLL_TotalLook += SLL_k;
+ decisions[decision].SLL_MinLook = decisions[decision].SLL_MinLook == 0 ? SLL_k : Math.Min(decisions[decision].SLL_MinLook, SLL_k);
+ if (SLL_k > decisions[decision].SLL_MaxLook)
+ {
+ decisions[decision].SLL_MaxLook = SLL_k;
+ decisions[decision].SLL_MaxLookEvent =
+ new LookaheadEventInfo(decision, null, alt, input, startIndex, sllStopIndex, false);
+ }
+
+ if (llStopIndex >= 0)
+ {
+ int LL_k = llStopIndex - startIndex + 1;
+ decisions[decision].LL_TotalLook += LL_k;
+ decisions[decision].LL_MinLook = decisions[decision].LL_MinLook == 0 ? LL_k : Math.Min(decisions[decision].LL_MinLook, LL_k);
+ if (LL_k > decisions[decision].LL_MaxLook)
+ {
+ decisions[decision].LL_MaxLook = LL_k;
+ decisions[decision].LL_MaxLookEvent =
+ new LookaheadEventInfo(decision, null, alt, input, startIndex, llStopIndex, true);
+ }
+ }
+
+ return alt;
+ }
+ finally
+ {
+ this.currentDecision = -1;
+ }
+ }
+
+ protected override DFAState GetExistingTargetState(DFAState previousD, int t)
+ {
+ // this method is called after each time the input position advances
+ // during SLL prediction
+ sllStopIndex = input.Index;
+
+ DFAState existingTargetState = base.GetExistingTargetState(previousD, t);
+ if (existingTargetState != null)
+ {
+ decisions[currentDecision].SLL_DFATransitions++; // count only if we transition over a DFA state
+ if (existingTargetState == ERROR)
+ {
+ decisions[currentDecision].errors.Add(
+ new ErrorInfo(currentDecision, previousD.configSet, input, startIndex, sllStopIndex, false)
+ );
+ }
+ }
+
+ currentState = existingTargetState;
+ return existingTargetState;
+ }
+
+ protected override DFAState ComputeTargetState(DFA dfa, DFAState previousD, int t)
+ {
+ DFAState state = base.ComputeTargetState(dfa, previousD, t);
+ currentState = state;
+ return state;
+ }
+
+ protected override ATNConfigSet ComputeReachSet(ATNConfigSet closure, int t, bool fullCtx)
+ {
+ if (fullCtx)
+ {
+ // this method is called after each time the input position advances
+ // during full context prediction
+ llStopIndex = input.Index;
+ }
+
+ ATNConfigSet reachConfigs = base.ComputeReachSet(closure, t, fullCtx);
+ if (fullCtx)
+ {
+ decisions[currentDecision].LL_ATNTransitions++; // count computation even if error
+ if (reachConfigs != null)
+ {
+ }
+ else { // no reach on current lookahead symbol. ERROR.
+ // TODO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule()
+ decisions[currentDecision].errors.Add(
+ new ErrorInfo(currentDecision, closure, input, startIndex, llStopIndex, true)
+ );
+ }
+ }
+ else {
+ decisions[currentDecision].SLL_ATNTransitions++;
+ if (reachConfigs != null)
+ {
+ }
+ else { // no reach on current lookahead symbol. ERROR.
+ decisions[currentDecision].errors.Add(
+ new ErrorInfo(currentDecision, closure, input, startIndex, sllStopIndex, false)
+ );
+ }
+ }
+ return reachConfigs;
+ }
+
+ protected override bool EvalSemanticContext(SemanticContext pred, ParserRuleContext parserCallStack, int alt, bool fullCtx)
+ {
+ bool result = base.EvalSemanticContext(pred, parserCallStack, alt, fullCtx);
+ if (!(pred is SemanticContext.PrecedencePredicate)) {
+ bool fullContext = llStopIndex >= 0;
+ int stopIndex = fullContext ? llStopIndex : sllStopIndex;
+ decisions[currentDecision].predicateEvals.Add(
+ new PredicateEvalInfo(currentDecision, input, startIndex, stopIndex, pred, result, alt, fullCtx)
+ );
+ }
+
+ return result;
+ }
+
+ protected override void ReportAttemptingFullContext(DFA dfa, BitSet conflictingAlts, ATNConfigSet configs, int startIndex, int stopIndex)
+ {
+ if (conflictingAlts != null)
+ {
+ conflictingAltResolvedBySLL = conflictingAlts.NextSetBit(0);
+ }
+ else {
+ conflictingAltResolvedBySLL = configs.GetAlts().NextSetBit(0);
+ }
+ decisions[currentDecision].LL_Fallback++;
+ base.ReportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex);
+ }
+
+ protected override void ReportContextSensitivity(DFA dfa, int prediction, ATNConfigSet configs, int startIndex, int stopIndex)
+ {
+ if (prediction != conflictingAltResolvedBySLL)
+ {
+ decisions[currentDecision].contextSensitivities.Add(
+ new ContextSensitivityInfo(currentDecision, configs, input, startIndex, stopIndex)
+ );
+ }
+ base.ReportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);
+ }
+
+ protected override void ReportAmbiguity(DFA dfa, DFAState D, int startIndex, int stopIndex, bool exact,
+ BitSet ambigAlts, ATNConfigSet configs)
+ {
+ int prediction;
+ if (ambigAlts != null)
+ {
+ prediction = ambigAlts.NextSetBit(0);
+ }
+ else {
+ prediction = configs.GetAlts().NextSetBit(0);
+ }
+ if (configs.fullCtx && prediction != conflictingAltResolvedBySLL)
+ {
+ // Even though this is an ambiguity we are reporting, we can
+ // still detect some context sensitivities. Both SLL and LL
+ // are showing a conflict, hence an ambiguity, but if they resolve
+ // to different minimum alternatives we have also identified a
+ // context sensitivity.
+ decisions[currentDecision].contextSensitivities.Add( new ContextSensitivityInfo(currentDecision, configs, input, startIndex, stopIndex) );
+ }
+ decisions[currentDecision].ambiguities.Add(
+ new AmbiguityInfo(currentDecision, configs, ambigAlts,
+ input, startIndex, stopIndex, configs.fullCtx)
+ );
+ base.ReportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configs);
+ }
+
+ // ---------------------------------------------------------------------
+
+ public DecisionInfo[] getDecisionInfo()
+ {
+ return decisions;
+ }
+
+ public DFAState getCurrentState()
+ {
+ return currentState;
+ }
}
}