Exemplo n.º 1
0
        protected virtual void OptimizeExitBranches(DFAState d)
        {
            int sI = d.stateNumber;

            if (_visited.Contains(sI))
            {
                return; // already visited
            }
            _visited.Add(sI);
            int nAlts = d.dfa.NumberOfAlts;

            for (int i = 0; i < d.NumberOfTransitions; i++)
            {
                Transition edge       = (Transition)d.Transition(i);
                DFAState   edgeTarget = ((DFAState)edge.target);

                /*
                 * [email protected](d.stateNumber+"-"+
                 *                 edge.label.toString(d.dfa.nfa.grammar)+"->"+
                 *                 edgeTarget.stateNumber);
                 */
                // if target is an accept state and that alt is the exit alt
                if (edgeTarget.IsAcceptState &&
                    edgeTarget.GetUniquelyPredictedAlt() == nAlts)
                {
                    /*
                     * [email protected]("ignoring transition "+i+" to max alt "+
                     *  d.dfa.getNumberOfAlts());
                     */
                    d.RemoveTransition(i);
                    i--; // back up one so that i++ of loop iteration stays within bounds
                }
                OptimizeExitBranches(edgeTarget);
            }
        }
Exemplo n.º 2
0
        // S U P P O R T

        /** Given a start state and a target state, return true if start can reach
         *  target state.  Also, compute the set of DFA states
         *  that are on a path from start to target; return in states parameter.
         */
        protected virtual bool ReachesState(DFAState startState,
                                            DFAState targetState,
                                            HashSet <object> states)
        {
            if (startState == targetState)
            {
                states.Add(targetState);
                //[email protected]("found target DFA state "+targetState.getStateNumber());
                _stateReachable[startState.stateNumber] = REACHABLE_YES;
                return(true);
            }

            DFAState s = startState;

            // avoid infinite loops
            _stateReachable[s.stateNumber] = REACHABLE_BUSY;

            // look for a path to targetState among transitions for this state
            // stop when you find the first one; I'm pretty sure there is
            // at most one path to any DFA state with conflicting predictions
            for (int i = 0; i < s.NumberOfTransitions; i++)
            {
                Transition t          = s.Transition(i);
                DFAState   edgeTarget = (DFAState)t.target;

                int targetStatus; //= stateReachable.get( edgeTarget.stateNumber );
                if (_stateReachable.TryGetValue(edgeTarget.stateNumber, out targetStatus))
                {
                    if (targetStatus == REACHABLE_BUSY)
                    { // avoid cycles; they say nothing
                        continue;
                    }
                    if (targetStatus == REACHABLE_YES)
                    { // return success!
                        _stateReachable[s.stateNumber] = REACHABLE_YES;
                        return(true);
                    }
                    if (targetStatus == REACHABLE_NO)
                    { // try another transition
                        continue;
                    }
                }

                // if null, target must be REACHABLE_UNKNOWN (i.e., unvisited)
                if (ReachesState(edgeTarget, targetState, states))
                {
                    states.Add(s);
                    _stateReachable[s.stateNumber] = REACHABLE_YES;
                    return(true);
                }
            }

            _stateReachable[s.stateNumber] = REACHABLE_NO;
            return(false); // no path to targetState found.
        }
Exemplo n.º 3
0
        protected virtual void OptimizeEOTBranches(DFAState d)
        {
            int sI = d.stateNumber;

            if (_visited.Contains(sI))
            {
                return; // already visited
            }
            _visited.Add(sI);
            for (int i = 0; i < d.NumberOfTransitions; i++)
            {
                Transition edge       = (Transition)d.Transition(i);
                DFAState   edgeTarget = ((DFAState)edge.target);

                /*
                 * [email protected](d.stateNumber+"-"+
                 *                 edge.label.toString(d.dfa.nfa.grammar)+"->"+
                 *                 edgeTarget.stateNumber);
                 */
                // if only one edge coming out, it is EOT, and target is accept prune
                if (PRUNE_TOKENS_RULE_SUPERFLUOUS_EOT_EDGES &&
                    edgeTarget.IsAcceptState &&
                    d.NumberOfTransitions == 1 &&
                    edge.label.IsAtom &&
                    edge.label.Atom == Label.EOT)
                {
                    //[email protected]("state "+d+" can be pruned");
                    // remove the superfluous EOT edge
                    d.RemoveTransition(i);
                    d.IsAcceptState = true; // make it an accept state
                    // force it to uniquely predict the originally predicted state
                    d.cachedUniquelyPredicatedAlt =
                        edgeTarget.GetUniquelyPredictedAlt();
                    i--; // back up one so that i++ of loop iteration stays within bounds
                }
                OptimizeEOTBranches(edgeTarget);
            }
        }
