Package org.antlr.v4.runtime.atn

Source Code of org.antlr.v4.runtime.atn.LL1Analyzer

/*
* [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.atn;

import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.Nullable;

import java.util.BitSet;
import java.util.HashSet;
import java.util.Set;

public class LL1Analyzer {
  /** Special value added to the lookahead sets to indicate that we hit
   *  a predicate during analysis if {@code seeThruPreds==false}.
   */
  public static final int HIT_PRED = Token.INVALID_TYPE;

  @NotNull
  public final ATN atn;

  public LL1Analyzer(@NotNull ATN atn) { this.atn = atn; }

  /**
   * Calculates the SLL(1) expected lookahead set for each outgoing transition
   * of an {@link ATNState}. The returned array has one element for each
   * outgoing transition in {@code s}. If the closure from transition
   * <em>i</em> leads to a semantic predicate before matching a symbol, the
   * element at index <em>i</em> of the result will be {@code null}.
   *
   * @param s the ATN state
   * @return the expected symbols for each outgoing transition of {@code s}.
   */
  @Nullable
  public IntervalSet[] getDecisionLookahead(@Nullable ATNState s) {
//    System.out.println("LOOK("+s.stateNumber+")");
    if ( s==null ) {
      return null;
    }

    IntervalSet[] look = new IntervalSet[s.getNumberOfTransitions()];
    for (int alt = 0; alt < s.getNumberOfTransitions(); alt++) {
      look[alt] = new IntervalSet();
      Set<ATNConfig> lookBusy = new HashSet<ATNConfig>();
      boolean seeThruPreds = false; // fail to get lookahead upon pred
      _LOOK(s.transition(alt).target, null, PredictionContext.EMPTY,
          look[alt], lookBusy, new BitSet(), seeThruPreds, false);
      // Wipe out lookahead for this alternative if we found nothing
      // or we had a predicate when we !seeThruPreds
      if ( look[alt].size()==0 || look[alt].contains(HIT_PRED) ) {
        look[alt] = null;
      }
    }
    return look;
  }

  /**
   * Compute set of tokens that can follow {@code s} in the ATN in the
   * specified {@code ctx}.
   *
   * <p>If {@code ctx} is {@code null} and the end of the rule containing
   * {@code s} is reached, {@link Token#EPSILON} is added to the result set.
   * If {@code ctx} is not {@code null} and the end of the outermost rule is
   * reached, {@link Token#EOF} is added to the result set.</p>
   *
   * @param s the ATN state
   * @param ctx the complete parser context, or {@code null} if the context
   * should be ignored
   *
   * @return The set of tokens that can follow {@code s} in the ATN in the
   * specified {@code ctx}.
   */
    @NotNull
     public IntervalSet LOOK(@NotNull ATNState s, @Nullable RuleContext ctx) {
    return LOOK(s, null, ctx);
     }

  /**
   * Compute set of tokens that can follow {@code s} in the ATN in the
   * specified {@code ctx}.
   *
   * <p>If {@code ctx} is {@code null} and the end of the rule containing
   * {@code s} is reached, {@link Token#EPSILON} is added to the result set.
   * If {@code ctx} is not {@code null} and the end of the outermost rule is
   * reached, {@link Token#EOF} is added to the result set.</p>
   *
   * @param s the ATN state
   * @param stopState the ATN state to stop at. This can be a
   * {@link BlockEndState} to detect epsilon paths through a closure.
   * @param ctx the complete parser context, or {@code null} if the context
   * should be ignored
   *
   * @return The set of tokens that can follow {@code s} in the ATN in the
   * specified {@code ctx}.
   */
    @NotNull
     public IntervalSet LOOK(@NotNull ATNState s, @Nullable ATNState stopState, @Nullable RuleContext ctx) {
       IntervalSet r = new IntervalSet();
    boolean seeThruPreds = true; // ignore preds; get all lookahead
    PredictionContext lookContext = ctx != null ? PredictionContext.fromRuleContext(s.atn, ctx) : null;
       _LOOK(s, stopState, lookContext,
        r, new HashSet<ATNConfig>(), new BitSet(), seeThruPreds, true);
       return r;
     }

  /**
   * Compute set of tokens that can follow {@code s} in the ATN in the
   * specified {@code ctx}.
   *
   * <p>If {@code ctx} is {@code null} and {@code stopState} or the end of the
   * rule containing {@code s} is reached, {@link Token#EPSILON} is added to
   * the result set. If {@code ctx} is not {@code null} and {@code addEOF} is
   * {@code true} and {@code stopState} or the end of the outermost rule is
   * reached, {@link Token#EOF} is added to the result set.</p>
   *
   * @param s the ATN state.
   * @param stopState the ATN state to stop at. This can be a
   * {@link BlockEndState} to detect epsilon paths through a closure.
   * @param ctx The outer context, or {@code null} if the outer context should
   * not be used.
   * @param look The result lookahead set.
   * @param lookBusy A set used for preventing epsilon closures in the ATN
   * from causing a stack overflow. Outside code should pass
   * {@code new HashSet<ATNConfig>} for this argument.
   * @param calledRuleStack A set used for preventing left recursion in the
   * ATN from causing a stack overflow. Outside code should pass
   * {@code new BitSet()} for this argument.
   * @param seeThruPreds {@code true} to true semantic predicates as
   * implicitly {@code true} and "see through them", otherwise {@code false}
   * to treat semantic predicates as opaque and add {@link #HIT_PRED} to the
   * result if one is encountered.
   * @param addEOF Add {@link Token#EOF} to the result if the end of the
   * outermost context is reached. This parameter has no effect if {@code ctx}
   * is {@code null}.
   */
    protected void _LOOK(@NotNull ATNState s,
             @Nullable ATNState stopState,
             @Nullable PredictionContext ctx,
             @NotNull IntervalSet look,
                         @NotNull Set<ATNConfig> lookBusy,
             @NotNull BitSet calledRuleStack,
             boolean seeThruPreds, boolean addEOF)
  {
//    System.out.println("_LOOK("+s.stateNumber+", ctx="+ctx);
        ATNConfig c = new ATNConfig(s, 0, ctx);
        if ( !lookBusy.add(c) ) return;

    if (s == stopState) {
      if (ctx == null) {
        look.add(Token.EPSILON);
        return;
      } else if (ctx.isEmpty() && addEOF) {
        look.add(Token.EOF);
        return;
      }
    }

        if ( s instanceof RuleStopState ) {
            if ( ctx==null ) {
                look.add(Token.EPSILON);
                return;
            } else if (ctx.isEmpty() && addEOF) {
        look.add(Token.EOF);
        return;
      }

      if ( ctx != PredictionContext.EMPTY ) {
        // run thru all possible stack tops in ctx
        for (int i = 0; i < ctx.size(); i++) {
          ATNState returnState = atn.states.get(ctx.getReturnState(i));
//          System.out.println("popping back to "+retState);

          boolean removed = calledRuleStack.get(returnState.ruleIndex);
          try {
            calledRuleStack.clear(returnState.ruleIndex);
            _LOOK(returnState, stopState, ctx.getParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
          }
          finally {
            if (removed) {
              calledRuleStack.set(returnState.ruleIndex);
            }
          }
        }
        return;
      }
        }

        int n = s.getNumberOfTransitions();
        for (int i=0; i<n; i++) {
      Transition t = s.transition(i);
      if ( t.getClass() == RuleTransition.class ) {
        if (calledRuleStack.get(((RuleTransition)t).target.ruleIndex)) {
          continue;
        }

        PredictionContext newContext =
          SingletonPredictionContext.create(ctx, ((RuleTransition)t).followState.stateNumber);

        try {
          calledRuleStack.set(((RuleTransition)t).target.ruleIndex);
          _LOOK(t.target, stopState, newContext, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
        }
        finally {
          calledRuleStack.clear(((RuleTransition)t).target.ruleIndex);
        }
      }
      else if ( t instanceof AbstractPredicateTransition ) {
        if ( seeThruPreds ) {
          _LOOK(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
        }
        else {
          look.add(HIT_PRED);
        }
      }
      else if ( t.isEpsilon() ) {
        _LOOK(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
      }
      else if ( t.getClass() == WildcardTransition.class ) {
        look.addAll( IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType) );
      }
      else {
//        System.out.println("adding "+ t);
        IntervalSet set = t.label();
        if (set != null) {
          if (t instanceof NotSetTransition) {
            set = set.complement(IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType));
          }
          look.addAll(set);
        }
      }
    }
  }
}
TOP

Related Classes of org.antlr.v4.runtime.atn.LL1Analyzer

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.