A DFA state represents a set of possible ATN configurations.
A DFA state represents a set of possible ATN configurations. As Aho, Sethi, Ullman p. 117 says "The DFA uses its state to keep track of all possible states the ATN can be in after reading each input symbol. That is to say, after reading input a1a2..an, the DFA is in a state that represents the subset T of the states of the ATN that are reachable from the ATN's start state along some path labeled a1a2..an." In conventional NFA→DFA conversion, therefore, the subset T would be a bitset representing the set of states the ATN could be in. We need to track the alt predicted by each state as well, however. More importantly, we need to maintain a stack of states, tracking the closure operations as they jump from rule to rule, emulating rule invocations (method calls). I have to add a stack to simulate the proper lookahead sequences for the underlying LL grammar from which the ATN was derived.

I use a set of ATNConfig objects not simple states. An ATNConfig is both a state (ala normal conversion) and a RuleContext describing the chain of rules (if any) followed to arrive at that state.

A DFA state may have multiple references to a particular state, but with different ATN contexts (with same or different alts) meaning that state was reached via a different set of rule invocations.

コード例 #1
0
 // forces unicode to stay in ATN
 protected internal virtual void Reset()
 {
     index = -1;
     line = 0;
     charPos = -1;
     dfaState = null;
 }
コード例 #2
0
        public override string ToString()
        {
            if (dfa.s0.Get() == null)
            {
                return(null);
            }
            StringBuilder buf = new StringBuilder();

            if (dfa.states != null)
            {
                List <DFAState> states = new List <DFAState>(dfa.states.Values);
                states.Sort(new _IComparer_103());
                foreach (DFAState s in states)
                {
                    IEnumerable <KeyValuePair <int, DFAState> > edges        = s.EdgeMap;
                    IEnumerable <KeyValuePair <int, DFAState> > contextEdges = s.ContextEdgeMap;
                    foreach (KeyValuePair <int, DFAState> entry in edges)
                    {
                        if ((entry.Value == null || entry.Value == ATNSimulator.Error) && !s.IsContextSymbol(entry.Key))
                        {
                            continue;
                        }
                        bool contextSymbol = false;
                        buf.Append(GetStateString(s)).Append("-").Append(GetEdgeLabel(entry.Key)).Append("->");
                        if (s.IsContextSymbol(entry.Key))
                        {
                            buf.Append("!");
                            contextSymbol = true;
                        }
                        DFAState t = entry.Value;
                        if (t != null && t.stateNumber != int.MaxValue)
                        {
                            buf.Append(GetStateString(t)).Append('\n');
                        }
                        else
                        {
                            if (contextSymbol)
                            {
                                buf.Append("ctx\n");
                            }
                        }
                    }
                    if (s.IsContextSensitive)
                    {
                        foreach (KeyValuePair <int, DFAState> entry_1 in contextEdges)
                        {
                            buf.Append(GetStateString(s)).Append("-").Append(GetContextLabel(entry_1.Key)).Append("->").Append(GetStateString(entry_1.Value)).Append("\n");
                        }
                    }
                }
            }
            string output = buf.ToString();

            if (output.Length == 0)
            {
                return(null);
            }
            //return Utils.sortLinesInString(output);
            return(output);
        }