Exemplo n.º 4
0
        /** Do a depth-first walk of the state machine graph and
         *  fill a DOT description template.  Keep filling the
         *  states and edges attributes.
         */
        protected virtual void WalkCreatingDFADOT( StringTemplate dot,
                                          DFAState s )
        {
            if ( markedStates.Contains( s.stateNumber ) )
            {
                return; // already visited this node
            }

            markedStates.Add( s.stateNumber ); // mark this node as completed.

            // first add this node
            StringTemplate st;
            if ( s.IsAcceptState )
            {
                st = stlib.GetInstanceOf( Path.Combine( dfaTemplateDirectoryName, "stopstate" ) );
            }
            else
            {
                st = stlib.GetInstanceOf( Path.Combine( dfaTemplateDirectoryName, "state" ) );
            }
            st.SetAttribute( "name", GetStateLabel( s ) );
            dot.SetAttribute( "states", st );

            // make a DOT edge for each transition
            for ( int i = 0; i < s.NumberOfTransitions; i++ )
            {
                Transition edge = (Transition)s.Transition( i );
                //Console.Out.WriteLine( "dfa " + s.dfa.decisionNumber + " edge from s"
                //    + s.stateNumber + " [" + i + "] of " + s.NumberOfTransitions );
                if ( StripNonreducedStates )
                {
                    if ( edge.target is DFAState &&
                        ( (DFAState)edge.target ).AcceptStateReachable != DFA.REACHABLE_YES )
                    {
                        continue; // don't generate nodes for terminal states
                    }
                }
                st = stlib.GetInstanceOf( Path.Combine( dfaTemplateDirectoryName, "edge" ) );
                st.SetAttribute( "label", GetEdgeLabel( edge ) );
                st.SetAttribute( "src", GetStateLabel( s ) );
                st.SetAttribute( "target", GetStateLabel( edge.target ) );
                st.SetAttribute( "arrowhead", arrowhead );
                dot.SetAttribute( "edges", st );
                WalkCreatingDFADOT( dot, (DFAState)edge.target ); // keep walkin'
            }
        }
Exemplo n.º 5
0
 protected virtual void OptimizeExitBranches( DFAState d )
 {
     int sI = d.stateNumber;
     if ( _visited.Contains( sI ) )
     {
         return; // already visited
     }
     _visited.Add( sI );
     int nAlts = d.dfa.NumberOfAlts;
     for ( int i = 0; i < d.NumberOfTransitions; i++ )
     {
         Transition edge = (Transition)d.Transition( i );
         DFAState edgeTarget = ( (DFAState)edge.target );
         /*
         [email protected](d.stateNumber+"-"+
                            edge.label.toString(d.dfa.nfa.grammar)+"->"+
                            edgeTarget.stateNumber);
         */
         // if target is an accept state and that alt is the exit alt
         if ( edgeTarget.IsAcceptState &&
             edgeTarget.GetUniquelyPredictedAlt() == nAlts )
         {
             /*
             [email protected]("ignoring transition "+i+" to max alt "+
                 d.dfa.getNumberOfAlts());
             */
             d.RemoveTransition( i );
             i--; // back up one so that i++ of loop iteration stays within bounds
         }
         OptimizeExitBranches( edgeTarget );
     }
 }
