Update to the latest working build of ANTLR 4

This commit is contained in:
Sam Harwell 2014-09-29 21:26:05 -05:00
parent c78833e705
commit c3a7bdce7b
34 changed files with 1506 additions and 443 deletions

@ -1 +1 @@
Subproject commit 1930a7b29d4e0bcc47f22d68282d70ad2552dc2e
Subproject commit 84f92bd938e05f803f81634f43902e4b47f08ab2

View File

@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.IO;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime
@ -58,35 +58,8 @@ namespace Antlr4.Runtime
/// <exception cref="System.IO.IOException"/>
public virtual void Load(string fileName, string encoding)
{
if (fileName == null)
{
return;
}
FilePath f = new FilePath(fileName);
int size = (int)f.Length();
StreamReader isr;
FileInputStream fis = new FileInputStream(fileName);
if (encoding != null)
{
isr = new StreamReader(fis, encoding);
}
else
{
isr = new StreamReader(fis);
}
try
{
data = new char[size];
n = isr.Read(data);
if (n < data.Length)
{
data = Arrays.CopyOf(data, n);
}
}
finally
{
isr.Close();
}
data = Utils.ReadFile(fileName, encoding);
this.n = data.Length;
}
public override string SourceName

View File

@ -314,6 +314,10 @@ namespace Antlr4.Runtime
{
get
{
if (name == null || name.IsEmpty())
{
return IntStreamConstants.UnknownSourceName;
}
return name;
}
}

View File

@ -48,10 +48,29 @@ namespace Antlr4.Runtime.Atn
/// </remarks>
public class ATNConfig
{
/// <summary>
/// This field stores the bit mask for implementing the
/// <see cref="PrecedenceFilterSuppressed()"/>
/// property as a bit within the
/// existing
/// <see cref="altAndOuterContextDepth"/>
/// field.
/// </summary>
private const int SuppressPrecedenceFilter = unchecked((int)(0x80000000));
/// <summary>The ATN state associated with this configuration</summary>
[NotNull]
private readonly ATNState state;
/// <summary>This is a bit-field currently containing the following values.</summary>
/// <remarks>
/// This is a bit-field currently containing the following values.
/// <ul>
/// <li>0x00FFFFFF: Alternative</li>
/// <li>0x7F000000: Outer context depth</li>
/// <li>0x80000000: Suppress precedence filter</li>
/// </ul>
/// </remarks>
private int altAndOuterContextDepth;
/// <summary>
@ -70,14 +89,14 @@ namespace Antlr4.Runtime.Atn
{
System.Diagnostics.Debug.Assert((alt & unchecked((int)(0xFFFFFF))) == alt);
this.state = state;
this.altAndOuterContextDepth = alt & unchecked((int)(0x7FFFFFFF));
this.altAndOuterContextDepth = alt;
this.context = context;
}
protected internal ATNConfig(Antlr4.Runtime.Atn.ATNConfig c, ATNState state, PredictionContext context)
{
this.state = state;
this.altAndOuterContextDepth = c.altAndOuterContextDepth & unchecked((int)(0x7FFFFFFF));
this.altAndOuterContextDepth = c.altAndOuterContextDepth;
this.context = context;
}
@ -137,25 +156,6 @@ namespace Antlr4.Runtime.Atn
}
}
public virtual bool IsHidden
{
get
{
return altAndOuterContextDepth < 0;
}
set
{
if (value)
{
altAndOuterContextDepth |= unchecked((int)(0x80000000));
}
else
{
altAndOuterContextDepth &= ~unchecked((int)(0x80000000));
}
}
}
public virtual PredictionContext Context
{
get
@ -187,9 +187,10 @@ namespace Antlr4.Runtime.Atn
/// no way to do this efficiently, we simply cannot evaluate
/// dependent predicates unless we are in the rule that initially
/// invokes the ATN simulator.
/// closure() tracks the depth of how far we dip into the
/// outer context: depth &gt; 0. Note that it may not be totally
/// accurate depth since I don't ever decrement. TODO: make it a boolean then
/// <p>
/// closure() tracks the depth of how far we dip into the outer context:
/// depth &gt; 0. Note that it may not be totally accurate depth since I
/// don't ever decrement. TODO: make it a boolean then</p>
/// </remarks>
public virtual int OuterContextDepth
{
@ -346,6 +347,25 @@ namespace Antlr4.Runtime.Atn
return false;
}
public bool PrecedenceFilterSuppressed
{
get
{
return (altAndOuterContextDepth & SuppressPrecedenceFilter) != 0;
}
set
{
if (value)
{
this.altAndOuterContextDepth |= SuppressPrecedenceFilter;
}
else
{
this.altAndOuterContextDepth &= ~SuppressPrecedenceFilter;
}
}
}
/// <summary>
/// An ATN configuration is equal to another if both have
/// the same state, they predict the same alternative, and
@ -378,7 +398,7 @@ namespace Antlr4.Runtime.Atn
return false;
}
}
return this.State.stateNumber == other.State.stateNumber && this.Alt == other.Alt && this.ReachesIntoOuterContext == other.ReachesIntoOuterContext && this.Context.Equals(other.Context) && this.SemanticContext.Equals(other.SemanticContext) && this.PassedThroughNonGreedyDecision == other.PassedThroughNonGreedyDecision && ObjectEqualityComparator.Instance.Equals(this.ActionExecutor, other.ActionExecutor);
return this.State.stateNumber == other.State.stateNumber && this.Alt == other.Alt && this.ReachesIntoOuterContext == other.ReachesIntoOuterContext && this.Context.Equals(other.Context) && this.SemanticContext.Equals(other.SemanticContext) && this.PrecedenceFilterSuppressed == other.PrecedenceFilterSuppressed && this.PassedThroughNonGreedyDecision == other.PassedThroughNonGreedyDecision && ObjectEqualityComparator.Instance.Equals(this.ActionExecutor, other.ActionExecutor);
}
public override int GetHashCode()

View File