コード例 #3
0
        /**
         * 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;
            }
        }
コード例 #4
0
        internal virtual string GetStateString(DFAState s)
        {
            if (s == ATNSimulator.ERROR)
            {
                return("ERROR");
            }

            int    n            = s.stateNumber;
            string baseStateStr = (s.isAcceptState ? ":" : "") + "s" + n + (s.requiresFullContext ? "^" : "");

            if (s.isAcceptState)
            {
                if (s.predicates != null)
                {
                    return(baseStateStr + "=>" + Arrays.ToString(s.predicates));
                }
                else
                {
                    return(baseStateStr + "=>" + s.prediction);
                }
            }
            else
            {
                return(baseStateStr);
            }
        }
コード例 #5
0
 /// <summary>Sets whether this is a precedence DFA.</summary>
 /// <remarks>
 /// Sets whether this is a precedence DFA. If the specified value differs
 /// from the current DFA configuration, the following actions are taken;
 /// otherwise no changes are made to the current DFA.
 /// <ul>
 /// <li>The
 /// <see cref="states">states</see>
 /// map is cleared</li>
 /// <li>If
 /// <code>precedenceDfa</code>
 /// is
 /// <code>false</code>
 /// , the initial state
 /// <see cref="s0">s0</see>
 /// is set to
 /// <code>null</code>
 /// ; otherwise, it is initialized to a new
 /// <see cref="DFAState">DFAState</see>
 /// with an empty outgoing
 /// <see cref="DFAState#edges">DFAState#edges</see>
 /// array to
 /// store the start states for individual precedence values.</li>
 /// <li>The
 /// <see cref="precedenceDfa">precedenceDfa</see>
 /// field is updated</li>
 /// </ul>
 /// </remarks>
 /// <param name="precedenceDfa">
 ///
 /// <code>true</code>
 /// if this is a precedence DFA; otherwise,
 /// <code>false</code>
 /// </param>
 public void SetPrecedenceDfa(bool precedenceDfa)
 {
     lock (this)
     {
         if (this.precedenceDfa != precedenceDfa)
         {
             this.states.Clear();
             if (precedenceDfa)
             {
                 DFAState precedenceState = new DFAState(new ATNConfigSet(), 0, 200);
                 precedenceState.isAcceptState = false;
                 this.s0.Set(precedenceState);
                 DFAState fullContextPrecedenceState = new DFAState(new ATNConfigSet(), 0, 200);
                 fullContextPrecedenceState.isAcceptState = false;
                 this.s0full.Set(fullContextPrecedenceState);
             }
             else
             {
                 this.s0.Set(null);
                 this.s0full.Set(null);
             }
             this.precedenceDfa = precedenceDfa;
         }
     }
 }
コード例 #6
0
ファイル: DFASerializer.cs プロジェクト: yuanyong00/antlr4cs
        internal virtual string GetStateString(DFAState s)
        {
            if (s == ATNSimulator.Error)
            {
                return("ERROR");
            }
            int    n        = s.stateNumber;
            string stateStr = "s" + n;

            if (s.IsAcceptState)
            {
                if (s.predicates != null)
                {
                    stateStr = ":s" + n + "=>" + Arrays.ToString(s.predicates);
                }
                else
                {
                    stateStr = ":s" + n + "=>" + s.Prediction;
                }
            }
            if (s.IsContextSensitive)
            {
                stateStr += "*";
                foreach (ATNConfig config in s.configs)
                {
                    if (config.ReachesIntoOuterContext)
                    {
                        stateStr += "*";
                        break;
                    }
                }
            }
            return(stateStr);
        }
コード例 #7
0
 /// <summary>Set the start state for a specific precedence value.</summary>
 /// <param name="precedence">The current precedence.</param>
 /// <param name="fullContext"></param>
 /// <param name="startState">
 /// The start state corresponding to the specified
 /// precedence.
 /// </param>
 /// <exception cref="System.InvalidOperationException">if this is not a precedence DFA.</exception>
 /// <seealso cref="IsPrecedenceDfa()"/>
 public void SetPrecedenceStartState(int precedence, bool fullContext, DFAState startState)
 {
     if (!IsPrecedenceDfa)
     {
         throw new InvalidOperationException("Only precedence DFAs may contain a precedence start state.");
     }
     if (precedence < 0)
     {
         return;
     }
     if (fullContext)
     {
         lock (s0full)
         {
             s0full.Get().SetTarget(precedence, startState);
         }
     }
     else
     {
         lock (s0)
         {
             s0.Get().SetTarget(precedence, startState);
         }
     }
 }
コード例 #8
0
ファイル: SimulatorState.cs プロジェクト: antlr/antlr4
 public SimulatorState(ParserRuleContext outerContext, DFAState s0, bool useContext, ParserRuleContext remainingOuterContext)
 {
     this.outerContext = outerContext != null ? outerContext : ParserRuleContext.EmptyContext;
     this.s0 = s0;
     this.useContext = useContext;
     this.remainingOuterContext = remainingOuterContext;
 }
コード例 #9
0
ファイル: DFAState.cs プロジェクト: rharrisxtheta/antlr4cs
 public virtual void SetTarget(int symbol, DFAState target)
 {
     lock (this)
     {
         if (edges == null)
         {
             edges = new SingletonEdgeMap <DFAState>(minSymbol, maxSymbol);
         }
         edges = edges.Put(symbol, target);
     }
 }
コード例 #10
0
 public virtual void SetContextTarget(int invokingState, DFAState target)
 {
     lock (this)
     {
         if (!IsContextSensitive)
         {
             throw new InvalidOperationException("The state is not context sensitive.");
         }
         if (invokingState == PredictionContext.EmptyFullStateKey)
         {
             invokingState = -1;
         }
         contextEdges = contextEdges.Put(invokingState, target);
     }
 }
コード例 #11
0
ファイル: DFA.cs プロジェクト: antlr/antlr4
        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;
            }
        }
コード例 #12
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;
            }
        }
コード例 #13
0
        /// <summary>
        /// Two
        /// <see cref="DFAState"/>
        /// instances are equal if their ATN configuration sets
        /// are the same. This method is used to see if a state already exists.
        /// <p>Because the number of alternatives and number of ATN configurations are
        /// finite, there is a finite number of DFA states that can be processed.
        /// This is necessary to show that the algorithm terminates.</p>
        /// <p>Cannot test the DFA state numbers here because in
        /// <see cref="Antlr4.Runtime.Atn.ParserATNSimulator.AddDFAState(DFA, Antlr4.Runtime.Atn.ATNConfigSet, Antlr4.Runtime.Atn.PredictionContextCache)"/>
        /// we need to know if any other state
        /// exists that has this exact set of ATN configurations. The
        /// <see cref="stateNumber"/>
        /// is irrelevant.</p>
        /// </summary>
        public override bool Equals(object o)
        {
            // compare set of ATN configurations in this set with other
            if (this == o)
            {
                return(true);
            }
            if (!(o is DFAState))
            {
                return(false);
            }
            DFAState other   = (DFAState)o;
            bool     sameSet = this.configs.Equals(other.configs);

            //		System.out.println("DFAState.equals: "+configs+(sameSet?"==":"!=")+other.configs);
            return(sameSet);
        }
コード例 #14
0
        public override string ToString()
        {
            if (dfa.s0 == null)
            {
                return(null);
            }
            StringBuilder buf = new StringBuilder();

            if (dfa.states != null)
            {
                List <DFAState> states = new List <DFAState>(dfa.states.Values);
                states.Sort((x, y) => x.stateNumber - y.stateNumber);
                foreach (DFAState s in states)
                {
                    int n = s.edges != null ? s.edges.Length : 0;
                    for (int i = 0; i < n; i++)
                    {
                        DFAState t = s.edges[i];
                        if (t != null && t.stateNumber != int.MaxValue)
                        {
                            buf.Append(GetStateString(s));
                            String label = GetEdgeLabel(i);
                            buf.Append("-");
                            buf.Append(label);
                            buf.Append("->");
                            buf.Append(GetStateString(t));
                            buf.Append('\n');
                        }
                    }
                }
            }
            string output = buf.ToString();

            if (output.Length == 0)
            {
                return(null);
            }
            return(output);
        }
コード例 #15
0
 protected internal virtual DFAState AddDFAEdge(DFAState from, int t, ATNConfigSet q)
 {
     /* leading to this call, ATNConfigSet.hasSemanticContext is used as a
     * marker indicating dynamic predicate evaluation makes this edge
     * dependent on the specific input sequence, so the static edge in the
     * DFA should be omitted. The target DFAState is still created since
     * execATN has the ability to resynchronize with the DFA state cache
     * following the predicate evaluation step.
     *
     * TJP notes: next time through the DFA, we see a pred again and eval.
     * If that gets us to a previously created (but dangling) DFA
     * state, we can continue in pure DFA mode from there.
     */
     bool suppressEdge = q.HasSemanticContext;
     if (suppressEdge)
     {
         q.ClearExplicitSemanticContext();
     }
     DFAState to = AddDFAState(q);
     if (suppressEdge)
     {
         return to;
     }
     AddDFAEdge(from, t, to);
     return to;
 }
