forked from jasder/antlr
710 lines
23 KiB
C#
710 lines
23 KiB
C#
/*
|
|
* [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;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Antlr4.Runtime.Atn;
|
|
using Antlr4.Runtime.Misc;
|
|
using Sharpen;
|
|
|
|
namespace Antlr4.Runtime.Atn
|
|
{
|
|
/// <author>Sam Harwell</author>
|
|
public class ATNConfigSet : ISet<ATNConfig>
|
|
{
|
|
/// <summary>
|
|
/// This maps (state, alt) -> merged
|
|
/// <see cref="ATNConfig">ATNConfig</see>
|
|
/// . The key does not account for
|
|
/// the
|
|
/// <see cref="ATNConfig.GetSemanticContext()">ATNConfig.GetSemanticContext()</see>
|
|
/// of the value, which is only a problem if a single
|
|
/// <code>ATNConfigSet</code>
|
|
/// contains two configs with the same state and alternative
|
|
/// but different semantic contexts. When this case arises, the first config
|
|
/// added to this map stays, and the remaining configs are placed in
|
|
/// <see cref="unmerged">unmerged</see>
|
|
/// .
|
|
/// <p>
|
|
/// This map is only used for optimizing the process of adding configs to the set,
|
|
/// and is
|
|
/// <code>null</code>
|
|
/// for read-only sets stored in the DFA.
|
|
/// </summary>
|
|
private readonly Dictionary<long, ATNConfig> mergedConfigs;
|
|
|
|
/// <summary>
|
|
/// This is an "overflow" list holding configs which cannot be merged with one
|
|
/// of the configs in
|
|
/// <see cref="mergedConfigs">mergedConfigs</see>
|
|
/// but have a colliding key. This
|
|
/// occurs when two configs in the set have the same state and alternative but
|
|
/// different semantic contexts.
|
|
/// <p>
|
|
/// This list is only used for optimizing the process of adding configs to the set,
|
|
/// and is
|
|
/// <code>null</code>
|
|
/// for read-only sets stored in the DFA.
|
|
/// </summary>
|
|
private readonly List<ATNConfig> unmerged;
|
|
|
|
/// <summary>This is a list of all configs in this set.</summary>
|
|
/// <remarks>This is a list of all configs in this set.</remarks>
|
|
private readonly List<ATNConfig> configs;
|
|
|
|
private int uniqueAlt;
|
|
|
|
private BitArray conflictingAlts;
|
|
|
|
private bool hasSemanticContext;
|
|
|
|
private bool dipsIntoOuterContext;
|
|
|
|
/// <summary>
|
|
/// When
|
|
/// <code>true</code>
|
|
/// , this config set represents configurations where the entire
|
|
/// outer context has been consumed by the ATN interpreter. This prevents the
|
|
/// <see cref="ParserATNSimulator.Closure(ATNConfigSet, ATNConfigSet, bool, bool, PredictionContextCache)
|
|
/// ">ParserATNSimulator.Closure(ATNConfigSet, ATNConfigSet, bool, bool, PredictionContextCache)
|
|
/// </see>
|
|
/// from pursuing the global FOLLOW when a
|
|
/// rule stop state is reached with an empty prediction context.
|
|
/// <p>
|
|
/// Note:
|
|
/// <code>outermostConfigSet</code>
|
|
/// and
|
|
/// <see cref="dipsIntoOuterContext">dipsIntoOuterContext</see>
|
|
/// should never
|
|
/// be true at the same time.
|
|
/// </summary>
|
|
private bool outermostConfigSet;
|
|
|
|
public ATNConfigSet()
|
|
{
|
|
// Used in parser and lexer. In lexer, it indicates we hit a pred
|
|
// while computing a closure operation. Don't make a DFA state from this.
|
|
this.mergedConfigs = new Dictionary<long, ATNConfig>();
|
|
this.unmerged = new List<ATNConfig>();
|
|
this.configs = new List<ATNConfig>();
|
|
this.uniqueAlt = ATN.InvalidAltNumber;
|
|
}
|
|
|
|
protected internal ATNConfigSet(Antlr4.Runtime.Atn.ATNConfigSet set, bool @readonly
|
|
)
|
|
{
|
|
if (@readonly)
|
|
{
|
|
this.mergedConfigs = null;
|
|
this.unmerged = null;
|
|
}
|
|
else
|
|
{
|
|
if (!set.IsReadOnly)
|
|
{
|
|
this.mergedConfigs = (Dictionary<long, ATNConfig>)set.mergedConfigs.Clone();
|
|
this.unmerged = (List<ATNConfig>)set.unmerged.Clone();
|
|
}
|
|
else
|
|
{
|
|
this.mergedConfigs = new Dictionary<long, ATNConfig>(set.configs.Count);
|
|
this.unmerged = new List<ATNConfig>();
|
|
}
|
|
}
|
|
this.configs = (List<ATNConfig>)set.configs.Clone();
|
|
this.dipsIntoOuterContext = set.dipsIntoOuterContext;
|
|
this.hasSemanticContext = set.hasSemanticContext;
|
|
this.outermostConfigSet = set.outermostConfigSet;
|
|
if (@readonly || !set.IsReadOnly)
|
|
{
|
|
this.uniqueAlt = set.uniqueAlt;
|
|
this.conflictingAlts = set.conflictingAlts;
|
|
}
|
|
}
|
|
|
|
// if (!readonly && set.isReadOnly()) -> addAll is called from clone()
|
|
/// <summary>
|
|
/// Get the set of all alternatives represented by configurations in this
|
|
/// set.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Get the set of all alternatives represented by configurations in this
|
|
/// set.
|
|
/// </remarks>
|
|
[NotNull]
|
|
public virtual BitArray GetRepresentedAlternatives()
|
|
{
|
|
if (conflictingAlts != null)
|
|
{
|
|
return (BitArray)conflictingAlts.Clone();
|
|
}
|
|
BitArray alts = new BitArray();
|
|
foreach (ATNConfig config in this)
|
|
{
|
|
alts.Set(config.GetAlt());
|
|
}
|
|
return alts;
|
|
}
|
|
|
|
public bool IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
return mergedConfigs == null;
|
|
}
|
|
}
|
|
|
|
public void StripHiddenConfigs()
|
|
{
|
|
EnsureWritable();
|
|
IEnumerator<KeyValuePair<long, ATNConfig>> iterator = mergedConfigs.EntrySet().GetEnumerator
|
|
();
|
|
while (iterator.HasNext())
|
|
{
|
|
if (iterator.Next().Value.IsHidden())
|
|
{
|
|
iterator.Remove();
|
|
}
|
|
}
|
|
IListIterator<ATNConfig> iterator2 = unmerged.ListIterator();
|
|
while (iterator2.HasNext())
|
|
{
|
|
if (iterator2.Next().IsHidden())
|
|
{
|
|
iterator2.Remove();
|
|
}
|
|
}
|
|
iterator2 = configs.ListIterator();
|
|
while (iterator2.HasNext())
|
|
{
|
|
if (iterator2.Next().IsHidden())
|
|
{
|
|
iterator2.Remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual bool IsOutermostConfigSet
|
|
{
|
|
get
|
|
{
|
|
return outermostConfigSet;
|
|
}
|
|
set
|
|
{
|
|
bool outermostConfigSet = value;
|
|
if (this.outermostConfigSet && !outermostConfigSet)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
System.Diagnostics.Debug.Assert(!outermostConfigSet || !dipsIntoOuterContext);
|
|
this.outermostConfigSet = outermostConfigSet;
|
|
}
|
|
}
|
|
|
|
public virtual ISet<ATNState> GetStates()
|
|
{
|
|
ISet<ATNState> states = new HashSet<ATNState>();
|
|
foreach (ATNConfig c in this.configs)
|
|
{
|
|
states.AddItem(c.GetState());
|
|
}
|
|
return states;
|
|
}
|
|
|
|
public virtual void OptimizeConfigs(ATNSimulator interpreter)
|
|
{
|
|
if (configs.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
for (int i = 0; i < configs.Count; i++)
|
|
{
|
|
ATNConfig config = configs[i];
|
|
config.SetContext(interpreter.atn.GetCachedContext(config.GetContext()));
|
|
}
|
|
}
|
|
|
|
public virtual Antlr4.Runtime.Atn.ATNConfigSet Clone(bool @readonly)
|
|
{
|
|
Antlr4.Runtime.Atn.ATNConfigSet copy = new Antlr4.Runtime.Atn.ATNConfigSet(this,
|
|
@readonly);
|
|
if (!@readonly && this.IsReadOnly)
|
|
{
|
|
Sharpen.Collections.AddAll(copy, this.configs);
|
|
}
|
|
return copy;
|
|
}
|
|
|
|
public virtual int Count
|
|
{
|
|
get
|
|
{
|
|
return configs.Count;
|
|
}
|
|
}
|
|
|
|
public virtual bool IsEmpty()
|
|
{
|
|
return configs.IsEmpty();
|
|
}
|
|
|
|
public virtual bool Contains(object o)
|
|
{
|
|
if (!(o is ATNConfig))
|
|
{
|
|
return false;
|
|
}
|
|
ATNConfig config = (ATNConfig)o;
|
|
long configKey = GetKey(config);
|
|
ATNConfig mergedConfig = mergedConfigs.Get(configKey);
|
|
if (mergedConfig != null && CanMerge(config, configKey, mergedConfig))
|
|
{
|
|
return mergedConfig.Contains(config);
|
|
}
|
|
foreach (ATNConfig c in unmerged)
|
|
{
|
|
if (c.Contains(config))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public virtual IEnumerator<ATNConfig> GetEnumerator()
|
|
{
|
|
return new ATNConfigSet.ATNConfigSetIterator(this);
|
|
}
|
|
|
|
public virtual object[] ToArray()
|
|
{
|
|
return Sharpen.Collections.ToArray(configs);
|
|
}
|
|
|
|
public virtual bool AddItem(ATNConfig e)
|
|
{
|
|
return Add(e, null);
|
|
}
|
|
|
|
public virtual bool Add(ATNConfig e, PredictionContextCache contextCache)
|
|
{
|
|
EnsureWritable();
|
|
System.Diagnostics.Debug.Assert(!outermostConfigSet || !e.GetReachesIntoOuterContext
|
|
());
|
|
System.Diagnostics.Debug.Assert(!e.IsHidden());
|
|
if (contextCache == null)
|
|
{
|
|
contextCache = PredictionContextCache.Uncached;
|
|
}
|
|
bool addKey;
|
|
long key = GetKey(e);
|
|
ATNConfig mergedConfig = mergedConfigs.Get(key);
|
|
addKey = (mergedConfig == null);
|
|
if (mergedConfig != null && CanMerge(e, key, mergedConfig))
|
|
{
|
|
mergedConfig.SetOuterContextDepth(Math.Max(mergedConfig.GetOuterContextDepth(), e
|
|
.GetOuterContextDepth()));
|
|
PredictionContext joined = PredictionContext.Join(mergedConfig.GetContext(), e.GetContext
|
|
(), contextCache);
|
|
UpdatePropertiesForMergedConfig(e);
|
|
if (mergedConfig.GetContext() == joined)
|
|
{
|
|
return false;
|
|
}
|
|
mergedConfig.SetContext(joined);
|
|
return true;
|
|
}
|
|
for (int i = 0; i < unmerged.Count; i++)
|
|
{
|
|
ATNConfig unmergedConfig = unmerged[i];
|
|
if (CanMerge(e, key, unmergedConfig))
|
|
{
|
|
unmergedConfig.SetOuterContextDepth(Math.Max(unmergedConfig.GetOuterContextDepth(
|
|
), e.GetOuterContextDepth()));
|
|
PredictionContext joined = PredictionContext.Join(unmergedConfig.GetContext(), e.
|
|
GetContext(), contextCache);
|
|
UpdatePropertiesForMergedConfig(e);
|
|
if (unmergedConfig.GetContext() == joined)
|
|
{
|
|
return false;
|
|
}
|
|
unmergedConfig.SetContext(joined);
|
|
if (addKey)
|
|
{
|
|
mergedConfigs.Put(key, unmergedConfig);
|
|
unmerged.RemoveAt(i);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
configs.AddItem(e);
|
|
if (addKey)
|
|
{
|
|
mergedConfigs.Put(key, e);
|
|
}
|
|
else
|
|
{
|
|
unmerged.AddItem(e);
|
|
}
|
|
UpdatePropertiesForAddedConfig(e);
|
|
return true;
|
|
}
|
|
|
|
private void UpdatePropertiesForMergedConfig(ATNConfig config)
|
|
{
|
|
// merged configs can't change the alt or semantic context
|
|
dipsIntoOuterContext |= config.GetReachesIntoOuterContext();
|
|
System.Diagnostics.Debug.Assert(!outermostConfigSet || !dipsIntoOuterContext);
|
|
}
|
|
|
|
private void UpdatePropertiesForAddedConfig(ATNConfig config)
|
|
{
|
|
if (configs.Count == 1)
|
|
{
|
|
uniqueAlt = config.GetAlt();
|
|
}
|
|
else
|
|
{
|
|
if (uniqueAlt != config.GetAlt())
|
|
{
|
|
uniqueAlt = ATN.InvalidAltNumber;
|
|
}
|
|
}
|
|
hasSemanticContext |= !SemanticContext.None.Equals(config.GetSemanticContext());
|
|
dipsIntoOuterContext |= config.GetReachesIntoOuterContext();
|
|
System.Diagnostics.Debug.Assert(!outermostConfigSet || !dipsIntoOuterContext);
|
|
}
|
|
|
|
protected internal virtual bool CanMerge(ATNConfig left, long leftKey, ATNConfig
|
|
right)
|
|
{
|
|
if (left.GetState().stateNumber != right.GetState().stateNumber)
|
|
{
|
|
return false;
|
|
}
|
|
if (leftKey != GetKey(right))
|
|
{
|
|
return false;
|
|
}
|
|
return left.GetSemanticContext().Equals(right.GetSemanticContext());
|
|
}
|
|
|
|
protected internal virtual long GetKey(ATNConfig e)
|
|
{
|
|
long key = e.GetState().stateNumber;
|
|
key = (key << 12) | (e.GetAlt() & unchecked((int)(0xFFF)));
|
|
return key;
|
|
}
|
|
|
|
public virtual bool Remove(object o)
|
|
{
|
|
EnsureWritable();
|
|
throw new NotSupportedException("Not supported yet.");
|
|
}
|
|
|
|
public virtual bool ContainsAll<_T0>(ICollection<_T0> c)
|
|
{
|
|
foreach (object o in c)
|
|
{
|
|
if (!(o is ATNConfig))
|
|
{
|
|
return false;
|
|
}
|
|
if (!Contains((ATNConfig)o))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public virtual bool AddAll<_T0>(ICollection<_T0> c) where _T0:ATNConfig
|
|
{
|
|
return AddAll(c, null);
|
|
}
|
|
|
|
public virtual bool AddAll<_T0>(ICollection<_T0> c, PredictionContextCache contextCache
|
|
) where _T0:ATNConfig
|
|
{
|
|
EnsureWritable();
|
|
bool changed = false;
|
|
foreach (ATNConfig group in c)
|
|
{
|
|
changed |= Add(group, contextCache);
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
public virtual bool RetainAll<_T0>(ICollection<_T0> c)
|
|
{
|
|
EnsureWritable();
|
|
throw new NotSupportedException("Not supported yet.");
|
|
}
|
|
|
|
public virtual bool RemoveAll<_T0>(ICollection<_T0> c)
|
|
{
|
|
EnsureWritable();
|
|
throw new NotSupportedException("Not supported yet.");
|
|
}
|
|
|
|
public virtual void Clear()
|
|
{
|
|
EnsureWritable();
|
|
mergedConfigs.Clear();
|
|
unmerged.Clear();
|
|
configs.Clear();
|
|
dipsIntoOuterContext = false;
|
|
hasSemanticContext = false;
|
|
uniqueAlt = ATN.InvalidAltNumber;
|
|
conflictingAlts = null;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (this == obj)
|
|
{
|
|
return true;
|
|
}
|
|
if (!(obj is Antlr4.Runtime.Atn.ATNConfigSet))
|
|
{
|
|
return false;
|
|
}
|
|
Antlr4.Runtime.Atn.ATNConfigSet other = (Antlr4.Runtime.Atn.ATNConfigSet)obj;
|
|
return this.outermostConfigSet == other.outermostConfigSet && Utils.Equals(conflictingAlts
|
|
, other.conflictingAlts) && configs.Equals(other.configs);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
int hashCode = 1;
|
|
hashCode = 5 * hashCode ^ (outermostConfigSet ? 1 : 0);
|
|
hashCode = 5 * hashCode ^ configs.GetHashCode();
|
|
return hashCode;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return ToString(false);
|
|
}
|
|
|
|
public virtual string ToString(bool showContext)
|
|
{
|
|
StringBuilder buf = new StringBuilder();
|
|
IList<ATNConfig> sortedConfigs = new List<ATNConfig>(configs);
|
|
sortedConfigs.Sort(new _IComparer_479());
|
|
buf.Append("[");
|
|
for (int i = 0; i < sortedConfigs.Count; i++)
|
|
{
|
|
if (i > 0)
|
|
{
|
|
buf.Append(", ");
|
|
}
|
|
buf.Append(sortedConfigs[i].ToString(null, true, showContext));
|
|
}
|
|
buf.Append("]");
|
|
if (hasSemanticContext)
|
|
{
|
|
buf.Append(",hasSemanticContext=").Append(hasSemanticContext);
|
|
}
|
|
if (uniqueAlt != ATN.InvalidAltNumber)
|
|
{
|
|
buf.Append(",uniqueAlt=").Append(uniqueAlt);
|
|
}
|
|
if (conflictingAlts != null)
|
|
{
|
|
buf.Append(",conflictingAlts=").Append(conflictingAlts);
|
|
}
|
|
if (dipsIntoOuterContext)
|
|
{
|
|
buf.Append(",dipsIntoOuterContext");
|
|
}
|
|
return buf.ToString();
|
|
}
|
|
|
|
private sealed class _IComparer_479 : IComparer<ATNConfig>
|
|
{
|
|
public _IComparer_479()
|
|
{
|
|
}
|
|
|
|
public int Compare(ATNConfig o1, ATNConfig o2)
|
|
{
|
|
if (o1.GetAlt() != o2.GetAlt())
|
|
{
|
|
return o1.GetAlt() - o2.GetAlt();
|
|
}
|
|
else
|
|
{
|
|
if (o1.GetState().stateNumber != o2.GetState().stateNumber)
|
|
{
|
|
return o1.GetState().stateNumber - o2.GetState().stateNumber;
|
|
}
|
|
else
|
|
{
|
|
return string.CompareOrdinal(o1.GetSemanticContext().ToString(), o2.GetSemanticContext
|
|
().ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual int UniqueAlt
|
|
{
|
|
get
|
|
{
|
|
return uniqueAlt;
|
|
}
|
|
}
|
|
|
|
public virtual bool HasSemanticContext
|
|
{
|
|
get
|
|
{
|
|
return hasSemanticContext;
|
|
}
|
|
}
|
|
|
|
public virtual void ClearExplicitSemanticContext()
|
|
{
|
|
EnsureWritable();
|
|
hasSemanticContext = false;
|
|
}
|
|
|
|
public virtual void MarkExplicitSemanticContext()
|
|
{
|
|
EnsureWritable();
|
|
hasSemanticContext = true;
|
|
}
|
|
|
|
public virtual BitArray ConflictingAlts
|
|
{
|
|
get
|
|
{
|
|
return conflictingAlts;
|
|
}
|
|
set
|
|
{
|
|
BitArray conflictingAlts = value;
|
|
EnsureWritable();
|
|
this.conflictingAlts = conflictingAlts;
|
|
}
|
|
}
|
|
|
|
public virtual bool DipsIntoOuterContext
|
|
{
|
|
get
|
|
{
|
|
return dipsIntoOuterContext;
|
|
}
|
|
}
|
|
|
|
public virtual ATNConfig this[int index]
|
|
{
|
|
get
|
|
{
|
|
return configs[index];
|
|
}
|
|
}
|
|
|
|
public virtual void Remove(int index)
|
|
{
|
|
EnsureWritable();
|
|
ATNConfig config = configs[index];
|
|
configs.Remove(config);
|
|
long key = GetKey(config);
|
|
if (mergedConfigs.Get(key) == config)
|
|
{
|
|
Sharpen.Collections.Remove(mergedConfigs, key);
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < unmerged.Count; i++)
|
|
{
|
|
if (unmerged[i] == config)
|
|
{
|
|
unmerged.RemoveAt(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected internal void EnsureWritable()
|
|
{
|
|
if (IsReadOnly)
|
|
{
|
|
throw new InvalidOperationException("This ATNConfigSet is read only.");
|
|
}
|
|
}
|
|
|
|
private sealed class ATNConfigSetIterator : IEnumerator<ATNConfig>
|
|
{
|
|
internal int index = -1;
|
|
|
|
internal bool removed = false;
|
|
|
|
public bool HasNext()
|
|
{
|
|
return this.index + 1 < this._enclosing.configs.Count;
|
|
}
|
|
|
|
public ATNConfig Next()
|
|
{
|
|
if (!this.HasNext())
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
this.index++;
|
|
this.removed = false;
|
|
return this._enclosing.configs[this.index];
|
|
}
|
|
|
|
public void Remove()
|
|
{
|
|
if (this.removed || this.index < 0 || this.index >= this._enclosing.configs.Count)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
this._enclosing.Remove(this.index);
|
|
this.removed = true;
|
|
}
|
|
|
|
internal ATNConfigSetIterator(ATNConfigSet _enclosing)
|
|
{
|
|
this._enclosing = _enclosing;
|
|
}
|
|
|
|
private readonly ATNConfigSet _enclosing;
|
|
}
|
|
}
|
|
}
|