Exemplo n.º 6
0
 protected virtual void OptimizeEOTBranches( DFAState d )
 {
     int sI = d.stateNumber;
     if ( _visited.Contains( sI ) )
     {
         return; // already visited
     }
     _visited.Add( sI );
     for ( int i = 0; i < d.NumberOfTransitions; i++ )
     {
         Transition edge = (Transition)d.Transition( i );
         DFAState edgeTarget = ( (DFAState)edge.target );
         /*
         [email protected](d.stateNumber+"-"+
                            edge.label.toString(d.dfa.nfa.grammar)+"->"+
                            edgeTarget.stateNumber);
         */
         // if only one edge coming out, it is EOT, and target is accept prune
         if ( PRUNE_TOKENS_RULE_SUPERFLUOUS_EOT_EDGES &&
             edgeTarget.IsAcceptState &&
             d.NumberOfTransitions == 1 &&
             edge.label.IsAtom &&
             edge.label.Atom == Label.EOT )
         {
             //[email protected]("state "+d+" can be pruned");
             // remove the superfluous EOT edge
             d.RemoveTransition( i );
             d.IsAcceptState = true; // make it an accept state
             // force it to uniquely predict the originally predicted state
             d.cachedUniquelyPredicatedAlt =
                 edgeTarget.GetUniquelyPredictedAlt();
             i--; // back up one so that i++ of loop iteration stays within bounds
         }
         OptimizeEOTBranches( edgeTarget );
     }
 }
Exemplo n.º 7
0
        /** A special state is huge (too big for state tables) or has a predicated
         *  edge.  Generate a simple if-then-else.  Cannot be an accept state as
         *  they have no emanating edges.  Don't worry about switch vs if-then-else
         *  because if you get here, the state is super complicated and needs an
         *  if-then-else.  This is used by the new DFA scheme created June 2006.
         */
        public virtual StringTemplate GenerateSpecialState( DFAState s )
        {
            StringTemplate stateST;
            stateST = templates.GetInstanceOf( "cyclicDFAState" );
            stateST.SetAttribute( "needErrorClause", true );
            stateST.SetAttribute( "semPredState", s.IsResolvedWithPredicates );
            stateST.SetAttribute( "stateNumber", s.stateNumber );
            stateST.SetAttribute( "decisionNumber", s.dfa.decisionNumber );

            bool foundGatedPred = false;
            StringTemplate eotST = null;
            for ( int i = 0; i < s.NumberOfTransitions; i++ )
            {
                Transition edge = (Transition)s.Transition( i );
                StringTemplate edgeST;
                if ( edge.label.Atom == Label.EOT )
                {
                    // this is the default clause; has to held until last
                    edgeST = templates.GetInstanceOf( "eotDFAEdge" );
                    stateST.RemoveAttribute( "needErrorClause" );
                    eotST = edgeST;
                }
                else
                {
                    edgeST = templates.GetInstanceOf( "cyclicDFAEdge" );
                    StringTemplate exprST =
                        GenLabelExpr( templates, edge, 1 );
                    edgeST.SetAttribute( "labelExpr", exprST );
                }
                edgeST.SetAttribute( "edgeNumber", i + 1 );
                edgeST.SetAttribute( "targetStateNumber",
                                     edge.target.stateNumber );
                // stick in any gated predicates for any edge if not already a pred
                if ( !edge.label.IsSemanticPredicate )
                {
                    DFAState t = (DFAState)edge.target;
                    SemanticContext preds = t.GetGatedPredicatesInNFAConfigurations();
                    if ( preds != null )
                    {
                        foundGatedPred = true;
                        StringTemplate predST = preds.GenExpr( this,
                                                              Templates,
                                                              t.dfa );
                        edgeST.SetAttribute( "predicates", predST.ToString() );
                    }
                }
                if ( edge.label.Atom != Label.EOT )
                {
                    stateST.SetAttribute( "edges", edgeST );
                }
            }
            if ( foundGatedPred )
            {
                // state has >= 1 edge with a gated pred (syn or sem)
                // must rewind input first, set flag.
                stateST.SetAttribute( "semPredState", foundGatedPred );
            }
            if ( eotST != null )
            {
                stateST.SetAttribute( "edges", eotST );
            }
            return stateST;
        }
