123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879 |
- /*
- * Copyright 2002-2004 Adrian Thurston <thurston@complang.org>
- */
- /* This file is part of Ragel.
- *
- * Ragel is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Ragel is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Ragel; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include "fsmgraph.h"
- #include <iostream>
- using std::cerr;
- using std::endl;
- CondData *condData = 0;
- KeyOps *keyOps = 0;
- /* Insert an action into an action table. */
- void ActionTable::setAction( int ordering, Action *action )
- {
- /* Multi-insert in case specific instances of an action appear in a
- * transition more than once. */
- insertMulti( ordering, action );
- }
- /* Set all the action from another action table in this table. */
- void ActionTable::setActions( const ActionTable &other )
- {
- for ( ActionTable::Iter action = other; action.lte(); action++ )
- insertMulti( action->key, action->value );
- }
- void ActionTable::setActions( int *orderings, Action **actions, int nActs )
- {
- for ( int a = 0; a < nActs; a++ )
- insertMulti( orderings[a], actions[a] );
- }
- bool ActionTable::hasAction( Action *action )
- {
- for ( int a = 0; a < length(); a++ ) {
- if ( data[a].value == action )
- return true;
- }
- return false;
- }
- /* Insert an action into an action table. */
- void LmActionTable::setAction( int ordering, LongestMatchPart *action )
- {
- /* Multi-insert in case specific instances of an action appear in a
- * transition more than once. */
- insertMulti( ordering, action );
- }
- /* Set all the action from another action table in this table. */
- void LmActionTable::setActions( const LmActionTable &other )
- {
- for ( LmActionTable::Iter action = other; action.lte(); action++ )
- insertMulti( action->key, action->value );
- }
- void ErrActionTable::setAction( int ordering, Action *action, int transferPoint )
- {
- insertMulti( ErrActionTableEl( action, ordering, transferPoint ) );
- }
- void ErrActionTable::setActions( const ErrActionTable &other )
- {
- for ( ErrActionTable::Iter act = other; act.lte(); act++ )
- insertMulti( ErrActionTableEl( act->action, act->ordering, act->transferPoint ) );
- }
- /* Insert a priority into this priority table. Looks out for priorities on
- * duplicate keys. */
- void PriorTable::setPrior( int ordering, PriorDesc *desc )
- {
- PriorEl *lastHit = 0;
- PriorEl *insed = insert( PriorEl(ordering, desc), &lastHit );
- if ( insed == 0 ) {
- /* This already has a priority on the same key as desc. Overwrite the
- * priority if the ordering is larger (later in time). */
- if ( ordering >= lastHit->ordering )
- *lastHit = PriorEl( ordering, desc );
- }
- }
- /* Set all the priorities from a priorTable in this table. */
- void PriorTable::setPriors( const PriorTable &other )
- {
- /* Loop src priorities once to overwrite duplicates. */
- PriorTable::Iter priorIt = other;
- for ( ; priorIt.lte(); priorIt++ )
- setPrior( priorIt->ordering, priorIt->desc );
- }
- /* Set the priority of starting transitions. Isolates the start state so it has
- * no other entry points, then sets the priorities of all the transitions out
- * of the start state. If the start state is final, then the outPrior of the
- * start state is also set. The idea is that a machine that accepts the null
- * string can still specify the starting trans prior for when it accepts the
- * null word. */
- void FsmAp::startFsmPrior( int ordering, PriorDesc *prior )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- /* Walk all transitions out of the start state. */
- for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) {
- if ( trans->toState != 0 )
- trans->priorTable.setPrior( ordering, prior );
- }
- /* If the new start state is final then set the out priority. This follows
- * the same convention as setting start action in the out action table of
- * a final start state. */
- if ( startState->stateBits & STB_ISFINAL )
- startState->outPriorTable.setPrior( ordering, prior );
- }
- /* Set the priority of all transitions in a graph. Walks all transition lists
- * and all def transitions. */
- void FsmAp::allTransPrior( int ordering, PriorDesc *prior )
- {
- /* Walk the list of all states. */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- /* Walk the out list of the state. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- if ( trans->toState != 0 )
- trans->priorTable.setPrior( ordering, prior );
- }
- }
- }
- /* Set the priority of all transitions that go into a final state. Note that if
- * any entry states are final, we will not be setting the priority of any
- * transitions that may go into those states in the future. The graph does not
- * support pending in transitions in the same way pending out transitions are
- * supported. */
- void FsmAp::finishFsmPrior( int ordering, PriorDesc *prior )
- {
- /* Walk all final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) {
- /* Walk all in transitions of the final state. */
- for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ )
- trans->priorTable.setPrior( ordering, prior );
- }
- }
- /* Set the priority of any future out transitions that may be made going out of
- * this state machine. */
- void FsmAp::leaveFsmPrior( int ordering, PriorDesc *prior )
- {
- /* Set priority in all final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->outPriorTable.setPrior( ordering, prior );
- }
- /* Set actions to execute on starting transitions. Isolates the start state
- * so it has no other entry points, then adds to the transition functions
- * of all the transitions out of the start state. If the start state is final,
- * then the func is also added to the start state's out func list. The idea is
- * that a machine that accepts the null string can execute a start func when it
- * matches the null word, which can only be done when leaving the start/final
- * state. */
- void FsmAp::startFsmAction( int ordering, Action *action )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- /* Walk the start state's transitions, setting functions. */
- for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) {
- if ( trans->toState != 0 )
- trans->actionTable.setAction( ordering, action );
- }
- /* If start state is final then add the action to the out action table.
- * This means that when the null string is accepted the start action will
- * not be bypassed. */
- if ( startState->stateBits & STB_ISFINAL )
- startState->outActionTable.setAction( ordering, action );
- }
- /* Set functions to execute on all transitions. Walks the out lists of all
- * states. */
- void FsmAp::allTransAction( int ordering, Action *action )
- {
- /* Walk all states. */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- /* Walk the out list of the state. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- if ( trans->toState != 0 )
- trans->actionTable.setAction( ordering, action );
- }
- }
- }
- /* Specify functions to execute upon entering final states. If the start state
- * is final we can't really specify a function to execute upon entering that
- * final state the first time. So function really means whenever entering a
- * final state from within the same fsm. */
- void FsmAp::finishFsmAction( int ordering, Action *action )
- {
- /* Walk all final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) {
- /* Walk the final state's in list. */
- for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ )
- trans->actionTable.setAction( ordering, action );
- }
- }
- /* Add functions to any future out transitions that may be made going out of
- * this state machine. */
- void FsmAp::leaveFsmAction( int ordering, Action *action )
- {
- /* Insert the action in the outActionTable of all final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->outActionTable.setAction( ordering, action );
- }
- /* Add functions to the longest match action table for constructing scanners. */
- void FsmAp::longMatchAction( int ordering, LongestMatchPart *lmPart )
- {
- /* Walk all final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) {
- /* Walk the final state's in list. */
- for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ )
- trans->lmActionTable.setAction( ordering, lmPart );
- }
- }
- void FsmAp::fillGaps( StateAp *state )
- {
- if ( state->outList.length() == 0 ) {
- /* Add the range on the lower and upper bound. */
- attachNewTrans( state, 0, keyOps->minKey, keyOps->maxKey );
- }
- else {
- TransList srcList;
- srcList.transfer( state->outList );
- /* Check for a gap at the beginning. */
- TransList::Iter trans = srcList, next;
- if ( keyOps->minKey < trans->lowKey ) {
- /* Make the high key and append. */
- Key highKey = trans->lowKey;
- highKey.decrement();
- attachNewTrans( state, 0, keyOps->minKey, highKey );
- }
- /* Write the transition. */
- next = trans.next();
- state->outList.append( trans );
- /* Keep the last high end. */
- Key lastHigh = trans->highKey;
- /* Loop each source range. */
- for ( trans = next; trans.lte(); trans = next ) {
- /* Make the next key following the last range. */
- Key nextKey = lastHigh;
- nextKey.increment();
- /* Check for a gap from last up to here. */
- if ( nextKey < trans->lowKey ) {
- /* Make the high end of the range that fills the gap. */
- Key highKey = trans->lowKey;
- highKey.decrement();
- attachNewTrans( state, 0, nextKey, highKey );
- }
- /* Reduce the transition. If it reduced to anything then add it. */
- next = trans.next();
- state->outList.append( trans );
- /* Keep the last high end. */
- lastHigh = trans->highKey;
- }
- /* Now check for a gap on the end to fill. */
- if ( lastHigh < keyOps->maxKey ) {
- /* Get a copy of the default. */
- lastHigh.increment();
- attachNewTrans( state, 0, lastHigh, keyOps->maxKey );
- }
- }
- }
- void FsmAp::setErrorActions( StateAp *state, const ActionTable &other )
- {
- /* Fill any gaps in the out list with an error transition. */
- fillGaps( state );
- /* Set error transitions in the transitions that go to error. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- if ( trans->toState == 0 )
- trans->actionTable.setActions( other );
- }
- }
- void FsmAp::setErrorAction( StateAp *state, int ordering, Action *action )
- {
- /* Fill any gaps in the out list with an error transition. */
- fillGaps( state );
- /* Set error transitions in the transitions that go to error. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- if ( trans->toState == 0 )
- trans->actionTable.setAction( ordering, action );
- }
- }
- /* Give a target state for error transitions. */
- void FsmAp::setErrorTarget( StateAp *state, StateAp *target, int *orderings,
- Action **actions, int nActs )
- {
- /* Fill any gaps in the out list with an error transition. */
- fillGaps( state );
- /* Set error target in the transitions that go to error. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- if ( trans->toState == 0 ) {
- /* The trans goes to error, redirect it. */
- redirectErrorTrans( trans->fromState, target, trans );
- trans->actionTable.setActions( orderings, actions, nActs );
- }
- }
- }
- void FsmAp::transferOutActions( StateAp *state )
- {
- for ( ActionTable::Iter act = state->outActionTable; act.lte(); act++ )
- state->eofActionTable.setAction( act->key, act->value );
- state->outActionTable.empty();
- }
- void FsmAp::transferErrorActions( StateAp *state, int transferPoint )
- {
- for ( int i = 0; i < state->errActionTable.length(); ) {
- ErrActionTableEl *act = state->errActionTable.data + i;
- if ( act->transferPoint == transferPoint ) {
- /* Transfer the error action and remove it. */
- setErrorAction( state, act->ordering, act->action );
- if ( ! state->isFinState() )
- state->eofActionTable.setAction( act->ordering, act->action );
- state->errActionTable.vremove( i );
- }
- else {
- /* Not transfering and deleting, skip over the item. */
- i += 1;
- }
- }
- }
- /* Set error actions in the start state. */
- void FsmAp::startErrorAction( int ordering, Action *action, int transferPoint )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- /* Add the actions. */
- startState->errActionTable.setAction( ordering, action, transferPoint );
- }
- /* Set error actions in all states where there is a transition out. */
- void FsmAp::allErrorAction( int ordering, Action *action, int transferPoint )
- {
- /* Insert actions in the error action table of all states. */
- for ( StateList::Iter state = stateList; state.lte(); state++ )
- state->errActionTable.setAction( ordering, action, transferPoint );
- }
- /* Set error actions in final states. */
- void FsmAp::finalErrorAction( int ordering, Action *action, int transferPoint )
- {
- /* Add the action to the error table of final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->errActionTable.setAction( ordering, action, transferPoint );
- }
- void FsmAp::notStartErrorAction( int ordering, Action *action, int transferPoint )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState )
- state->errActionTable.setAction( ordering, action, transferPoint );
- }
- }
- void FsmAp::notFinalErrorAction( int ordering, Action *action, int transferPoint )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( ! state->isFinState() )
- state->errActionTable.setAction( ordering, action, transferPoint );
- }
- }
- /* Set error actions in the states that have transitions into a final state. */
- void FsmAp::middleErrorAction( int ordering, Action *action, int transferPoint )
- {
- /* Isolate the start state in case it is reachable from in inside the
- * machine, in which case we don't want it set. */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState && ! state->isFinState() )
- state->errActionTable.setAction( ordering, action, transferPoint );
- }
- }
- /* Set EOF actions in the start state. */
- void FsmAp::startEOFAction( int ordering, Action *action )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- /* Add the actions. */
- startState->eofActionTable.setAction( ordering, action );
- }
- /* Set EOF actions in all states where there is a transition out. */
- void FsmAp::allEOFAction( int ordering, Action *action )
- {
- /* Insert actions in the EOF action table of all states. */
- for ( StateList::Iter state = stateList; state.lte(); state++ )
- state->eofActionTable.setAction( ordering, action );
- }
- /* Set EOF actions in final states. */
- void FsmAp::finalEOFAction( int ordering, Action *action )
- {
- /* Add the action to the error table of final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->eofActionTable.setAction( ordering, action );
- }
- void FsmAp::notStartEOFAction( int ordering, Action *action )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState )
- state->eofActionTable.setAction( ordering, action );
- }
- }
- void FsmAp::notFinalEOFAction( int ordering, Action *action )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( ! state->isFinState() )
- state->eofActionTable.setAction( ordering, action );
- }
- }
- /* Set EOF actions in the states that have transitions into a final state. */
- void FsmAp::middleEOFAction( int ordering, Action *action )
- {
- /* Set the actions in all states that are not the start state and not final. */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState && ! state->isFinState() )
- state->eofActionTable.setAction( ordering, action );
- }
- }
- /*
- * Set To State Actions.
- */
- /* Set to state actions in the start state. */
- void FsmAp::startToStateAction( int ordering, Action *action )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- startState->toStateActionTable.setAction( ordering, action );
- }
- /* Set to state actions in all states. */
- void FsmAp::allToStateAction( int ordering, Action *action )
- {
- /* Insert the action on all states. */
- for ( StateList::Iter state = stateList; state.lte(); state++ )
- state->toStateActionTable.setAction( ordering, action );
- }
- /* Set to state actions in final states. */
- void FsmAp::finalToStateAction( int ordering, Action *action )
- {
- /* Add the action to the error table of final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->toStateActionTable.setAction( ordering, action );
- }
- void FsmAp::notStartToStateAction( int ordering, Action *action )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState )
- state->toStateActionTable.setAction( ordering, action );
- }
- }
- void FsmAp::notFinalToStateAction( int ordering, Action *action )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( ! state->isFinState() )
- state->toStateActionTable.setAction( ordering, action );
- }
- }
- /* Set to state actions in states that are not final and not the start state. */
- void FsmAp::middleToStateAction( int ordering, Action *action )
- {
- /* Set the action in all states that are not the start state and not final. */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState && ! state->isFinState() )
- state->toStateActionTable.setAction( ordering, action );
- }
- }
- /*
- * Set From State Actions.
- */
- void FsmAp::startFromStateAction( int ordering, Action *action )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- startState->fromStateActionTable.setAction( ordering, action );
- }
- void FsmAp::allFromStateAction( int ordering, Action *action )
- {
- /* Insert the action on all states. */
- for ( StateList::Iter state = stateList; state.lte(); state++ )
- state->fromStateActionTable.setAction( ordering, action );
- }
- void FsmAp::finalFromStateAction( int ordering, Action *action )
- {
- /* Add the action to the error table of final states. */
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->fromStateActionTable.setAction( ordering, action );
- }
- void FsmAp::notStartFromStateAction( int ordering, Action *action )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState )
- state->fromStateActionTable.setAction( ordering, action );
- }
- }
- void FsmAp::notFinalFromStateAction( int ordering, Action *action )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( ! state->isFinState() )
- state->fromStateActionTable.setAction( ordering, action );
- }
- }
- void FsmAp::middleFromStateAction( int ordering, Action *action )
- {
- /* Set the action in all states that are not the start state and not final. */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- if ( state != startState && ! state->isFinState() )
- state->fromStateActionTable.setAction( ordering, action );
- }
- }
- /* Shift the function ordering of the start transitions to start
- * at fromOrder and increase in units of 1. Useful before staring.
- * Returns the maximum number of order numbers used. */
- int FsmAp::shiftStartActionOrder( int fromOrder )
- {
- int maxUsed = 0;
- /* Walk the start state's transitions, shifting function ordering. */
- for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) {
- /* Walk the function data for the transition and set the keys to
- * increasing values starting at fromOrder. */
- int curFromOrder = fromOrder;
- ActionTable::Iter action = trans->actionTable;
- for ( ; action.lte(); action++ )
- action->key = curFromOrder++;
-
- /* Keep track of the max number of orders used. */
- if ( curFromOrder - fromOrder > maxUsed )
- maxUsed = curFromOrder - fromOrder;
- }
-
- return maxUsed;
- }
- /* Remove all priorities. */
- void FsmAp::clearAllPriorities()
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- /* Clear out priority data. */
- state->outPriorTable.empty();
- /* Clear transition data from the out transitions. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ )
- trans->priorTable.empty();
- }
- }
- /* Zeros out the function ordering keys. This may be called before minimization
- * when it is known that no more fsm operations are going to be done. This
- * will achieve greater reduction as states will not be separated on the basis
- * of function ordering. */
- void FsmAp::nullActionKeys( )
- {
- /* For each state... */
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- /* Walk the transitions for the state. */
- for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
- /* Walk the action table for the transition. */
- for ( ActionTable::Iter action = trans->actionTable;
- action.lte(); action++ )
- action->key = 0;
- /* Walk the action table for the transition. */
- for ( LmActionTable::Iter action = trans->lmActionTable;
- action.lte(); action++ )
- action->key = 0;
- }
- /* Null the action keys of the to state action table. */
- for ( ActionTable::Iter action = state->toStateActionTable;
- action.lte(); action++ )
- action->key = 0;
- /* Null the action keys of the from state action table. */
- for ( ActionTable::Iter action = state->fromStateActionTable;
- action.lte(); action++ )
- action->key = 0;
- /* Null the action keys of the out transtions. */
- for ( ActionTable::Iter action = state->outActionTable;
- action.lte(); action++ )
- action->key = 0;
- /* Null the action keys of the error action table. */
- for ( ErrActionTable::Iter action = state->errActionTable;
- action.lte(); action++ )
- action->ordering = 0;
- /* Null the action keys eof action table. */
- for ( ActionTable::Iter action = state->eofActionTable;
- action.lte(); action++ )
- action->key = 0;
- }
- }
- /* Walk the list of states and verify that non final states do not have out
- * data, that all stateBits are cleared, and that there are no states with
- * zero foreign in transitions. */
- void FsmAp::verifyStates()
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ ) {
- /* Non final states should not have leaving data. */
- if ( ! (state->stateBits & STB_ISFINAL) ) {
- assert( state->outActionTable.length() == 0 );
- assert( state->outCondSet.length() == 0 );
- assert( state->outPriorTable.length() == 0 );
- }
- /* Data used in algorithms should be cleared. */
- assert( (state->stateBits & STB_BOTH) == 0 );
- assert( state->foreignInTrans > 0 );
- }
- }
- /* Compare two transitions according to their relative priority. Since the
- * base transition has no priority associated with it, the default is to
- * return equal. */
- int FsmAp::comparePrior( const PriorTable &priorTable1, const PriorTable &priorTable2 )
- {
- /* Looking for differing priorities on same keys. Need to concurrently
- * scan the priority lists. */
- PriorTable::Iter pd1 = priorTable1;
- PriorTable::Iter pd2 = priorTable2;
- while ( pd1.lte() && pd2.lte() ) {
- /* Check keys. */
- if ( pd1->desc->key < pd2->desc->key )
- pd1.increment();
- else if ( pd1->desc->key > pd2->desc->key )
- pd2.increment();
- /* Keys are the same, check priorities. */
- else if ( pd1->desc->priority < pd2->desc->priority )
- return -1;
- else if ( pd1->desc->priority > pd2->desc->priority )
- return 1;
- else {
- /* Keys and priorities are equal, advance both. */
- pd1.increment();
- pd2.increment();
- }
- }
- /* No differing priorities on the same key. */
- return 0;
- }
- /* Compares two transitions according to priority and functions. Pointers
- * should not be null. Does not consider to state or from state. Compare two
- * transitions according to the data contained in the transitions. Data means
- * any properties added to user transitions that may differentiate them. Since
- * the base transition has no data, the default is to return equal. */
- int FsmAp::compareTransData( TransAp *trans1, TransAp *trans2 )
- {
- /* Compare the prior table. */
- int cmpRes = CmpPriorTable::compare( trans1->priorTable,
- trans2->priorTable );
- if ( cmpRes != 0 )
- return cmpRes;
- /* Compare longest match action tables. */
- cmpRes = CmpLmActionTable::compare(trans1->lmActionTable,
- trans2->lmActionTable);
- if ( cmpRes != 0 )
- return cmpRes;
-
- /* Compare action tables. */
- return CmpActionTable::compare(trans1->actionTable,
- trans2->actionTable);
- }
- /* Callback invoked when another trans (or possibly this) is added into this
- * transition during the merging process. Draw in any properties of srcTrans
- * into this transition. AddInTrans is called when a new transitions is made
- * that will be a duplicate of another transition or a combination of several
- * other transitions. AddInTrans will be called for each transition that the
- * new transition is to represent. */
- void FsmAp::addInTrans( TransAp *destTrans, TransAp *srcTrans )
- {
- /* Protect against adding in from ourselves. */
- if ( srcTrans == destTrans ) {
- /* Adding in ourselves, need to make a copy of the source transitions.
- * The priorities are not copied in as that would have no effect. */
- destTrans->lmActionTable.setActions( LmActionTable(srcTrans->lmActionTable) );
- destTrans->actionTable.setActions( ActionTable(srcTrans->actionTable) );
- }
- else {
- /* Not a copy of ourself, get the functions and priorities. */
- destTrans->lmActionTable.setActions( srcTrans->lmActionTable );
- destTrans->actionTable.setActions( srcTrans->actionTable );
- destTrans->priorTable.setPriors( srcTrans->priorTable );
- }
- }
- /* Compare the properties of states that are embedded by users. Compares out
- * priorities, out transitions, to, from, out, error and eof action tables. */
- int FsmAp::compareStateData( const StateAp *state1, const StateAp *state2 )
- {
- /* Compare the out priority table. */
- int cmpRes = CmpPriorTable::
- compare( state1->outPriorTable, state2->outPriorTable );
- if ( cmpRes != 0 )
- return cmpRes;
-
- /* Test to state action tables. */
- cmpRes = CmpActionTable::compare( state1->toStateActionTable,
- state2->toStateActionTable );
- if ( cmpRes != 0 )
- return cmpRes;
- /* Test from state action tables. */
- cmpRes = CmpActionTable::compare( state1->fromStateActionTable,
- state2->fromStateActionTable );
- if ( cmpRes != 0 )
- return cmpRes;
- /* Test out action tables. */
- cmpRes = CmpActionTable::compare( state1->outActionTable,
- state2->outActionTable );
- if ( cmpRes != 0 )
- return cmpRes;
- /* Test out condition sets. */
- cmpRes = CmpOutCondSet::compare( state1->outCondSet,
- state2->outCondSet );
- if ( cmpRes != 0 )
- return cmpRes;
- /* Test out error action tables. */
- cmpRes = CmpErrActionTable::compare( state1->errActionTable,
- state2->errActionTable );
- if ( cmpRes != 0 )
- return cmpRes;
- /* Test eof action tables. */
- return CmpActionTable::compare( state1->eofActionTable,
- state2->eofActionTable );
- }
- /* Invoked when a state looses its final state status and the leaving
- * transition embedding data should be deleted. */
- void FsmAp::clearOutData( StateAp *state )
- {
- /* Kill the out actions and priorities. */
- state->outActionTable.empty();
- state->outCondSet.empty();
- state->outPriorTable.empty();
- }
- bool FsmAp::hasOutData( StateAp *state )
- {
- return ( state->outActionTable.length() > 0 ||
- state->outCondSet.length() > 0 ||
- state->outPriorTable.length() > 0 );
- }
- /*
- * Setting Conditions.
- */
- void logNewExpansion( Expansion *exp );
- void logCondSpace( CondSpace *condSpace );
- CondSpace *FsmAp::addCondSpace( const CondSet &condSet )
- {
- CondSpace *condSpace = condData->condSpaceMap.find( condSet );
- if ( condSpace == 0 ) {
- /* Do we have enough keyspace left? */
- Size availableSpace = condData->lastCondKey.availableSpace();
- Size neededSpace = (1 << condSet.length() ) * keyOps->alphSize();
- if ( neededSpace > availableSpace )
- throw FsmConstructFail( FsmConstructFail::CondNoKeySpace );
- Key baseKey = condData->lastCondKey;
- baseKey.increment();
- condData->lastCondKey += (1 << condSet.length() ) * keyOps->alphSize();
- condSpace = new CondSpace( condSet );
- condSpace->baseKey = baseKey;
- condData->condSpaceMap.insert( condSpace );
- #ifdef LOG_CONDS
- cerr << "adding new condition space" << endl;
- cerr << " condition set: ";
- logCondSpace( condSpace );
- cerr << endl;
- cerr << " baseKey: " << baseKey.getVal() << endl;
- #endif
- }
- return condSpace;
- }
- void FsmAp::startFsmCondition( Action *condAction, bool sense )
- {
- /* Make sure the start state has no other entry points. */
- isolateStartState();
- embedCondition( startState, condAction, sense );
- }
- void FsmAp::allTransCondition( Action *condAction, bool sense )
- {
- for ( StateList::Iter state = stateList; state.lte(); state++ )
- embedCondition( state, condAction, sense );
- }
- void FsmAp::leaveFsmCondition( Action *condAction, bool sense )
- {
- for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
- (*state)->outCondSet.insert( OutCond( condAction, sense ) );
- }
|