CSharp.src.Atn.ATNConfig.cs Maven / Gradle / Ivy
Show all versions of antlr4-runtime-testsuite Show documentation
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
using System;
using System.Collections.Generic;
using System.Text;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Atn
{
/** A tuple: (ATN state, predicted alt, syntactic, semantic context).
* The syntactic context is a graph-structured stack node whose
* path(s) to the root is the rule invocation(s)
* chain used to arrive at the state. The semantic context is
* the tree of semantic predicates encountered before reaching
* an ATN state.
*/
public class ATNConfig
{
/**
* This field stores the bit mask for implementing the
* {@link #isPrecedenceFilterSuppressed} property as a bit within the
* existing {@link #reachesIntoOuterContext} field.
*/
private static readonly int SUPPRESS_PRECEDENCE_FILTER = 0x40000000;
/** The ATN state associated with this configuration */
public readonly ATNState state;
/** What alt (or lexer rule) is predicted by this configuration */
public readonly int alt;
/** The stack of invoking states leading to the rule/states associated
* with this config. We track only those contexts pushed during
* execution of the ATN simulator.
*/
public PredictionContext context;
/**
* We cannot execute predicates dependent upon local context unless
* we know for sure we are in the correct context. Because there is
* no way to do this efficiently, we simply cannot evaluate
* dependent predicates unless we are in the rule that initially
* invokes the ATN simulator.
*
*
* closure() tracks the depth of how far we dip into the outer context:
* depth > 0. Note that it may not be totally accurate depth since I
* don't ever decrement. TODO: make it a boolean then
*
*
* For memory efficiency, the {@link #isPrecedenceFilterSuppressed} method
* is also backed by this field. Since the field is publicly accessible, the
* highest bit which would not cause the value to become negative is used to
* store this field. This choice minimizes the risk that code which only
* compares this value to 0 would be affected by the new purpose of the
* flag. It also ensures the performance of the existing {@link ATNConfig}
* constructors as well as certain operations like
* {@link ATNConfigSet#add(ATNConfig, DoubleKeyMap)} method are
* completely unaffected by the change.
*/
public int reachesIntoOuterContext;
public readonly SemanticContext semanticContext;
public ATNConfig(ATNConfig old)
{ // dup
this.state = old.state;
this.alt = old.alt;
this.context = old.context;
this.semanticContext = old.semanticContext;
this.reachesIntoOuterContext = old.reachesIntoOuterContext;
}
public ATNConfig(ATNState state,
int alt,
PredictionContext context)
: this(state, alt, context, SemanticContext.NONE)
{
}
public ATNConfig(ATNState state,
int alt,
PredictionContext context,
SemanticContext semanticContext)
{
this.state = state;
this.alt = alt;
this.context = context;
this.semanticContext = semanticContext;
}
public ATNConfig(ATNConfig c, ATNState state)
: this(c, state, c.context, c.semanticContext)
{
}
public ATNConfig(ATNConfig c, ATNState state,
SemanticContext semanticContext)
: this(c, state, c.context, semanticContext)
{
}
public ATNConfig(ATNConfig c,
SemanticContext semanticContext)
: this(c, c.state, c.context, semanticContext)
{
}
public ATNConfig(ATNConfig c, ATNState state,
PredictionContext context)
: this(c, state, context, c.semanticContext)
{
}
public ATNConfig(ATNConfig c, ATNState state,
PredictionContext context,
SemanticContext semanticContext)
{
this.state = state;
this.alt = c.alt;
this.context = context;
this.semanticContext = semanticContext;
this.reachesIntoOuterContext = c.reachesIntoOuterContext;
}
/**
* This method gets the value of the {@link #reachesIntoOuterContext} field
* as it existed prior to the introduction of the
* {@link #isPrecedenceFilterSuppressed} method.
*/
public int OuterContextDepth
{
get
{
return reachesIntoOuterContext & ~SUPPRESS_PRECEDENCE_FILTER;
}
}
public bool IsPrecedenceFilterSuppressed
{
get
{
return (reachesIntoOuterContext & SUPPRESS_PRECEDENCE_FILTER) != 0;
}
}
public void SetPrecedenceFilterSuppressed(bool value)
{
if (value)
{
this.reachesIntoOuterContext |= SUPPRESS_PRECEDENCE_FILTER;
}
else {
this.reachesIntoOuterContext &= ~SUPPRESS_PRECEDENCE_FILTER;
}
}
/** An ATN configuration is equal to another if both have
* the same state, they predict the same alternative, and
* syntactic/semantic contexts are the same.
*/
public override bool Equals(Object o)
{
if (!(o is ATNConfig)) {
return false;
}
return this.Equals((ATNConfig)o);
}
public virtual bool Equals(ATNConfig other)
{
if (this == other)
{
return true;
}
else if (other == null)
{
return false;
}
return this.state.stateNumber == other.state.stateNumber
&& this.alt == other.alt
&& (this.context == other.context || (this.context != null && this.context.Equals(other.context)))
&& this.semanticContext.Equals(other.semanticContext)
&& this.IsPrecedenceFilterSuppressed == other.IsPrecedenceFilterSuppressed;
}
public override int GetHashCode()
{
int hashCode = MurmurHash.Initialize(7);
hashCode = MurmurHash.Update(hashCode, state.stateNumber);
hashCode = MurmurHash.Update(hashCode, alt);
hashCode = MurmurHash.Update(hashCode, context);
hashCode = MurmurHash.Update(hashCode, semanticContext);
hashCode = MurmurHash.Finish(hashCode, 4);
return hashCode;
}
public override String ToString()
{
return ToString(null, true);
}
public String ToString(IRecognizer recog, bool showAlt)
{
StringBuilder buf = new StringBuilder();
// if ( state.ruleIndex>=0 ) {
// if ( recog!=null ) buf.append(recog.getRuleNames()[state.ruleIndex]+":");
// else buf.append(state.ruleIndex+":");
// }
buf.Append('(');
buf.Append(state);
if (showAlt)
{
buf.Append(",");
buf.Append(alt);
}
if (context != null)
{
buf.Append(",[");
buf.Append(context.ToString());
buf.Append("]");
}
if (semanticContext != null && semanticContext != SemanticContext.NONE)
{
buf.Append(",");
buf.Append(semanticContext);
}
if (OuterContextDepth > 0)
{
buf.Append(",up=").Append(OuterContextDepth);
}
buf.Append(')');
return buf.ToString();
}
}
}