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 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.IO; using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen; using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime namespace Antlr4.Runtime
@ -58,35 +58,8 @@ namespace Antlr4.Runtime
/// <exception cref="System.IO.IOException"/> /// <exception cref="System.IO.IOException"/>
public virtual void Load(string fileName, string encoding) public virtual void Load(string fileName, string encoding)
{ {
if (fileName == null) data = Utils.ReadFile(fileName, encoding);
{ this.n = data.Length;
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();
}
} }
public override string SourceName public override string SourceName

View File

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

View File

@ -48,10 +48,29 @@ namespace Antlr4.Runtime.Atn
/// </remarks> /// </remarks>
public class ATNConfig 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> /// <summary>The ATN state associated with this configuration</summary>
[NotNull] [NotNull]
private readonly ATNState state; 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; private int altAndOuterContextDepth;
/// <summary> /// <summary>
@ -70,14 +89,14 @@ namespace Antlr4.Runtime.Atn
{ {
System.Diagnostics.Debug.Assert((alt & unchecked((int)(0xFFFFFF))) == alt); System.Diagnostics.Debug.Assert((alt & unchecked((int)(0xFFFFFF))) == alt);
this.state = state; this.state = state;
this.altAndOuterContextDepth = alt & unchecked((int)(0x7FFFFFFF)); this.altAndOuterContextDepth = alt;
this.context = context; this.context = context;
} }
protected internal ATNConfig(Antlr4.Runtime.Atn.ATNConfig c, ATNState state, PredictionContext context) protected internal ATNConfig(Antlr4.Runtime.Atn.ATNConfig c, ATNState state, PredictionContext context)
{ {
this.state = state; this.state = state;
this.altAndOuterContextDepth = c.altAndOuterContextDepth & unchecked((int)(0x7FFFFFFF)); this.altAndOuterContextDepth = c.altAndOuterContextDepth;
this.context = context; 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 public virtual PredictionContext Context
{ {
get get
@ -187,9 +187,10 @@ namespace Antlr4.Runtime.Atn
/// no way to do this efficiently, we simply cannot evaluate /// no way to do this efficiently, we simply cannot evaluate
/// dependent predicates unless we are in the rule that initially /// dependent predicates unless we are in the rule that initially
/// invokes the ATN simulator. /// invokes the ATN simulator.
/// closure() tracks the depth of how far we dip into the /// <p>
/// outer context: depth &gt; 0. Note that it may not be totally /// closure() tracks the depth of how far we dip into the outer context:
/// accurate depth since I don't ever decrement. TODO: make it a boolean then /// 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> /// </remarks>
public virtual int OuterContextDepth public virtual int OuterContextDepth
{ {
@ -346,6 +347,25 @@ namespace Antlr4.Runtime.Atn
return false; return false;
} }
public bool PrecedenceFilterSuppressed
{
get
{
return (altAndOuterContextDepth & SuppressPrecedenceFilter) != 0;
}
set
{
if (value)
{
this.altAndOuterContextDepth |= SuppressPrecedenceFilter;
}
else
{
this.altAndOuterContextDepth &= ~SuppressPrecedenceFilter;
}
}
}
/// <summary> /// <summary>
/// An ATN configuration is equal to another if both have /// An ATN configuration is equal to another if both have
/// the same state, they predict the same alternative, and /// the same state, they predict the same alternative, and
@ -378,7 +398,7 @@ namespace Antlr4.Runtime.Atn
return false; 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() public override int GetHashCode()

View File

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

View File

@ -354,7 +354,16 @@ namespace Antlr4.Runtime.Atn
{ {
continue; 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) foreach (ATNState state_2 in atn.states)
@ -847,7 +856,7 @@ namespace Antlr4.Runtime.Atn
{ {
Transition transition = state.GetOptimizedTransition(i); Transition transition = state.GetOptimizedTransition(i);
ATNState intermediate = transition.target; 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) if (optimizedTransitions != null)
{ {
@ -857,7 +866,7 @@ namespace Antlr4.Runtime.Atn
} }
for (int j = 0; j < intermediate.NumberOfOptimizedTransitions; j++) 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) if (optimizedTransitions != null)
{ {

View File

@ -71,7 +71,7 @@ namespace Antlr4.Runtime.Atn
static ATNSimulator() 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; 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 public sealed class EpsilonTransition : Transition
{ {
private readonly int outermostPrecedenceReturn;
public EpsilonTransition(ATNState target) public EpsilonTransition(ATNState target)
: this(target, -1)
{
}
public EpsilonTransition(ATNState target, int outermostPrecedenceReturn)
: base(target) : 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 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) protected internal virtual int ExecATN(ICharStream input, DFAState ds0)
{ {
//System.out.println("enter exec index "+input.index()+" from "+ds0.configs); //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); int t = input.La(1);
DFAState s = ds0; DFAState s = ds0;
// s is current/from DFA state // s is current/from DFA state
@ -222,7 +229,7 @@ namespace Antlr4.Runtime.Atn
{ {
break; break;
} }
if (target.isAcceptState) if (target.IsAcceptState)
{ {
CaptureSimState(prevAccept, input, target); CaptureSimState(prevAccept, input, target);
if (t == IntStreamConstants.Eof) if (t == IntStreamConstants.Eof)
@ -318,9 +325,9 @@ namespace Antlr4.Runtime.Atn
{ {
if (prevAccept.dfaState != null) if (prevAccept.dfaState != null)
{ {
LexerActionExecutor lexerActionExecutor = prevAccept.dfaState.lexerActionExecutor; LexerActionExecutor lexerActionExecutor = prevAccept.dfaState.LexerActionExecutor;
Accept(input, lexerActionExecutor, startIndex, prevAccept.index, prevAccept.line, prevAccept.charPos); Accept(input, lexerActionExecutor, startIndex, prevAccept.index, prevAccept.line, prevAccept.charPos);
return prevAccept.dfaState.prediction; return prevAccept.dfaState.Prediction;
} }
else else
{ {
@ -719,14 +726,14 @@ namespace Antlr4.Runtime.Atn
protected internal virtual DFAState AddDFAState(ATNConfigSet configs) protected internal virtual DFAState AddDFAState(ATNConfigSet configs)
{ {
System.Diagnostics.Debug.Assert(!configs.HasSemanticContext); 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); DFAState existing = atn.modeToDFA[mode].states.Get(proposed);
if (existing != null) if (existing != null)
{ {
return existing; return existing;
} }
configs.OptimizeConfigs(this); 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; ATNConfig firstConfigWithRuleStopState = null;
foreach (ATNConfig c in configs) foreach (ATNConfig c in configs)
{ {
@ -738,9 +745,9 @@ namespace Antlr4.Runtime.Atn
} }
if (firstConfigWithRuleStopState != null) if (firstConfigWithRuleStopState != null)
{ {
newState.isAcceptState = true; int prediction = atn.ruleToTokenType[firstConfigWithRuleStopState.State.ruleIndex];
newState.lexerActionExecutor = firstConfigWithRuleStopState.ActionExecutor; LexerActionExecutor lexerActionExecutor = firstConfigWithRuleStopState.ActionExecutor;
newState.prediction = atn.ruleToTokenType[firstConfigWithRuleStopState.State.ruleIndex]; newState.AcceptStateInfo = new AcceptStateInfo(prediction, lexerActionExecutor);
} }
return atn.modeToDFA[mode].AddState(newState); return atn.modeToDFA[mode].AddState(newState);
} }

View File

@ -341,6 +341,7 @@ namespace Antlr4.Runtime.Atn
public bool optimize_ll1 = true; 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_hidden_conflicted_configs = false;
public bool optimize_tail_calls = true; public bool optimize_tail_calls = true;
@ -386,6 +387,8 @@ namespace Antlr4.Runtime.Atn
/// </remarks> /// </remarks>
protected internal bool userWantsCtxSensitive = true; protected internal bool userWantsCtxSensitive = true;
private DFA dfa;
/// <summary>Testing only!</summary> /// <summary>Testing only!</summary>
public ParserATNSimulator(ATN atn) public ParserATNSimulator(ATN atn)
: this(null, atn) : this(null, atn)
@ -437,6 +440,7 @@ namespace Antlr4.Runtime.Atn
} }
} }
} }
this.dfa = dfa;
if (force_global_context) if (force_global_context)
{ {
useContext = true; useContext = true;
@ -475,6 +479,7 @@ namespace Antlr4.Runtime.Atn
} }
finally finally
{ {
this.dfa = null;
input.Seek(index); input.Seek(index);
input.Release(m); input.Release(m);
} }
@ -568,7 +573,7 @@ namespace Antlr4.Runtime.Atn
s = next; s = next;
} }
} }
if (s.isAcceptState) if (IsAcceptState(s, state.useContext))
{ {
if (s.predicates != null) if (s.predicates != null)
{ {
@ -580,14 +585,14 @@ namespace Antlr4.Runtime.Atn
break; break;
} }
// t is not updated if one of these states is reached // 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 // if no edge, pop over to ATN interpreter, update DFA and return
DFAState target = GetExistingTargetState(s, t); DFAState target = GetExistingTargetState(s, t);
if (target == null) if (target == null)
{ {
if (dfa_debug && t >= 0) 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; int alt;
SimulatorState initialState = new SimulatorState(outerContext, s, state.useContext, remainingOuterContext); SimulatorState initialState = new SimulatorState(outerContext, s, state.useContext, remainingOuterContext);
@ -606,7 +611,7 @@ namespace Antlr4.Runtime.Atn
} }
} }
s = target; s = target;
if (!s.isAcceptState && t != IntStreamConstants.Eof) if (!IsAcceptState(s, state.useContext) && t != IntStreamConstants.Eof)
{ {
input.Consume(); input.Consume();
t = input.La(1); t = input.La(1);
@ -616,11 +621,11 @@ namespace Antlr4.Runtime.Atn
// if ( debug ) System.out.println("!!! no viable alt in dfa"); // if ( debug ) System.out.println("!!! no viable alt in dfa");
// return -1; // return -1;
// } // }
if (s.configs.ConflictingAlts != null) if (!state.useContext && s.configs.ConflictInformation != null)
{ {
if (dfa.atnStartState is DecisionState) 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 else
@ -695,12 +700,82 @@ namespace Antlr4.Runtime.Atn
{ {
input.Seek(stopIndex); 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 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> /// <summary>
@ -764,13 +839,13 @@ namespace Antlr4.Runtime.Atn
} }
DFAState D = nextState.s0; DFAState D = nextState.s0;
// predicted alt => accept state // 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 // conflicted => accept state
System.Diagnostics.Debug.Assert(D.isAcceptState || D.configs.ConflictingAlts == null); System.Diagnostics.Debug.Assert(D.IsAcceptState || D.configs.ConflictInformation == null);
if (D.isAcceptState) if (IsAcceptState(D, useContext))
{ {
BitSet conflictingAlts = D.configs.ConflictingAlts; 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 (predictedAlt != ATN.InvalidAltNumber)
{ {
if (optimize_ll1 && input.Index == startIndex && !dfa.IsPrecedenceDfa && nextState.outerContext == nextState.remainingOuterContext && dfa.decision >= 0 && !D.configs.HasSemanticContext) 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); ReportContextSensitivity(dfa, predictedAlt, nextState, startIndex, input.Index);
} }
} }
predictedAlt = D.prediction; predictedAlt = D.Prediction;
// int k = input.index() - startIndex + 1; // how much input we used // int k = input.index() - startIndex + 1; // how much input we used
// System.out.println("used k="+k); // System.out.println("used k="+k);
bool attemptFullContext = conflictingAlts != null && userWantsCtxSensitive; bool attemptFullContext = conflictingAlts != null && userWantsCtxSensitive;
if (attemptFullContext) if (attemptFullContext)
{ {
if (predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection) // 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.ConflictingAlts.Cardinality() > 2) && (!treat_sllk1_conflict_as_ambiguity || input.Index != startIndex); attemptFullContext = !useContext && (D.configs.DipsIntoOuterContext || !D.configs.IsExactConflict) && (!treat_sllk1_conflict_as_ambiguity || input.Index != startIndex);
}
else
{
attemptFullContext = D.configs.DipsIntoOuterContext && (!treat_sllk1_conflict_as_ambiguity || input.Index != startIndex);
}
} }
if (D.configs.HasSemanticContext) if (D.configs.HasSemanticContext)
{ {
@ -844,7 +914,7 @@ namespace Antlr4.Runtime.Atn
{ {
if (reportAmbiguities && conflictingAlts.Cardinality() > 1) 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); predictedAlt = conflictingAlts.NextSetBit(0);
} }
@ -853,7 +923,7 @@ namespace Antlr4.Runtime.Atn
else else
{ {
System.Diagnostics.Debug.Assert(!useContext); System.Diagnostics.Debug.Assert(!useContext);
System.Diagnostics.Debug.Assert(D.isAcceptState); System.Diagnostics.Debug.Assert(IsAcceptState(D, false));
SimulatorState fullContextState = ComputeStartState(dfa, outerContext, true); SimulatorState fullContextState = ComputeStartState(dfa, outerContext, true);
if (reportAmbiguities) if (reportAmbiguities)
{ {
@ -1055,8 +1125,8 @@ namespace Antlr4.Runtime.Atn
s = next; s = next;
} }
} }
System.Diagnostics.Debug.Assert(!s.isAcceptState); System.Diagnostics.Debug.Assert(!IsAcceptState(s, useContext));
if (s.isAcceptState) if (IsAcceptState(s, useContext))
{ {
return new SimulatorState(previous.outerContext, s, useContext, remainingGlobalContext); return new SimulatorState(previous.outerContext, s, useContext, remainingGlobalContext);
} }
@ -1357,6 +1427,16 @@ namespace Antlr4.Runtime.Atn
{ {
configs.IsOutermostConfigSet = true; 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; bool collectPredicates = true;
Closure(reachIntermediate, configs, collectPredicates, hasMoreContext, contextCache, false); Closure(reachIntermediate, configs, collectPredicates, hasMoreContext, contextCache, false);
bool stepIntoGlobal = configs.DipsIntoOuterContext; bool stepIntoGlobal = configs.DipsIntoOuterContext;
@ -1370,13 +1450,6 @@ namespace Antlr4.Runtime.Atn
{ {
if (s0 == null) if (s0 == null)
{ {
if (!dfa.IsPrecedenceDfa && dfa.atnStartState is StarLoopEntryState)
{
if (((StarLoopEntryState)dfa.atnStartState).precedenceRuleDecision)
{
dfa.IsPrecedenceDfa = true;
}
}
if (!dfa.IsPrecedenceDfa) if (!dfa.IsPrecedenceDfa)
{ {
AtomicReference<DFAState> reference = useContext ? dfa.s0full : dfa.s0; 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 /// <li>Evaluate the precedence predicates for each configuration using
/// <see cref="SemanticContext.EvalPrecedence(Antlr4.Runtime.Recognizer{Symbol, ATNInterpreter}, Antlr4.Runtime.RuleContext)"/> /// <see cref="SemanticContext.EvalPrecedence(Antlr4.Runtime.Recognizer{Symbol, ATNInterpreter}, Antlr4.Runtime.RuleContext)"/>
/// .</li> /// .</li>
/// <li>Remove all configurations which predict an alternative greater than /// <li>When
/// 1, for which another configuration that predicts alternative 1 is in the /// <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 /// same ATN state with the same prediction context. This transformation is
/// valid for the following reasons: /// valid for the following reasons:
/// <ul> /// <ul>
@ -1454,7 +1532,11 @@ namespace Antlr4.Runtime.Atn
/// epsilon transition, so the only way an alternative other than 1 can exist /// 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 /// 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 /// 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> /// </ul>
/// </li> /// </li>
/// </ol> /// </ol>
@ -1535,11 +1617,14 @@ namespace Antlr4.Runtime.Atn
// already handled // already handled
continue; continue;
} }
PredictionContext context = statesFromAlt1.Get(config_1.State.stateNumber); if (!config_1.PrecedenceFilterSuppressed)
if (context != null && context.Equals(config_1.Context))
{ {
// eliminated PredictionContext context = statesFromAlt1.Get(config_1.State.stateNumber);
continue; if (context != null && context.Equals(config_1.Context))
{
// eliminated
continue;
}
} }
configSet.Add(config_1, contextCache); configSet.Add(config_1, contextCache);
} }
@ -1569,9 +1654,7 @@ namespace Antlr4.Runtime.Atn
// Update DFA so reach becomes accept state with predicate // Update DFA so reach becomes accept state with predicate
predPredictions = GetPredicatePredictions(conflictingAlts, altToPred); predPredictions = GetPredicatePredictions(conflictingAlts, altToPred);
D.predicates = predPredictions; D.predicates = predPredictions;
D.prediction = ATN.InvalidAltNumber;
} }
// make sure we use preds
return predPredictions; return predPredictions;
} }
@ -1767,6 +1850,7 @@ namespace Antlr4.Runtime.Atn
// gotten that context AFTER having fallen off a rule. // gotten that context AFTER having fallen off a rule.
// Make sure we track that we are now out of context. // Make sure we track that we are now out of context.
c.OuterContextDepth = config.OuterContextDepth; c.OuterContextDepth = config.OuterContextDepth;
c.PrecedenceFilterSuppressed = config.PrecedenceFilterSuppressed;
System.Diagnostics.Debug.Assert(depth > int.MinValue); System.Diagnostics.Debug.Assert(depth > int.MinValue);
Closure(c, configs, intermediate, closureBusy, collectPredicates, hasMoreContexts, contextCache, depth - 1, treatEofAsEpsilon); 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 // no need to keep full context overhead when we step out
config = config.Transform(config.State, PredictionContext.EmptyLocal, false); 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 // avoid infinite recursion for right-recursive rules
continue; continue;
} }
if (dfa != null && dfa.IsPrecedenceDfa)
{
int outermostPrecedenceReturn = ((EpsilonTransition)t).OutermostPrecedenceReturn;
if (outermostPrecedenceReturn == dfa.atnStartState.ruleIndex)
{
c.PrecedenceFilterSuppressed = true;
}
}
c.OuterContextDepth = c.OuterContextDepth + 1; c.OuterContextDepth = c.OuterContextDepth + 1;
System.Diagnostics.Debug.Assert(newDepth > int.MinValue); System.Diagnostics.Debug.Assert(newDepth > int.MinValue);
newDepth--; newDepth--;
@ -1997,9 +2097,9 @@ namespace Antlr4.Runtime.Atn
return config.Transform(t.target, newContext, false); 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) if (configset.UniqueAlt != ATN.InvalidAltNumber || configset.Count <= 1)
{ {
@ -2029,7 +2129,7 @@ namespace Antlr4.Runtime.Atn
} }
IList<ATNConfig> configs = new List<ATNConfig>(configset); IList<ATNConfig> configs = new List<ATNConfig>(configset);
configs.Sort(StateAltSortComparator); configs.Sort(StateAltSortComparator);
bool exact = !configset.DipsIntoOuterContext && predictionMode == Antlr4.Runtime.Atn.PredictionMode.LlExactAmbigDetection; bool exact = !configset.DipsIntoOuterContext;
BitSet alts = new BitSet(); BitSet alts = new BitSet();
int minAlt = configs[0].Alt; int minAlt = configs[0].Alt;
alts.Set(minAlt); alts.Set(minAlt);
@ -2077,7 +2177,8 @@ namespace Antlr4.Runtime.Atn
{ {
if (currentAlt != maxAlt) if (currentAlt != maxAlt)
{ {
return null; exact = false;
break;
} }
currentState = stateNumber; currentState = stateNumber;
currentAlt = minAlt; currentAlt = minAlt;
@ -2088,7 +2189,8 @@ namespace Antlr4.Runtime.Atn
{ {
if (alt != representedAlts.NextSetBit(currentAlt + 1)) if (alt != representedAlts.NextSetBit(currentAlt + 1))
{ {
return null; exact = false;
break;
} }
currentAlt = alt; currentAlt = alt;
} }
@ -2159,43 +2261,15 @@ namespace Antlr4.Runtime.Atn
joinedCheckContext2 = contextCache.Join(joinedCheckContext2, config2.Context); joinedCheckContext2 = contextCache.Join(joinedCheckContext2, config2.Context);
} }
i_1 = lastIndexCurrentStateCurrentAlt; i_1 = lastIndexCurrentStateCurrentAlt;
if (exact) PredictionContext check = contextCache.Join(joinedCheckContext, joinedCheckContext2);
if (!joinedCheckContext.Equals(check))
{ {
if (!joinedCheckContext.Equals(joinedCheckContext2)) return null;
{
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;
}
} }
// update exact if necessary
exact = exact && joinedCheckContext.Equals(joinedCheckContext2);
} }
return alts; return new ConflictInfo(alts, exact);
} }
protected internal virtual BitSet GetConflictingAltsFromConfigSet(ATNConfigSet configs) protected internal virtual BitSet GetConflictingAltsFromConfigSet(ATNConfigSet configs)
@ -2209,14 +2283,6 @@ namespace Antlr4.Runtime.Atn
return conflictingAlts; 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] [NotNull]
public virtual string GetTokenName(int t) public virtual string GetTokenName(int t)
{ {
@ -2224,20 +2290,13 @@ namespace Antlr4.Runtime.Atn
{ {
return "EOF"; 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; return displayName;
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 t.ToString(); return displayName + "<" + t + ">";
} }
public virtual string GetLookaheadName(ITokenStream input) public virtual string GetLookaheadName(ITokenStream input)
@ -2393,7 +2452,7 @@ namespace Antlr4.Runtime.Atn
{ {
configs.OptimizeConfigs(this); configs.OptimizeConfigs(this);
} }
DFAState proposed = CreateDFAState(configs); DFAState proposed = CreateDFAState(dfa, configs);
DFAState existing = dfa.states.Get(proposed); DFAState existing = dfa.states.Get(proposed);
if (existing != null) if (existing != null)
{ {
@ -2402,42 +2461,26 @@ namespace Antlr4.Runtime.Atn
} }
if (!configs.IsReadOnly) if (!configs.IsReadOnly)
{ {
if (configs.ConflictingAlts == null) if (configs.ConflictInformation == null)
{ {
configs.ConflictingAlts = IsConflicted(configs, contextCache); configs.ConflictInformation = 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;
}
}
}
} }
} }
DFAState newState = CreateDFAState(configs.Clone(true)); DFAState newState = CreateDFAState(dfa, configs.Clone(true));
DecisionState decisionState = atn.GetDecisionState(dfa.decision); DecisionState decisionState = atn.GetDecisionState(dfa.decision);
int predictedAlt = GetUniqueAlt(configs); int predictedAlt = GetUniqueAlt(configs);
if (predictedAlt != ATN.InvalidAltNumber) if (predictedAlt != ATN.InvalidAltNumber)
{ {
newState.isAcceptState = true; newState.AcceptStateInfo = new AcceptStateInfo(predictedAlt);
newState.prediction = predictedAlt;
} }
else else
{ {
if (configs.ConflictingAlts != null) if (configs.ConflictingAlts != null)
{ {
newState.isAcceptState = true; newState.AcceptStateInfo = new AcceptStateInfo(newState.configs.ConflictingAlts.NextSetBit(0));
newState.prediction = ResolveToMinAlt(newState, newState.configs.ConflictingAlts);
} }
} }
if (newState.isAcceptState && configs.HasSemanticContext) if (newState.IsAcceptState && configs.HasSemanticContext)
{ {
PredicateDFAState(newState, configs, decisionState.NumberOfTransitions); PredicateDFAState(newState, configs, decisionState.NumberOfTransitions);
} }
@ -2454,9 +2497,9 @@ namespace Antlr4.Runtime.Atn
} }
[NotNull] [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) 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._input = input;
this._startIndex = input.Index; 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._llStopIndex = -1;
this.currentDecision = decision; this.currentDecision = decision;
this.currentState = null; this.currentState = null;