コード例 #16
0
 public virtual DFAState AddState(DFAState state)
 {
     state.stateNumber = Interlocked.Increment(ref nextStateNumber) - 1;
     return(states.GetOrAdd(state, state));
 }
コード例 #17
0
ファイル: DFA.cs プロジェクト: RainerBosch/antlr4
 /// <summary>Set the start state for a specific precedence value.</summary>
 /// <remarks>Set the start state for a specific precedence value.</remarks>
 /// <param name="precedence">The current precedence.</param>
 /// <param name="fullContext">Whether to set local of full context.</param>
 /// <param name="startState">
 /// The start state corresponding to the specified
 /// precedence.
 /// </param>
 /// <exception cref="System.InvalidOperationException">if this is not a precedence DFA.</exception>
 /// <seealso cref="IsPrecedenceDfa()"/>
 public void SetPrecedenceStartState(int precedence, bool fullContext, DFAState startState)
 {
     if (!IsPrecedenceDfa)
     {
         throw new InvalidOperationException("Only precedence DFAs may contain a precedence start state.");
     }
     if (precedence < 0)
     {
         return;
     }
     if (fullContext)
     {
         lock (s0full)
         {
             s0full.Get().SetTarget(precedence, startState);
         }
     }
     else
     {
         lock (s0)
         {
             s0.Get().SetTarget(precedence, startState);
         }
     }
 }
コード例 #18
0
ファイル: ProfilingATNSimulator.cs プロジェクト: antlr/antlr4
 protected override DFAState ComputeTargetState(DFA dfa, DFAState previousD, int t)
 {
     DFAState state = base.ComputeTargetState(dfa, previousD, t);
     currentState = state;
     return state;
 }
コード例 #19
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        /**
         * Add state {@code D} to the DFA if it is not already present, and return
         * the actual instance stored in the DFA. If a state equivalent to {@code D}
         * is already in the DFA, the existing state is returned. Otherwise this
         * method returns {@code D} after adding it to the DFA.
         *
         * <p>If {@code D} is {@link #ERROR}, this method returns {@link #ERROR} and
         * does not change the DFA.</p>
         *
         * @param dfa The dfa
         * @param D The DFA state to add
         * @return The state stored in the DFA. This will be either the existing
         * state if {@code D} is already in the DFA, or {@code D} itself if the
         * state was not already present.
         */
        protected DFAState AddDFAState(DFA dfa, DFAState D)
        {
            if (D == ERROR)
            {
                return D;
            }

            lock (dfa.states)
            {
                DFAState existing = dfa.states.Get(D);
                if (existing != null) return existing;

                D.stateNumber = dfa.states.Count;
                if (!D.configSet.IsReadOnly)
                {
                    D.configSet.OptimizeConfigs(this);
                    D.configSet.IsReadOnly = true;
                }
                dfa.states.Put(D, D);
                if (debug) Console.WriteLine("adding new DFA state: " + D);
                return D;
            }
        }
コード例 #20
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        // configs that LL not SLL considered conflicting
        /** If context sensitive parsing, we know it's ambiguity not conflict */
        protected virtual void ReportAmbiguity(DFA dfa,
									   DFAState D, // the DFA state from execATN() that had SLL conflicts
									   int startIndex, int stopIndex,
									   bool exact,
									   BitSet ambigAlts,
									   ATNConfigSet configs)
        {
            if (debug || retry_debug)
            {
                Interval interval = Interval.Of(startIndex, stopIndex);
                Console.WriteLine("ReportAmbiguity " +
                                   ambigAlts + ":" + configs +
                                   ", input=" + parser.TokenStream.GetText(interval));
            }
            if (parser != null) parser.ErrorListenerDispatch.ReportAmbiguity(parser, dfa, startIndex, stopIndex,
                                                                                  exact, ambigAlts, configs);
        }
