Search in sources :

Example 1 with PlusBlockStartState

use of org.antlr.v4.runtime.atn.PlusBlockStartState in project antlr4 by antlr.

the class DOTGenerator method getDOT.

/**
 * Return a String containing a DOT description that, when displayed,
 *  will show the incoming state machine visually.  All nodes reachable
 *  from startState will be included.
 */
public String getDOT(ATNState startState, String[] ruleNames, boolean isLexer) {
    if (startState == null)
        return null;
    // The output DOT graph for visualization
    Set<ATNState> markedStates = new HashSet<ATNState>();
    ST dot = stlib.getInstanceOf("atn");
    dot.add("startState", startState.stateNumber);
    dot.add("rankdir", rankdir);
    List<ATNState> work = new LinkedList<ATNState>();
    work.add(startState);
    while (!work.isEmpty()) {
        ATNState s = work.get(0);
        if (markedStates.contains(s)) {
            work.remove(0);
            continue;
        }
        markedStates.add(s);
        // don't go past end of rule node to the follow states
        if (s instanceof RuleStopState)
            continue;
        // special case: if decision point, then line up the alt start states
        // unless it's an end of block
        // if ( s instanceof BlockStartState ) {
        // ST rankST = stlib.getInstanceOf("decision-rank");
        // DecisionState alt = (DecisionState)s;
        // for (int i=0; i<alt.getNumberOfTransitions(); i++) {
        // ATNState target = alt.transition(i).target;
        // if ( target!=null ) {
        // rankST.add("states", target.stateNumber);
        // }
        // }
        // dot.add("decisionRanks", rankST);
        // }
        // make a DOT edge for each transition
        ST edgeST;
        for (int i = 0; i < s.getNumberOfTransitions(); i++) {
            Transition edge = s.transition(i);
            if (edge instanceof RuleTransition) {
                RuleTransition rr = ((RuleTransition) edge);
                // don't jump to other rules, but display edge to follow node
                edgeST = stlib.getInstanceOf("edge");
                String label = "<" + ruleNames[rr.ruleIndex];
                if (((RuleStartState) rr.target).isLeftRecursiveRule) {
                    label += "[" + rr.precedence + "]";
                }
                label += ">";
                edgeST.add("label", label);
                edgeST.add("src", "s" + s.stateNumber);
                edgeST.add("target", "s" + rr.followState.stateNumber);
                edgeST.add("arrowhead", arrowhead);
                dot.add("edges", edgeST);
                work.add(rr.followState);
                continue;
            }
            if (edge instanceof ActionTransition) {
                edgeST = stlib.getInstanceOf("action-edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
            } else if (edge instanceof AbstractPredicateTransition) {
                edgeST = stlib.getInstanceOf("edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
            } else if (edge.isEpsilon()) {
                edgeST = stlib.getInstanceOf("epsilon-edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
                boolean loopback = false;
                if (edge.target instanceof PlusBlockStartState) {
                    loopback = s.equals(((PlusBlockStartState) edge.target).loopBackState);
                } else if (edge.target instanceof StarLoopEntryState) {
                    loopback = s.equals(((StarLoopEntryState) edge.target).loopBackState);
                }
                edgeST.add("loopback", loopback);
            } else if (edge instanceof AtomTransition) {
                edgeST = stlib.getInstanceOf("edge");
                AtomTransition atom = (AtomTransition) edge;
                String label = String.valueOf(atom.label);
                if (isLexer)
                    label = "'" + getEdgeLabel(new StringBuilder().appendCodePoint(atom.label).toString()) + "'";
                else if (grammar != null)
                    label = grammar.getTokenDisplayName(atom.label);
                edgeST.add("label", getEdgeLabel(label));
            } else if (edge instanceof SetTransition) {
                edgeST = stlib.getInstanceOf("edge");
                SetTransition set = (SetTransition) edge;
                String label = set.label().toString();
                if (isLexer)
                    label = set.label().toString(true);
                else if (grammar != null)
                    label = set.label().toString(grammar.getVocabulary());
                if (edge instanceof NotSetTransition)
                    label = "~" + label;
                edgeST.add("label", getEdgeLabel(label));
            } else if (edge instanceof RangeTransition) {
                edgeST = stlib.getInstanceOf("edge");
                RangeTransition range = (RangeTransition) edge;
                String label = range.label().toString();
                if (isLexer)
                    label = range.toString();
                else if (grammar != null)
                    label = range.label().toString(grammar.getVocabulary());
                edgeST.add("label", getEdgeLabel(label));
            } else {
                edgeST = stlib.getInstanceOf("edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
            }
            edgeST.add("src", "s" + s.stateNumber);
            edgeST.add("target", "s" + edge.target.stateNumber);
            edgeST.add("arrowhead", arrowhead);
            if (s.getNumberOfTransitions() > 1) {
                edgeST.add("transitionIndex", i);
            } else {
                edgeST.add("transitionIndex", false);
            }
            dot.add("edges", edgeST);
            work.add(edge.target);
        }
    }
    // }
    for (ATNState s : markedStates) {
        if (!(s instanceof RuleStopState))
            continue;
        ST st = stlib.getInstanceOf("stopstate");
        st.add("name", "s" + s.stateNumber);
        st.add("label", getStateLabel(s));
        dot.add("states", st);
    }
    for (ATNState s : markedStates) {
        if (s instanceof RuleStopState)
            continue;
        ST st = stlib.getInstanceOf("state");
        st.add("name", "s" + s.stateNumber);
        st.add("label", getStateLabel(s));
        st.add("transitions", s.getTransitions());
        dot.add("states", st);
    }
    return dot.render();
}
Also used : ST(org.stringtemplate.v4.ST) RuleStopState(org.antlr.v4.runtime.atn.RuleStopState) AtomTransition(org.antlr.v4.runtime.atn.AtomTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) SetTransition(org.antlr.v4.runtime.atn.SetTransition) RangeTransition(org.antlr.v4.runtime.atn.RangeTransition) LinkedList(java.util.LinkedList) ATNState(org.antlr.v4.runtime.atn.ATNState) PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) ActionTransition(org.antlr.v4.runtime.atn.ActionTransition) StarLoopEntryState(org.antlr.v4.runtime.atn.StarLoopEntryState) RuleStartState(org.antlr.v4.runtime.atn.RuleStartState) RuleTransition(org.antlr.v4.runtime.atn.RuleTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) RuleTransition(org.antlr.v4.runtime.atn.RuleTransition) ActionTransition(org.antlr.v4.runtime.atn.ActionTransition) Transition(org.antlr.v4.runtime.atn.Transition) AbstractPredicateTransition(org.antlr.v4.runtime.atn.AbstractPredicateTransition) AtomTransition(org.antlr.v4.runtime.atn.AtomTransition) SetTransition(org.antlr.v4.runtime.atn.SetTransition) RangeTransition(org.antlr.v4.runtime.atn.RangeTransition) AbstractPredicateTransition(org.antlr.v4.runtime.atn.AbstractPredicateTransition) HashSet(java.util.HashSet)

Example 2 with PlusBlockStartState

use of org.antlr.v4.runtime.atn.PlusBlockStartState in project antlr4 by tunnelvisionlabs.

the class DOTGenerator method getDOT.

/**
 * Return a String containing a DOT description that, when displayed,
 *  will show the incoming state machine visually.  All nodes reachable
 *  from startState will be included.
 */
public String getDOT(ATNState startState, String[] ruleNames, boolean isLexer) {
    if (startState == null)
        return null;
    // The output DOT graph for visualization
    Set<ATNState> markedStates = new HashSet<ATNState>();
    ST dot = stlib.getInstanceOf("atn");
    dot.add("startState", startState.stateNumber);
    dot.add("rankdir", rankdir);
    List<ATNState> work = new LinkedList<ATNState>();
    work.add(startState);
    while (!work.isEmpty()) {
        ATNState s = work.get(0);
        if (markedStates.contains(s)) {
            work.remove(0);
            continue;
        }
        markedStates.add(s);
        // don't go past end of rule node to the follow states
        if (s instanceof RuleStopState)
            continue;
        // special case: if decision point, then line up the alt start states
        // unless it's an end of block
        // if ( s instanceof BlockStartState ) {
        // ST rankST = stlib.getInstanceOf("decision-rank");
        // DecisionState alt = (DecisionState)s;
        // for (int i=0; i<alt.getNumberOfTransitions(); i++) {
        // ATNState target = alt.transition(i).target;
        // if ( target!=null ) {
        // rankST.add("states", target.stateNumber);
        // }
        // }
        // dot.add("decisionRanks", rankST);
        // }
        // make a DOT edge for each transition
        ST edgeST;
        for (int i = 0; i < s.getNumberOfTransitions(); i++) {
            Transition edge = s.transition(i);
            if (edge instanceof RuleTransition) {
                RuleTransition rr = ((RuleTransition) edge);
                // don't jump to other rules, but display edge to follow node
                edgeST = stlib.getInstanceOf("edge");
                String label = "<" + ruleNames[rr.ruleIndex];
                if (((RuleStartState) rr.target).isPrecedenceRule) {
                    label += "[" + rr.precedence + "]";
                }
                label += ">";
                edgeST.add("label", label);
                edgeST.add("src", "s" + s.stateNumber);
                edgeST.add("target", "s" + rr.followState.stateNumber);
                edgeST.add("arrowhead", arrowhead);
                dot.add("edges", edgeST);
                work.add(rr.followState);
                continue;
            }
            if (edge instanceof ActionTransition) {
                edgeST = stlib.getInstanceOf("action-edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
            } else if (edge instanceof AbstractPredicateTransition) {
                edgeST = stlib.getInstanceOf("edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
            } else if (edge.isEpsilon()) {
                edgeST = stlib.getInstanceOf("epsilon-edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
                boolean loopback = false;
                if (edge.target instanceof PlusBlockStartState) {
                    loopback = s.equals(((PlusBlockStartState) edge.target).loopBackState);
                } else if (edge.target instanceof StarLoopEntryState) {
                    loopback = s.equals(((StarLoopEntryState) edge.target).loopBackState);
                }
                edgeST.add("loopback", loopback);
            } else if (edge instanceof AtomTransition) {
                edgeST = stlib.getInstanceOf("edge");
                AtomTransition atom = (AtomTransition) edge;
                String label = String.valueOf(atom.label);
                if (isLexer)
                    label = "'" + getEdgeLabel(new StringBuilder().appendCodePoint(atom.label).toString()) + "'";
                else if (grammar != null)
                    label = grammar.getTokenDisplayName(atom.label);
                edgeST.add("label", getEdgeLabel(label));
            } else if (edge instanceof SetTransition) {
                edgeST = stlib.getInstanceOf("edge");
                SetTransition set = (SetTransition) edge;
                String label = set.label().toString();
                if (isLexer)
                    label = set.label().toString(true);
                else if (grammar != null)
                    label = set.label().toString(grammar.getVocabulary());
                if (edge instanceof NotSetTransition)
                    label = "~" + label;
                edgeST.add("label", getEdgeLabel(label));
            } else if (edge instanceof RangeTransition) {
                edgeST = stlib.getInstanceOf("edge");
                RangeTransition range = (RangeTransition) edge;
                String label = range.label().toString();
                if (isLexer)
                    label = range.toString();
                else if (grammar != null)
                    label = range.label().toString(grammar.getVocabulary());
                edgeST.add("label", getEdgeLabel(label));
            } else {
                edgeST = stlib.getInstanceOf("edge");
                edgeST.add("label", getEdgeLabel(edge.toString()));
            }
            edgeST.add("src", "s" + s.stateNumber);
            edgeST.add("target", "s" + edge.target.stateNumber);
            edgeST.add("arrowhead", arrowhead);
            if (s.getNumberOfTransitions() > 1) {
                edgeST.add("transitionIndex", i);
            } else {
                edgeST.add("transitionIndex", false);
            }
            dot.add("edges", edgeST);
            work.add(edge.target);
        }
    }
    // }
    for (ATNState s : markedStates) {
        if (!(s instanceof RuleStopState))
            continue;
        ST st = stlib.getInstanceOf("stopstate");
        st.add("name", "s" + s.stateNumber);
        st.add("label", getStateLabel(s));
        dot.add("states", st);
    }
    for (ATNState s : markedStates) {
        if (s instanceof RuleStopState)
            continue;
        ST st = stlib.getInstanceOf("state");
        st.add("name", "s" + s.stateNumber);
        st.add("label", getStateLabel(s));
        st.add("transitions", s.getTransitions());
        dot.add("states", st);
    }
    return dot.render();
}
Also used : ST(org.stringtemplate.v4.ST) RuleStopState(org.antlr.v4.runtime.atn.RuleStopState) AtomTransition(org.antlr.v4.runtime.atn.AtomTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) SetTransition(org.antlr.v4.runtime.atn.SetTransition) RangeTransition(org.antlr.v4.runtime.atn.RangeTransition) LinkedList(java.util.LinkedList) ATNState(org.antlr.v4.runtime.atn.ATNState) PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) ActionTransition(org.antlr.v4.runtime.atn.ActionTransition) StarLoopEntryState(org.antlr.v4.runtime.atn.StarLoopEntryState) RuleStartState(org.antlr.v4.runtime.atn.RuleStartState) RuleTransition(org.antlr.v4.runtime.atn.RuleTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) RuleTransition(org.antlr.v4.runtime.atn.RuleTransition) ActionTransition(org.antlr.v4.runtime.atn.ActionTransition) Transition(org.antlr.v4.runtime.atn.Transition) AbstractPredicateTransition(org.antlr.v4.runtime.atn.AbstractPredicateTransition) AtomTransition(org.antlr.v4.runtime.atn.AtomTransition) SetTransition(org.antlr.v4.runtime.atn.SetTransition) RangeTransition(org.antlr.v4.runtime.atn.RangeTransition) AbstractPredicateTransition(org.antlr.v4.runtime.atn.AbstractPredicateTransition) HashSet(java.util.HashSet)

Example 3 with PlusBlockStartState

use of org.antlr.v4.runtime.atn.PlusBlockStartState in project antlr4 by tunnelvisionlabs.

the class ATNDeserializer method deserialize.

@SuppressWarnings("deprecation")
public ATN deserialize(@NotNull char[] data) {
    data = data.clone();
    // was implemented.
    for (int i = 1; i < data.length; i++) {
        data[i] = (char) (data[i] - 2);
    }
    int p = 0;
    int version = toInt(data[p++]);
    if (version != SERIALIZED_VERSION) {
        String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with version %d (expected %d).", version, SERIALIZED_VERSION);
        throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
    }
    UUID uuid = toUUID(data, p);
    p += 8;
    if (!SUPPORTED_UUIDS.contains(uuid)) {
        String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with UUID %s (expected %s or a legacy UUID).", uuid, SERIALIZED_UUID);
        throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
    }
    boolean supportsLexerActions = isFeatureSupported(ADDED_LEXER_ACTIONS, uuid);
    ATNType grammarType = ATNType.values()[toInt(data[p++])];
    int maxTokenType = toInt(data[p++]);
    ATN atn = new ATN(grammarType, maxTokenType);
    // 
    // STATES
    // 
    List<Tuple2<LoopEndState, Integer>> loopBackStateNumbers = new ArrayList<Tuple2<LoopEndState, Integer>>();
    List<Tuple2<BlockStartState, Integer>> endStateNumbers = new ArrayList<Tuple2<BlockStartState, Integer>>();
    int nstates = toInt(data[p++]);
    for (int i = 0; i < nstates; i++) {
        int stype = toInt(data[p++]);
        // ignore bad type of states
        if (stype == ATNState.INVALID_TYPE) {
            atn.addState(null);
            continue;
        }
        int ruleIndex = toInt(data[p++]);
        if (ruleIndex == Character.MAX_VALUE) {
            ruleIndex = -1;
        }
        ATNState s = stateFactory(stype, ruleIndex);
        if (stype == ATNState.LOOP_END) {
            // special case
            int loopBackStateNumber = toInt(data[p++]);
            loopBackStateNumbers.add(Tuple.create((LoopEndState) s, loopBackStateNumber));
        } else if (s instanceof BlockStartState) {
            int endStateNumber = toInt(data[p++]);
            endStateNumbers.add(Tuple.create((BlockStartState) s, endStateNumber));
        }
        atn.addState(s);
    }
    // delay the assignment of loop back and end states until we know all the state instances have been initialized
    for (Tuple2<LoopEndState, Integer> pair : loopBackStateNumbers) {
        pair.getItem1().loopBackState = atn.states.get(pair.getItem2());
    }
    for (Tuple2<BlockStartState, Integer> pair : endStateNumbers) {
        pair.getItem1().endState = (BlockEndState) atn.states.get(pair.getItem2());
    }
    int numNonGreedyStates = toInt(data[p++]);
    for (int i = 0; i < numNonGreedyStates; i++) {
        int stateNumber = toInt(data[p++]);
        ((DecisionState) atn.states.get(stateNumber)).nonGreedy = true;
    }
    int numSllDecisions = toInt(data[p++]);
    for (int i = 0; i < numSllDecisions; i++) {
        int stateNumber = toInt(data[p++]);
        ((DecisionState) atn.states.get(stateNumber)).sll = true;
    }
    int numPrecedenceStates = toInt(data[p++]);
    for (int i = 0; i < numPrecedenceStates; i++) {
        int stateNumber = toInt(data[p++]);
        ((RuleStartState) atn.states.get(stateNumber)).isPrecedenceRule = true;
    }
    // 
    // RULES
    // 
    int nrules = toInt(data[p++]);
    if (atn.grammarType == ATNType.LEXER) {
        atn.ruleToTokenType = new int[nrules];
    }
    atn.ruleToStartState = new RuleStartState[nrules];
    for (int i = 0; i < nrules; i++) {
        int s = toInt(data[p++]);
        RuleStartState startState = (RuleStartState) atn.states.get(s);
        startState.leftFactored = toInt(data[p++]) != 0;
        atn.ruleToStartState[i] = startState;
        if (atn.grammarType == ATNType.LEXER) {
            int tokenType = toInt(data[p++]);
            if (tokenType == 0xFFFF) {
                tokenType = Token.EOF;
            }
            atn.ruleToTokenType[i] = tokenType;
            if (!isFeatureSupported(ADDED_LEXER_ACTIONS, uuid)) {
                // this piece of unused metadata was serialized prior to the
                // addition of LexerAction
                int actionIndexIgnored = toInt(data[p++]);
                if (actionIndexIgnored == 0xFFFF) {
                    actionIndexIgnored = -1;
                }
            }
        }
    }
    atn.ruleToStopState = new RuleStopState[nrules];
    for (ATNState state : atn.states) {
        if (!(state instanceof RuleStopState)) {
            continue;
        }
        RuleStopState stopState = (RuleStopState) state;
        atn.ruleToStopState[state.ruleIndex] = stopState;
        atn.ruleToStartState[state.ruleIndex].stopState = stopState;
    }
    // 
    // MODES
    // 
    int nmodes = toInt(data[p++]);
    for (int i = 0; i < nmodes; i++) {
        int s = toInt(data[p++]);
        atn.modeToStartState.add((TokensStartState) atn.states.get(s));
    }
    atn.modeToDFA = new DFA[nmodes];
    for (int i = 0; i < nmodes; i++) {
        atn.modeToDFA[i] = new DFA(atn.modeToStartState.get(i));
    }
    // 
    // SETS
    // 
    List<IntervalSet> sets = new ArrayList<IntervalSet>();
    // First, read all sets with 16-bit Unicode code points <= U+FFFF.
    p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_BMP));
    // deserialize sets with 32-bit arguments <= U+10FFFF.
    if (isFeatureSupported(ADDED_UNICODE_SMP, uuid)) {
        int previousSetCount = sets.size();
        p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_SMP));
        atn.setHasUnicodeSMPTransitions(sets.size() > previousSetCount);
    }
    // 
    // EDGES
    // 
    int nedges = toInt(data[p++]);
    for (int i = 0; i < nedges; i++) {
        int src = toInt(data[p]);
        int trg = toInt(data[p + 1]);
        int ttype = toInt(data[p + 2]);
        int arg1 = toInt(data[p + 3]);
        int arg2 = toInt(data[p + 4]);
        int arg3 = toInt(data[p + 5]);
        Transition trans = edgeFactory(atn, ttype, src, trg, arg1, arg2, arg3, sets);
        // System.out.println("EDGE "+trans.getClass().getSimpleName()+" "+
        // src+"->"+trg+
        // " "+Transition.serializationNames[ttype]+
        // " "+arg1+","+arg2+","+arg3);
        ATNState srcState = atn.states.get(src);
        srcState.addTransition(trans);
        p += 6;
    }
    // edges for rule stop states can be derived, so they aren't serialized
    // Map rule stop state -> return state -> outermost precedence return
    Set<Tuple3<Integer, Integer, Integer>> returnTransitions = new LinkedHashSet<Tuple3<Integer, Integer, Integer>>();
    for (ATNState state : atn.states) {
        boolean returningToLeftFactored = state.ruleIndex >= 0 && atn.ruleToStartState[state.ruleIndex].leftFactored;
        for (int i = 0; i < state.getNumberOfTransitions(); i++) {
            Transition t = state.transition(i);
            if (!(t instanceof RuleTransition)) {
                continue;
            }
            RuleTransition ruleTransition = (RuleTransition) t;
            boolean returningFromLeftFactored = atn.ruleToStartState[ruleTransition.target.ruleIndex].leftFactored;
            if (!returningFromLeftFactored && returningToLeftFactored) {
                continue;
            }
            int outermostPrecedenceReturn = -1;
            if (atn.ruleToStartState[ruleTransition.target.ruleIndex].isPrecedenceRule) {
                if (ruleTransition.precedence == 0) {
                    outermostPrecedenceReturn = ruleTransition.target.ruleIndex;
                }
            }
            returnTransitions.add(Tuple.create(ruleTransition.target.ruleIndex, ruleTransition.followState.stateNumber, outermostPrecedenceReturn));
        }
    }
    // Add all elements from returnTransitions to the ATN
    for (Tuple3<Integer, Integer, Integer> returnTransition : returnTransitions) {
        EpsilonTransition transition = new EpsilonTransition(atn.states.get(returnTransition.getItem2()), returnTransition.getItem3());
        atn.ruleToStopState[returnTransition.getItem1()].addTransition(transition);
    }
    for (ATNState state : atn.states) {
        if (state instanceof BlockStartState) {
            // we need to know the end state to set its start state
            if (((BlockStartState) state).endState == null) {
                throw new IllegalStateException();
            }
            // block end states can only be associated to a single block start state
            if (((BlockStartState) state).endState.startState != null) {
                throw new IllegalStateException();
            }
            ((BlockStartState) state).endState.startState = (BlockStartState) state;
        }
        if (state instanceof PlusLoopbackState) {
            PlusLoopbackState loopbackState = (PlusLoopbackState) state;
            for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
                ATNState target = loopbackState.transition(i).target;
                if (target instanceof PlusBlockStartState) {
                    ((PlusBlockStartState) target).loopBackState = loopbackState;
                }
            }
        } else if (state instanceof StarLoopbackState) {
            StarLoopbackState loopbackState = (StarLoopbackState) state;
            for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
                ATNState target = loopbackState.transition(i).target;
                if (target instanceof StarLoopEntryState) {
                    ((StarLoopEntryState) target).loopBackState = loopbackState;
                }
            }
        }
    }
    // 
    // DECISIONS
    // 
    int ndecisions = toInt(data[p++]);
    for (int i = 1; i <= ndecisions; i++) {
        int s = toInt(data[p++]);
        DecisionState decState = (DecisionState) atn.states.get(s);
        atn.decisionToState.add(decState);
        decState.decision = i - 1;
    }
    // 
    if (atn.grammarType == ATNType.LEXER) {
        if (supportsLexerActions) {
            atn.lexerActions = new LexerAction[toInt(data[p++])];
            for (int i = 0; i < atn.lexerActions.length; i++) {
                LexerActionType actionType = LexerActionType.values()[toInt(data[p++])];
                int data1 = toInt(data[p++]);
                if (data1 == 0xFFFF) {
                    data1 = -1;
                }
                int data2 = toInt(data[p++]);
                if (data2 == 0xFFFF) {
                    data2 = -1;
                }
                LexerAction lexerAction = lexerActionFactory(actionType, data1, data2);
                atn.lexerActions[i] = lexerAction;
            }
        } else {
            // for compatibility with older serialized ATNs, convert the old
            // serialized action index for action transitions to the new
            // form, which is the index of a LexerCustomAction
            List<LexerAction> legacyLexerActions = new ArrayList<LexerAction>();
            for (ATNState state : atn.states) {
                for (int i = 0; i < state.getNumberOfTransitions(); i++) {
                    Transition transition = state.transition(i);
                    if (!(transition instanceof ActionTransition)) {
                        continue;
                    }
                    int ruleIndex = ((ActionTransition) transition).ruleIndex;
                    int actionIndex = ((ActionTransition) transition).actionIndex;
                    LexerCustomAction lexerAction = new LexerCustomAction(ruleIndex, actionIndex);
                    state.setTransition(i, new ActionTransition(transition.target, ruleIndex, legacyLexerActions.size(), false));
                    legacyLexerActions.add(lexerAction);
                }
            }
            atn.lexerActions = legacyLexerActions.toArray(new LexerAction[legacyLexerActions.size()]);
        }
    }
    markPrecedenceDecisions(atn);
    atn.decisionToDFA = new DFA[ndecisions];
    for (int i = 0; i < ndecisions; i++) {
        atn.decisionToDFA[i] = new DFA(atn.decisionToState.get(i), i);
    }
    if (deserializationOptions.isVerifyATN()) {
        verifyATN(atn);
    }
    if (deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType.PARSER) {
        atn.ruleToTokenType = new int[atn.ruleToStartState.length];
        for (int i = 0; i < atn.ruleToStartState.length; i++) {
            atn.ruleToTokenType[i] = atn.maxTokenType + i + 1;
        }
        for (int i = 0; i < atn.ruleToStartState.length; i++) {
            BasicBlockStartState bypassStart = new BasicBlockStartState();
            bypassStart.ruleIndex = i;
            atn.addState(bypassStart);
            BlockEndState bypassStop = new BlockEndState();
            bypassStop.ruleIndex = i;
            atn.addState(bypassStop);
            bypassStart.endState = bypassStop;
            atn.defineDecisionState(bypassStart);
            bypassStop.startState = bypassStart;
            ATNState endState;
            Transition excludeTransition = null;
            if (atn.ruleToStartState[i].isPrecedenceRule) {
                // wrap from the beginning of the rule to the StarLoopEntryState
                endState = null;
                for (ATNState state : atn.states) {
                    if (state.ruleIndex != i) {
                        continue;
                    }
                    if (!(state instanceof StarLoopEntryState)) {
                        continue;
                    }
                    ATNState maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target;
                    if (!(maybeLoopEndState instanceof LoopEndState)) {
                        continue;
                    }
                    if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target instanceof RuleStopState) {
                        endState = state;
                        break;
                    }
                }
                if (endState == null) {
                    throw new UnsupportedOperationException("Couldn't identify final state of the precedence rule prefix section.");
                }
                excludeTransition = ((StarLoopEntryState) endState).loopBackState.transition(0);
            } else {
                endState = atn.ruleToStopState[i];
            }
            // all non-excluded transitions that currently target end state need to target blockEnd instead
            for (ATNState state : atn.states) {
                for (Transition transition : state.transitions) {
                    if (transition == excludeTransition) {
                        continue;
                    }
                    if (transition.target == endState) {
                        transition.target = bypassStop;
                    }
                }
            }
            // all transitions leaving the rule start state need to leave blockStart instead
            while (atn.ruleToStartState[i].getNumberOfTransitions() > 0) {
                Transition transition = atn.ruleToStartState[i].removeTransition(atn.ruleToStartState[i].getNumberOfTransitions() - 1);
                bypassStart.addTransition(transition);
            }
            // link the new states
            atn.ruleToStartState[i].addTransition(new EpsilonTransition(bypassStart));
            bypassStop.addTransition(new EpsilonTransition(endState));
            ATNState matchState = new BasicState();
            atn.addState(matchState);
            matchState.addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i]));
            bypassStart.addTransition(new EpsilonTransition(matchState));
        }
        if (deserializationOptions.isVerifyATN()) {
            // reverify after modification
            verifyATN(atn);
        }
    }
    if (deserializationOptions.isOptimize()) {
        while (true) {
            int optimizationCount = 0;
            optimizationCount += inlineSetRules(atn);
            optimizationCount += combineChainedEpsilons(atn);
            boolean preserveOrder = atn.grammarType == ATNType.LEXER;
            optimizationCount += optimizeSets(atn, preserveOrder);
            if (optimizationCount == 0) {
                break;
            }
        }
        if (deserializationOptions.isVerifyATN()) {
            // reverify after modification
            verifyATN(atn);
        }
    }
    identifyTailCalls(atn);
    return atn;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) UUID(java.util.UUID) InvalidClassException(java.io.InvalidClassException) Tuple2(org.antlr.v4.runtime.misc.Tuple2) IntervalSet(org.antlr.v4.runtime.misc.IntervalSet) Tuple3(org.antlr.v4.runtime.misc.Tuple3) DFA(org.antlr.v4.runtime.dfa.DFA)