View File

@ -376,7 +376,7 @@ namespace Antlr4.Runtime
/// <param name="e">the recognition exception</param> /// <param name="e">the recognition exception</param>
protected internal virtual void ReportInputMismatch(Parser recognizer, InputMismatchException e) 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); NotifyErrorListeners(recognizer, msg, e);
} }
@ -434,7 +434,7 @@ namespace Antlr4.Runtime
IToken t = recognizer.CurrentToken; IToken t = recognizer.CurrentToken;
string tokenName = GetTokenErrorDisplay(t); string tokenName = GetTokenErrorDisplay(t);
IntervalSet expecting = GetExpectedTokens(recognizer); 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); recognizer.NotifyErrorListeners(t, msg, null);
} }
@ -472,7 +472,7 @@ namespace Antlr4.Runtime
BeginErrorCondition(recognizer); BeginErrorCondition(recognizer);
IToken t = recognizer.CurrentToken; IToken t = recognizer.CurrentToken;
IntervalSet expecting = GetExpectedTokens(recognizer); 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); recognizer.NotifyErrorListeners(t, msg, null);
} }
@ -713,7 +713,7 @@ namespace Antlr4.Runtime
} }
else else
{ {
tokenText = "<missing " + recognizer.TokenNames[expectedTokenType] + ">"; tokenText = "<missing " + recognizer.Vocabulary.GetDisplayName(expectedTokenType) + ">";
} }
IToken current = currentSymbol; IToken current = currentSymbol;
IToken lookback = ((ITokenStream)recognizer.InputStream).Lt(-1); 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 namespace Antlr4.Runtime.Dfa
{ {
/// <author>sam</author> /// <author>Sam Harwell</author>
public class ArrayEdgeMap<T> : AbstractEdgeMap<T> 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) public ArrayEdgeMap(int minIndex, int maxIndex)
: base(minIndex, 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 public override int Count
{ {
get get
{ {
return size; return size.Get();
} }
} }
@ -59,7 +60,7 @@ namespace Antlr4.Runtime.Dfa
{ {
get get
{ {
return size == 0; return Count == 0;
} }
} }
@ -76,7 +77,7 @@ namespace Antlr4.Runtime.Dfa
{ {
return null; return null;
} }
return arrayData[key - minIndex]; return arrayData.Get(key - minIndex);
} }
} }
@ -84,17 +85,16 @@ namespace Antlr4.Runtime.Dfa
{ {
if (key >= minIndex && key <= maxIndex) if (key >= minIndex && key <= maxIndex)
{ {
T existing = arrayData[key - minIndex]; T existing = arrayData.GetAndSet(key - minIndex, value);
arrayData[key - minIndex] = value;
if (existing == null && value != null) if (existing == null && value != null)
{ {
size++; size.IncrementAndGet();
} }
else else
{ {
if (existing != null && value == null) 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; Antlr4.Runtime.Dfa.ArrayEdgeMap<T> other = (Antlr4.Runtime.Dfa.ArrayEdgeMap<T>)m;
int minOverlap = Math.Max(minIndex, other.minIndex); int minOverlap = Math.Max(minIndex, other.minIndex);
int maxOverlap = Math.Min(maxIndex, other.maxIndex); int maxOverlap = Math.Min(maxIndex, other.maxIndex);
Antlr4.Runtime.Dfa.ArrayEdgeMap<T> result = this;
for (int i = minOverlap; i <= maxOverlap; i++) for (int i = minOverlap; i <= maxOverlap; i++)
{ {
T target = other.arrayData[i - other.minIndex]; result = ((Antlr4.Runtime.Dfa.ArrayEdgeMap<T>)result.Put(i, m[i]));
if (target != null)
{
T current = this.arrayData[i - this.minIndex];
this.arrayData[i - this.minIndex] = target;
size += (current != null ? 0 : 1);
}
} }
return this; return result;
} }
else else
{ {
@ -142,14 +137,17 @@ namespace Antlr4.Runtime.Dfa
if (m is SparseEdgeMap<object>) if (m is SparseEdgeMap<object>)
{ {
SparseEdgeMap<T> other = (SparseEdgeMap<T>)m; SparseEdgeMap<T> other = (SparseEdgeMap<T>)m;
int[] keys = other.Keys; lock (other)
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])); 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 else
{ {
@ -161,8 +159,7 @@ namespace Antlr4.Runtime.Dfa
public override AbstractEdgeMap<T> Clear() public override AbstractEdgeMap<T> Clear()
{ {
Arrays.Fill(arrayData, null); return new EmptyEdgeMap<T>(minIndex, maxIndex);
return this;
} }
public override IDictionary<int, T> ToMap() public override IDictionary<int, T> ToMap()
@ -172,13 +169,14 @@ namespace Antlr4.Runtime.Dfa
return Antlr4.Runtime.Sharpen.Collections.EmptyMap(); return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
} }
IDictionary<int, T> result = new LinkedHashMap<int, T>(); 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; continue;
} }
result.Put(i + minIndex, arrayData[i]); result.Put(i + minIndex, element);
} }
return result; return result;
} }