コード例 #21
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
 protected internal virtual DFAState ComputeTargetState(ICharStream input, DFAState
      s, int t)
 {
     ATNConfigSet reach = new OrderedATNConfigSet();
     // if we don't find an existing DFA state
     // Fill reach starting from closure, following t transitions
     GetReachableConfigSet(input, s.configs, reach, t);
     if (reach.IsEmpty())
     {
         // we got nowhere on t from s
         // we got nowhere on t, don't throw out this knowledge; it'd
         // cause a failover from DFA later.
         AddDFAEdge(s, t, Error);
         // stop when we can't match any more char
         return Error;
     }
     // Add an edge from s to target DFA found/created for reach
     return AddDFAEdge(s, t, reach);
 }
コード例 #22
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
        protected internal virtual DFAState GetExistingTargetState(DFAState s, int t)
        {
            DFAState target = s.GetTarget(t);
#if !PORTABLE
            if (debug && target != null)
            {
                System.Console.Out.WriteLine("reuse state " + s.stateNumber + " edge to " + target
                    .stateNumber);
            }
#endif
            return target;
        }
コード例 #23
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
 protected internal virtual int ExecATN(ICharStream input, DFAState ds0)
 {
     //System.out.println("enter exec index "+input.index()+" from "+ds0.configs);
     int t = input.La(1);
     DFAState s = ds0;
     // s is current/from DFA state
     while (true)
     {
         // while more work
         // As we move src->trg, src->trg, we keep track of the previous trg to
         // avoid looking up the DFA state again, which is expensive.
         // If the previous target was already part of the DFA, we might
         // be able to avoid doing a reach operation upon t. If s!=null,
         // it means that semantic predicates didn't prevent us from
         // creating a DFA state. Once we know s!=null, we check to see if
         // the DFA state has an edge already for t. If so, we can just reuse
         // it's configuration set; there's no point in re-computing it.
         // This is kind of like doing DFA simulation within the ATN
         // simulation because DFA simulation is really just a way to avoid
         // computing reach/closure sets. Technically, once we know that
         // we have a previously added DFA state, we could jump over to
         // the DFA simulator. But, that would mean popping back and forth
         // a lot and making things more complicated algorithmically.
         // This optimization makes a lot of sense for loops within DFA.
         // A character will take us back to an existing DFA state
         // that already has lots of edges out of it. e.g., .* in comments.
         DFAState target = GetExistingTargetState(s, t);
         if (target == null)
         {
             target = ComputeTargetState(input, s, t);
         }
         if (target == Error)
         {
             break;
         }
         if (target.isAcceptState)
         {
             CaptureSimState(prevAccept, input, target);
             if (t == IntStreamConstants.Eof)
             {
                 break;
             }
         }
         if (t != IntStreamConstants.Eof)
         {
             Consume(input);
             t = input.La(1);
         }
         s = target;
     }
     // flip; current DFA target becomes new src/from state
     return FailOrAccept(prevAccept, input, s.configs, t);
 }
コード例 #24
0
 protected internal override DFAState GetExistingTargetState(DFAState previousD, int t)
 {
     // this method is called after each time the input position advances
     if (currentState.useContext)
     {
         _llStopIndex = _input.Index;
     }
     else
     {
         _sllStopIndex = _input.Index;
     }
     DFAState existingTargetState = base.GetExistingTargetState(previousD, t);
     if (existingTargetState != null)
     {
         // this method is directly called by execDFA; must construct a SimulatorState
         // to represent the current state for this case
         currentState = new SimulatorState(currentState.outerContext, existingTargetState, currentState.useContext, currentState.remainingOuterContext);
         if (currentState.useContext)
         {
             decisions[currentDecision].LL_DFATransitions++;
         }
         else
         {
             decisions[currentDecision].SLL_DFATransitions++;
         }
         // count only if we transition over a DFA state
         if (existingTargetState == Error)
         {
             SimulatorState state = new SimulatorState(currentState.outerContext, previousD, currentState.useContext, currentState.remainingOuterContext);
             decisions[currentDecision].errors.Add(new ErrorInfo(currentDecision, state, _input, _startIndex, _input.Index));
         }
     }
     return existingTargetState;
 }
コード例 #25
0
 protected internal override Tuple<DFAState, ParserRuleContext> ComputeTargetState(DFA dfa, DFAState s, ParserRuleContext remainingGlobalContext, int t, bool useContext, PredictionContextCache contextCache)
 {
     Tuple<DFAState, ParserRuleContext> targetState = base.ComputeTargetState(dfa, s, remainingGlobalContext, t, useContext, contextCache);
     if (useContext)
     {
         decisions[currentDecision].LL_ATNTransitions++;
     }
     else
     {
         decisions[currentDecision].SLL_ATNTransitions++;
     }
     return targetState;
 }
コード例 #26
0
 protected internal virtual DFAState AddDFAState(ATNConfigSet configs)
 {
     /* the lexer evaluates predicates on-the-fly; by this point configs
     * should not contain any configurations with unevaluated predicates.
     */
     System.Diagnostics.Debug.Assert(!configs.HasSemanticContext);
     DFAState proposed = new DFAState(atn.modeToDFA[mode], configs);
     DFAState existing;
     if (atn.modeToDFA[mode].states.TryGetValue(proposed, out existing))
     {
         return existing;
     }
     configs.OptimizeConfigs(this);
     DFAState newState = new DFAState(atn.modeToDFA[mode], configs.Clone(true));
     ATNConfig firstConfigWithRuleStopState = null;
     foreach (ATNConfig c in configs)
     {
         if (c.State is RuleStopState)
         {
             firstConfigWithRuleStopState = c;
             break;
         }
     }
     if (firstConfigWithRuleStopState != null)
     {
         int prediction = atn.ruleToTokenType[firstConfigWithRuleStopState.State.ruleIndex];
         LexerActionExecutor lexerActionExecutor = firstConfigWithRuleStopState.ActionExecutor;
         newState.AcceptStateInfo = new AcceptStateInfo(prediction, lexerActionExecutor);
     }
     return atn.modeToDFA[mode].AddState(newState);
 }
