diff --git a/tool/src/org/antlr/v4/automata/ParserATNFactory.java b/tool/src/org/antlr/v4/automata/ParserATNFactory.java index efc4921da..c8b39e146 100644 --- a/tool/src/org/antlr/v4/automata/ParserATNFactory.java +++ b/tool/src/org/antlr/v4/automata/ParserATNFactory.java @@ -58,41 +58,6 @@ import java.util.List; * No side-effects. It builds an ATN object and returns it. */ public class ParserATNFactory implements ATNFactory { - class TailEpsilonRemover extends ATNVisitor { - @Override - public void visitState(ATNState p) { - if ( p.getClass() == ATNState.class && p.getNumberOfTransitions()==1 ) { - ATNState q = p.transition(0).target; - if ( p.transition(0) instanceof RuleTransition ) { - q = ((RuleTransition)p.transition(0)).followState; - } - if ( q.getClass() == ATNState.class ) { - // we have p-x->q for x in {rule, action, pred, token, ...} - // if edge out of q is single epsilon to block end - // we can strip epsilon p-x->q-eps->r - Transition trans = q.transition(0); - if ( q.getNumberOfTransitions()==1 && trans.isEpsilon() && - !(trans instanceof ActionTransition) ) { - ATNState r = trans.target; - if ( r instanceof BlockEndState || - r instanceof PlusLoopbackState || - r instanceof StarLoopbackState ) - { - // skip over q - if ( p.transition(0) instanceof RuleTransition ) { - ((RuleTransition)p.transition(0)).followState = r; - } - else { - p.transition(0).target = r; - } - atn.removeState(q); - } - } - } - } - } - } - @NotNull public final Grammar g; @@ -373,7 +338,7 @@ public class ParserATNFactory implements ATNFactory { epsilon(alt.right, end); // no back link in ATN so must walk entire alt to see if we can // strip out the epsilon to 'end' state - TailEpsilonRemover opt = new TailEpsilonRemover(); + TailEpsilonRemover opt = new TailEpsilonRemover(atn); opt.visit(alt.left); } Handle h = new Handle(start, end); diff --git a/tool/src/org/antlr/v4/automata/TailEpsilonRemover.java b/tool/src/org/antlr/v4/automata/TailEpsilonRemover.java new file mode 100644 index 000000000..26a82a0c3 --- /dev/null +++ b/tool/src/org/antlr/v4/automata/TailEpsilonRemover.java @@ -0,0 +1,81 @@ +/* + [The "BSD license"] + Copyright (c) 2012 Terence Parr + 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.automata; + +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.ActionTransition; +import org.antlr.v4.runtime.atn.BlockEndState; +import org.antlr.v4.runtime.atn.PlusLoopbackState; +import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.StarLoopbackState; +import org.antlr.v4.runtime.atn.Transition; +import org.antlr.v4.runtime.misc.NotNull; + +/** + * + * @author Terence Parr + */ +public class TailEpsilonRemover extends ATNVisitor { + @NotNull + private final ATN _atn; + + public TailEpsilonRemover(@NotNull ATN atn) { + this._atn = atn; + } + + @Override + public void visitState(@NotNull ATNState p) { + if (p.getClass() == ATNState.class && p.getNumberOfTransitions() == 1) { + ATNState q = p.transition(0).target; + if (p.transition(0) instanceof RuleTransition) { + q = ((RuleTransition) p.transition(0)).followState; + } + if (q.getClass() == ATNState.class) { + // we have p-x->q for x in {rule, action, pred, token, ...} + // if edge out of q is single epsilon to block end + // we can strip epsilon p-x->q-eps->r + Transition trans = q.transition(0); + if (q.getNumberOfTransitions() == 1 && trans.isEpsilon() && !(trans instanceof ActionTransition)) { + ATNState r = trans.target; + if (r instanceof BlockEndState || r instanceof PlusLoopbackState || r instanceof StarLoopbackState) { + // skip over q + if (p.transition(0) instanceof RuleTransition) { + ((RuleTransition) p.transition(0)).followState = r; + } else { + p.transition(0).target = r; + } + _atn.removeState(q); + } + } + } + } + } +}