Example 4 with PlusBlockStartState

use of org.antlr.v4.runtime.atn.PlusBlockStartState in project antlr4 by tunnelvisionlabs.

the class ParserATNFactory method plus.

/**
 * From {@code (blk)+} build
 *
 * <pre>
 *   |---------|
 *   v         |
 *  [o-blk-o]-&gt;o-&gt;o
 * </pre>
 *
 * We add a decision for loop back node to the existing one at {@code blk}
 * start.
 */
@NotNull
@Override
public Handle plus(@NotNull GrammarAST plusAST, @NotNull Handle blk) {
    PlusBlockStartState blkStart = (PlusBlockStartState) blk.left;
    BlockEndState blkEnd = (BlockEndState) blk.right;
    preventEpsilonClosureBlocks.add(Tuple.create(currentRule, blkStart, blkEnd));
    PlusLoopbackState loop = newState(PlusLoopbackState.class, plusAST);
    loop.nonGreedy = !((QuantifierAST) plusAST).isGreedy();
    // no way to express SLL restriction
    loop.sll = false;
    atn.defineDecisionState(loop);
    LoopEndState end = newState(LoopEndState.class, plusAST);
    blkStart.loopBackState = loop;
    end.loopBackState = loop;
    plusAST.atnState = loop;
    // blk can see loop back
    epsilon(blkEnd, loop);
    BlockAST blkAST = (BlockAST) plusAST.getChild(0);
    if (((QuantifierAST) plusAST).isGreedy()) {
        if (expectNonGreedy(blkAST)) {
            g.tool.errMgr.grammarError(ErrorType.EXPECTED_NON_GREEDY_WILDCARD_BLOCK, g.fileName, plusAST.getToken(), plusAST.getToken().getText());
        }
        // loop back to start
        epsilon(loop, blkStart);
        // or exit
        epsilon(loop, end);
    } else {
        // if not greedy, priority to exit branch; make it first
        // exit
        epsilon(loop, end);
        // loop back to start
        epsilon(loop, blkStart);
    }
    return new Handle(blkStart, end);
}
Also used : LoopEndState(org.antlr.v4.runtime.atn.LoopEndState) PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) PlusLoopbackState(org.antlr.v4.runtime.atn.PlusLoopbackState) BlockAST(org.antlr.v4.tool.ast.BlockAST) QuantifierAST(org.antlr.v4.tool.ast.QuantifierAST) BlockEndState(org.antlr.v4.runtime.atn.BlockEndState) NotNull(org.antlr.v4.runtime.misc.NotNull)