View File

@ -29,6 +29,7 @@
*/ */
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn; using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Dfa; using Antlr4.Runtime.Dfa;
using Antlr4.Runtime.Misc; using Antlr4.Runtime.Misc;
@ -64,6 +65,19 @@ namespace Antlr4.Runtime.Dfa
private readonly AtomicInteger nextStateNumber = new AtomicInteger(); 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> /// <summary>
/// <see langword="true"/> /// <see langword="true"/>
/// if this DFA is for a precedence decision; otherwise, /// if this DFA is for a precedence decision; otherwise,
@ -85,6 +99,50 @@ namespace Antlr4.Runtime.Dfa
{ {
this.atnStartState = atnStartState; this.atnStartState = atnStartState;
this.decision = decision; 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> /// <summary>Gets whether this DFA is a precedence DFA.</summary>
@ -161,12 +219,8 @@ namespace Antlr4.Runtime.Dfa
this.states.Clear(); this.states.Clear();
if (precedenceDfa) if (precedenceDfa)
{ {
DFAState precedenceState = new DFAState(new ATNConfigSet(), 0, 200); this.s0.Set(new DFAState(emptyPrecedenceEdges, EmptyContextEdgeMap, new ATNConfigSet()));
precedenceState.isAcceptState = false; this.s0full.Set(new DFAState(emptyPrecedenceEdges, EmptyContextEdgeMap, new ATNConfigSet()));
this.s0.Set(precedenceState);
DFAState fullContextPrecedenceState = new DFAState(new ATNConfigSet(), 0, 200);
fullContextPrecedenceState.isAcceptState = false;
this.s0full.Set(fullContextPrecedenceState);
} }
else else
{ {
@ -277,9 +331,10 @@ namespace Antlr4.Runtime.Dfa
public override string ToString() 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) public virtual string ToString(string[] tokenNames)
{ {
if (s0.Get() == null) if (s0.Get() == null)
@ -290,6 +345,17 @@ namespace Antlr4.Runtime.Dfa
return serializer.ToString(); 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) public virtual string ToString(string[] tokenNames, string[] ruleNames)
{ {
if (s0.Get() == null) if (s0.Get() == null)
@ -300,6 +366,16 @@ namespace Antlr4.Runtime.Dfa
return serializer.ToString(); 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() public virtual string ToLexerString()
{ {
if (s0.Get() == null) if (s0.Get() == null)

View File

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

View File

@ -72,32 +72,15 @@ namespace Antlr4.Runtime.Dfa
/// <c>edges.get(symbol)</c> /// <c>edges.get(symbol)</c>
/// points to target of symbol. /// points to target of symbol.
/// </summary> /// </summary>
[Nullable] [NotNull]
private AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> edges; private volatile AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> edges;
private readonly int minSymbol; private Antlr4.Runtime.Dfa.AcceptStateInfo acceptStateInfo;
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;
/// <summary>These keys for these edges are the top level element of the global context.</summary> /// <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> /// <remarks>These keys for these edges are the top level element of the global context.</remarks>
[Nullable] [NotNull]
private AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> contextEdges; private volatile AbstractEdgeMap<Antlr4.Runtime.Dfa.DFAState> contextEdges;
/// <summary>Symbols in this set require a global context transition before matching an input symbol.</summary> /// <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> /// <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.configs = configs;
this.minSymbol = minSymbol; this.edges = emptyEdges;
this.maxSymbol = maxSymbol; this.contextEdges = emptyContextEdges;
} }
public bool IsContextSensitive public bool IsContextSensitive
{ {
get get
{ {
return contextEdges != null; return contextSymbols != null;
} }
} }
public bool IsContextSymbol(int symbol) public bool IsContextSymbol(int symbol)
{ {
if (!IsContextSensitive || symbol < minSymbol) if (!IsContextSensitive || symbol < edges.minIndex)
{ {
return false; return false;
} }
return contextSymbols.Get(symbol - minSymbol); return contextSymbols.Get(symbol - edges.minIndex);
} }
public void SetContextSymbol(int symbol) public void SetContextSymbol(int symbol)
{ {
System.Diagnostics.Debug.Assert(IsContextSensitive); System.Diagnostics.Debug.Assert(IsContextSensitive);
if (symbol < minSymbol) if (symbol < edges.minIndex)
{ {
return; return;
} }
contextSymbols.Set(symbol - minSymbol); contextSymbols.Set(symbol - edges.minIndex);
} }
public virtual void SetContextSensitive(ATN atn) public virtual void SetContextSensitive(ATN atn)
{ {
System.Diagnostics.Debug.Assert(!configs.IsOutermostConfigSet);
if (IsContextSensitive)
{
return;
}
lock (this) lock (this)
{ {
System.Diagnostics.Debug.Assert(!configs.IsOutermostConfigSet); if (contextSymbols == null)
if (IsContextSensitive)
{ {
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) public virtual DFAState GetTarget(int symbol)
{ {
lock (this) return edges[symbol];
{
if (edges == null)
{
return null;
}
return edges[symbol];
}
} }
public virtual void SetTarget(int symbol, DFAState target) public virtual void SetTarget(int symbol, DFAState target)
{ {
lock (this) edges = edges.Put(symbol, target);
{
if (edges == null)
{
edges = new SingletonEdgeMap<DFAState>(minSymbol, maxSymbol);
}
edges = edges.Put(symbol, target);
}
} }
public virtual IDictionary<int, DFAState> EdgeMap public virtual IDictionary<int, DFAState> EdgeMap
{ {
get get
{ {
if (edges == null)
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
return edges.ToMap(); return edges.ToMap();
} }
} }
@ -222,10 +239,6 @@ namespace Antlr4.Runtime.Dfa
{ {
lock (this) lock (this)
{ {
if (contextEdges == null)
{
return null;
}
if (invokingState == PredictionContext.EmptyFullStateKey) if (invokingState == PredictionContext.EmptyFullStateKey)
{ {
invokingState = -1; invokingState = -1;
@ -238,7 +251,7 @@ namespace Antlr4.Runtime.Dfa
{ {
lock (this) lock (this)
{ {
if (contextEdges == null) if (!IsContextSensitive)
{ {
throw new InvalidOperationException("The state is not context sensitive."); throw new InvalidOperationException("The state is not context sensitive.");
} }
@ -254,10 +267,6 @@ namespace Antlr4.Runtime.Dfa
{ {
get get
{ {
if (contextEdges == null)
{
return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
}
IDictionary<int, DFAState> map = contextEdges.ToMap(); IDictionary<int, DFAState> map = contextEdges.ToMap();
if (map.ContainsKey(-1)) if (map.ContainsKey(-1))
{ {
@ -327,7 +336,7 @@ namespace Antlr4.Runtime.Dfa
{ {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.Append(stateNumber).Append(":").Append(configs); buf.Append(stateNumber).Append(":").Append(configs);
if (isAcceptState) if (IsAcceptState)
{ {
buf.Append("=>"); buf.Append("=>");
if (predicates != null) if (predicates != null)
@ -336,7 +345,7 @@ namespace Antlr4.Runtime.Dfa
} }
else else
{ {
buf.Append(prediction); buf.Append(Prediction);
} }
} }
return buf.ToString(); 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 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using Antlr4.Runtime;
using Antlr4.Runtime.Dfa; using Antlr4.Runtime.Dfa;
using Antlr4.Runtime.Misc; using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen; using Antlr4.Runtime.Sharpen;
@ -36,7 +37,7 @@ namespace Antlr4.Runtime.Dfa
public class LexerDFASerializer : DFASerializer public class LexerDFASerializer : DFASerializer
{ {
public LexerDFASerializer(DFA dfa) 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 namespace Antlr4.Runtime.Dfa
{ {
/// <author>Sam Harwell</author> /// <author>Sam Harwell</author>
public class SingletonEdgeMap<T> : AbstractEdgeMap<T> public sealed class SingletonEdgeMap<T> : AbstractEdgeMap<T>
{ {
private readonly int key; private readonly int key;
private readonly T value; 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) public SingletonEdgeMap(int minIndex, int maxIndex, int key, T value)
: base(minIndex, maxIndex) : base(minIndex, maxIndex)
{ {
@ -62,7 +55,7 @@ namespace Antlr4.Runtime.Dfa
} }
} }
public virtual int Key public int Key
{ {
get get
{ {
@ -70,7 +63,7 @@ namespace Antlr4.Runtime.Dfa
} }
} }
public virtual T Value public T Value
{ {
get get
{ {
@ -141,7 +134,7 @@ namespace Antlr4.Runtime.Dfa
{ {
if (key == this.key && this.value != null) if (key == this.key && this.value != null)
{ {
return new Antlr4.Runtime.Dfa.SingletonEdgeMap<T>(minIndex, maxIndex); return new EmptyEdgeMap<T>(minIndex, maxIndex);
} }
return this; return this;
} }
@ -150,7 +143,7 @@ namespace Antlr4.Runtime.Dfa
{ {
if (this.value != null) if (this.value != null)
{ {
return new Antlr4.Runtime.Dfa.SingletonEdgeMap<T>(minIndex, maxIndex); return new EmptyEdgeMap<T>(minIndex, maxIndex);
} }
return this; return this;
} }

View File

@ -35,7 +35,7 @@ using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa namespace Antlr4.Runtime.Dfa
{ {
/// <author>Sam Harwell</author> /// <author>Sam Harwell</author>
public class SparseEdgeMap<T> : AbstractEdgeMap<T> public sealed class SparseEdgeMap<T> : AbstractEdgeMap<T>
{ {
private const int DefaultMaxSize = 5; private const int DefaultMaxSize = 5;
@ -58,16 +58,19 @@ namespace Antlr4.Runtime.Dfa
private SparseEdgeMap(Antlr4.Runtime.Dfa.SparseEdgeMap<T> map, int maxSparseSize) private SparseEdgeMap(Antlr4.Runtime.Dfa.SparseEdgeMap<T> map, int maxSparseSize)
: base(map.minIndex, map.maxIndex) : 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 get
{ {
@ -75,7 +78,7 @@ namespace Antlr4.Runtime.Dfa
} }
} }
public virtual IList<T> Values public IList<T> Values
{ {
get get
{ {
@ -83,7 +86,7 @@ namespace Antlr4.Runtime.Dfa
} }
} }
public virtual int MaxSparseSize public int MaxSparseSize
{ {
get get
{ {
@ -116,6 +119,9 @@ namespace Antlr4.Runtime.Dfa
{ {
get 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); int index = System.Array.BinarySearch(keys, 0, Count, key);
if (index < 0) if (index < 0)
{ {
@ -135,7 +141,7 @@ namespace Antlr4.Runtime.Dfa
{ {
return ((Antlr4.Runtime.Dfa.SparseEdgeMap<T>)Remove(key)); return ((Antlr4.Runtime.Dfa.SparseEdgeMap<T>)Remove(key));
} }
lock (values) lock (this)
{ {
int index = System.Array.BinarySearch(keys, 0, Count, key); int index = System.Array.BinarySearch(keys, 0, Count, key);
if (index >= 0) if (index >= 0)
@ -166,7 +172,7 @@ namespace Antlr4.Runtime.Dfa
else else
{ {
Antlr4.Runtime.Dfa.SparseEdgeMap<T> resized = new Antlr4.Runtime.Dfa.SparseEdgeMap<T>(this, desiredSize); 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.keys[insertIndex] = key;
resized.values.Add(insertIndex, value); resized.values.Add(insertIndex, value);
return resized; return resized;
@ -176,20 +182,18 @@ namespace Antlr4.Runtime.Dfa
public override AbstractEdgeMap<T> Remove(int key) public override AbstractEdgeMap<T> Remove(int key)
{ {
int index = System.Array.BinarySearch(keys, 0, Count, key); lock (this)
if (index < 0)
{ {
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() public override AbstractEdgeMap<T> Clear()
@ -198,9 +202,7 @@ namespace Antlr4.Runtime.Dfa
{ {
return this; return this;
} }
Antlr4.Runtime.Dfa.SparseEdgeMap<T> result = new Antlr4.Runtime.Dfa.SparseEdgeMap<T>(this, MaxSparseSize); return new EmptyEdgeMap<T>(minIndex, maxIndex);
result.values.Clear();
return result;
} }
public override IDictionary<int, T> ToMap() public override IDictionary<int, T> ToMap()
@ -209,12 +211,15 @@ namespace Antlr4.Runtime.Dfa
{ {
return Antlr4.Runtime.Sharpen.Collections.EmptyMap(); return Antlr4.Runtime.Sharpen.Collections.EmptyMap();
} }
IDictionary<int, T> result = new LinkedHashMap<int, T>(); lock (this)
for (int i = 0; i < Count; i++)
{ {
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. /// by parser.
/// </remarks> /// </remarks>
public const int HiddenChannel = 1; 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 System.Collections.Generic;
using Antlr4.Runtime; using Antlr4.Runtime;
using Antlr4.Runtime.Atn; using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen; using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime namespace Antlr4.Runtime
@ -41,13 +42,23 @@ namespace Antlr4.Runtime
protected internal readonly ATN atn; protected internal readonly ATN atn;
[Obsolete]
protected internal readonly string[] tokenNames; protected internal readonly string[] tokenNames;
protected internal readonly string[] ruleNames; protected internal readonly string[] ruleNames;
protected internal readonly string[] modeNames; 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) 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) : base(input)
{ {
if (atn.grammarType != ATNType.Lexer) if (atn.grammarType != ATNType.Lexer)
@ -56,9 +67,14 @@ namespace Antlr4.Runtime
} }
this.grammarFileName = grammarFileName; this.grammarFileName = grammarFileName;
this.atn = atn; 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.ruleNames = Sharpen.Collections.ToArray(ruleNames, new string[ruleNames.Count]);
this.modeNames = Sharpen.Collections.ToArray(modeNames, new string[modeNames.Count]); this.modeNames = Sharpen.Collections.ToArray(modeNames, new string[modeNames.Count]);
this.vocabulary = vocabulary;
this._interp = new LexerATNSimulator(this, atn); this._interp = new LexerATNSimulator(this, atn);
} }
@ -101,5 +117,17 @@ namespace Antlr4.Runtime
return modeNames; 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(); return buf.ToString();
} }
[System.ObsoleteAttribute(@"Use ToString(Antlr4.Runtime.IVocabulary) instead.")]
public virtual string ToString(string[] tokenNames) public virtual string ToString(string[] tokenNames)
{
return ToString(Vocabulary.FromTokenNames(tokenNames));
}
public virtual string ToString(IVocabulary vocabulary)
{ {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
if (this.intervals == null || this.intervals.IsEmpty()) if (this.intervals == null || this.intervals.IsEmpty())
@ -722,7 +728,7 @@ namespace Antlr4.Runtime.Misc
int b = I.b; int b = I.b;
if (a == b) if (a == b)
{ {
buf.Append(ElementName(tokenNames, a)); buf.Append(ElementName(vocabulary, a));
} }
else else
{ {
@ -732,7 +738,7 @@ namespace Antlr4.Runtime.Misc
{ {
buf.Append(", "); buf.Append(", ");
} }
buf.Append(ElementName(tokenNames, i)); buf.Append(ElementName(vocabulary, i));
} }
} }
if (iter.HasNext()) if (iter.HasNext())
@ -747,7 +753,14 @@ namespace Antlr4.Runtime.Misc
return buf.ToString(); return buf.ToString();
} }
[System.ObsoleteAttribute(@"Use ElementName(Antlr4.Runtime.IVocabulary, int) instead.")]
protected internal virtual string ElementName(string[] tokenNames, int a) 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) if (a == TokenConstants.Eof)
{ {
@ -761,7 +774,7 @@ namespace Antlr4.Runtime.Misc
} }
else 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;
using Antlr4.Runtime.Sharpen.Annotation; using Antlr4.Runtime.Sharpen.Annotation;
using Javax.Annotation.Processing; using Javax.Annotation.Processing;
using Javax.Lang.Model;
using Javax.Lang.Model.Element; using Javax.Lang.Model.Element;
using Javax.Lang.Model.Type; using Javax.Lang.Model.Type;
using Javax.Tools; 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) public override bool Process<_T0>(HashSet<_T0> annotations, IRoundEnvironment roundEnv)
{ {
if (!CheckClassNameConstants()) if (!CheckClassNameConstants())

View File

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

View File

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

View File

@ -41,13 +41,13 @@ namespace Antlr4.Runtime
{ {
public const int Eof = -1; 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 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); this.Add(ConsoleErrorListener.Instance);
@ -56,7 +56,7 @@ namespace Antlr4.Runtime
} }
[NotNull] [NotNull]
private IList<IAntlrErrorListener<Symbol>> _listeners = new _CopyOnWriteArrayList_59(); private IList<IAntlrErrorListener<Symbol>> _listeners = new _CopyOnWriteArrayList_60();
protected internal ATNInterpreter _interp; protected internal ATNInterpreter _interp;
@ -71,6 +71,7 @@ namespace Antlr4.Runtime
/// error reporting. The generated parsers implement a method /// error reporting. The generated parsers implement a method
/// that overrides this to point to their String[] tokenNames. /// that overrides this to point to their String[] tokenNames.
/// </remarks> /// </remarks>
[System.ObsoleteAttribute(@"Use Recognizer{Symbol, ATNInterpreter}.Vocabulary() instead.")]
public abstract string[] TokenNames public abstract string[] TokenNames
{ {
get; get;
@ -81,6 +82,22 @@ namespace Antlr4.Runtime
get; 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> /// <summary>Get a map from token names to token types.</summary>
/// <remarks> /// <remarks>
/// Get a map from token names to token types. /// Get a map from token names to token types.
@ -90,20 +107,29 @@ namespace Antlr4.Runtime
{ {
get get
{ {
string[] tokenNames = TokenNames; IVocabulary vocabulary = Vocabulary;
if (tokenNames == null)
{
throw new NotSupportedException("The current recognizer does not provide a list of token names.");
}
lock (tokenTypeMapCache) lock (tokenTypeMapCache)
{ {
IDictionary<string, int> result = tokenTypeMapCache.Get(tokenNames); IDictionary<string, int> result = tokenTypeMapCache.Get(vocabulary);
if (result == null) 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.Put("EOF", TokenConstants.Eof);
result = Antlr4.Runtime.Sharpen.Collections.UnmodifiableMap(result); result = Antlr4.Runtime.Sharpen.Collections.UnmodifiableMap(result);
tokenTypeMapCache.Put(tokenNames, result); tokenTypeMapCache.Put(vocabulary, result);
} }
return result; return result;
} }

View File

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

View File

@ -326,7 +326,7 @@ namespace Antlr4.Runtime.Tree.Pattern
IList<IToken> tokenList = Tokenize(pattern); IList<IToken> tokenList = Tokenize(pattern);
ListTokenSource tokenSrc = new ListTokenSource(tokenList); ListTokenSource tokenSrc = new ListTokenSource(tokenList);
CommonTokenStream tokens = new CommonTokenStream(tokenSrc); 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; IParseTree tree = null;
try try
{ {

View File

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