@ -81,7 +81,7 @@ namespace Antlr4.Runtime.Atn
private int uniqueAlt;
private BitSet conflictingAlts;
private ConflictInfo conflictInfo;
private bool hasSemanticContext;
@ -144,7 +144,7 @@ namespace Antlr4.Runtime.Atn
if (@readonly || !set.IsReadOnly)
{
this.uniqueAlt = set.uniqueAlt;
this.conflictingAlts = set.conflictingAlts;
this.conflictInfo = set.conflictInfo;
}
}
@ -161,9 +161,9 @@ namespace Antlr4.Runtime.Atn
get
{
// if (!readonly && set.isReadOnly()) -> addAll is called from clone()
if (conflictingAlts != null)
if (conflictInfo != null)
{
return (BitSet)conflictingAlts.Clone();
return (BitSet)conflictInfo.ConflictedAlts.Clone();
}
BitSet alts = new BitSet();
foreach (ATNConfig config in this)
@ -182,35 +182,6 @@ namespace Antlr4.Runtime.Atn
}
}
public void StripHiddenConfigs()
{
EnsureWritable();
IEnumerator<KeyValuePair<long, ATNConfig>> iterator = mergedConfigs.EntrySet().GetEnumerator();
while (iterator.HasNext())
{
if (iterator.Next().Value.IsHidden)
{
iterator.Remove();
}
}
IListIterator<ATNConfig> iterator2 = unmerged.ListIterator();
while (iterator2.HasNext())
{
if (iterator2.Next().IsHidden)
{
iterator2.Remove();
}
}
iterator2 = configs.ListIterator();
while (iterator2.HasNext())
{
if (iterator2.Next().IsHidden)
{
iterator2.Remove();
}
}
}
public virtual bool IsOutermostConfigSet
{
get
@ -320,7 +291,6 @@ namespace Antlr4.Runtime.Atn
{
EnsureWritable();
System.Diagnostics.Debug.Assert(!outermostConfigSet || !e.ReachesIntoOuterContext);
System.Diagnostics.Debug.Assert(!e.IsHidden);
if (contextCache == null)
{
contextCache = PredictionContextCache.Uncached;
@ -332,6 +302,10 @@ namespace Antlr4.Runtime.Atn
if (mergedConfig != null && CanMerge(e, key, mergedConfig))
{
mergedConfig.OuterContextDepth = Math.Max(mergedConfig.OuterContextDepth, e.OuterContextDepth);
if (e.PrecedenceFilterSuppressed)
{
mergedConfig.PrecedenceFilterSuppressed = true;
}
PredictionContext joined = PredictionContext.Join(mergedConfig.Context, e.Context, contextCache);
UpdatePropertiesForMergedConfig(e);
if (mergedConfig.Context == joined)
@ -347,6 +321,10 @@ namespace Antlr4.Runtime.Atn
if (CanMerge(e, key, unmergedConfig))
{
unmergedConfig.OuterContextDepth = Math.Max(unmergedConfig.OuterContextDepth, e.OuterContextDepth);
if (e.PrecedenceFilterSuppressed)
{
unmergedConfig.PrecedenceFilterSuppressed = true;
}
PredictionContext joined = PredictionContext.Join(unmergedConfig.Context, e.Context, contextCache);
UpdatePropertiesForMergedConfig(e);
if (unmergedConfig.Context == joined)
@ -481,7 +459,7 @@ namespace Antlr4.Runtime.Atn
dipsIntoOuterContext = false;
hasSemanticContext = false;
uniqueAlt = ATN.InvalidAltNumber;
conflictingAlts = null;
conflictInfo = null;
}
public override bool Equals(object obj)
@ -495,7 +473,7 @@ namespace Antlr4.Runtime.Atn
return false;
}
Antlr4.Runtime.Atn.ATNConfigSet other = (Antlr4.Runtime.Atn.ATNConfigSet)obj;
return this.outermostConfigSet == other.outermostConfigSet && Utils.Equals(conflictingAlts, other.conflictingAlts) && configs.Equals(other.configs);
return this.outermostConfigSet == other.outermostConfigSet && Utils.Equals(conflictInfo, other.conflictInfo) && configs.Equals(other.configs);
}
public override int GetHashCode()
@ -523,7 +501,7 @@ namespace Antlr4.Runtime.Atn
{
StringBuilder buf = new StringBuilder();
IList<ATNConfig> sortedConfigs = new List<ATNConfig>(configs);
sortedConfigs.Sort(new _IComparer_495());
sortedConfigs.Sort(new _IComparer_475());
buf.Append("[");
for (int i = 0; i < sortedConfigs.Count; i++)
{
@ -542,9 +520,13 @@ namespace Antlr4.Runtime.Atn
{
buf.Append(",uniqueAlt=").Append(uniqueAlt);
}
if (conflictingAlts != null)
if (conflictInfo != null)
{
buf.Append(",conflictingAlts=").Append(conflictingAlts);
buf.Append(",conflictingAlts=").Append(conflictInfo.ConflictedAlts);
if (!conflictInfo.IsExact)
{
buf.Append("*");
}
}
if (dipsIntoOuterContext)
{
@ -553,9 +535,9 @@ namespace Antlr4.Runtime.Atn
return buf.ToString();
}
private sealed class _IComparer_495 : IComparer<ATNConfig>
private sealed class _IComparer_475 : IComparer<ATNConfig>
{
public _IComparer_495()
public _IComparer_475()
{
}
@ -607,17 +589,41 @@ namespace Antlr4.Runtime.Atn
hasSemanticContext = true;
}
public virtual ConflictInfo ConflictInformation
{
get
{
return conflictInfo;
}
set
{
ConflictInfo conflictInfo = value;
EnsureWritable();
this.conflictInfo = conflictInfo;
}
}
public virtual BitSet ConflictingAlts
{
get
{
return conflictingAlts;
if (conflictInfo == null)
{
return null;
}
return conflictInfo.ConflictedAlts;
}
set
}
public virtual bool IsExactConflict
{
get
{
BitSet conflictingAlts = value;
EnsureWritable();
this.conflictingAlts = conflictingAlts;
if (conflictInfo == null)
{
return false;
}
return conflictInfo.IsExact;
}
}

View File

@ -354,7 +354,16 @@ namespace Antlr4.Runtime.Atn
{
continue;
}
atn.ruleToStopState[ruleTransition.target.ruleIndex].AddTransition(new EpsilonTransition(ruleTransition.followState));
int outermostPrecedenceReturn = -1;
if (atn.ruleToStartState[ruleTransition.target.ruleIndex].isPrecedenceRule)
{
if (ruleTransition.precedence == 0)
{
outermostPrecedenceReturn = ruleTransition.target.ruleIndex;
}
}
EpsilonTransition returnTransition = new EpsilonTransition(ruleTransition.followState, outermostPrecedenceReturn);
atn.ruleToStopState[ruleTransition.target.ruleIndex].AddTransition(returnTransition);
}
}
foreach (ATNState state_2 in atn.states)
@ -847,7 +856,7 @@ namespace Antlr4.Runtime.Atn
{
Transition transition = state.GetOptimizedTransition(i);
ATNState intermediate = transition.target;
if (transition.TransitionType != TransitionType.Epsilon || intermediate.StateType != StateType.Basic || !intermediate.OnlyHasEpsilonTransitions)
if (transition.TransitionType != TransitionType.Epsilon || ((EpsilonTransition)transition).OutermostPrecedenceReturn != -1 || intermediate.StateType != StateType.Basic || !intermediate.OnlyHasEpsilonTransitions)
{
if (optimizedTransitions != null)
{
@ -857,7 +866,7 @@ namespace Antlr4.Runtime.Atn
}
for (int j = 0; j < intermediate.NumberOfOptimizedTransitions; j++)
{
if (intermediate.GetOptimizedTransition(j).TransitionType != TransitionType.Epsilon)
if (intermediate.GetOptimizedTransition(j).TransitionType != TransitionType.Epsilon || ((EpsilonTransition)intermediate.GetOptimizedTransition(j)).OutermostPrecedenceReturn != -1)
{
if (optimizedTransitions != null)
{

View File

@ -71,7 +71,7 @@ namespace Antlr4.Runtime.Atn
static ATNSimulator()
{
Error = new DFAState(new ATNConfigSet(), 0, 0);
Error = new DFAState(new EmptyEdgeMap<DFAState>(0, -1), new EmptyEdgeMap<DFAState>(0, -1), new ATNConfigSet());
Error.stateNumber = int.MaxValue;
}

View File

@ -0,0 +1,106 @@
/*
* [The "BSD license"]
* Copyright (c) 2013 Terence Parr
* Copyright (c) 2013 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Atn
{
/// <summary>This class stores information about a configuration conflict.</summary>
/// <remarks>This class stores information about a configuration conflict.</remarks>
/// <author>Sam Harwell</author>
public class ConflictInfo
{
private readonly BitSet conflictedAlts;
private readonly bool exact;
public ConflictInfo(BitSet conflictedAlts, bool exact)
{
this.conflictedAlts = conflictedAlts;
this.exact = exact;
}
/// <summary>Gets the set of conflicting alternatives for the configuration set.</summary>
/// <remarks>Gets the set of conflicting alternatives for the configuration set.</remarks>
public BitSet ConflictedAlts
{
get
{
return conflictedAlts;
}
}
/// <summary>Gets whether or not the configuration conflict is an exact conflict.</summary>
/// <remarks>
/// Gets whether or not the configuration conflict is an exact conflict.
/// An exact conflict occurs when the prediction algorithm determines that
/// the represented alternatives for a particular configuration set cannot be
/// further reduced by consuming additional input. After reaching an exact
/// conflict during an SLL prediction, only switch to full-context prediction
/// could reduce the set of viable alternatives. In LL prediction, an exact
/// conflict indicates a true ambiguity in the input.
/// <p>
/// For the
/// <see cref="PredictionMode.LlExactAmbigDetection"/>
/// prediction mode,
/// accept states are conflicting but not exact are treated as non-accept
/// states.</p>
/// </remarks>
public bool IsExact
{
get
{
return exact;
}
}
public override bool Equals(object obj)
{
if (obj == this)
{
return true;
}
else
{
if (!(obj is Antlr4.Runtime.Atn.ConflictInfo))
{
return false;
}
}
Antlr4.Runtime.Atn.ConflictInfo other = (Antlr4.Runtime.Atn.ConflictInfo)obj;
return IsExact == other.IsExact && Utils.Equals(ConflictedAlts, other.ConflictedAlts);
}
public override int GetHashCode()
{
return ConflictedAlts.GetHashCode();
}
}
}

View File

@ -35,9 +35,32 @@ namespace Antlr4.Runtime.Atn
{
public sealed class EpsilonTransition : Transition
{
private readonly int outermostPrecedenceReturn;
public EpsilonTransition(ATNState target)
: this(target, -1)
{
}
public EpsilonTransition(ATNState target, int outermostPrecedenceReturn)
: base(target)
{
this.outermostPrecedenceReturn = outermostPrecedenceReturn;
}
/// <returns>
/// the rule index of a precedence rule for which this transition is
/// returning from, where the precedence value is 0; otherwise, -1.
/// </returns>
/// <seealso cref="ATNConfig.PrecedenceFilterSuppressed()"/>
/// <seealso cref="ParserATNSimulator.ApplyPrecedenceFilter(ATNConfigSet, Antlr4.Runtime.ParserRuleContext, PredictionContextCache)"/>
/// <since>4.4.1</since>
public int OutermostPrecedenceReturn
{
get
{
return outermostPrecedenceReturn;
}
}
public override Antlr4.Runtime.Atn.TransitionType TransitionType

View File

@ -190,6 +190,13 @@ namespace Antlr4.Runtime.Atn
protected internal virtual int ExecATN(ICharStream input, DFAState ds0)
{
//System.out.println("enter exec index "+input.index()+" from "+ds0.configs);
if (ds0.IsAcceptState)
{
// allow zero-length tokens
CaptureSimState(prevAccept, input, ds0);
// adjust index since the current input character was not yet consumed
prevAccept.index--;
}
int t = input.La(1);
DFAState s = ds0;
// s is current/from DFA state
@ -222,7 +229,7 @@ namespace Antlr4.Runtime.Atn
{
break;
}
if (target.isAcceptState)
if (target.IsAcceptState)
{
CaptureSimState(prevAccept, input, target);
if (t == IntStreamConstants.Eof)
@ -318,9 +325,9 @@ namespace Antlr4.Runtime.Atn
{
if (prevAccept.dfaState != null)
{
LexerActionExecutor lexerActionExecutor = prevAccept.dfaState.lexerActionExecutor;
LexerActionExecutor lexerActionExecutor = prevAccept.dfaState.LexerActionExecutor;
Accept(input, lexerActionExecutor, startIndex, prevAccept.index, prevAccept.line, prevAccept.charPos);
return prevAccept.dfaState.prediction;
return prevAccept.dfaState.Prediction;
}
else
{
@ -719,14 +726,14 @@ namespace Antlr4.Runtime.Atn
protected internal virtual DFAState AddDFAState(ATNConfigSet configs)
{
System.Diagnostics.Debug.Assert(!configs.HasSemanticContext);
DFAState proposed = new DFAState(configs, 0, MaxDfaEdge);
DFAState proposed = new DFAState(atn.modeToDFA[mode], configs);
DFAState existing = atn.modeToDFA[mode].states.Get(proposed);
if (existing != null)
{
return existing;
}
configs.OptimizeConfigs(this);
DFAState newState = new DFAState(configs.Clone(true), 0, MaxDfaEdge);
DFAState newState = new DFAState(atn.modeToDFA[mode], configs.Clone(true));
ATNConfig firstConfigWithRuleStopState = null;
foreach (ATNConfig c in configs)
{
@ -738,9 +745,9 @@ namespace Antlr4.Runtime.Atn
}
if (firstConfigWithRuleStopState != null)
{
newState.isAcceptState = true;
newState.lexerActionExecutor = firstConfigWithRuleStopState.ActionExecutor;
newState.prediction = atn.ruleToTokenType[firstConfigWithRuleStopState.State.ruleIndex];
int prediction = atn.ruleToTokenType[firstConfigWithRuleStopState.State.ruleIndex];
LexerActionExecutor lexerActionExecutor = firstConfigWithRuleStopState.ActionExecutor;
newState.AcceptStateInfo = new AcceptStateInfo(prediction, lexerActionExecutor);
}
return atn.modeToDFA[mode].AddState(newState);
}

View File

@ -341,6 +341,7 @@ namespace Antlr4.Runtime.Atn
public bool optimize_ll1 = true;
[System.ObsoleteAttribute(@"This flag is not currently used by the ATN simulator.")]
public bool optimize_hidden_conflicted_configs = false;
public bool optimize_tail_calls = true;
@ -386,6 +387,8 @@ namespace Antlr4.Runtime.Atn
/// </remarks>
protected internal bool userWantsCtxSensitive = true;
private DFA dfa;
/// <summary>Testing only!</summary>
public ParserATNSimulator(ATN atn)
: this(null, atn)
@ -437,6 +440,7 @@ namespace Antlr4.Runtime.Atn
}
}
}
this.dfa = dfa;
if (force_global_context)
{
useContext = true;
@ -475,6 +479,7 @@ namespace Antlr4.Runtime.Atn
}
finally
{
this.dfa = null;
input.Seek(index);
input.Release(m);
}
@ -568,7 +573,7 @@ namespace Antlr4.Runtime.Atn
s = next;
}
}
if (s.isAcceptState)
if (IsAcceptState(s, state.useContext))
{
if (s.predicates != null)
{
@ -580,14 +585,14 @@ namespace Antlr4.Runtime.Atn
break;
}
// t is not updated if one of these states is reached
System.Diagnostics.Debug.Assert(!s.isAcceptState);
System.Diagnostics.Debug.Assert(!IsAcceptState(s, state.useContext));
// if no edge, pop over to ATN interpreter, update DFA and return
DFAState target = GetExistingTargetState(s, t);
if (target == null)
{
if (dfa_debug && t >= 0)
{
System.Console.Out.WriteLine("no edge for " + parser.TokenNames[t]);
System.Console.Out.WriteLine("no edge for " + parser.Vocabulary.GetDisplayName(t));
}
int alt;
SimulatorState initialState = new SimulatorState(outerContext, s, state.useContext, remainingOuterContext);
@ -606,7 +611,7 @@ namespace Antlr4.Runtime.Atn
}
}
s = target;
if (!s.isAcceptState && t != IntStreamConstants.Eof)
if (!IsAcceptState(s, state.useContext) && t != IntStreamConstants.Eof)
{
input.Consume();
t = input.La(1);
@ -616,11 +621,11 @@ namespace Antlr4.Runtime.Atn
// if ( debug ) System.out.println("!!! no viable alt in dfa");
// return -1;
// }
if (s.configs.ConflictingAlts != null)
if (!state.useContext && s.configs.ConflictInformation != null)
{
if (dfa.atnStartState is DecisionState)
{
if (!userWantsCtxSensitive || !s.configs.DipsIntoOuterContext || (treat_sllk1_conflict_as_ambiguity && input.Index == startIndex))
if (!userWantsCtxSensitive || (!s.configs.DipsIntoOuterContext && s.configs.IsExactConflict) || (treat_sllk1_conflict_as_ambiguity && input.Index == startIndex))
{
}
else
@ -695,12 +700,82 @@ namespace Antlr4.Runtime.Atn
{
input.Seek(stopIndex);
}
ReportAmbiguity(dfa, s, startIndex, stopIndex, predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection, alts, s.configs);
ReportAmbiguity(dfa, s, startIndex, stopIndex, s.configs.IsExactConflict, alts, s.configs);
return alts.NextSetBit(0);
}
}
}
return s.prediction;
return s.Prediction;
}
/// <summary>
/// Determines if a particular DFA state should be treated as an accept state
/// for the current prediction mode.
/// </summary>
/// <remarks>
/// Determines if a particular DFA state should be treated as an accept state
/// for the current prediction mode. In addition to the
/// <paramref name="useContext"/>
/// parameter, the
/// <see cref="PredictionMode()"/>
/// method provides the
/// prediction mode controlling the prediction algorithm as a whole.
/// <p>
/// The default implementation simply returns the value of
/// <see cref="Antlr4.Runtime.Dfa.DFAState.IsAcceptState()"/>
/// except for conflict states when
/// <paramref name="useContext"/>
/// is
/// <see langword="true"/>
/// and
/// <see cref="PredictionMode()"/>
/// is
/// <see cref="PredictionMode.LlExactAmbigDetection"/>
/// . In that case, only
/// conflict states where
/// <see cref="ATNConfigSet.IsExactConflict()"/>
/// is
/// <see langword="true"/>
/// are considered accept states.
/// </p>
/// </remarks>
/// <param name="state">The DFA state to check.</param>
/// <param name="useContext">
///
/// <see langword="true"/>
/// if the prediction algorithm is currently
/// considering the full parser context; otherwise,
/// <see langword="false"/>
/// if the
/// algorithm is currently performing a local context prediction.
/// </param>
/// <returns>
///
/// <see langword="true"/>
/// if the specified
/// <paramref name="state"/>
/// is an accept state;
/// otherwise,
/// <see langword="false"/>
/// .
/// </returns>
protected internal virtual bool IsAcceptState(DFAState state, bool useContext)
{
if (!state.IsAcceptState)
{
return false;
}
if (state.configs.ConflictingAlts == null)
{
// unambiguous
return true;
}
// More picky when we need exact conflicts
if (useContext && predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection)
{
return state.configs.IsExactConflict;
}
return true;
}
/// <summary>
@ -764,13 +839,13 @@ namespace Antlr4.Runtime.Atn
}
DFAState D = nextState.s0;
// predicted alt => accept state
System.Diagnostics.Debug.Assert(D.isAcceptState || GetUniqueAlt(D.configs) == ATN.InvalidAltNumber);
System.Diagnostics.Debug.Assert(D.IsAcceptState || D.Prediction == ATN.InvalidAltNumber);
// conflicted => accept state
System.Diagnostics.Debug.Assert(D.isAcceptState || D.configs.ConflictingAlts == null);
if (D.isAcceptState)
System.Diagnostics.Debug.Assert(D.IsAcceptState || D.configs.ConflictInformation == null);
if (IsAcceptState(D, useContext))
{
BitSet conflictingAlts = D.configs.ConflictingAlts;
int predictedAlt = conflictingAlts == null ? GetUniqueAlt(D.configs) : ATN.InvalidAltNumber;
int predictedAlt = conflictingAlts == null ? D.Prediction : ATN.InvalidAltNumber;
if (predictedAlt != ATN.InvalidAltNumber)
{
if (optimize_ll1 && input.Index == startIndex && !dfa.IsPrecedenceDfa && nextState.outerContext == nextState.remainingOuterContext && dfa.decision >= 0 && !D.configs.HasSemanticContext)
@ -786,20 +861,15 @@ namespace Antlr4.Runtime.Atn
ReportContextSensitivity(dfa, predictedAlt, nextState, startIndex, input.Index);
}
}
predictedAlt = D.prediction;
predictedAlt = D.Prediction;
// int k = input.index() - startIndex + 1; // how much input we used
// System.out.println("used k="+k);
bool attemptFullContext = conflictingAlts != null && userWantsCtxSensitive;
if (attemptFullContext)
{
if (predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection)
{
attemptFullContext = !useContext && (D.configs.DipsIntoOuterContext || D.configs.ConflictingAlts.Cardinality() > 2) && (!treat_sllk1_conflict_as_ambiguity || input.Index != startIndex);
}
else
{
attemptFullContext = D.configs.DipsIntoOuterContext && (!treat_sllk1_conflict_as_ambiguity || input.Index != startIndex);
}
// Only exact conflicts are known to be ambiguous when local
// prediction does not step out of the decision rule.
attemptFullContext = !useContext && (D.configs.DipsIntoOuterContext || !D.configs.IsExactConflict) && (!treat_sllk1_conflict_as_ambiguity || input.Index != startIndex);
}
if (D.configs.HasSemanticContext)
{
@ -844,7 +914,7 @@ namespace Antlr4.Runtime.Atn
{
if (reportAmbiguities && conflictingAlts.Cardinality() > 1)
{
ReportAmbiguity(dfa, D, startIndex, input.Index, predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection, conflictingAlts, D.configs);
ReportAmbiguity(dfa, D, startIndex, input.Index, D.configs.IsExactConflict, conflictingAlts, D.configs);
}
predictedAlt = conflictingAlts.NextSetBit(0);
}
@ -853,7 +923,7 @@ namespace Antlr4.Runtime.Atn
else
{
System.Diagnostics.Debug.Assert(!useContext);
System.Diagnostics.Debug.Assert(D.isAcceptState);
System.Diagnostics.Debug.Assert(IsAcceptState(D, false));
SimulatorState fullContextState = ComputeStartState(dfa, outerContext, true);
if (reportAmbiguities)
{
@ -1055,8 +1125,8 @@ namespace Antlr4.Runtime.Atn
s = next;
}
}
System.Diagnostics.Debug.Assert(!s.isAcceptState);
if (s.isAcceptState)
System.Diagnostics.Debug.Assert(!IsAcceptState(s, useContext));
if (IsAcceptState(s, useContext))
{
return new SimulatorState(previous.outerContext, s, useContext, remainingGlobalContext);
}
@ -1357,6 +1427,16 @@ namespace Antlr4.Runtime.Atn
{
configs.IsOutermostConfigSet = true;
}
if (!useContext || enable_global_context_dfa)
{
if (!dfa.IsPrecedenceDfa && dfa.atnStartState is StarLoopEntryState)
{
if (((StarLoopEntryState)dfa.atnStartState).precedenceRuleDecision)
{
dfa.IsPrecedenceDfa = true;
}
}
}
bool collectPredicates = true;
Closure(reachIntermediate, configs, collectPredicates, hasMoreContext, contextCache, false);
bool stepIntoGlobal = configs.DipsIntoOuterContext;
@ -1370,13 +1450,6 @@ namespace Antlr4.Runtime.Atn
{
if (s0 == null)
{
if (!dfa.IsPrecedenceDfa && dfa.atnStartState is StarLoopEntryState)
{
if (((StarLoopEntryState)dfa.atnStartState).precedenceRuleDecision)
{
dfa.IsPrecedenceDfa = true;
}
}
if (!dfa.IsPrecedenceDfa)
{
AtomicReference<DFAState> reference = useContext ? dfa.s0full : dfa.s0;
@ -1441,8 +1514,13 @@ namespace Antlr4.Runtime.Atn
/// <li>Evaluate the precedence predicates for each configuration using
/// <see cref="SemanticContext.EvalPrecedence(Antlr4.Runtime.Recognizer{Symbol, ATNInterpreter}, Antlr4.Runtime.RuleContext)"/>
/// .</li>
/// <li>Remove all configurations which predict an alternative greater than
/// 1, for which another configuration that predicts alternative 1 is in the
/// <li>When
/// <see cref="ATNConfig.PrecedenceFilterSuppressed()"/>
/// is
/// <see langword="false"/>
/// ,
/// remove all configurations which predict an alternative greater than 1,
/// for which another configuration that predicts alternative 1 is in the
/// same ATN state with the same prediction context. This transformation is
/// valid for the following reasons:
/// <ul>
@ -1454,7 +1532,11 @@ namespace Antlr4.Runtime.Atn
/// epsilon transition, so the only way an alternative other than 1 can exist
/// in a state that is also reachable via alternative 1 is by nesting calls
/// to the left-recursive rule, with the outer calls not being at the
/// preferred precedence level.</li>
/// preferred precedence level. The
/// <see cref="ATNConfig.PrecedenceFilterSuppressed()"/>
/// property marks ATN
/// configurations which do not meet this condition, and therefore are not
/// eligible for elimination during the filtering process.</li>
/// </ul>
/// </li>
/// </ol>
@ -1535,11 +1617,14 @@ namespace Antlr4.Runtime.Atn
// already handled
continue;
}
PredictionContext context = statesFromAlt1.Get(config_1.State.stateNumber);
if (context != null && context.Equals(config_1.Context))
if (!config_1.PrecedenceFilterSuppressed)
{
// eliminated
continue;
PredictionContext context = statesFromAlt1.Get(config_1.State.stateNumber);
if (context != null && context.Equals(config_1.Context))
{
// eliminated
continue;
}
}
configSet.Add(config_1, contextCache);
}
@ -1569,9 +1654,7 @@ namespace Antlr4.Runtime.Atn
// Update DFA so reach becomes accept state with predicate
predPredictions = GetPredicatePredictions(conflictingAlts, altToPred);
D.predicates = predPredictions;
D.prediction = ATN.InvalidAltNumber;
}
// make sure we use preds
return predPredictions;
}
@ -1767,6 +1850,7 @@ namespace Antlr4.Runtime.Atn
// gotten that context AFTER having fallen off a rule.
// Make sure we track that we are now out of context.
c.OuterContextDepth = config.OuterContextDepth;
c.PrecedenceFilterSuppressed = config.PrecedenceFilterSuppressed;
System.Diagnostics.Debug.Assert(depth > int.MinValue);
Closure(c, configs, intermediate, closureBusy, collectPredicates, hasMoreContexts, contextCache, depth - 1, treatEofAsEpsilon);
}
@ -1791,6 +1875,14 @@ namespace Antlr4.Runtime.Atn
// no need to keep full context overhead when we step out
config = config.Transform(config.State, PredictionContext.EmptyLocal, false);
}
else
{
if (!config.ReachesIntoOuterContext && PredictionContext.IsEmptyLocal(config.Context))
{
// add stop state when leaving decision rule for the first time
configs.Add(config, contextCache);
}
}
}
}
}
@ -1835,6 +1927,14 @@ namespace Antlr4.Runtime.Atn
// avoid infinite recursion for right-recursive rules
continue;
}
if (dfa != null && dfa.IsPrecedenceDfa)
{
int outermostPrecedenceReturn = ((EpsilonTransition)t).OutermostPrecedenceReturn;
if (outermostPrecedenceReturn == dfa.atnStartState.ruleIndex)
{
c.PrecedenceFilterSuppressed = true;
}
}
c.OuterContextDepth = c.OuterContextDepth + 1;
System.Diagnostics.Debug.Assert(newDepth > int.MinValue);
newDepth--;
@ -1997,9 +2097,9 @@ namespace Antlr4.Runtime.Atn
return config.Transform(t.target, newContext, false);
}
private sealed class _IComparer_1928 : IComparer<ATNConfig>
private sealed class _IComparer_1996 : IComparer<ATNConfig>
{
public _IComparer_1928()
public _IComparer_1996()
{
}
@ -2019,9 +2119,9 @@ namespace Antlr4.Runtime.Atn
}
}
private static readonly IComparer<ATNConfig> StateAltSortComparator = new _IComparer_1928();
private static readonly IComparer<ATNConfig> StateAltSortComparator = new _IComparer_1996();
private BitSet IsConflicted(ATNConfigSet configset, PredictionContextCache contextCache)
private ConflictInfo IsConflicted(ATNConfigSet configset, PredictionContextCache contextCache)
{
if (configset.UniqueAlt != ATN.InvalidAltNumber || configset.Count <= 1)
{
@ -2029,7 +2129,7 @@ namespace Antlr4.Runtime.Atn
}
IList<ATNConfig> configs = new List<ATNConfig>(configset);
configs.Sort(StateAltSortComparator);
bool exact = !configset.DipsIntoOuterContext && predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection;
bool exact = !configset.DipsIntoOuterContext;
BitSet alts = new BitSet();
int minAlt = configs[0].Alt;
alts.Set(minAlt);
@ -2077,7 +2177,8 @@ namespace Antlr4.Runtime.Atn
{
if (currentAlt != maxAlt)
{
return null;
exact = false;
break;
}
currentState = stateNumber;
currentAlt = minAlt;
@ -2088,7 +2189,8 @@ namespace Antlr4.Runtime.Atn
{
if (alt != representedAlts.NextSetBit(currentAlt + 1))
{
return null;
exact = false;
break;
}
currentAlt = alt;
}
@ -2159,43 +2261,15 @@ namespace Antlr4.Runtime.Atn
joinedCheckContext2 = contextCache.Join(joinedCheckContext2, config2.Context);
}
i_1 = lastIndexCurrentStateCurrentAlt;
if (exact)
PredictionContext check = contextCache.Join(joinedCheckContext, joinedCheckContext2);
if (!joinedCheckContext.Equals(check))
{
if (!joinedCheckContext.Equals(joinedCheckContext2))
{
return null;
}
}
else
{
PredictionContext check = contextCache.Join(joinedCheckContext, joinedCheckContext2);
if (!joinedCheckContext.Equals(check))
{
return null;
}
}
if (!exact && optimize_hidden_conflicted_configs)
{
for (int j = firstIndexCurrentState; j_1 <= lastIndexCurrentStateMinAlt; j_1++)
{
ATNConfig checkConfig = configs[j_1];
if (checkConfig.SemanticContext != SemanticContext.None && !checkConfig.SemanticContext.Equals(config_1.SemanticContext))
{
continue;
}
if (joinedCheckContext != checkConfig.Context)
{
PredictionContext check = contextCache.Join(checkConfig.Context, config_1.Context);
if (!checkConfig.Context.Equals(check))
{
continue;
}
}
config_1.IsHidden = true;
}
return null;
}
// update exact if necessary
exact = exact && joinedCheckContext.Equals(joinedCheckContext2);
}
return alts;
return new ConflictInfo(alts, exact);
}
protected internal virtual BitSet GetConflictingAltsFromConfigSet(ATNConfigSet configs)
@ -2209,14 +2283,6 @@ namespace Antlr4.Runtime.Atn
return conflictingAlts;
}
protected internal virtual int ResolveToMinAlt(DFAState D, BitSet conflictingAlts)
{
// kill dead alts so we don't chase them ever
// killAlts(conflictingAlts, D.configset);
D.prediction = conflictingAlts.NextSetBit(0);
return D.prediction;
}
[NotNull]
public virtual string GetTokenName(int t)
{
@ -2224,20 +2290,13 @@ namespace Antlr4.Runtime.Atn
{
return "EOF";
}
if (parser != null && parser.TokenNames != null)
IVocabulary vocabulary = parser != null ? parser.Vocabulary : Vocabulary.EmptyVocabulary;
string displayName = vocabulary.GetDisplayName(t);
if (displayName.Equals(Antlr4.Runtime.Sharpen.Extensions.ToString(t)))
{
string[] tokensNames = parser.TokenNames;
if (t >= tokensNames.Length)
{
System.Console.Error.WriteLine(t + " ttype out of range: " + Arrays.ToString(tokensNames));
System.Console.Error.WriteLine(((CommonTokenStream)((ITokenStream)parser.InputStream)).GetTokens());
}
else
{
return tokensNames[t] + "<" + t + ">";
}
return displayName;
}
return t.ToString();
return displayName + "<" + t + ">";
}
public virtual string GetLookaheadName(ITokenStream input)
@ -2393,7 +2452,7 @@ namespace Antlr4.Runtime.Atn
{
configs.OptimizeConfigs(this);
}
DFAState proposed = CreateDFAState(configs);
DFAState proposed = CreateDFAState(dfa, configs);
DFAState existing = dfa.states.Get(proposed);
if (existing != null)
{
@ -2402,42 +2461,26 @@ namespace Antlr4.Runtime.Atn
}
if (!configs.IsReadOnly)
{
if (configs.ConflictingAlts == null)
if (configs.ConflictInformation == null)
{
configs.ConflictingAlts = IsConflicted(configs, contextCache);
if (optimize_hidden_conflicted_configs && configs.ConflictingAlts != null)
{
int size = configs.Count;
configs.StripHiddenConfigs();
if (enableDfa && configs.Count < size)
{
DFAState proposed = CreateDFAState(configs);
DFAState existing = dfa.states.Get(proposed);
if (existing != null)
{
return existing;
}
}
}
configs.ConflictInformation = IsConflicted(configs, contextCache);
}
}
DFAState newState = CreateDFAState(configs.Clone(true));
DFAState newState = CreateDFAState(dfa, configs.Clone(true));
DecisionState decisionState = atn.GetDecisionState(dfa.decision);
int predictedAlt = GetUniqueAlt(configs);
if (predictedAlt != ATN.InvalidAltNumber)
{
newState.isAcceptState = true;
newState.prediction = predictedAlt;
newState.AcceptStateInfo = new AcceptStateInfo(predictedAlt);
}
else
{
if (configs.ConflictingAlts != null)
{
newState.isAcceptState = true;
newState.prediction = ResolveToMinAlt(newState, newState.configs.ConflictingAlts);
newState.AcceptStateInfo = new AcceptStateInfo(newState.configs.ConflictingAlts.NextSetBit(0));
}
}
if (newState.isAcceptState && configs.HasSemanticContext)
if (newState.IsAcceptState && configs.HasSemanticContext)
{
PredicateDFAState(newState, configs, decisionState.NumberOfTransitions);
}
@ -2454,9 +2497,9 @@ namespace Antlr4.Runtime.Atn
}
[NotNull]
protected internal virtual DFAState CreateDFAState(ATNConfigSet configs)
protected internal virtual DFAState CreateDFAState(DFA dfa, ATNConfigSet configs)
{
return new DFAState(configs, -1, atn.maxTokenType);
return new DFAState(dfa, configs);
}
protected internal virtual void ReportAttemptingFullContext(DFA dfa, BitSet conflictingAlts, SimulatorState conflictState, int startIndex, int stopIndex)

View File

@ -91,7 +91,8 @@ namespace Antlr4.Runtime.Atn
{
this._input = input;
this._startIndex = input.Index;
this._sllStopIndex = -1;
// it's possible for SLL to reach a conflict state without consuming any input
this._sllStopIndex = _startIndex - 1;
this._llStopIndex = -1;
this.currentDecision = decision;
this.currentState = null;

View File

@ -376,7 +376,7 @@ namespace Antlr4.Runtime
/// <param name="e">the recognition exception</param>
protected internal virtual void ReportInputMismatch(Parser recognizer, InputMismatchException e)
{
string msg = "mismatched input " + GetTokenErrorDisplay(e.OffendingToken) + " expecting " + e.GetExpectedTokens().ToString(recognizer.TokenNames);
string msg = "mismatched input " + GetTokenErrorDisplay(e.OffendingToken) + " expecting " + e.GetExpectedTokens().ToString(recognizer.Vocabulary);
NotifyErrorListeners(recognizer, msg, e);
}
@ -434,7 +434,7 @@ namespace Antlr4.Runtime
IToken t = recognizer.CurrentToken;
string tokenName = GetTokenErrorDisplay(t);
IntervalSet expecting = GetExpectedTokens(recognizer);
string msg = "extraneous input " + tokenName + " expecting " + expecting.ToString(recognizer.TokenNames);
string msg = "extraneous input " + tokenName + " expecting " + expecting.ToString(recognizer.Vocabulary);
recognizer.NotifyErrorListeners(t, msg, null);
}
@ -472,7 +472,7 @@ namespace Antlr4.Runtime
BeginErrorCondition(recognizer);
IToken t = recognizer.CurrentToken;
IntervalSet expecting = GetExpectedTokens(recognizer);
string msg = "missing " + expecting.ToString(recognizer.TokenNames) + " at " + GetTokenErrorDisplay(t);
string msg = "missing " + expecting.ToString(recognizer.Vocabulary) + " at " + GetTokenErrorDisplay(t);
recognizer.NotifyErrorListeners(t, msg, null);
}
@ -713,7 +713,7 @@ namespace Antlr4.Runtime
}
else
{
tokenText = "<missing " + recognizer.TokenNames[expectedTokenType] + ">";
tokenText = "<missing " + recognizer.Vocabulary.GetDisplayName(expectedTokenType) + ">";
}
IToken current = currentSymbol;
IToken lookback = ((ITokenStream)recognizer.InputStream).Lt(-1);

View File

@ -0,0 +1,96 @@
/*
* [The "BSD license"]
* Copyright (c) 2013 Terence Parr
* Copyright (c) 2013 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa
{
/// <summary>
/// Stores information about a
/// <see cref="DFAState"/>
/// which is an accept state under
/// some condition. Certain settings, such as
/// <see cref="Antlr4.Runtime.Atn.ParserATNSimulator.PredictionMode()"/>
/// , may be used in addition to
/// this information to determine whether or not a particular state is an accept
/// state.
/// </summary>
/// <author>Sam Harwell</author>
public class AcceptStateInfo
{
private readonly int prediction;
private readonly Antlr4.Runtime.Atn.LexerActionExecutor lexerActionExecutor;
public AcceptStateInfo(int prediction)
{
this.prediction = prediction;
this.lexerActionExecutor = null;
}
public AcceptStateInfo(int prediction, Antlr4.Runtime.Atn.LexerActionExecutor lexerActionExecutor)
{
this.prediction = prediction;
this.lexerActionExecutor = lexerActionExecutor;
}
/// <summary>Gets the prediction made by this accept state.</summary>
/// <remarks>
/// Gets the prediction made by this accept state. Note that this value
/// assumes the predicates, if any, in the
/// <see cref="DFAState"/>
/// evaluate to
/// <see langword="true"/>
/// . If predicate evaluation is enabled, the final prediction of
/// the accept state will be determined by the result of predicate
/// evaluation.
/// </remarks>
public virtual int Prediction
{
get
{
return prediction;
}
}
/// <summary>
/// Gets the
/// <see cref="Antlr4.Runtime.Atn.LexerActionExecutor"/>
/// which can be used to execute actions
/// and/or commands after the lexer matches a token.
/// </summary>
public virtual Antlr4.Runtime.Atn.LexerActionExecutor LexerActionExecutor
{
get
{
return lexerActionExecutor;
}
}
}
}

View File

@ -34,24 +34,25 @@ using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa
{
/// <author>sam</author>
public class ArrayEdgeMap<T> : AbstractEdgeMap<T>
/// <author>Sam Harwell</author>
public sealed class ArrayEdgeMap<T> : AbstractEdgeMap<T>
{
private readonly T[] arrayData;
private readonly AtomicReferenceArray<T> arrayData;
private int size;
private readonly AtomicInteger size;
public ArrayEdgeMap(int minIndex, int maxIndex)
: base(minIndex, maxIndex)
{
arrayData = (T[])new object[maxIndex - minIndex + 1];
arrayData = new AtomicReferenceArray<T>(maxIndex - minIndex + 1);
size = new AtomicInteger();
}
public override int Count
{
get
{
return size;
return size.Get();
}
}
@ -59,7 +60,7 @@ namespace Antlr4.Runtime.Dfa
{
get
{
return size == 0;
return Count == 0;
}
}
@ -76,7 +77,7 @@ namespace Antlr4.Runtime.Dfa
{
return null;
}
return arrayData[key - minIndex];
return arrayData.Get(key - minIndex);
}
}
@ -84,17 +85,16 @@ namespace Antlr4.Runtime.Dfa
{
if (key >= minIndex && key <= maxIndex)
{
T existing = arrayData[key - minIndex];
arrayData[key - minIndex] = value;
T existing = arrayData.GetAndSet(key - minIndex, value);
if (existing == null && value != null)
{
size++;
size.IncrementAndGet();
}
else
{
if (existing != null && value == null)
{
size--;
size.DecrementAndGet();
}
}
}
@ -117,17 +117,12 @@ namespace Antlr4.Runtime.Dfa
Antlr4.Runtime.Dfa.ArrayEdgeMap<T> other = (Antlr4.Runtime.Dfa.ArrayEdgeMap<T>)m;
int minOverlap = Math.Max(minIndex, other.minIndex);
int maxOverlap = Math.Min(maxIndex, other.maxIndex);
Antlr4.Runtime.Dfa.ArrayEdgeMap<T> result = this;
for (int i = minOverlap; i <= maxOverlap; i++)
{
T target = other.arrayData[i - other.minIndex];
if (target != null)
{
T current = this.arrayData[i - this.minIndex];
this.arrayData[i - this.minIndex] = target;
size += (current != null ? 0 : 1);
}
result = ((Antlr4.Runtime.Dfa.ArrayEdgeMap<T>)result.Put(i, m[i]));
}
return this;
return result;
}
else
{
@ -142,14 +137,17 @@ namespace Antlr4.Runtime.Dfa
if (m is SparseEdgeMap<object>)
{
SparseEdgeMap<T> other = (SparseEdgeMap<T>)m;
int[] keys = other.Keys;
IList<T> values = other.Values;
Antlr4.Runtime.Dfa.ArrayEdgeMap<T> result = this;
for (int i = 0; i < values.Count; i++)
lock (other)
{
result = ((Antlr4.Runtime.Dfa.ArrayEdgeMap<T>)result.Put(keys[i], values[i]));
int[] keys = other.Keys;
IList<T> values = other.Values;
Antlr4.Runtime.Dfa.ArrayEdgeMap<T> result = this;
for (int i = 0; i < values.Count; i++)
{
result = ((Antlr4.Runtime.Dfa.ArrayEdgeMap<T>)result.Put(keys[i], values[i]));
}
return result;
}
return result;
}
else
{
@ -161,8 +159,7 @@ namespace Antlr4.Runtime.Dfa
public override AbstractEdgeMap<T> Clear()
{
Arrays.Fill(arrayData, null);
return this;
return new EmptyEdgeMap<T>(minIndex, maxIndex);
}
public override IDictionary<int, T> ToMap()
@ -172,13 +169,14 @@ namespace Antlr4.Runtime.Dfa
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
IDictionary<int, T> result = new LinkedHashMap<int, T>();
for (int i = 0; i < arrayData.Length; i++)
for (int i = 0; i < arrayData.Length(); i++)
{
if (arrayData[i] == null)
T element = arrayData.Get(i);
if (element == null)
{
continue;
}
result.Put(i + minIndex, arrayData[i]);
result.Put(i + minIndex, element);
}
return result;
}

View File

@ -29,6 +29,7 @@
*/
using System;
using System.Collections.Concurrent;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Dfa;
using Antlr4.Runtime.Misc;
@ -64,6 +65,19 @@ namespace Antlr4.Runtime.Dfa
private readonly AtomicInteger nextStateNumber = new AtomicInteger();
private readonly int minDfaEdge;
private readonly int maxDfaEdge;
[NotNull]
private static readonly Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState> emptyPrecedenceEdges = new Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState>(0, 200);
[NotNull]
private readonly Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState> emptyEdgeMap;
[NotNull]
private readonly Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState> emptyContextEdgeMap;
/// <summary>
/// <see langword="true"/>
/// if this DFA is for a precedence decision; otherwise,
@ -85,6 +99,50 @@ namespace Antlr4.Runtime.Dfa
{
this.atnStartState = atnStartState;
this.decision = decision;
if (this.atnStartState.atn.grammarType == ATNType.Lexer)
{
minDfaEdge = LexerATNSimulator.MinDfaEdge;
maxDfaEdge = LexerATNSimulator.MaxDfaEdge;
}
else
{
minDfaEdge = TokenConstants.Eof;
maxDfaEdge = atnStartState.atn.maxTokenType;
}
this.emptyEdgeMap = new Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState>(minDfaEdge, maxDfaEdge);
this.emptyContextEdgeMap = new Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState>(-1, atnStartState.atn.states.Count - 1);
}
public int MinDfaEdge
{
get
{
return minDfaEdge;
}
}
public int MaxDfaEdge
{
get
{
return maxDfaEdge;
}
}
public virtual Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState> EmptyEdgeMap
{
get
{
return emptyEdgeMap;
}
}
public virtual Antlr4.Runtime.Dfa.EmptyEdgeMap<DFAState> EmptyContextEdgeMap
{
get
{
return emptyContextEdgeMap;
}
}
/// <summary>Gets whether this DFA is a precedence DFA.</summary>
@ -161,12 +219,8 @@ namespace Antlr4.Runtime.Dfa
this.states.Clear();
if (precedenceDfa)
{
DFAState precedenceState = new DFAState(new ATNConfigSet(), 0, 200);
precedenceState.isAcceptState = false;
this.s0.Set(precedenceState);
DFAState fullContextPrecedenceState = new DFAState(new ATNConfigSet(), 0, 200);
fullContextPrecedenceState.isAcceptState = false;
this.s0full.Set(fullContextPrecedenceState);
this.s0.Set(new DFAState(emptyPrecedenceEdges, EmptyContextEdgeMap, new ATNConfigSet()));
this.s0full.Set(new DFAState(emptyPrecedenceEdges, EmptyContextEdgeMap, new ATNConfigSet()));
}
else
{
@ -277,9 +331,10 @@ namespace Antlr4.Runtime.Dfa
public override string ToString()
{
return ToString(null);
return ToString(Vocabulary.EmptyVocabulary);
}
[System.ObsoleteAttribute(@"Use ToString(Antlr4.Runtime.IVocabulary) instead.")]
public virtual string ToString(string[] tokenNames)
{
if (s0.Get() == null)
@ -290,6 +345,17 @@ namespace Antlr4.Runtime.Dfa
return serializer.ToString();
}
public virtual string ToString(IVocabulary vocabulary)
{
if (s0.Get() == null)
{
return string.Empty;
}
DFASerializer serializer = new DFASerializer(this, vocabulary);
return serializer.ToString();
}
[System.ObsoleteAttribute(@"Use ToString(Antlr4.Runtime.IVocabulary, string[]) instead.")]
public virtual string ToString(string[] tokenNames, string[] ruleNames)
{
if (s0.Get() == null)
@ -300,6 +366,16 @@ namespace Antlr4.Runtime.Dfa
return serializer.ToString();
}
public virtual string ToString(IVocabulary vocabulary, string[] ruleNames)
{
if (s0.Get() == null)
{
return string.Empty;
}
DFASerializer serializer = new DFASerializer(this, vocabulary, ruleNames, atnStartState.atn);
return serializer.ToString();
}
public virtual string ToLexerString()
{
if (s0.Get() == null)

View File

@ -27,6 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using Antlr4.Runtime;
@ -42,10 +43,10 @@ namespace Antlr4.Runtime.Dfa
public class DFASerializer
{
[NotNull]
internal readonly DFA dfa;
private readonly DFA dfa;
[Nullable]
internal readonly string[] tokenNames;
[NotNull]
private readonly IVocabulary vocabulary;
[Nullable]
internal readonly string[] ruleNames;
@ -53,20 +54,32 @@ namespace Antlr4.Runtime.Dfa
[Nullable]
internal readonly ATN atn;
[System.ObsoleteAttribute(@"Use DFASerializer(DFA, Antlr4.Runtime.IVocabulary) instead.")]
public DFASerializer(DFA dfa, string[] tokenNames)
: this(dfa, tokenNames, null, null)
: this(dfa, Vocabulary.FromTokenNames(tokenNames), null, null)
{
}
public DFASerializer(DFA dfa, IVocabulary vocabulary)
: this(dfa, vocabulary, null, null)
{
}
public DFASerializer(DFA dfa, Recognizer<object, object> parser)
: this(dfa, parser != null ? parser.TokenNames : null, parser != null ? parser.RuleNames : null, parser != null ? parser.Atn : null)
: this(dfa, parser != null ? parser.Vocabulary : Vocabulary.EmptyVocabulary, parser != null ? parser.RuleNames : null, parser != null ? parser.Atn : null)
{
}
[System.ObsoleteAttribute(@"Use DFASerializer(DFA, Antlr4.Runtime.IVocabulary, string[], Antlr4.Runtime.Atn.ATN) instead.")]
public DFASerializer(DFA dfa, string[] tokenNames, string[] ruleNames, ATN atn)
: this(dfa, Vocabulary.FromTokenNames(tokenNames), ruleNames, atn)
{
}
public DFASerializer(DFA dfa, IVocabulary vocabulary, string[] ruleNames, ATN atn)
{
this.dfa = dfa;
this.tokenNames = tokenNames;
this.vocabulary = vocabulary;
this.ruleNames = ruleNames;
this.atn = atn;
}
@ -81,7 +94,7 @@ namespace Antlr4.Runtime.Dfa
if (dfa.states != null)
{
IList<DFAState> states = new List<DFAState>(dfa.states.Values);
states.Sort(new _IComparer_85());
states.Sort(new _IComparer_103());
foreach (DFAState s in states)
{
IDictionary<int, DFAState> edges = s.EdgeMap;
@ -130,9 +143,9 @@ namespace Antlr4.Runtime.Dfa
return output;
}
private sealed class _IComparer_85 : IComparer<DFAState>
private sealed class _IComparer_103 : IComparer<DFAState>
{
public _IComparer_85()
public _IComparer_103()
{
}
@ -169,20 +182,7 @@ namespace Antlr4.Runtime.Dfa
protected internal virtual string GetEdgeLabel(int i)
{
string label;
if (i == -1)
{
return "EOF";
}
if (tokenNames != null)
{
label = tokenNames[i];
}
else
{
label = i.ToString();
}
return label;
return vocabulary.GetDisplayName(i);
}
internal virtual string GetStateString(DFAState s)
@ -193,7 +193,7 @@ namespace Antlr4.Runtime.Dfa
}
int n = s.stateNumber;
string stateStr = "s" + n;
if (s.isAcceptState)
if (s.IsAcceptState)
{
if (s.predicates != null)
{
@ -201,7 +201,7 @@ namespace Antlr4.Runtime.Dfa
}
else
{
stateStr = ":s" + n + "=>" + s.prediction;
stateStr = ":s" + n + "=>" + s.Prediction;
}
}
if (s.IsContextSensitive)

View File

@ -72,32 +72,15 @@ namespace Antlr4.Runtime.Dfa
/// <c>edges.get(symbol)</c>
/// points to target of symbol.
/// </summary>
[Nullable]
private AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> edges;
[NotNull]
private volatile AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> edges;
private readonly int minSymbol;
private readonly int maxSymbol;
public bool isAcceptState = false;
/// <summary>
/// if accept state, what ttype do we match or alt do we predict?
/// This is set to
/// <see cref="Antlr4.Runtime.Atn.ATN.InvalidAltNumber"/>
/// when
/// <see cref="predicates"/>
/// <c>!=null</c>
/// .
/// </summary>
public int prediction;
public LexerActionExecutor lexerActionExecutor;
private Antlr4.Runtime.Dfa.AcceptStateInfo acceptStateInfo;
/// <summary>These keys for these edges are the top level element of the global context.</summary>
/// <remarks>These keys for these edges are the top level element of the global context.</remarks>
[Nullable]
private AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> contextEdges;
[NotNull]
private volatile AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> contextEdges;
/// <summary>Symbols in this set require a global context transition before matching an input symbol.</summary>
/// <remarks>Symbols in this set require a global context transition before matching an input symbol.</remarks>
@ -134,86 +117,120 @@ namespace Antlr4.Runtime.Dfa
}
}
public DFAState(ATNConfigSet configs, int minSymbol, int maxSymbol)
public DFAState(DFA dfa, ATNConfigSet configs)
: this(dfa.EmptyEdgeMap, dfa.EmptyContextEdgeMap, configs)
{
}
public DFAState(EmptyEdgeMap<DFAState> emptyEdges, EmptyEdgeMap<DFAState> emptyContextEdges, ATNConfigSet configs)
{
this.configs = configs;
this.minSymbol = minSymbol;
this.maxSymbol = maxSymbol;
this.edges = emptyEdges;
this.contextEdges = emptyContextEdges;
}
public bool IsContextSensitive
{
get
{
return contextEdges != null;
return contextSymbols != null;
}
}
public bool IsContextSymbol(int symbol)
{
if (!IsContextSensitive || symbol < minSymbol)
if (!IsContextSensitive || symbol < edges.minIndex)
{
return false;
}
return contextSymbols.Get(symbol - minSymbol);
return contextSymbols.Get(symbol - edges.minIndex);
}
public void SetContextSymbol(int symbol)
{
System.Diagnostics.Debug.Assert(IsContextSensitive);
if (symbol < minSymbol)
if (symbol < edges.minIndex)
{
return;
}
contextSymbols.Set(symbol - minSymbol);
contextSymbols.Set(symbol - edges.minIndex);
}
public virtual void SetContextSensitive(ATN atn)
{
System.Diagnostics.Debug.Assert(!configs.IsOutermostConfigSet);
if (IsContextSensitive)
{
return;
}
lock (this)
{
System.Diagnostics.Debug.Assert(!configs.IsOutermostConfigSet);
if (IsContextSensitive)
if (contextSymbols == null)
{
return;
contextSymbols = new BitSet();
}
contextSymbols = new BitSet();
contextEdges = new SingletonEdgeMap<DFAState>(-1, atn.states.Count - 1);
}
}
public AcceptStateInfo AcceptStateInfo
{
get
{
return acceptStateInfo;
}
set
{
AcceptStateInfo acceptStateInfo = value;
this.acceptStateInfo = acceptStateInfo;
}
}
public bool IsAcceptState
{
get
{
return acceptStateInfo != null;
}
}
public int Prediction
{
get
{
if (acceptStateInfo == null)
{
return ATN.InvalidAltNumber;
}
return acceptStateInfo.Prediction;
}
}
public LexerActionExecutor LexerActionExecutor
{
get
{
if (acceptStateInfo == null)
{
return null;
}
return acceptStateInfo.LexerActionExecutor;
}
}
public virtual DFAState GetTarget(int symbol)
{
lock (this)
{
if (edges == null)
{
return null;
}
return edges[symbol];
}
return edges[symbol];
}
public virtual void SetTarget(int symbol, DFAState target)
{
lock (this)
{
if (edges == null)
{
edges = new SingletonEdgeMap<DFAState>(minSymbol, maxSymbol);
}
edges = edges.Put(symbol, target);
}
edges = edges.Put(symbol, target);
}
public virtual IDictionary<int, DFAState> EdgeMap
{
get
{
if (edges == null)
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
return edges.ToMap();
}
}
@ -222,10 +239,6 @@ namespace Antlr4.Runtime.Dfa
{
lock (this)
{
if (contextEdges == null)
{
return null;
}
if (invokingState == PredictionContext.EmptyFullStateKey)
{
invokingState = -1;
@ -238,7 +251,7 @@ namespace Antlr4.Runtime.Dfa
{
lock (this)
{
if (contextEdges == null)
if (!IsContextSensitive)
{
throw new InvalidOperationException("The state is not context sensitive.");
}
@ -254,10 +267,6 @@ namespace Antlr4.Runtime.Dfa
{
get
{
if (contextEdges == null)
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
IDictionary<int, DFAState> map = contextEdges.ToMap();
if (map.ContainsKey(-1))
{
@ -327,7 +336,7 @@ namespace Antlr4.Runtime.Dfa
{
StringBuilder buf = new StringBuilder();
buf.Append(stateNumber).Append(":").Append(configs);
if (isAcceptState)
if (IsAcceptState)
{
buf.Append("=>");
if (predicates != null)
@ -336,7 +345,7 @@ namespace Antlr4.Runtime.Dfa
}
else
{
buf.Append(prediction);
buf.Append(Prediction);
}
}
return buf.ToString();

View File

@ -0,0 +1,108 @@
/*
* [The "BSD license"]
* Copyright (c) 2013 Terence Parr
* Copyright (c) 2013 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Collections.Generic;
using Antlr4.Runtime.Dfa;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa
{
/// <summary>
/// This implementation of
/// <see cref="AbstractEdgeMap{T}"/>
/// represents an empty edge map.
/// </summary>
/// <author>Sam Harwell</author>
public sealed class EmptyEdgeMap<T> : AbstractEdgeMap<T>
{
public EmptyEdgeMap(int minIndex, int maxIndex)
: base(minIndex, maxIndex)
{
}
public override AbstractEdgeMap<T> Put(int key, T value)
{
if (value == null || key < minIndex || key > maxIndex)
{
// remains empty
return this;
}
return new SingletonEdgeMap<T>(minIndex, maxIndex, key, value);
}
public override AbstractEdgeMap<T> Clear()
{
return this;
}
public override AbstractEdgeMap<T> Remove(int key)
{
return this;
}
public override int Count
{
get
{
return 0;
}
}
public override bool IsEmpty
{
get
{
return true;
}
}
public override bool ContainsKey(int key)
{
return false;
}
public override T this[int key]
{
get
{
return null;
}
}
public override IDictionary<int, T> ToMap()
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
public override HashSet<KeyValuePair<int, T>> EntrySet()
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap<int, T>().EntrySet();
}
}
}

View File

@ -27,6 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Antlr4.Runtime;
using Antlr4.Runtime.Dfa;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
@ -36,7 +37,7 @@ namespace Antlr4.Runtime.Dfa
public class LexerDFASerializer : DFASerializer
{
public LexerDFASerializer(DFA dfa)
: base(dfa, (string[])null)
: base(dfa, Vocabulary.EmptyVocabulary)
{
}

View File

@ -34,19 +34,12 @@ using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa
{
/// <author>Sam Harwell</author>
public class SingletonEdgeMap<T> : AbstractEdgeMap<T>
public sealed class SingletonEdgeMap<T> : AbstractEdgeMap<T>
{
private readonly int key;
private readonly T value;
public SingletonEdgeMap(int minIndex, int maxIndex)
: base(minIndex, maxIndex)
{
this.key = 0;
this.value = null;
}
public SingletonEdgeMap(int minIndex, int maxIndex, int key, T value)
: base(minIndex, maxIndex)
{
@ -62,7 +55,7 @@ namespace Antlr4.Runtime.Dfa
}
}
public virtual int Key
public int Key
{
get
{
@ -70,7 +63,7 @@ namespace Antlr4.Runtime.Dfa
}
}
public virtual T Value
public T Value
{
get
{
@ -141,7 +134,7 @@ namespace Antlr4.Runtime.Dfa
{
if (key == this.key && this.value != null)
{
return new Antlr4.Runtime.Dfa.SingletonEdgeMap<T>(minIndex, maxIndex);
return new EmptyEdgeMap<T>(minIndex, maxIndex);
}
return this;
}
@ -150,7 +143,7 @@ namespace Antlr4.Runtime.Dfa
{
if (this.value != null)
{
return new Antlr4.Runtime.Dfa.SingletonEdgeMap<T>(minIndex, maxIndex);
return new EmptyEdgeMap<T>(minIndex, maxIndex);
}
return this;
}

View File

@ -35,7 +35,7 @@ using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa
{
/// <author>Sam Harwell</author>
public class SparseEdgeMap<T> : AbstractEdgeMap<T>
public sealed class SparseEdgeMap<T> : AbstractEdgeMap<T>
{
private const int DefaultMaxSize = 5;
@ -58,16 +58,19 @@ namespace Antlr4.Runtime.Dfa
private SparseEdgeMap(Antlr4.Runtime.Dfa.SparseEdgeMap<T> map, int maxSparseSize)
: base(map.minIndex, map.maxIndex)
{
if (maxSparseSize < map.values.Count)
lock (map)
{
throw new ArgumentException();
if (maxSparseSize < map.values.Count)
{
throw new ArgumentException();
}
keys = Arrays.CopyOf(map.keys, maxSparseSize);
values = new List<T>(maxSparseSize);
Sharpen.Collections.AddAll(values, map.values);
}
keys = Arrays.CopyOf(map.keys, maxSparseSize);
values = new List<T>(maxSparseSize);
Sharpen.Collections.AddAll(values, map.values);
}
public virtual int[] Keys
public int[] Keys
{
get
{
@ -75,7 +78,7 @@ namespace Antlr4.Runtime.Dfa
}
}
public virtual IList<T> Values
public IList<T> Values
{
get
{
@ -83,7 +86,7 @@ namespace Antlr4.Runtime.Dfa
}
}
public virtual int MaxSparseSize
public int MaxSparseSize
{
get
{
@ -116,6 +119,9 @@ namespace Antlr4.Runtime.Dfa
{
get
{
// Special property of this collection: values are only even added to
// the end, else a new object is returned from put(). Therefore no lock
// is required in this method.
int index = System.Array.BinarySearch(keys, 0, Count, key);
if (index < 0)
{
@ -135,7 +141,7 @@ namespace Antlr4.Runtime.Dfa
{
return ((Antlr4.Runtime.Dfa.SparseEdgeMap<T>)Remove(key));
}
lock (values)
lock (this)
{
int index = System.Array.BinarySearch(keys, 0, Count, key);
if (index >= 0)
@ -166,7 +172,7 @@ namespace Antlr4.Runtime.Dfa
else
{
Antlr4.Runtime.Dfa.SparseEdgeMap<T> resized = new Antlr4.Runtime.Dfa.SparseEdgeMap<T>(this, desiredSize);
System.Array.Copy(resized.keys, insertIndex, resized.keys, insertIndex + 1, resized.keys.Length - insertIndex - 1);
System.Array.Copy(resized.keys, insertIndex, resized.keys, insertIndex + 1, Count - insertIndex);
resized.keys[insertIndex] = key;
resized.values.Add(insertIndex, value);
return resized;
@ -176,20 +182,18 @@ namespace Antlr4.Runtime.Dfa
public override AbstractEdgeMap<T> Remove(int key)
{
int index = System.Array.BinarySearch(keys, 0, Count, key);
if (index < 0)
lock (this)
{
return this;
int index = System.Array.BinarySearch(keys, 0, Count, key);
if (index < 0)
{
return this;
}
Antlr4.Runtime.Dfa.SparseEdgeMap<T> result = new Antlr4.Runtime.Dfa.SparseEdgeMap<T>(this, MaxSparseSize);
System.Array.Copy(result.keys, index + 1, result.keys, index, Count - index - 1);
result.values.RemoveAt(index);
return result;
}
if (index == values.Count - 1)
{
values.RemoveAt(index);
return this;
}
Antlr4.Runtime.Dfa.SparseEdgeMap<T> result = new Antlr4.Runtime.Dfa.SparseEdgeMap<T>(this, MaxSparseSize);
System.Array.Copy(result.keys, index + 1, result.keys, index, Count - index - 1);
result.values.RemoveAt(index);
return result;
}
public override AbstractEdgeMap<T> Clear()
@ -198,9 +202,7 @@ namespace Antlr4.Runtime.Dfa
{
return this;
}
Antlr4.Runtime.Dfa.SparseEdgeMap<T> result = new Antlr4.Runtime.Dfa.SparseEdgeMap<T>(this, MaxSparseSize);
result.values.Clear();
return result;
return new EmptyEdgeMap<T>(minIndex, maxIndex);
}
public override IDictionary<int, T> ToMap()
@ -209,12 +211,15 @@ namespace Antlr4.Runtime.Dfa
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
IDictionary<int, T> result = new LinkedHashMap<int, T>();
for (int i = 0; i < Count; i++)
lock (this)
{
result.Put(keys[i], values[i]);
IDictionary<int, T> result = new LinkedHashMap<int, T>();
for (int i = 0; i < Count; i++)
{
result.Put(keys[i], values[i]);
}
return result;
}
return result;
}
}
}

View File

@ -182,5 +182,25 @@ namespace Antlr4.Runtime
/// by parser.
/// </remarks>
public const int HiddenChannel = 1;
/// <summary>
/// This is the minimum constant value which can be assigned to a
/// user-defined token channel.
/// </summary>
/// <remarks>
/// This is the minimum constant value which can be assigned to a
/// user-defined token channel.
/// <p>
/// The non-negative numbers less than
/// <see cref="MinUserChannelValue"/>
/// are
/// assigned to the predefined channels
/// <see cref="DefaultChannel"/>
/// and
/// <see cref="HiddenChannel"/>
/// .</p>
/// </remarks>
/// <seealso cref="Channel()"/>
public const int MinUserChannelValue = 2;
}
}

View File

@ -0,0 +1,198 @@
/*
* [The "BSD license"]
* Copyright (c) 2013 Terence Parr
* Copyright (c) 2013 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Antlr4.Runtime;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime
{
/// <summary>
/// This interface provides information about the vocabulary used by a
/// recognizer.
/// </summary>
/// <remarks>
/// This interface provides information about the vocabulary used by a
/// recognizer.
/// </remarks>
/// <seealso cref="Recognizer{Symbol, ATNInterpreter}.Vocabulary()"/>
/// <author>Sam Harwell</author>
public interface IVocabulary
{
/// <summary>Gets the string literal associated with a token type.</summary>
/// <remarks>
/// Gets the string literal associated with a token type. The string returned
/// by this method, when not
/// <see langword="null"/>
/// , can be used unaltered in a parser
/// grammar to represent this token type.
/// <p>The following table shows examples of lexer rules and the literal
/// names assigned to the corresponding token types.</p>
/// <table>
/// <tr>
/// <th>Rule</th>
/// <th>Literal Name</th>
/// <th>Java String Literal</th>
/// </tr>
/// <tr>
/// <td>
/// <c>THIS : 'this';</c>
/// </td>
/// <td>
/// <c>'this'</c>
/// </td>
/// <td>
/// <c>"'this'"</c>
/// </td>
/// </tr>
/// <tr>
/// <td>
/// <c>SQUOTE : '\'';</c>
/// </td>
/// <td>
/// <c>'\''</c>
/// </td>
/// <td>
/// <c>"'\\''"</c>
/// </td>
/// </tr>
/// <tr>
/// <td>
/// <c>ID : [A-Z]+;</c>
/// </td>
/// <td>n/a</td>
/// <td>
/// <see langword="null"/>
/// </td>
/// </tr>
/// </table>
/// </remarks>
/// <param name="tokenType">The token type.</param>
/// <returns>
/// The string literal associated with the specified token type, or
/// <see langword="null"/>
/// if no string literal is associated with the type.
/// </returns>
[Nullable]
string GetLiteralName(int tokenType);
/// <summary>Gets the symbolic name associated with a token type.</summary>
/// <remarks>
/// Gets the symbolic name associated with a token type. The string returned
/// by this method, when not
/// <see langword="null"/>
/// , can be used unaltered in a parser
/// grammar to represent this token type.
/// <p>This method supports token types defined by any of the following
/// methods:</p>
/// <ul>
/// <li>Tokens created by lexer rules.</li>
/// <li>Tokens defined in a
/// <c/>
/// tokens
/// block in a lexer or parser
/// grammar.</li>
/// <li>The implicitly defined
/// <c>EOF</c>
/// token, which has the token type
/// <see cref="IToken.Eof"/>
/// .</li>
/// </ul>
/// <p>The following table shows examples of lexer rules and the literal
/// names assigned to the corresponding token types.</p>
/// <table>
/// <tr>
/// <th>Rule</th>
/// <th>Symbolic Name</th>
/// </tr>
/// <tr>
/// <td>
/// <c>THIS : 'this';</c>
/// </td>
/// <td>
/// <c>THIS</c>
/// </td>
/// </tr>
/// <tr>
/// <td>
/// <c>SQUOTE : '\'';</c>
/// </td>
/// <td>
/// <c>SQUOTE</c>
/// </td>
/// </tr>
/// <tr>
/// <td>
/// <c>ID : [A-Z]+;</c>
/// </td>
/// <td>
/// <c>ID</c>
/// </td>
/// </tr>
/// </table>
/// </remarks>
/// <param name="tokenType">The token type.</param>
/// <returns>
/// The symbolic name associated with the specified token type, or
/// <see langword="null"/>
/// if no symbolic name is associated with the type.
/// </returns>
[Nullable]
string GetSymbolicName(int tokenType);
/// <summary>Gets the display name of a token type.</summary>
/// <remarks>
/// Gets the display name of a token type.
/// <p>ANTLR provides a default implementation of this method, but
/// applications are free to override the behavior in any manner which makes
/// sense for the application. The default implementation returns the first
/// result from the following list which produces a non-
/// <see langword="null"/>
/// result.</p>
/// <ol>
/// <li>The result of
/// <see cref="GetLiteralName(int)"/>
/// </li>
/// <li>The result of
/// <see cref="GetSymbolicName(int)"/>
/// </li>
/// <li>The result of
/// <see cref="int.ToString()"/>
/// </li>
/// </ol>
/// </remarks>
/// <param name="tokenType">The token type.</param>
/// <returns>
/// The display name of the token type, for use in error reporting or
/// other user-visible messages which reference specific token types.
/// </returns>
[NotNull]
string GetDisplayName(int tokenType);
}
}

View File

@ -31,6 +31,7 @@ using System;
using System.Collections.Generic;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime
@ -41,13 +42,23 @@ namespace Antlr4.Runtime
protected internal readonly ATN atn;
[Obsolete]
protected internal readonly string[] tokenNames;
protected internal readonly string[] ruleNames;
protected internal readonly string[] modeNames;
[NotNull]
private readonly IVocabulary vocabulary;
[Obsolete]
public LexerInterpreter(string grammarFileName, ICollection<string> tokenNames, ICollection<string> ruleNames, ICollection<string> modeNames, ATN atn, ICharStream input)
: this(grammarFileName, Antlr4.Runtime.Vocabulary.FromTokenNames(Sharpen.Collections.ToArray(tokenNames, new string[tokenNames.Count])), ruleNames, modeNames, atn, input)
{
}
public LexerInterpreter(string grammarFileName, IVocabulary vocabulary, ICollection<string> ruleNames, ICollection<string> modeNames, ATN atn, ICharStream input)
: base(input)
{
if (atn.grammarType != ATNType.Lexer)
@ -56,9 +67,14 @@ namespace Antlr4.Runtime
}
this.grammarFileName = grammarFileName;
this.atn = atn;
this.tokenNames = Sharpen.Collections.ToArray(tokenNames, new string[tokenNames.Count]);
this.tokenNames = new string[atn.maxTokenType];
for (int i = 0; i < tokenNames.Length; i++)
{
tokenNames[i] = vocabulary.GetDisplayName(i);
}
this.ruleNames = Sharpen.Collections.ToArray(ruleNames, new string[ruleNames.Count]);
this.modeNames = Sharpen.Collections.ToArray(modeNames, new string[modeNames.Count]);
this.vocabulary = vocabulary;
this._interp = new LexerATNSimulator(this, atn);
}
@ -101,5 +117,17 @@ namespace Antlr4.Runtime
return modeNames;
}
}
public override IVocabulary Vocabulary
{
get
{
if (vocabulary != null)
{
return vocabulary;
}
return base.Vocabulary;
}
}
}
}

View File

@ -703,7 +703,13 @@ namespace Antlr4.Runtime.Misc
return buf.ToString();
}
[System.ObsoleteAttribute(@"Use ToString(Antlr4.Runtime.IVocabulary) instead.")]
public virtual string ToString(string[] tokenNames)
{
return ToString(Vocabulary.FromTokenNames(tokenNames));
}
public virtual string ToString(IVocabulary vocabulary)
{
StringBuilder buf = new StringBuilder();
if (this.intervals == null || this.intervals.IsEmpty())
@ -722,7 +728,7 @@ namespace Antlr4.Runtime.Misc
int b = I.b;
if (a == b)
{
buf.Append(ElementName(tokenNames, a));
buf.Append(ElementName(vocabulary, a));
}
else
{
@ -732,7 +738,7 @@ namespace Antlr4.Runtime.Misc
{
buf.Append(", ");
}
buf.Append(ElementName(tokenNames, i));
buf.Append(ElementName(vocabulary, i));
}
}
if (iter.HasNext())
@ -747,7 +753,14 @@ namespace Antlr4.Runtime.Misc
return buf.ToString();
}
[System.ObsoleteAttribute(@"Use ElementName(Antlr4.Runtime.IVocabulary, int) instead.")]
protected internal virtual string ElementName(string[] tokenNames, int a)
{
return ElementName(Vocabulary.FromTokenNames(tokenNames), a);
}
[NotNull]
protected internal virtual string ElementName(IVocabulary vocabulary, int a)
{
if (a == TokenConstants.Eof)
{
@ -761,7 +774,7 @@ namespace Antlr4.Runtime.Misc
}
else
{
return tokenNames[a];
return vocabulary.GetDisplayName(a);
}
}
}

View File

@ -36,6 +36,7 @@ using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
using Antlr4.Runtime.Sharpen.Annotation;
using Javax.Annotation.Processing;
using Javax.Lang.Model;
using Javax.Lang.Model.Element;
using Javax.Lang.Model.Type;
using Javax.Tools;
@ -59,6 +60,27 @@ namespace Antlr4.Runtime.Misc
{
}
public override SourceVersion GetSupportedSourceVersion()
{
SourceVersion latestSupported = SourceVersion.LatestSupported();
if ((int)(latestSupported) <= 6)
{
return SourceVersion.Release6;
}
else
{
if ((int)(latestSupported) <= 8)
{
return latestSupported;
}
else
{
// this annotation processor is tested through Java 8
return SourceVersion.Values()[8];
}
}
}
public override bool Process<_T0>(HashSet<_T0> annotations, IRoundEnvironment roundEnv)
{
if (!CheckClassNameConstants())

View File

@ -1134,7 +1134,7 @@ namespace Antlr4.Runtime
for (int d = 0; d < _interp.atn.decisionToDFA.Length; d++)
{
DFA dfa = _interp.atn.decisionToDFA[d];
s.Add(dfa.ToString(TokenNames, RuleNames));
s.Add(dfa.ToString(Vocabulary, RuleNames));
}
return s;
}
@ -1154,7 +1154,7 @@ namespace Antlr4.Runtime
System.Console.Out.WriteLine();
}
System.Console.Out.WriteLine("Decision " + dfa.decision + ":");
System.Console.Out.Write(dfa.ToString(TokenNames, RuleNames));
System.Console.Out.Write(dfa.ToString(Vocabulary, RuleNames));
seenOne = true;
}
}

View File

@ -31,6 +31,7 @@ using System;
using System.Collections.Generic;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime
@ -58,19 +59,34 @@ namespace Antlr4.Runtime
protected internal readonly BitSet pushRecursionContextStates;
[Obsolete]
protected internal readonly string[] tokenNames;
protected internal readonly string[] ruleNames;
[NotNull]
private readonly IVocabulary vocabulary;
protected internal readonly Stack<Tuple<ParserRuleContext, int>> _parentContextStack = new Stack<Tuple<ParserRuleContext, int>>();
[System.ObsoleteAttribute(@"Use ParserInterpreter(string, IVocabulary, System.Collections.Generic.ICollection{E}, Antlr4.Runtime.Atn.ATN, ITokenStream) instead.")]
public ParserInterpreter(string grammarFileName, ICollection<string> tokenNames, ICollection<string> ruleNames, ATN atn, ITokenStream input)
: this(grammarFileName, Antlr4.Runtime.Vocabulary.FromTokenNames(Sharpen.Collections.ToArray(tokenNames, new string[tokenNames.Count])), ruleNames, atn, input)
{
}
public ParserInterpreter(string grammarFileName, IVocabulary vocabulary, ICollection<string> ruleNames, ATN atn, ITokenStream input)
: base(input)
{
this.grammarFileName = grammarFileName;
this.atn = atn;
this.tokenNames = Sharpen.Collections.ToArray(tokenNames, new string[tokenNames.Count]);
this.tokenNames = new string[atn.maxTokenType];
for (int i = 0; i < tokenNames.Length; i++)
{
tokenNames[i] = vocabulary.GetDisplayName(i);
}
this.ruleNames = Sharpen.Collections.ToArray(ruleNames, new string[ruleNames.Count]);
this.vocabulary = vocabulary;
// identify the ATN states where pushNewRecursionContext must be called
this.pushRecursionContextStates = new BitSet(atn.states.Count);
foreach (ATNState state in atn.states)
@ -104,6 +120,14 @@ namespace Antlr4.Runtime
}
}
public override IVocabulary Vocabulary
{
get
{
return vocabulary;
}
}
public override string[] RuleNames
{
get

View File

@ -41,13 +41,13 @@ namespace Antlr4.Runtime
{
public const int Eof = -1;
private static readonly IDictionary<string[], IDictionary<string, int>> tokenTypeMapCache = new WeakHashMap<string[], IDictionary<string, int>>();
private static readonly IDictionary<IVocabulary, IDictionary<string, int>> tokenTypeMapCache = new WeakHashMap<IVocabulary, IDictionary<string, int>>();
private static readonly IDictionary<string[], IDictionary<string, int>> ruleIndexMapCache = new WeakHashMap<string[], IDictionary<string, int>>();
private sealed class _CopyOnWriteArrayList_59 : CopyOnWriteArrayList<IAntlrErrorListener<Symbol>>
private sealed class _CopyOnWriteArrayList_60 : CopyOnWriteArrayList<IAntlrErrorListener<Symbol>>
{
public _CopyOnWriteArrayList_59()
public _CopyOnWriteArrayList_60()
{
{
this.Add(ConsoleErrorListener.Instance);
@ -56,7 +56,7 @@ namespace Antlr4.Runtime
}
[NotNull]
private IList<IAntlrErrorListener<Symbol>> _listeners = new _CopyOnWriteArrayList_59();
private IList<IAntlrErrorListener<Symbol>> _listeners = new _CopyOnWriteArrayList_60();
protected internal ATNInterpreter _interp;
@ -71,6 +71,7 @@ namespace Antlr4.Runtime
/// error reporting. The generated parsers implement a method
/// that overrides this to point to their String[] tokenNames.
/// </remarks>
[System.ObsoleteAttribute(@"Use Recognizer{Symbol, ATNInterpreter}.Vocabulary() instead.")]
public abstract string[] TokenNames
{
get;
@ -81,6 +82,22 @@ namespace Antlr4.Runtime
get;
}
/// <summary>Get the vocabulary used by the recognizer.</summary>
/// <remarks>Get the vocabulary used by the recognizer.</remarks>
/// <returns>
/// A
/// <see cref="IVocabulary"/>
/// instance providing information about the
/// vocabulary used by the grammar.
/// </returns>
public virtual IVocabulary Vocabulary
{
get
{
return Antlr4.Runtime.Vocabulary.FromTokenNames(TokenNames);
}
}
/// <summary>Get a map from token names to token types.</summary>
/// <remarks>
/// Get a map from token names to token types.
@ -90,20 +107,29 @@ namespace Antlr4.Runtime
{
get
{
string[] tokenNames = TokenNames;
if (tokenNames == null)
{
throw new NotSupportedException("The current recognizer does not provide a list of token names.");
}
IVocabulary vocabulary = Vocabulary;
lock (tokenTypeMapCache)
{
IDictionary<string, int> result = tokenTypeMapCache.Get(tokenNames);
IDictionary<string, int> result = tokenTypeMapCache.Get(vocabulary);
if (result == null)
{
result = Utils.ToMap(tokenNames);
result = new Dictionary<string, int>();
for (int i = 0; i < Atn.maxTokenType; i++)
{
string literalName = vocabulary.GetLiteralName(i);
if (literalName != null)
{
result.Put(literalName, i);
}
string symbolicName = vocabulary.GetSymbolicName(i);
if (symbolicName != null)
{
result.Put(symbolicName, i);
}
}
result.Put("EOF", TokenConstants.Eof);
result = Antlr4.Runtime.Sharpen.Collections.UnmodifiableMap(result);
tokenTypeMapCache.Put(tokenNames, result);
tokenTypeMapCache.Put(vocabulary, result);
}
return result;
}

View File

@ -274,7 +274,7 @@ namespace Antlr4.Runtime
/// <remarks>
/// Rollback the instruction stream for a program so that
/// the indicated instruction (via instructionIndex) is no
/// longer in the stream. UNTESTED!
/// longer in the stream. UNTESTED!
/// </remarks>
public virtual void Rollback(string programName, int instructionIndex)
{
@ -549,8 +549,8 @@ namespace Antlr4.Runtime
/// </summary>
/// <remarks>
/// We need to combine operations and report invalid operations (like
/// overlapping replaces that are not completed nested). Inserts to
/// same index need to be combined etc... Here are the cases:
/// overlapping replaces that are not completed nested). Inserts to
/// same index need to be combined etc... Here are the cases:
/// I.i.u I.j.v leave alone, nonoverlapping
/// I.i.u I.i.v combine: Iivu
/// R.i-j.u R.x-y.v | i-j in x-y delete first R
@ -567,7 +567,7 @@ namespace Antlr4.Runtime
/// R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping
/// I.i.u = insert u before op @ index i
/// R.x-y.u = replace x-y indexed tokens with u
/// First we need to examine replaces. For any replace op:
/// First we need to examine replaces. For any replace op:
/// 1. wipe out any insertions before op within that range.
/// 2. Drop any replace op before that is contained completely within
/// that range.
@ -580,7 +580,7 @@ namespace Antlr4.Runtime
/// Don't actually delete; make op null in list. Easier to walk list.
/// Later we can throw as we add to index &rarr; op map.
/// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
/// inserted stuff would be before the replace range. But, if you
/// inserted stuff would be before the replace range. But, if you
/// add tokens in front of a method body '{' and then delete the method
/// body, I think the stuff before the '{' you added should disappear too.
/// Return a map from token index to operation.

View File

@ -326,7 +326,7 @@ namespace Antlr4.Runtime.Tree.Pattern
IList<IToken> tokenList = Tokenize(pattern);
ListTokenSource tokenSrc = new ListTokenSource(tokenList);
CommonTokenStream tokens = new CommonTokenStream(tokenSrc);
ParserInterpreter parserInterp = new ParserInterpreter(parser.GrammarFileName, Arrays.AsList(parser.TokenNames), Arrays.AsList(parser.RuleNames), parser.GetATNWithBypassAlts(), tokens);
ParserInterpreter parserInterp = new ParserInterpreter(parser.GrammarFileName, parser.Vocabulary, Arrays.AsList(parser.RuleNames), parser.GetATNWithBypassAlts(), tokens);
IParseTree tree = null;
try
{

View File

@ -411,6 +411,10 @@ namespace Antlr4.Runtime
{
get
{
if (name == null || name.IsEmpty())
{
return IntStreamConstants.UnknownSourceName;
}
return name;
}
}

View File

@ -0,0 +1,250 @@
/*
* [The "BSD license"]
* Copyright (c) 2013 Terence Parr
* Copyright (c) 2013 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Antlr4.Runtime;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime
{
/// <summary>
/// This class provides a default implementation of the
/// <see cref="IVocabulary"/>
/// interface.
/// </summary>
/// <author>Sam Harwell</author>
public class Vocabulary : IVocabulary
{
private static readonly string[] EmptyNames = new string[0];
/// <summary>
/// Gets an empty
/// <see cref="IVocabulary"/>
/// instance.
/// <p>
/// No literal or symbol names are assigned to token types, so
/// <see cref="GetDisplayName(int)"/>
/// returns the numeric value for all tokens
/// except
/// <see cref="IToken.Eof"/>
/// .</p>
/// </summary>
[NotNull]
public static readonly Vocabulary EmptyVocabulary = new Vocabulary(EmptyNames, EmptyNames, EmptyNames);
[NotNull]
private readonly string[] literalNames;
[NotNull]
private readonly string[] symbolicNames;
[NotNull]
private readonly string[] displayNames;
/// <summary>
/// Constructs a new instance of
/// <see cref="Vocabulary"/>
/// from the specified
/// literal and symbolic token names.
/// </summary>
/// <param name="literalNames">
/// The literal names assigned to tokens, or
/// <see langword="null"/>
/// if no literal names are assigned.
/// </param>
/// <param name="symbolicNames">
/// The symbolic names assigned to tokens, or
/// <see langword="null"/>
/// if no symbolic names are assigned.
/// </param>
/// <seealso cref="GetLiteralName(int)"/>
/// <seealso cref="GetSymbolicName(int)"/>
public Vocabulary(string[] literalNames, string[] symbolicNames)
: this(literalNames, symbolicNames, null)
{
}
/// <summary>
/// Constructs a new instance of
/// <see cref="Vocabulary"/>
/// from the specified
/// literal, symbolic, and display token names.
/// </summary>
/// <param name="literalNames">
/// The literal names assigned to tokens, or
/// <see langword="null"/>
/// if no literal names are assigned.
/// </param>
/// <param name="symbolicNames">
/// The symbolic names assigned to tokens, or
/// <see langword="null"/>
/// if no symbolic names are assigned.
/// </param>
/// <param name="displayNames">
/// The display names assigned to tokens, or
/// <see langword="null"/>
/// to use the values in
/// <paramref name="literalNames"/>
/// and
/// <paramref name="symbolicNames"/>
/// as
/// the source of display names, as described in
/// <see cref="GetDisplayName(int)"/>
/// .
/// </param>
/// <seealso cref="GetLiteralName(int)"/>
/// <seealso cref="GetSymbolicName(int)"/>
/// <seealso cref="GetDisplayName(int)"/>
public Vocabulary(string[] literalNames, string[] symbolicNames, string[] displayNames)
{
this.literalNames = literalNames != null ? literalNames : EmptyNames;
this.symbolicNames = symbolicNames != null ? symbolicNames : EmptyNames;
this.displayNames = displayNames != null ? displayNames : EmptyNames;
}
/// <summary>
/// Returns a
/// <see cref="Vocabulary"/>
/// instance from the specified set of token
/// names. This method acts as a compatibility layer for the single
/// <paramref name="tokenNames"/>
/// array generated by previous releases of ANTLR.
/// <p>The resulting vocabulary instance returns
/// <see langword="null"/>
/// for
/// <see cref="GetLiteralName(int)"/>
/// and
/// <see cref="GetSymbolicName(int)"/>
/// , and the
/// value from
/// <paramref name="tokenNames"/>
/// for the display names.</p>
/// </summary>
/// <param name="tokenNames">
/// The token names, or
/// <see langword="null"/>
/// if no token names are
/// available.
/// </param>
/// <returns>
/// A
/// <see cref="IVocabulary"/>
/// instance which uses
/// <paramref name="tokenNames"/>
/// for
/// the display names of tokens.
/// </returns>
public static IVocabulary FromTokenNames(string[] tokenNames)
{
if (tokenNames == null || tokenNames.Length == 0)
{
return EmptyVocabulary;
}
string[] literalNames = Arrays.CopyOf(tokenNames, tokenNames.Length);
string[] symbolicNames = Arrays.CopyOf(tokenNames, tokenNames.Length);
for (int i = 0; i < tokenNames.Length; i++)
{
string tokenName = tokenNames[i];
if (tokenName == null)
{
continue;
}
if (!tokenName.IsEmpty())
{
char firstChar = tokenName[0];
if (firstChar == '\'')
{
symbolicNames[i] = null;
continue;
}
else
{
if (System.Char.IsUpper(firstChar))
{
literalNames[i] = null;
continue;
}
}
}
// wasn't a literal or symbolic name
literalNames[i] = null;
symbolicNames[i] = null;
}
return new Vocabulary(literalNames, symbolicNames, tokenNames);
}
[Nullable]
public virtual string GetLiteralName(int tokenType)
{
if (tokenType >= 0 && tokenType < literalNames.Length)
{
return literalNames[tokenType];
}
return null;
}
[Nullable]
public virtual string GetSymbolicName(int tokenType)
{
if (tokenType >= 0 && tokenType < symbolicNames.Length)
{
return symbolicNames[tokenType];
}
if (tokenType == TokenConstants.Eof)
{
return "EOF";
}
return null;
}
[NotNull]
public virtual string GetDisplayName(int tokenType)
{
if (tokenType >= 0 && tokenType < displayNames.Length)
{
string displayName = displayNames[tokenType];
if (displayName != null)
{
return displayName;
}
}
string literalName = GetLiteralName(tokenType);
if (literalName != null)
{
return literalName;
}
string symbolicName = GetSymbolicName(tokenType);
if (symbolicName != null)
{
return symbolicName;
}
return Antlr4.Runtime.Sharpen.Extensions.ToString(tokenType);
}
}
}