Example 5 with PlusBlockStartState

use of org.antlr.v4.runtime.atn.PlusBlockStartState in project antlr4 by tunnelvisionlabs.

the class ParserATNFactory method block.

/**
 * From {@code A|B|..|Z} alternative block build
 *
 * <pre>
 *  o-&gt;o-A-&gt;o-&gt;o (last ATNState is BlockEndState pointed to by all alts)
 *  |          ^
 *  |-&gt;o-B-&gt;o--|
 *  |          |
 *  ...        |
 *  |          |
 *  |-&gt;o-Z-&gt;o--|
 * </pre>
 *
 * So start node points at every alternative with epsilon transition and
 * every alt right side points at a block end ATNState.
 * <p>
 * Special case: only one alternative: don't make a block with alt
 * begin/end.
 * <p>
 * Special case: if just a list of tokens/chars/sets, then collapse to a
 * single edged o-set-&gt;o graph.
 * <p>
 * TODO: Set alt number (1..n) in the states?
 */
@NotNull
@Override
public Handle block(@NotNull BlockAST blkAST, @NotNull GrammarAST ebnfRoot, @NotNull List<Handle> alts) {
    if (ebnfRoot == null) {
        if (alts.size() == 1) {
            Handle h = alts.get(0);
            blkAST.atnState = h.left;
            return h;
        }
        BlockStartState start = newState(BasicBlockStartState.class, blkAST);
        if (alts.size() > 1)
            atn.defineDecisionState(start);
        return makeBlock(start, blkAST, alts);
    }
    switch(ebnfRoot.getType()) {
        case ANTLRParser.OPTIONAL:
            BlockStartState start = newState(BasicBlockStartState.class, blkAST);
            atn.defineDecisionState(start);
            Handle h = makeBlock(start, blkAST, alts);
            return optional(ebnfRoot, h);
        case ANTLRParser.CLOSURE:
            BlockStartState star = newState(StarBlockStartState.class, ebnfRoot);
            if (alts.size() > 1)
                atn.defineDecisionState(star);
            h = makeBlock(star, blkAST, alts);
            return star(ebnfRoot, h);
        case ANTLRParser.POSITIVE_CLOSURE:
            PlusBlockStartState plus = newState(PlusBlockStartState.class, ebnfRoot);
            if (alts.size() > 1)
                atn.defineDecisionState(plus);
            h = makeBlock(plus, blkAST, alts);
            return plus(ebnfRoot, h);
    }
    return null;
}
Also used : PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) PlusBlockStartState(org.antlr.v4.runtime.atn.PlusBlockStartState) StarBlockStartState(org.antlr.v4.runtime.atn.StarBlockStartState) BasicBlockStartState(org.antlr.v4.runtime.atn.BasicBlockStartState) BlockStartState(org.antlr.v4.runtime.atn.BlockStartState) NotNull(org.antlr.v4.runtime.misc.NotNull)

