Search in sources :

Example 1 with Graph

use of org.antlr.v4.misc.Graph 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 Graph

use of org.antlr.v4.misc.Graph in project antlr4 by antlr.

the class Tool method sortGrammarByTokenVocab.

public List<GrammarRootAST> sortGrammarByTokenVocab(List<String> fileNames) {
    //		System.out.println(fileNames);
    Graph<String> g = new Graph<String>();
    List<GrammarRootAST> roots = new ArrayList<GrammarRootAST>();
    for (String fileName : fileNames) {
        GrammarAST t = parseGrammar(fileName);
        // came back as error node
        if (t == null || t instanceof GrammarASTErrorNode)
            continue;
        if (((GrammarRootAST) t).hasErrors)
            continue;
        GrammarRootAST root = (GrammarRootAST) t;
        roots.add(root);
        root.fileName = fileName;
        String grammarName = root.getChild(0).getText();
        GrammarAST tokenVocabNode = findOptionValueAST(root, "tokenVocab");
        // Make grammars depend on any tokenVocab options
        if (tokenVocabNode != null) {
            String vocabName = tokenVocabNode.getText();
            // Strip quote characters if any
            int len = vocabName.length();
            int firstChar = vocabName.charAt(0);
            int lastChar = vocabName.charAt(len - 1);
            if (len >= 2 && firstChar == '\'' && lastChar == '\'') {
                vocabName = vocabName.substring(1, len - 1);
            }
            // If the name contains a path delimited by forward slashes,
            // use only the part after the last slash as the name
            int lastSlash = vocabName.lastIndexOf('/');
            if (lastSlash >= 0) {
                vocabName = vocabName.substring(lastSlash + 1);
            }
            g.addEdge(grammarName, vocabName);
        }
        // add cycle to graph so we always process a grammar if no error
        // even if no dependency
        g.addEdge(grammarName, grammarName);
    }
    List<String> sortedGrammarNames = g.sort();
    //		System.out.println("sortedGrammarNames="+sortedGrammarNames);
    List<GrammarRootAST> sortedRoots = new ArrayList<GrammarRootAST>();
    for (String grammarName : sortedGrammarNames) {
        for (GrammarRootAST root : roots) {
            if (root.getGrammarName().equals(grammarName)) {
                sortedRoots.add(root);
                break;
            }
        }
    }
    return sortedRoots;
}
Also used : Graph(org.antlr.v4.misc.Graph) GrammarASTErrorNode(org.antlr.v4.tool.ast.GrammarASTErrorNode) GrammarRootAST(org.antlr.v4.tool.ast.GrammarRootAST) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList)

Example 3 with Graph

use of org.antlr.v4.misc.Graph in project antlr4 by antlr.

the class ParserATNFactory method set.

/** From set build single edge graph {@code o->o-set->o}.  To conform to
     *  what an alt block looks like, must have extra state on left.
	 *  This also handles {@code ~A}, converted to {@code ~{A}} set.
     */
@Override
public Handle set(GrammarAST associatedAST, List<GrammarAST> terminals, boolean invert) {
    ATNState left = newState(associatedAST);
    ATNState right = newState(associatedAST);
    IntervalSet set = new IntervalSet();
    for (GrammarAST t : terminals) {
        int ttype = g.getTokenType(t.getText());
        set.add(ttype);
    }
    if (invert) {
        left.addTransition(new NotSetTransition(right, set));
    } else {
        left.addTransition(new SetTransition(right, set));
    }
    associatedAST.atnState = left;
    return new Handle(left, right);
}
Also used : IntervalSet(org.antlr.v4.runtime.misc.IntervalSet) GrammarAST(org.antlr.v4.tool.ast.GrammarAST) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) NotSetTransition(org.antlr.v4.runtime.atn.NotSetTransition) SetTransition(org.antlr.v4.runtime.atn.SetTransition) ATNState(org.antlr.v4.runtime.atn.ATNState)

Example 4 with Graph

use of org.antlr.v4.misc.Graph in project antlr4 by antlr.

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?
	 */
@Override
public Handle block(BlockAST blkAST, GrammarAST ebnfRoot, 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)

Example 5 with Graph

use of org.antlr.v4.misc.Graph in project antlr4 by antlr.

the class ParserATNFactory method tokenRef.

/** From label {@code A} build graph {@code o-A->o}. */
@Override
public Handle tokenRef(TerminalAST node) {
    ATNState left = newState(node);
    ATNState right = newState(node);
    int ttype = g.getTokenType(node.getText());
    left.addTransition(new AtomTransition(right, ttype));
    node.atnState = left;
    return new Handle(left, right);
}
Also used : AtomTransition(org.antlr.v4.runtime.atn.AtomTransition) ATNState(org.antlr.v4.runtime.atn.ATNState)

Aggregations

ATNState (org.antlr.v4.runtime.atn.ATNState)3 AtomTransition (org.antlr.v4.runtime.atn.AtomTransition)2 NotSetTransition (org.antlr.v4.runtime.atn.NotSetTransition)2 PlusBlockStartState (org.antlr.v4.runtime.atn.PlusBlockStartState)2 SetTransition (org.antlr.v4.runtime.atn.SetTransition)2 GrammarAST (org.antlr.v4.tool.ast.GrammarAST)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 Graph (org.antlr.v4.misc.Graph)1 AbstractPredicateTransition (org.antlr.v4.runtime.atn.AbstractPredicateTransition)1 ActionTransition (org.antlr.v4.runtime.atn.ActionTransition)1 BasicBlockStartState (org.antlr.v4.runtime.atn.BasicBlockStartState)1 BlockStartState (org.antlr.v4.runtime.atn.BlockStartState)1 RangeTransition (org.antlr.v4.runtime.atn.RangeTransition)1 RuleStartState (org.antlr.v4.runtime.atn.RuleStartState)1 RuleStopState (org.antlr.v4.runtime.atn.RuleStopState)1 RuleTransition (org.antlr.v4.runtime.atn.RuleTransition)1 StarBlockStartState (org.antlr.v4.runtime.atn.StarBlockStartState)1