using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Atn
{
public class ATNConfigSet
{
protected bool readOnly = false;
public ConfigHashSet configLookup;
public ArrayList<ATNConfig> configs = new ArrayList<ATNConfig>(7);
public int uniqueAlt;
public BitSet conflictingAlts;
public bool hasSemanticContext;
public bool dipsIntoOuterContext;
public readonly bool fullCtx;
private int cachedHashCode = -1;
public ATNConfigSet(bool fullCtx)
{
configLookup = new ConfigHashSet();
this.fullCtx = fullCtx;
}
public ATNConfigSet()
: this(true)
{
}
public ATNConfigSet(ATNConfigSet old)
: this(old.fullCtx)
{
AddAll(old.configs);
this.uniqueAlt = old.uniqueAlt;
this.conflictingAlts = old.conflictingAlts;
this.hasSemanticContext = old.hasSemanticContext;
this.dipsIntoOuterContext = old.dipsIntoOuterContext;
}
public bool Add(ATNConfig config)
{
return Add(config, null);
}
public bool Add(ATNConfig config, MergeCache mergeCache)
{
if (readOnly)
throw new Exception("This set is readonly");
if (config.semanticContext != SemanticContext.Empty.Instance)
{
hasSemanticContext = true;
}
if (config.OuterContextDepth > 0)
{
dipsIntoOuterContext = true;
}
ATNConfig existing = configLookup.GetOrAdd(config);
if (existing == config)
{ cachedHashCode = -1;
configs.Add(config); return true;
}
bool rootIsWildcard = !fullCtx;
PredictionContext merged = PredictionContext.Merge(existing.context, config.context, rootIsWildcard, mergeCache);
existing.reachesIntoOuterContext = Math.Max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext);
if (config.IsPrecedenceFilterSuppressed)
{
existing.SetPrecedenceFilterSuppressed(true);
}
existing.context = merged; return true;
}
public List<ATNConfig> Elements
{
get
{
return configs;
}
}
public HashSet<ATNState> GetStates()
{
HashSet<ATNState> states = new HashSet<ATNState>();
foreach (ATNConfig c in configs)
{
states.Add(c.state);
}
return states;
}
public BitSet GetAlts()
{
BitSet alts = new BitSet();
foreach (ATNConfig config in configs)
{
alts.Set(config.alt);
}
return alts;
}
public List<SemanticContext> GetPredicates()
{
List<SemanticContext> preds = new List<SemanticContext>();
foreach (ATNConfig c in configs)
{
if (c.semanticContext != SemanticContext.Empty.Instance)
{
preds.Add(c.semanticContext);
}
}
return preds;
}
public ATNConfig Get(int i) { return configs[i]; }
public void OptimizeConfigs(ATNSimulator interpreter)
{
if (readOnly)
throw new Exception("This set is readonly");
if (configLookup.Count == 0)
return;
foreach (ATNConfig config in configs)
{
config.context = interpreter.getCachedContext(config.context);
}
}
public bool AddAll(ICollection<ATNConfig> coll)
{
foreach (ATNConfig c in coll) Add(c);
return false;
}
public override bool Equals(Object o)
{
if (o == this)
{
return true;
}
else if (!(o is ATNConfigSet))
{
return false;
}
ATNConfigSet other = (ATNConfigSet)o;
bool same = configs != null &&
configs.Equals(other.configs) && this.fullCtx == other.fullCtx &&
this.uniqueAlt == other.uniqueAlt &&
this.conflictingAlts == other.conflictingAlts &&
this.hasSemanticContext == other.hasSemanticContext &&
this.dipsIntoOuterContext == other.dipsIntoOuterContext;
return same;
}
public override int GetHashCode()
{
if (IsReadOnly)
{
if (cachedHashCode == -1)
{
cachedHashCode = configs.GetHashCode();
}
return cachedHashCode;
}
return configs.GetHashCode();
}
public int Count
{
get
{
return configs.Count;
}
}
public bool Empty
{
get
{
return configs.Count == 0;
}
}
public bool Contains(Object o)
{
if (configLookup == null)
{
throw new Exception("This method is not implemented for readonly sets.");
}
return configLookup.ContainsKey((ATNConfig)o);
}
public void Clear()
{
if (readOnly)
throw new Exception("This set is readonly");
configs.Clear();
cachedHashCode = -1;
configLookup.Clear();
}
public bool IsReadOnly
{
get
{
return readOnly;
}
set
{
this.readOnly = value;
configLookup = null; }
}
public override String ToString()
{
StringBuilder buf = new StringBuilder();
buf.Append('[');
List<ATNConfig> cfgs = Elements;
if (cfgs.Count > 0)
{
foreach (ATNConfig c in cfgs)
{
buf.Append(c.ToString());
buf.Append(", ");
}
buf.Length = buf.Length - 2;
}
buf.Append(']');
if (hasSemanticContext)
buf.Append(",hasSemanticContext=")
.Append(hasSemanticContext.ToString().ToLower());
if (uniqueAlt != ATN.INVALID_ALT_NUMBER)
buf.Append(",uniqueAlt=")
.Append(uniqueAlt);
if (conflictingAlts != null)
buf.Append(",conflictingAlts=")
.Append(conflictingAlts);
if (dipsIntoOuterContext)
buf.Append(",dipsIntoOuterContext");
return buf.ToString();
}
}
public class OrderedATNConfigSet : ATNConfigSet
{
public OrderedATNConfigSet()
{
this.configLookup = new LexerConfigHashSet();
}
public class LexerConfigHashSet : ConfigHashSet
{
public LexerConfigHashSet()
: base(new ObjectEqualityComparator())
{
}
}
}
public class ObjectEqualityComparator : IEqualityComparer<ATNConfig>
{
public int GetHashCode(ATNConfig o)
{
if (o == null)
return 0;
else
return o.GetHashCode();
}
public bool Equals(ATNConfig a, ATNConfig b)
{
if (a == b) return true;
if (a == null || b == null) return false;
return a.Equals(b);
}
}
public class ConfigHashSet : Dictionary<ATNConfig, ATNConfig>
{
public ConfigHashSet(IEqualityComparer<ATNConfig> comparer)
: base(comparer)
{
}
public ConfigHashSet()
: base(new ConfigEqualityComparator())
{
}
public ATNConfig GetOrAdd(ATNConfig config)
{
ATNConfig existing;
if (this.TryGetValue(config, out existing))
return existing;
else
{
this.Put(config, config);
return config;
}
}
}
public class ConfigEqualityComparator : IEqualityComparer<ATNConfig>
{
public int GetHashCode(ATNConfig o)
{
int hashCode = 7;
hashCode = 31 * hashCode + o.state.stateNumber;
hashCode = 31 * hashCode + o.alt;
hashCode = 31 * hashCode + o.semanticContext.GetHashCode();
return hashCode;
}
public bool Equals(ATNConfig a, ATNConfig b)
{
if (a == b) return true;
if (a == null || b == null) return false;
return a.state.stateNumber == b.state.stateNumber
&& a.alt == b.alt
&& a.semanticContext.Equals(b.semanticContext);
}
}
}