Exemplo n.º 8
0
 /** You can generate a switch rather than if-then-else for a DFA state
  *  if there are no semantic predicates and the number of edge label
  *  values is small enough; e.g., don't generate a switch for a state
  *  containing an edge label such as 20..52330 (the resulting byte codes
  *  would overflow the method 65k limit probably).
  */
 protected internal virtual bool CanGenerateSwitch( DFAState s )
 {
     if ( !GenerateSwitchesWhenPossible )
     {
         return false;
     }
     int size = 0;
     for ( int i = 0; i < s.NumberOfTransitions; i++ )
     {
         Transition edge = (Transition)s.Transition( i );
         if ( edge.label.IsSemanticPredicate )
         {
             return false;
         }
         // can't do a switch if the edges are going to require predicates
         if ( edge.label.Atom == Label.EOT )
         {
             int EOTPredicts = ( (DFAState)edge.target ).GetUniquelyPredictedAlt();
             if ( EOTPredicts == NFA.INVALID_ALT_NUMBER )
             {
                 // EOT target has to be a predicate then; no unique alt
                 return false;
             }
         }
         // if target is a state with gated preds, we need to use preds on
         // this edge then to reach it.
         if ( ( (DFAState)edge.target ).GetGatedPredicatesInNFAConfigurations() != null )
         {
             return false;
         }
         size += edge.label.Set.Count;
     }
     if ( s.NumberOfTransitions < MinSwitchAlts ||
          size > MaxSwitchCaseLabels )
     {
         return false;
     }
     return true;
 }
