Package org.antlr.v4.runtime.dfa

Source Code of org.antlr.v4.runtime.dfa.DFA

/*
* [The "BSD license"]
*  Copyright (c) 2012 Terence Parr
*  Copyright (c) 2012 Sam Harwell
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*  1. Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*  2. Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*  3. The name of the author may not be used to endorse or promote products
*     derived from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
*  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
*  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
*  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.dfa;

import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.Vocabulary;
import org.antlr.v4.runtime.VocabularyImpl;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.Nullable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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).
     */
    @NotNull
  public final Map<DFAState, DFAState> states = new HashMap<DFAState, DFAState>();
  @Nullable
  public volatile DFAState s0;

  public final int decision;

  /** From which ATN state did we create this DFA? */
  @NotNull
  public final DecisionState atnStartState;

  /**
   * {@code true} if this DFA is for a precedence decision; otherwise,
   * {@code false}. This is the backing field for {@link #isPrecedenceDfa},
   * {@link #setPrecedenceDfa}.
   */
  private volatile boolean precedenceDfa;

  public DFA(@NotNull DecisionState atnStartState) {
    this(atnStartState, 0);
  }

  public DFA(@NotNull DecisionState atnStartState, int decision) {
    this.atnStartState = atnStartState;
    this.decision = decision;
  }

  /**
   * 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 final boolean isPrecedenceDfa() {
    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()
   */
  @SuppressWarnings("null")
  public final DFAState getPrecedenceStartState(int precedence) {
    if (!isPrecedenceDfa()) {
      throw new IllegalStateException("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()
   */
  @SuppressWarnings({"SynchronizeOnNonFinalField", "null"})
  public final void setPrecedenceStartState(int precedence, DFAState startState) {
    if (!isPrecedenceDfa()) {
      throw new IllegalStateException("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
    synchronized (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;
    }
  }

  /**
   * 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 {@link #states} map is cleared</li>
   * <li>If {@code precedenceDfa} is {@code false}, the initial state
   * {@link #s0} is set to {@code null}; otherwise, it is initialized to a new
   * {@link DFAState} with an empty outgoing {@link DFAState#edges} array to
   * store the start states for individual precedence values.</li>
   * <li>The {@link #precedenceDfa} field is updated</li>
   * </ul>
   *
   * @param precedenceDfa {@code true} if this is a precedence DFA; otherwise,
   * {@code false}
   */
  public final synchronized void setPrecedenceDfa(boolean precedenceDfa) {
    if (this.precedenceDfa != precedenceDfa) {
      this.states.clear();
      if (precedenceDfa) {
        DFAState precedenceState = new DFAState(new ATNConfigSet());
        precedenceState.edges = new DFAState[0];
        precedenceState.isAcceptState = false;
        precedenceState.requiresFullContext = false;
        this.s0 = precedenceState;
      }
      else {
        this.s0 = null;
      }

      this.precedenceDfa = precedenceDfa;
    }
  }

  /**
   * Return a list of all states in this DFA, ordered by state number.
   */
  @NotNull
  public List<DFAState> getStates() {
    List<DFAState> result = new ArrayList<DFAState>(states.keySet());
    Collections.sort(result, new Comparator<DFAState>() {
      @Override
      public int compare(DFAState o1, DFAState o2) {
        return o1.stateNumber - o2.stateNumber;
      }
    });

    return result;
  }

  @Override
  public String toString() { return toString(VocabularyImpl.EMPTY_VOCABULARY); }

  /**
   * @deprecated Use {@link #toString(Vocabulary)} instead.
   */
  @Deprecated
  public String toString(@Nullable String[] tokenNames) {
    if ( s0==null ) return "";
    DFASerializer serializer = new DFASerializer(this,tokenNames);
    return serializer.toString();
  }

  public String toString(@NotNull Vocabulary 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();
  }

}
TOP

Related Classes of org.antlr.v4.runtime.dfa.DFA

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.