コード例 #27
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        /**
         * Get an existing target state for an edge in the DFA. If the target state
         * for the edge has not yet been computed or is otherwise not available,
         * this method returns {@code null}.
         *
         * @param previousD The current DFA state
         * @param t The next input symbol
         * @return The existing target DFA state for the given input symbol
         * {@code t}, or {@code null} if the target state for this edge is not
         * already cached
         */
        protected virtual DFAState GetExistingTargetState(DFAState previousD, int t)
        {
            DFAState[] edges = previousD.edges;
            if (edges == null || t + 1 < 0 || t + 1 >= edges.Length)
            {
                return null;
            }

            return edges[t + 1];
        }
コード例 #28
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
 protected void PredicateDFAState(DFAState dfaState, DecisionState decisionState)
 {
     // We need to test all predicates, even in DFA states that
     // uniquely predict alternative.
     int nalts = decisionState.NumberOfTransitions;
     // Update DFA so reach becomes accept state with (predicate,alt)
     // pairs if preds found for conflicting alts
     BitSet altsToCollectPredsFrom = GetConflictingAltsOrUniqueAlt(dfaState.configSet);
     SemanticContext[] altToPred = GetPredsForAmbigAlts(altsToCollectPredsFrom, dfaState.configSet, nalts);
     if (altToPred != null)
     {
         dfaState.predicates = GetPredicatePredictions(altsToCollectPredsFrom, altToPred);
         dfaState.prediction = ATN.INVALID_ALT_NUMBER; // make sure we use preds
     }
     else {
         // There are preds in configs but they might go away
         // when OR'd together like {p}? || NONE == NONE. If neither
         // alt has preds, resolve to min alt
         dfaState.prediction = altsToCollectPredsFrom.NextSetBit(0);
     }
 }
コード例 #29
0
ファイル: DFAState.cs プロジェクト: RainerBosch/antlr4
 public virtual void SetTarget(int symbol, DFAState target)
 {
     edges = edges.Put(symbol, target);
 }
コード例 #30
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        /**
         * Add an edge to the DFA, if possible. This method calls
         * {@link #addDFAState} to ensure the {@code to} state is present in the
         * DFA. If {@code from} is {@code null}, or if {@code t} is outside the
         * range of edges that can be represented in the DFA tables, this method
         * returns without adding the edge to the DFA.
         *
         * <p>If {@code to} is {@code null}, this method returns {@code null}.
         * Otherwise, this method returns the {@link DFAState} returned by calling
         * {@link #addDFAState} for the {@code to} state.</p>
         *
         * @param dfa The DFA
         * @param from The source state for the edge
         * @param t The input symbol
         * @param to The target state for the edge
         *
         * @return If {@code to} is {@code null}, this method returns {@code null};
         * otherwise this method returns the result of calling {@link #addDFAState}
         * on {@code to}
         */
        protected DFAState AddDFAEdge(DFA dfa,
									  DFAState from,
									  int t,
									  DFAState to)
        {
            if (debug)
            {
                Console.WriteLine("EDGE " + from + " -> " + to + " upon " + GetTokenName(t));
            }

            if (to == null)
            {
                return null;
            }

            to = AddDFAState(dfa, to); // used existing if possible not incoming
            if (from == null || t < -1 || t > atn.maxTokenType)
            {
                return to;
            }

            lock (from)
            {
                if (from.edges == null)
                {
                    from.edges = new DFAState[atn.maxTokenType + 1 + 1];
                }

                from.edges[t + 1] = to; // connect
            }

            if (debug)
            {
                Console.WriteLine("DFA=\n" + dfa.ToString(parser != null ? parser.Vocabulary : Vocabulary.EmptyVocabulary));
            }

            return to;
        }
コード例 #31
0
ファイル: ProfilingATNSimulator.cs プロジェクト: antlr/antlr4
        protected override DFAState GetExistingTargetState(DFAState previousD, int t)
        {
            // this method is called after each time the input position advances
            // during SLL prediction
            sllStopIndex = input.Index;

            DFAState existingTargetState = base.GetExistingTargetState(previousD, t);
            if (existingTargetState != null)
            {
            decisions[currentDecision].SLL_DFATransitions++; // count only if we transition over a DFA state
            if (existingTargetState == ERROR)
            {
                decisions[currentDecision].errors.Add(
                        new ErrorInfo(currentDecision, null /*previousD.configs*/, input, startIndex, sllStopIndex)
                );
            }
            }

            currentState = existingTargetState;
            return existingTargetState;
        }
コード例 #32
0
 public virtual void SetTarget(int symbol, DFAState target)
 {
     edges = edges.Put(symbol, target);
 }
コード例 #33
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
 protected internal virtual void AddDFAEdge(DFAState p, int t, DFAState q)
 {
     if (p != null)
     {
         p.SetTarget(t, q);
     }
 }
