CSharp.src.Atn.ATN.cs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of antlr4-runtime-testsuite Show documentation
Show all versions of antlr4-runtime-testsuite Show documentation
A collection of tests for ANTLR 4 Runtime libraries.
/* 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.Concurrent;
using System.Collections.Generic;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Dfa;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Atn
{
public class ATN
{
public const int INVALID_ALT_NUMBER = 0;
[NotNull]
public readonly IList states = new List();
///
/// Each subrule/rule is a decision point and we must track them so we
/// can go back later and build DFA predictors for them.
///
///
/// Each subrule/rule is a decision point and we must track them so we
/// can go back later and build DFA predictors for them. This includes
/// all the rules, subrules, optional blocks, ()+, ()* etc...
///
[NotNull]
public readonly IList decisionToState = new List();
/// Maps from rule index to starting state number.
/// Maps from rule index to starting state number.
public RuleStartState[] ruleToStartState;
/// Maps from rule index to stop state number.
/// Maps from rule index to stop state number.
public RuleStopState[] ruleToStopState;
[NotNull]
public readonly IDictionary modeNameToStartState = new Dictionary();
/// The type of the ATN.
/// The type of the ATN.
public readonly ATNType grammarType;
/// The maximum value for any symbol recognized by a transition in the ATN.
/// The maximum value for any symbol recognized by a transition in the ATN.
public readonly int maxTokenType;
/// For lexer ATNs, this maps the rule index to the resulting token type.
///
/// For lexer ATNs, this maps the rule index to the resulting token type.
/// For parser ATNs, this maps the rule index to the generated bypass token
/// type if the
///
/// deserialization option was specified; otherwise, this is
///
/// .
///
public int[] ruleToTokenType;
///
/// For lexer ATNs, this is an array of
///
/// objects which may
/// be referenced by action transitions in the ATN.
///
public ILexerAction[] lexerActions;
[NotNull]
public readonly IList modeToStartState = new List();
private readonly PredictionContextCache contextCache = new PredictionContextCache();
[NotNull]
public DFA[] decisionToDFA = new DFA[0];
[NotNull]
public DFA[] modeToDFA = new DFA[0];
protected internal readonly ConcurrentDictionary LL1Table = new ConcurrentDictionary();
/// Used for runtime deserialization of ATNs from strings
public ATN(ATNType grammarType, int maxTokenType)
{
this.grammarType = grammarType;
this.maxTokenType = maxTokenType;
}
public virtual PredictionContext GetCachedContext(PredictionContext context)
{
return PredictionContext.GetCachedContext(context, contextCache, new PredictionContext.IdentityHashMap());
}
///
/// Compute the set of valid tokens that can occur starting in state
///
/// .
/// If
///
/// is
///
/// , the set of tokens will not include what can follow
/// the rule surrounding
///
/// . In other words, the set will be
/// restricted to tokens reachable staying within
///
/// 's rule.
///
[return: NotNull]
public virtual IntervalSet NextTokens(ATNState s, RuleContext ctx)
{
LL1Analyzer anal = new LL1Analyzer(this);
IntervalSet next = anal.Look(s, ctx);
return next;
}
///
/// Compute the set of valid tokens that can occur starting in
///
/// and
/// staying in same rule.
///
/// is in set if we reach end of
/// rule.
///
[return: NotNull]
public virtual IntervalSet NextTokens(ATNState s)
{
if (s.nextTokenWithinRule != null)
{
return s.nextTokenWithinRule;
}
s.nextTokenWithinRule = NextTokens(s, null);
s.nextTokenWithinRule.SetReadonly(true);
return s.nextTokenWithinRule;
}
public virtual void AddState(ATNState state)
{
if (state != null)
{
state.atn = this;
state.stateNumber = states.Count;
}
states.Add(state);
}
public virtual void RemoveState(ATNState state)
{
states[state.stateNumber] = null;
}
// just free mem, don't shift states in list
public virtual void DefineMode(string name, TokensStartState s)
{
modeNameToStartState[name] = s;
modeToStartState.Add(s);
modeToDFA = Arrays.CopyOf(modeToDFA, modeToStartState.Count);
modeToDFA[modeToDFA.Length - 1] = new DFA(s);
DefineDecisionState(s);
}
public virtual int DefineDecisionState(DecisionState s)
{
decisionToState.Add(s);
s.decision = decisionToState.Count - 1;
decisionToDFA = Arrays.CopyOf(decisionToDFA, decisionToState.Count);
decisionToDFA[decisionToDFA.Length - 1] = new DFA(s, s.decision);
return s.decision;
}
public virtual DecisionState GetDecisionState(int decision)
{
if (decisionToState.Count != 0)
{
return decisionToState[decision];
}
return null;
}
public virtual int NumberOfDecisions
{
get
{
return decisionToState.Count;
}
}
///
/// Computes the set of input symbols which could follow ATN state number
///
/// in the specified full
///
/// . This method
/// considers the complete parser context, but does not evaluate semantic
/// predicates (i.e. all predicates encountered during the calculation are
/// assumed true). If a path in the ATN exists from the starting state to the
///
/// of the outermost context without matching any
/// symbols,
///
/// is added to the returned set.
/// If
///
/// is
///
/// , it is treated as
///
/// .
///
/// the ATN state number
/// the full parse context
///
/// The set of potentially valid input symbols which could follow the
/// specified state in the specified context.
///
///
/// if the ATN does not contain a state with
/// number
///
///
[return: NotNull]
public virtual IntervalSet GetExpectedTokens(int stateNumber, RuleContext context)
{
if (stateNumber < 0 || stateNumber >= states.Count)
{
throw new ArgumentException("Invalid state number.");
}
RuleContext ctx = context;
ATNState s = states[stateNumber];
IntervalSet following = NextTokens(s);
if (!following.Contains(TokenConstants.EPSILON))
{
return following;
}
IntervalSet expected = new IntervalSet();
expected.AddAll(following);
expected.Remove(TokenConstants.EPSILON);
while (ctx != null && ctx.invokingState >= 0 && following.Contains(TokenConstants.EPSILON))
{
ATNState invokingState = states[ctx.invokingState];
RuleTransition rt = (RuleTransition)invokingState.Transition(0);
following = NextTokens(rt.followState);
expected.AddAll(following);
expected.Remove(TokenConstants.EPSILON);
ctx = ctx.Parent;
}
if (following.Contains(TokenConstants.EPSILON))
{
expected.Add(TokenConstants.EOF);
}
return expected;
}
}
}