From: thurston Date: Sun, 4 Feb 2007 03:15:18 +0000 (+0000) Subject: The frontend is now responsible for creating the error state, if needed. The X-Git-Tag: 2.0_alpha~414 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3762b079c0ad4a87dfe8964f4ce38651899c0922;p=external%2Fragel.git The frontend is now responsible for creating the error state, if needed. The error state id is passed using the tag. git-svn-id: http://svn.complang.org/ragel/trunk@72 052ea7fc-9027-0410-9066-f65837a77df0 --- diff --git a/ragel/fsmbase.cpp b/ragel/fsmbase.cpp index 9976fae..96b3488 100644 --- a/ragel/fsmbase.cpp +++ b/ragel/fsmbase.cpp @@ -46,6 +46,7 @@ FsmAp::FsmAp() : /* No start state. */ startState(0), + errState(0), /* Misfit accounting is a switch, turned on only at specific times. It * controls what happens when states have no way in from the outside @@ -65,6 +66,7 @@ FsmAp::FsmAp( const FsmAp &graph ) * pointers will be resolved later. */ entryPoints(graph.entryPoints), startState(graph.startState), + errState(0), /* Will be filled by copy. */ finStateSet(), @@ -509,6 +511,8 @@ void FsmAp::depthFirstOrdering() depthFirstOrdering( startState ); for ( EntryMap::Iter en = entryPoints; en.lte(); en++ ) depthFirstOrdering( en->value ); + if ( errState != 0 ) + depthFirstOrdering( errState ); /* Make sure we put everything back on. */ assert( stateListLen == stateList.length() ); @@ -540,3 +544,55 @@ void FsmAp::setStateNumbers( int base ) state->alg.stateNum = base++; } + +bool FsmAp::checkErrTrans( StateAp *state, TransAp *trans ) +{ + /* Might go directly to error state. */ + if ( trans->toState == 0 ) + return true; + + if ( trans->prev == 0 ) { + /* If this is the first transition. */ + if ( keyOps->minKey < trans->lowKey ) + return true; + } + else { + /* Not the first transition. Compare against the prev. */ + TransAp *prev = trans->prev; + Key nextKey = prev->highKey; + nextKey.increment(); + if ( nextKey < trans->lowKey ) + return true; + } + return false; +} + +bool FsmAp::checkErrTransFinish( StateAp *state ) +{ + /* Check if there are any ranges already. */ + if ( state->outList.length() == 0 ) + return true; + else { + /* Get the last and check for a gap on the end. */ + TransAp *last = state->outList.tail; + if ( last->highKey < keyOps->maxKey ) + return true; + } + return 0; +} + +bool FsmAp::hasErrorTrans() +{ + bool result; + for ( StateList::Iter st = stateList; st.lte(); st++ ) { + for ( TransList::Iter tr = st->outList; tr.lte(); tr++ ) { + result = checkErrTrans( st, tr ); + if ( result ) + return true; + } + result = checkErrTransFinish( st ); + if ( result ) + return true; + } + return false; +} diff --git a/ragel/fsmgraph.h b/ragel/fsmgraph.h index 3b29856..e47525a 100644 --- a/ragel/fsmgraph.h +++ b/ragel/fsmgraph.h @@ -971,6 +971,11 @@ struct FsmAp /* The start state. */ StateAp *startState; + /* Error state, possibly created only when the final machine has been + * created and the XML machine is about to be written. No transitions + * point to this state. */ + StateAp *errState; + /* The set of final states. */ StateSet finStateSet; @@ -1369,6 +1374,12 @@ struct FsmAp /* Merge neighboring transitions go to the same state and have the same * transitions data. */ void compressTransitions(); + + /* Returns true if there is a transtion (either explicit or by a gap) to + * the error state. */ + bool checkErrTrans( StateAp *state, TransAp *trans ); + bool checkErrTransFinish( StateAp *state ); + bool hasErrorTrans(); }; diff --git a/ragel/parsedata.cpp b/ragel/parsedata.cpp index 2352bb8..5332286 100644 --- a/ragel/parsedata.cpp +++ b/ragel/parsedata.cpp @@ -1309,6 +1309,13 @@ void ParseData::prepareMachineGen( GraphDictEl *graphDictEl ) /* Depends on the graph analysis. */ setLongestMatchData( sectionGraph ); + /* Decide if an error state is necessary. + * 1. There is an error transition + * 2. There is a gap in the transitions + * 3. The longest match operator requires it. */ + if ( lmRequiresErrorState || sectionGraph->hasErrorTrans() ) + sectionGraph->errState = sectionGraph->addState(); + /* State numbers need to be assigned such that all final states have a * larger state id number than all non-final states. This enables the * first_final mechanism to function correctly. We also want states to be @@ -1319,6 +1326,7 @@ void ParseData::prepareMachineGen( GraphDictEl *graphDictEl ) sectionGraph->depthFirstOrdering(); sectionGraph->sortStatesByFinal(); sectionGraph->setStateNumbers( 0 ); + } void ParseData::generateXML( ostream &out ) diff --git a/ragel/xmlcodegen.cpp b/ragel/xmlcodegen.cpp index 3831c3e..f2bb591 100644 --- a/ragel/xmlcodegen.cpp +++ b/ragel/xmlcodegen.cpp @@ -595,7 +595,13 @@ void XMLCodeGen::writeMachine() /* Start state. */ out << " " << fsm->startState->alg.stateNum << - "\n"; + "\n"; + + /* Error state. */ + if ( fsm->errState != 0 ) { + out << " " << fsm->errState->alg.stateNum << + "\n"; + } writeEntryPoints(); writeStateList(); diff --git a/redfsm/gendata.cpp b/redfsm/gendata.cpp index db5b8da..7a1963c 100644 --- a/redfsm/gendata.cpp +++ b/redfsm/gendata.cpp @@ -37,7 +37,8 @@ CodeGenData::CodeGenData( ostream &out ) allCondSpaces(0), allStates(0), nameIndex(0), - startState(0), + startState(-1), + errState(-1), getKeyExpr(0), accessExpr(0), curStateExpr(0), @@ -83,6 +84,14 @@ void CodeGenData::initStateList( unsigned long length ) allStates = new RedStateAp[length]; for ( unsigned long s = 0; s < length; s++ ) redFsm->stateList.append( allStates+s ); + + /* We get the start state as an offset, set the pointer now. */ + assert( startState >= 0 ); + redFsm->startState = allStates + startState; + if ( errState >= 0 ) + redFsm->errState = allStates + errState; + for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) + redFsm->entryPoints.insert( allStates + *en ); } void CodeGenData::setStartState( unsigned long startState ) @@ -90,6 +99,11 @@ void CodeGenData::setStartState( unsigned long startState ) this->startState = startState; } +void CodeGenData::setErrorState( unsigned long errState ) +{ + this->errState = errState; +} + void CodeGenData::addEntryPoint( char *name, unsigned long entryState ) { entryPointIds.append( entryState ); @@ -227,14 +241,6 @@ void CodeGenData::resolveTargetStates( InlineList *inlineList ) void CodeGenData::closeMachine() { - if ( redFsm->forcedErrorState ) - redFsm->getErrorState(); - - /* We get the start state as an offset, set the pointer now. */ - redFsm->startState = allStates + startState; - for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) - redFsm->entryPoints.insert( allStates + *en ); - for ( ActionList::Iter a = actionList; a.lte(); a++ ) resolveTargetStates( a->inlineList ); diff --git a/redfsm/gendata.h b/redfsm/gendata.h index ec22e15..e0ee6df 100644 --- a/redfsm/gendata.h +++ b/redfsm/gendata.h @@ -59,6 +59,7 @@ struct CodeGenData RedStateAp *allStates; NameInst **nameIndex; int startState; + int errState; ActionList actionList; ConditionList conditionList; CondSpaceList condSpaceList; @@ -83,6 +84,7 @@ struct CodeGenData void initActionTableList( unsigned long length ); void initStateList( unsigned long length ); void setStartState( unsigned long startState ); + void setErrorState( unsigned long errState ); void addEntryPoint( char *name, unsigned long entryState ); void setId( int snum, int id ); void setFinal( int snum ); diff --git a/redfsm/redfsm.cpp b/redfsm/redfsm.cpp index c8495ee..9b1af9b 100644 --- a/redfsm/redfsm.cpp +++ b/redfsm/redfsm.cpp @@ -491,11 +491,9 @@ RedTransAp *RedFsmAp::getErrorTrans( ) RedStateAp *RedFsmAp::getErrorState() { - /* Check if we need to init the error trans. */ - if ( errState == 0 ) { - errState = new RedStateAp(); - stateList.append( errState ); - } + /* Something went wrong. An error state is needed but one was not supplied + * by the frontend. */ + assert( errState != 0 ); return errState; } diff --git a/redfsm/xmlparse.kh b/redfsm/xmlparse.kh index eda8384..38d6703 100644 --- a/redfsm/xmlparse.kh +++ b/redfsm/xmlparse.kh @@ -104,9 +104,9 @@ struct Parser token TAG_unknown, TAG_ragel, TAG_ragel_def, TAG_host, TAG_state_list, TAG_state, TAG_trans_list, TAG_t, TAG_machine, TAG_start_state, - TAG_action_list, TAG_action_table_list, TAG_action, - TAG_action_table, TAG_alphtype, TAG_element, TAG_getkey, - TAG_state_actions, TAG_entry_points, TAG_sub_action, + TAG_error_state, TAG_action_list, TAG_action_table_list, + TAG_action, TAG_action_table, TAG_alphtype, TAG_element, + TAG_getkey, TAG_state_actions, TAG_entry_points, TAG_sub_action, TAG_cond_space_list, TAG_cond_space, TAG_cond_list, TAG_c; # Inline block tokens. diff --git a/redfsm/xmlparse.kl b/redfsm/xmlparse.kl index 78d895e..0d90418 100644 --- a/redfsm/xmlparse.kl +++ b/redfsm/xmlparse.kl @@ -220,6 +220,7 @@ machine_item_list: machine_item_list machine_item; machine_item_list: ; machine_item: tag_start_state; +machine_item: tag_error_state; machine_item: tag_entry_points; machine_item: tag_state_list; machine_item: tag_action_list; @@ -236,6 +237,12 @@ tag_start_state: TAG_start_state '/' TAG_start_state cgd->setStartState( startState ); }; +tag_error_state: TAG_error_state '/' TAG_error_state + final { + unsigned long errorState = strtoul( $3->tag->content, 0, 10 ); + cgd->setErrorState( errorState ); + }; + tag_entry_points: TAG_entry_points entry_point_list '/' TAG_entry_points final { Attribute *errorAttr = $1->tag->findAttr( "error" ); diff --git a/redfsm/xmlscan.rl b/redfsm/xmlscan.rl index b826a02..988f589 100644 --- a/redfsm/xmlscan.rl +++ b/redfsm/xmlscan.rl @@ -313,8 +313,9 @@ int xml_parse( std::istream &input, char *fileName, case TAG_call: case TAG_next: case TAG_entry: case TAG_set_tokend: case TAG_set_act: case TAG_start_state: - case TAG_state_actions: case TAG_action_table: - case TAG_cond_space: case TAG_c: + case TAG_error_state: case TAG_state_actions: + case TAG_action_table: case TAG_cond_space: + case TAG_c: tag->content = new char[scanner.buffer.length+1]; memcpy( tag->content, scanner.buffer.data, scanner.buffer.length ); diff --git a/redfsm/xmltags.gperf b/redfsm/xmltags.gperf index 31c32d1..ca7baac 100644 --- a/redfsm/xmltags.gperf +++ b/redfsm/xmltags.gperf @@ -36,6 +36,7 @@ trans_list, TAG_trans_list t, TAG_t machine, TAG_machine start_state, TAG_start_state +error_state, TAG_error_state action_list, TAG_action_list action, TAG_action action_table_list, TAG_action_table_list