コード例 #34
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
 protected internal virtual DFAState AddDFAState(ATNConfigSet configs)
 {
     System.Diagnostics.Debug.Assert(!configs.HasSemanticContext);
     DFAState proposed = new DFAState(configs, 0, MaxDfaEdge);
     DFAState existing;
     if (atn.modeToDFA[mode].states.TryGetValue(proposed, out existing))
     {
         return existing;
     }
     configs.OptimizeConfigs(this);
     DFAState newState = new DFAState(configs.Clone(true), 0, MaxDfaEdge);
     ATNConfig firstConfigWithRuleStopState = null;
     foreach (ATNConfig c in configs)
     {
         if (c.State is RuleStopState)
         {
             firstConfigWithRuleStopState = c;
             break;
         }
     }
     if (firstConfigWithRuleStopState != null)
     {
         newState.isAcceptState = true;
         newState.lexerRuleIndex = firstConfigWithRuleStopState.State.ruleIndex;
         newState.lexerActionIndex = firstConfigWithRuleStopState.ActionIndex;
         newState.prediction = atn.ruleToTokenType[newState.lexerRuleIndex];
     }
     return atn.modeToDFA[mode].AddState(newState);
 }
コード例 #35
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        /**
         * Compute a target state for an edge in the DFA, and attempt to add the
         * computed state and corresponding edge to the DFA.
         *
         * @param dfa The DFA
         * @param previousD The current DFA state
         * @param t The next input symbol
         *
         * @return The computed target DFA state for the given input symbol
         * {@code t}. If {@code t} does not lead to a valid DFA state, this method
         * returns {@link #ERROR}.
         */
        protected virtual DFAState ComputeTargetState(DFA dfa, DFAState previousD, int t)
        {
            ATNConfigSet reach = ComputeReachSet(previousD.configSet, t, false);
            if (reach == null)
            {
                AddDFAEdge(dfa, previousD, t, ERROR);
                return ERROR;
            }

            // create new target state; we'll add to DFA after it's complete
            DFAState D = new DFAState(reach);

            int predictedAlt = GetUniqueAlt(reach);

            if (debug)
            {
                ICollection<BitSet> altSubSets = PredictionMode.GetConflictingAltSubsets(reach.configs);
                Console.WriteLine("SLL altSubSets=" + altSubSets +
                                   ", configs=" + reach +
                                   ", predict=" + predictedAlt + ", allSubsetsConflict=" +
                                       PredictionMode.AllSubsetsConflict(altSubSets) + ", conflictingAlts=" +
                                   GetConflictingAlts(reach));
            }

            if (predictedAlt != ATN.INVALID_ALT_NUMBER)
            {
                // NO CONFLICT, UNIQUELY PREDICTED ALT
                D.isAcceptState = true;
                D.configSet.uniqueAlt = predictedAlt;
                D.prediction = predictedAlt;
            }
            else if (PredictionMode.HasSLLConflictTerminatingPrediction(mode, reach))
            {
                // MORE THAN ONE VIABLE ALTERNATIVE
                D.configSet.conflictingAlts = GetConflictingAlts(reach);
                D.requiresFullContext = true;
                // in SLL-only mode, we will stop at this state and return the minimum alt
                D.isAcceptState = true;
                D.prediction = D.configSet.conflictingAlts.NextSetBit(0);
            }

            if (D.isAcceptState && D.configSet.hasSemanticContext)
            {
                PredicateDFAState(D, atn.GetDecisionState(dfa.decision));
                if (D.predicates != null)
                {
                    D.prediction = ATN.INVALID_ALT_NUMBER;
                }
            }

            // all adds to dfa are done after we've created full D state
            D = AddDFAEdge(dfa, previousD, t, D);
            return D;
        }
コード例 #36
0
ファイル: DFA.cs プロジェクト: RainerBosch/antlr4
 public virtual DFAState AddState(DFAState state)
 {
     state.stateNumber = Interlocked.Increment(ref nextStateNumber) - 1;
     return states.GetOrAdd(state, state);
 }