Exemplo n.º 9
0
        protected virtual StringTemplate WalkFixedDFAGeneratingStateMachine(
                StringTemplateGroup templates,
                DFA dfa,
                DFAState s,
                int k )
        {
            //System.Console.Out.WriteLine( "walk " + s.stateNumber + " in dfa for decision " + dfa.decisionNumber );
            if ( s.IsAcceptState )
            {
                StringTemplate dfaST2 = templates.GetInstanceOf( "dfaAcceptState" );
                dfaST2.SetAttribute( "alt", s.GetUniquelyPredictedAlt() );
                return dfaST2;
            }

            // the default templates for generating a state and its edges
            // can be an if-then-else structure or a switch
            string dfaStateName = "dfaState";
            string dfaLoopbackStateName = "dfaLoopbackState";
            string dfaOptionalBlockStateName = "dfaOptionalBlockState";
            string dfaEdgeName = "dfaEdge";
            if ( parentGenerator.CanGenerateSwitch( s ) )
            {
                dfaStateName = "dfaStateSwitch";
                dfaLoopbackStateName = "dfaLoopbackStateSwitch";
                dfaOptionalBlockStateName = "dfaOptionalBlockStateSwitch";
                dfaEdgeName = "dfaEdgeSwitch";
            }

            StringTemplate dfaST = templates.GetInstanceOf( dfaStateName );
            if ( dfa.NFADecisionStartState.decisionStateType == NFAState.LOOPBACK )
            {
                dfaST = templates.GetInstanceOf( dfaLoopbackStateName );
            }
            else if ( dfa.NFADecisionStartState.decisionStateType == NFAState.OPTIONAL_BLOCK_START )
            {
                dfaST = templates.GetInstanceOf( dfaOptionalBlockStateName );
            }
            dfaST.SetAttribute( "k", k );
            dfaST.SetAttribute( "stateNumber", s.stateNumber );
            dfaST.SetAttribute( "semPredState",
                               s.IsResolvedWithPredicates );
            /*
            string description = dfa.getNFADecisionStartState().Description;
            description = parentGenerator.target.getTargetStringLiteralFromString( description );
            //System.Console.Out.WriteLine( "DFA: " + description + " associated with AST " + dfa.getNFADecisionStartState() );
            if ( description != null )
            {
                dfaST.SetAttribute( "description", description );
            }
            */
            int EOTPredicts = NFA.INVALID_ALT_NUMBER;
            DFAState EOTTarget = null;
            //System.Console.Out.WriteLine( "DFA state " + s.stateNumber );
            for ( int i = 0; i < s.NumberOfTransitions; i++ )
            {
                Transition edge = (Transition)s.Transition( i );
                //System.Console.Out.WriteLine( "edge " + s.stateNumber + "-" + edge.label.ToString() + "->" + edge.target.stateNumber );
                if ( edge.label.Atom == Label.EOT )
                {
                    // don't generate a real edge for EOT; track alt EOT predicts
                    // generate that prediction in the else clause as default case
                    EOTTarget = (DFAState)edge.target;
                    EOTPredicts = EOTTarget.GetUniquelyPredictedAlt();
                    /*
                    System.Console.Out.WriteLine("DFA s"+s.stateNumber+" EOT goes to s"+
                                       edge.target.stateNumber+" predicates alt "+
                                       EOTPredicts);
                    */
                    continue;
                }
                StringTemplate edgeST = templates.GetInstanceOf( dfaEdgeName );
                // If the template wants all the label values delineated, do that
                if ( edgeST.GetFormalArgument( "labels" ) != null )
                {
                    List<string> labels = edge.Label.Set.Select( value => parentGenerator.GetTokenTypeAsTargetLabel( value ) ).ToList();
                    edgeST.SetAttribute( "labels", labels );
                }
                else
                { // else create an expression to evaluate (the general case)
                    edgeST.SetAttribute( "labelExpr",
                                        parentGenerator.GenLabelExpr( templates, edge, k ) );
                }

                // stick in any gated predicates for any edge if not already a pred
                if ( !edge.label.IsSemanticPredicate )
                {
                    DFAState target = (DFAState)edge.target;
                    SemanticContext preds =
                        target.GetGatedPredicatesInNFAConfigurations();
                    if ( preds != null )
                    {
                        //System.Console.Out.WriteLine( "preds=" + target.getGatedPredicatesInNFAConfigurations() );
                        StringTemplate predST = preds.GenExpr( parentGenerator,
                                                              parentGenerator.Templates,
                                                              dfa );
                        edgeST.SetAttribute( "predicates", predST );
                    }
                }

                StringTemplate targetST =
                    WalkFixedDFAGeneratingStateMachine( templates,
                                                       dfa,
                                                       (DFAState)edge.target,
                                                       k + 1 );
                edgeST.SetAttribute( "targetState", targetST );
                dfaST.SetAttribute( "edges", edgeST );
                //System.Console.Out.WriteLine( "back to DFA " + dfa.decisionNumber + "." + s.stateNumber );
            }

            // HANDLE EOT EDGE
            if ( EOTPredicts != NFA.INVALID_ALT_NUMBER )
            {
                // EOT unique predicts an alt
                dfaST.SetAttribute( "eotPredictsAlt", EOTPredicts );
            }
            else if ( EOTTarget != null && EOTTarget.NumberOfTransitions > 0 )
            {
                // EOT state has transitions so must split on predicates.
                // Generate predicate else-if clauses and then generate
                // NoViableAlt exception as else clause.
                // Note: these predicates emanate from the EOT target state
                // rather than the current DFAState s so the error message
                // might be slightly misleading if you are looking at the
                // state number.  Predicates emanating from EOT targets are
                // hoisted up to the state that has the EOT edge.
                for ( int i = 0; i < EOTTarget.NumberOfTransitions; i++ )
                {
                    Transition predEdge = (Transition)EOTTarget.Transition( i );
                    StringTemplate edgeST = templates.GetInstanceOf( dfaEdgeName );
                    edgeST.SetAttribute( "labelExpr",
                                        parentGenerator.GenSemanticPredicateExpr( templates, predEdge ) );
                    // the target must be an accept state
                    //System.Console.Out.WriteLine( "EOT edge" );
                    StringTemplate targetST =
                        WalkFixedDFAGeneratingStateMachine( templates,
                                                           dfa,
                                                           (DFAState)predEdge.target,
                                                           k + 1 );
                    edgeST.SetAttribute( "targetState", targetST );
                    dfaST.SetAttribute( "edges", edgeST );
                }
            }
            return dfaST;
        }