Aggregations

PlusBlockStartState (org.antlr.v4.runtime.atn.PlusBlockStartState)6 ATNState (org.antlr.v4.runtime.atn.ATNState)3 InvalidClassException (java.io.InvalidClassException)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 LinkedList (java.util.LinkedList)2 UUID (java.util.UUID)2 AbstractPredicateTransition (org.antlr.v4.runtime.atn.AbstractPredicateTransition)2 ActionTransition (org.antlr.v4.runtime.atn.ActionTransition)2 AtomTransition (org.antlr.v4.runtime.atn.AtomTransition)2 BasicBlockStartState (org.antlr.v4.runtime.atn.BasicBlockStartState)2 BlockEndState (org.antlr.v4.runtime.atn.BlockEndState)2 BlockStartState (org.antlr.v4.runtime.atn.BlockStartState)2 LoopEndState (org.antlr.v4.runtime.atn.LoopEndState)2 NotSetTransition (org.antlr.v4.runtime.atn.NotSetTransition)2 PlusLoopbackState (org.antlr.v4.runtime.atn.PlusLoopbackState)2 RangeTransition (org.antlr.v4.runtime.atn.RangeTransition)2 RuleStartState (org.antlr.v4.runtime.atn.RuleStartState)2 RuleStopState (org.antlr.v4.runtime.atn.RuleStopState)2 RuleTransition (org.antlr.v4.runtime.atn.RuleTransition)2