コード例 #37
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        /** Performs ATN simulation to compute a predicted alternative based
         *  upon the remaining input, but also updates the DFA cache to avoid
         *  having to traverse the ATN again for the same input sequence.

         There are some key conditions we're looking for after computing a new
         set of ATN configs (proposed DFA state):
               * if the set is empty, there is no viable alternative for current symbol
               * does the state uniquely predict an alternative?
               * does the state have a conflict that would prevent us from
                 putting it on the work list?

         We also have some key operations to do:
               * add an edge from previous DFA state to potentially new DFA state, D,
                 upon current symbol but only if adding to work list, which means in all
                 cases except no viable alternative (and possibly non-greedy decisions?)
               * collecting predicates and adding semantic context to DFA accept states
               * adding rule context to context-sensitive DFA accept states
               * consuming an input symbol
               * reporting a conflict
               * reporting an ambiguity
               * reporting a context sensitivity
               * reporting insufficient predicates

         cover these cases:
            dead end
            single alt
            single alt + preds
            conflict
            conflict + preds
         */
        protected int ExecATN(DFA dfa, DFAState s0,
						   ITokenStream input, int startIndex,
						   ParserRuleContext outerContext)
        {
            if (debug || debug_list_atn_decisions)
            {
                Console.WriteLine("execATN decision " + dfa.decision +
                                   " exec LA(1)==" + GetLookaheadName(input) +
                                   " line " + input.LT(1).Line + ":" + input.LT(1).Column);
            }

            DFAState previousD = s0;

            if (debug) Console.WriteLine("s0 = " + s0);

            int t = input.LA(1);

            while (true)
            { // while more work
                DFAState D = GetExistingTargetState(previousD, t);
                if (D == null)
                {
                    D = ComputeTargetState(dfa, previousD, t);
                }

                if (D == ERROR)
                {
                    // if any configs in previous dipped into outer context, that
                    // means that input up to t actually finished entry rule
                    // at least for SLL decision. Full LL doesn't dip into outer
                    // so don't need special case.
                    // We will get an error no matter what so delay until after
                    // decision; better error message. Also, no reachable target
                    // ATN states in SLL implies LL will also get nowhere.
                    // If conflict in states that dip out, choose min since we
                    // will get error no matter what.
                    NoViableAltException e = NoViableAlt(input, outerContext, previousD.configSet, startIndex);
                    input.Seek(startIndex);
                    int alt = GetSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configSet, outerContext);
                    if (alt != ATN.INVALID_ALT_NUMBER)
                    {
                        return alt;
                    }
                    throw e;
                }

                if (D.requiresFullContext && mode != PredictionMode.SLL)
                {
                    // IF PREDS, MIGHT RESOLVE TO SINGLE ALT => SLL (or syntax error)
                    BitSet conflictingAlts = D.configSet.conflictingAlts;
                    if (D.predicates != null)
                    {
                        if (debug) Console.WriteLine("DFA state has preds in DFA sim LL failover");
                        int conflictIndex = input.Index;
                        if (conflictIndex != startIndex)
                        {
                            input.Seek(startIndex);
                        }

                        conflictingAlts = EvalSemanticContext(D.predicates, outerContext, true);
                        if (conflictingAlts.Cardinality() == 1)
                        {
                            if (debug) Console.WriteLine("Full LL avoided");
                            return conflictingAlts.NextSetBit(0);
                        }

                        if (conflictIndex != startIndex)
                        {
                            // restore the index so reporting the fallback to full
                            // context occurs with the index at the correct spot
                            input.Seek(conflictIndex);
                        }
                    }

                    if (dfa_debug) Console.WriteLine("ctx sensitive state " + outerContext + " in " + D);
                    bool fullCtx = true;
                    ATNConfigSet s0_closure =
                        ComputeStartState(dfa.atnStartState, outerContext, fullCtx);
                    ReportAttemptingFullContext(dfa, conflictingAlts, D.configSet, startIndex, input.Index);
                    int alt = ExecATNWithFullContext(dfa, D, s0_closure,
                                                     input, startIndex,
                                                     outerContext);
                    return alt;
                }

                if (D.isAcceptState)
                {
                    if (D.predicates == null)
                    {
                        return D.prediction;
                    }

                    int stopIndex = input.Index;
                    input.Seek(startIndex);
                    BitSet alts = EvalSemanticContext(D.predicates, outerContext, true);
                    switch (alts.Cardinality())
                    {
                        case 0:
                            throw NoViableAlt(input, outerContext, D.configSet, startIndex);

                        case 1:
                            return alts.NextSetBit(0);

                        default:
                            // report ambiguity after predicate evaluation to make sure the correct
                            // set of ambig alts is reported.
                            ReportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configSet);
                            return alts.NextSetBit(0);
                    }
                }

                previousD = D;

                if (t != IntStreamConstants.EOF)
                {
                    input.Consume();
                    t = input.LA(1);
                }
            }
        }
コード例 #38
0
ファイル: DFAState.cs プロジェクト: nickdurcholz/antlr4cs
 public virtual void SetTarget(int symbol, DFAState target)
 {
     lock (this)
     {
         if (edges == null)
         {
             edges = new SingletonEdgeMap<DFAState>(minSymbol, maxSymbol);
         }
         edges = edges.Put(symbol, target);
     }
 }
