Repository URL to install this package:
|
Version:
2023.12.1 ▾
|
/* 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 Antlr4.Runtime.Atn;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime.Dfa
{
public class DFA
{
/** A set of all DFA states. Use {@link Map} so we can get old state back
* ({@link Set} only allows you to see if it's there).
*/
public Dictionary<DFAState, DFAState> states = new Dictionary<DFAState, DFAState>();
public DFAState s0;
public int decision;
/** From which ATN state did we create this DFA? */
public DecisionState atnStartState;
/**
* {@code true} if this DFA is for a precedence decision; otherwise,
* {@code false}. This is the backing field for {@link #isPrecedenceDfa}.
*/
private bool precedenceDfa;
public DFA(DecisionState atnStartState)
: this(atnStartState, 0)
{
}
public DFA(DecisionState atnStartState, int decision)
{
this.atnStartState = atnStartState;
this.decision = decision;
this.precedenceDfa = false;
if (atnStartState is StarLoopEntryState && ((StarLoopEntryState)atnStartState).isPrecedenceDecision)
{
this.precedenceDfa = true;
DFAState precedenceState = new DFAState(new ATNConfigSet());
precedenceState.edges = new DFAState[0];
precedenceState.isAcceptState = false;
precedenceState.requiresFullContext = false;
this.s0 = precedenceState;
}
}
/**
* Gets whether this DFA is a precedence DFA. Precedence DFAs use a special
* start state {@link #s0} which is not stored in {@link #states}. The
* {@link DFAState#edges} array for this start state contains outgoing edges
* supplying individual start states corresponding to specific precedence
* values.
*
* @return {@code true} if this is a precedence DFA; otherwise,
* {@code false}.
* @see Parser#getPrecedence()
*/
public bool IsPrecedenceDfa
{
get
{
return precedenceDfa;
}
}
/**
* Get the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @return The start state corresponding to the specified precedence, or
* {@code null} if no start state exists for the specified precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.
* @see #isPrecedenceDfa()
*/
public DFAState GetPrecedenceStartState(int precedence)
{
if (!IsPrecedenceDfa)
{
throw new Exception("Only precedence DFAs may contain a precedence start state.");
}
// s0.edges is never null for a precedence DFA
if (precedence < 0 || precedence >= s0.edges.Length)
{
return null;
}
return s0.edges[precedence];
}
/**
* Set the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @param startState The start state corresponding to the specified
* precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.
* @see #isPrecedenceDfa()
*/
public void SetPrecedenceStartState(int precedence, DFAState startState)
{
if (!IsPrecedenceDfa)
{
throw new Exception("Only precedence DFAs may contain a precedence start state.");
}
if (precedence < 0)
{
return;
}
// synchronization on s0 here is ok. when the DFA is turned into a
// precedence DFA, s0 will be initialized once and not updated again
lock (s0)
{
// s0.edges is never null for a precedence DFA
if (precedence >= s0.edges.Length)
{
s0.edges = Arrays.CopyOf(s0.edges, precedence + 1);
}
s0.edges[precedence] = startState;
}
}
/**
* Return a list of all states in this DFA, ordered by state number.
*/
public List<DFAState> GetStates()
{
List<DFAState> result = new List<DFAState>(states.Keys);
result.Sort((x, y) => x.stateNumber - y.stateNumber);
return result;
}
public override String ToString() { return ToString(Vocabulary.EmptyVocabulary); }
public String ToString(IVocabulary vocabulary)
{
if (s0 == null)
{
return "";
}
DFASerializer serializer = new DFASerializer(this, vocabulary);
return serializer.ToString();
}
public String ToLexerString()
{
if (s0 == null)
return "";
DFASerializer serializer = new LexerDFASerializer(this);
return serializer.ToString();
}
}
}