コード例 #39
0
ファイル: ParserATNSimulator.cs プロジェクト: antlr/antlr4
        // comes back with reach.UniqueAlt set to a valid alt
        protected int ExecATNWithFullContext(DFA dfa,
											 DFAState D, // how far we got in SLL DFA before failing over
											 ATNConfigSet s0,
											 ITokenStream input, int startIndex,
											 ParserRuleContext outerContext)
        {
            if (debug || debug_list_atn_decisions)
            {
                Console.WriteLine("execATNWithFullContext " + s0);
            }
            bool fullCtx = true;
            bool foundExactAmbig = false;
            ATNConfigSet reach = null;
            ATNConfigSet previous = s0;
            input.Seek(startIndex);
            int t = input.LA(1);
            int predictedAlt;
            while (true)
            { // while more work
              //			Console.WriteLine("LL REACH "+GetLookaheadName(input)+
              //							   " from configs.size="+previous.size()+
              //							   " line "+input.LT(1)Line+":"+input.LT(1).Column);
                reach = ComputeReachSet(previous, t, fullCtx);
                if (reach == null)
                {
                    // if any configs in previous dipped into outer context, that
                    // means that input up to t actually finished entry rule
                    // at least for LL decision. Full LL doesn't dip into outer
                    // so don't need special case.
                    // We will get an error no matter what so delay until after
                    // decision; better error message. Also, no reachable target
                    // ATN states in SLL implies LL will also get nowhere.
                    // If conflict in states that dip out, choose min since we
                    // will get error no matter what.
                    NoViableAltException e = NoViableAlt(input, outerContext, previous, startIndex);
                    input.Seek(startIndex);
                    int alt = GetSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext);
                    if (alt != ATN.INVALID_ALT_NUMBER)
                    {
                        return alt;
                    }
                    throw e;
                }

                ICollection<BitSet> altSubSets = PredictionMode.GetConflictingAltSubsets(reach.configs);
                if (debug)
                {
                    Console.WriteLine("LL altSubSets=" + altSubSets +
                                       ", predict=" + PredictionMode.GetUniqueAlt(altSubSets) +
                                       ", ResolvesToJustOneViableAlt=" +
                                           PredictionMode.ResolvesToJustOneViableAlt(altSubSets));
                }

                //			Console.WriteLine("altSubSets: "+altSubSets);
                //			System.err.println("reach="+reach+", "+reach.conflictingAlts);
                reach.uniqueAlt = GetUniqueAlt(reach);
                // unique prediction?
                if (reach.uniqueAlt != ATN.INVALID_ALT_NUMBER)
                {
                    predictedAlt = reach.uniqueAlt;
                    break;
                }
                if (mode != PredictionMode.LL_EXACT_AMBIG_DETECTION)
                {
                    predictedAlt = PredictionMode.ResolvesToJustOneViableAlt(altSubSets);
                    if (predictedAlt != ATN.INVALID_ALT_NUMBER)
                    {
                        break;
                    }
                }
                else {
                    // In exact ambiguity mode, we never try to terminate early.
                    // Just keeps scarfing until we know what the conflict is
                    if (PredictionMode.AllSubsetsConflict(altSubSets) &&
                         PredictionMode.AllSubsetsEqual(altSubSets))
                    {
                        foundExactAmbig = true;
                        predictedAlt = PredictionMode.GetSingleViableAlt(altSubSets);
                        break;
                    }
                    // else there are multiple non-conflicting subsets or
                    // we're not sure what the ambiguity is yet.
                    // So, keep going.
                }

                previous = reach;
                if (t != IntStreamConstants.EOF)
                {
                    input.Consume();
                    t = input.LA(1);
                }
            }

            // If the configuration set uniquely predicts an alternative,
            // without conflict, then we know that it's a full LL decision
            // not SLL.
            if (reach.uniqueAlt != ATN.INVALID_ALT_NUMBER)
            {
                ReportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.Index);
                return predictedAlt;
            }

            // We do not check predicates here because we have checked them
            // on-the-fly when doing full context prediction.

            /*
            In non-exact ambiguity detection mode, we might	actually be able to
            detect an exact ambiguity, but I'm not going to spend the cycles
            needed to check. We only emit ambiguity warnings in exact ambiguity
            mode.

            For example, we might know that we have conflicting configurations.
            But, that does not mean that there is no way forward without a
            conflict. It's possible to have nonconflicting alt subsets as in:

               LL altSubSets=[{1, 2}, {1, 2}, {1}, {1, 2}]

            from

               [(17,1,[5 $]), (13,1,[5 10 $]), (21,1,[5 10 $]), (11,1,[$]),
                (13,2,[5 10 $]), (21,2,[5 10 $]), (11,2,[$])]

            In this case, (17,1,[5 $]) indicates there is some next sequence that
            would resolve this without conflict to alternative 1. Any other viable
            next sequence, however, is associated with a conflict.  We stop
            looking for input because no amount of further lookahead will alter
            the fact that we should predict alternative 1.  We just can't say for
            sure that there is an ambiguity without looking further.
            */
            ReportAmbiguity(dfa, D, startIndex, input.Index, foundExactAmbig, reach.GetAlts(), reach);

            return predictedAlt;
        }
コード例 #40
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
 protected internal virtual void CaptureSimState(LexerATNSimulator.SimState settings
     , ICharStream input, DFAState dfaState)
 {
     settings.index = input.Index;
     settings.line = line;
     settings.charPos = charPositionInLine;
     settings.dfaState = dfaState;
 }
コード例 #41
0
 protected internal override void ReportAmbiguity(DFA dfa, DFAState D, int startIndex, int stopIndex, bool exact, BitSet ambigAlts, ATNConfigSet configs)
 {
     int prediction;
     if (ambigAlts != null)
     {
         prediction = ambigAlts.NextSetBit(0);
     }
     else
     {
         prediction = configs.RepresentedAlternatives.NextSetBit(0);
     }
     if (conflictingAltResolvedBySLL != ATN.InvalidAltNumber && prediction != conflictingAltResolvedBySLL)
     {
         // Even though this is an ambiguity we are reporting, we can
         // still detect some context sensitivities.  Both SLL and LL
         // are showing a conflict, hence an ambiguity, but if they resolve
         // to different minimum alternatives we have also identified a
         // context sensitivity.
         decisions[currentDecision].contextSensitivities.Add(new ContextSensitivityInfo(currentDecision, currentState, _input, startIndex, stopIndex));
     }
     decisions[currentDecision].ambiguities.Add(new AmbiguityInfo(currentDecision, currentState, ambigAlts, _input, startIndex, stopIndex));
     base.ReportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configs);
 }
コード例 #42
0
ファイル: DFAState.cs プロジェクト: RainerBosch/antlr4
 public virtual void SetContextTarget(int invokingState, DFAState target)
 {
     lock (this)
     {
         if (!IsContextSensitive)
         {
             throw new InvalidOperationException("The state is not context sensitive.");
         }
         if (invokingState == PredictionContext.EmptyFullStateKey)
         {
             invokingState = -1;
         }
         contextEdges = contextEdges.Put(invokingState, target);
     }
 }
コード例 #43
0
ファイル: LexerATNSimulator.cs プロジェクト: hustsii/antlr4cs
 protected internal virtual DFAState AddDFAEdge(DFAState from, int t, ATNConfigSet
      q)
 {
     bool suppressEdge = q.HasSemanticContext;
     if (suppressEdge)
     {
         q.ClearExplicitSemanticContext();
     }
     DFAState to = AddDFAState(q);
     if (suppressEdge)
     {
         return to;
     }
     AddDFAEdge(from, t, to);
     return to;
 }