+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. */
void FsmAp::setErrorAction( StateAp *state, int ordering, Action *action )
{
/* Fill any gaps in the out list with an error transition. */
/* Action setting support. */
void transferOutActions( StateAp *state );
void transferErrorActions( StateAp *state, int transferPoint );
/* Action setting support. */
void transferOutActions( StateAp *state );
void transferErrorActions( StateAp *state, int transferPoint );
+ void setErrorActions( StateAp *state, const ActionTable &other );
void setErrorAction( StateAp *state, int ordering, Action *action );
/* Fill all spaces in a transition list with an error transition. */
void setErrorAction( StateAp *state, int ordering, Action *action );
/* Fill all spaces in a transition list with an error transition. */
/* For each part create actions for setting the match type. We need
* to do this so that the actions will go into the actionIndex. */
InlineList *inlineList = new InlineList;
/* For each part create actions for setting the match type. We need
* to do this so that the actions will go into the actionIndex. */
InlineList *inlineList = new InlineList;
- inlineList->append( new InlineItem( lmi->getLoc(), this, lmi, InlineItem::LmSetActId ) );
+ inlineList->append( new InlineItem( lmi->getLoc(), this, lmi,
+ InlineItem::LmSetActId ) );
char *actName = new char[50];
sprintf( actName, "store%i", lmi->longestMatchId );
lmi->setActId = newAction( pd, lmi->getLoc(), actName, inlineList );
}
char *actName = new char[50];
sprintf( actName, "store%i", lmi->longestMatchId );
lmi->setActId = newAction( pd, lmi->getLoc(), actName, inlineList );
}
- /* Make actions that execute the user action and restart on the last character. */
+ /* Make actions that execute the user action and restart on the last
+ * character. */
for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) {
/* For each part create actions for setting the match type. We need
* to do this so that the actions will go into the actionIndex. */
for ( LmPartList::Iter lmi = *longestMatchList; lmi.lte(); lmi++ ) {
/* For each part create actions for setting the match type. We need
* to do this so that the actions will go into the actionIndex. */
graph->attachTrans( fromState, graph->startState, trans );
}
graph->attachTrans( fromState, graph->startState, trans );
}
-void LongestMatch::runLonestMatch( ParseData *pd, FsmAp *graph )
+void LongestMatch::runLongestMatch( ParseData *pd, FsmAp *graph )
{
graph->markReachableFromHereStopFinal( graph->startState );
for ( StateList::Iter ms = graph->stateList; ms.lte(); ms++ ) {
{
graph->markReachableFromHereStopFinal( graph->startState );
for ( StateList::Iter ms = graph->stateList; ms.lte(); ms++ ) {
StateAp *toState = trans->toState;
assert( toState );
StateAp *toState = trans->toState;
assert( toState );
- /* Check if there are transitions out, this may be a very
- * close approximation? Out transitions going nowhere?
- * FIXME: Check. */
+ /* Can only optimize this if there are no transitions out.
+ * Note there can be out transitions going nowhere with
+ * actions and they too must inhibit this optimization. */
if ( toState->outList.length() > 0 ) {
/* Fill the item sets. */
graph->markReachableFromHereStopFinal( toState );
if ( toState->outList.length() > 0 ) {
/* Fill the item sets. */
graph->markReachableFromHereStopFinal( toState );
StateAp *toState = trans->toState;
assert( toState );
StateAp *toState = trans->toState;
assert( toState );
- /* Check if there are transitions out, this may be a very
- * close approximation? Out transitions going nowhere?
- * FIXME: Check. */
+ /* Can only optimize this if there are no transitions out.
+ * Note there can be out transitions going nowhere with
+ * actions and they too must inhibit this optimization. */
if ( toState->outList.length() == 0 ) {
/* Can execute the immediate action for the longest match
if ( toState->outList.length() == 0 ) {
/* Can execute the immediate action for the longest match
- * part. Redirect the action to the start state. */
+ * part. Redirect the action to the start state.
+ *
+ * NOTE: When we need to inhibit on_last due to leaving
+ * actions the above test suffices. If the state has out
+ * actions then it will fail because the out action will
+ * have been transferred to an error transition, which
+ * makes the outlist non-empty. */
trans->actionTable.setAction( lmAct->key,
lmAct->value->actOnLast );
restartTrans.append( trans );
trans->actionTable.setAction( lmAct->key,
lmAct->value->actOnLast );
restartTrans.append( trans );
}
}
else if ( st->lmItemSet.length() > 1 ) {
}
}
else if ( st->lmItemSet.length() > 1 ) {
- /* Need to use the select. Take note of the which items the select
+ /* Need to use the select. Take note of which items the select
* is needed for so only the necessary actions are included. */
for ( LmItemSet::Iter plmi = st->lmItemSet; plmi.lte(); plmi++ ) {
if ( *plmi != 0 )
* is needed for so only the necessary actions are included. */
for ( LmItemSet::Iter plmi = st->lmItemSet; plmi.lte(); plmi++ ) {
if ( *plmi != 0 )
graph->setFinState( graph->startState );
}
graph->setFinState( graph->startState );
}
+void LongestMatch::transferScannerLeavingActions( FsmAp *graph )
+{
+ for ( StateList::Iter st = graph->stateList; st.lte(); st++ ) {
+ if ( st->outActionTable.length() > 0 )
+ graph->setErrorActions( st, st->outActionTable );
+ }
+}
+
FsmAp *LongestMatch::walk( ParseData *pd )
{
/* The longest match has it's own name scope. */
FsmAp *LongestMatch::walk( ParseData *pd )
{
/* The longest match has it's own name scope. */
parts[i]->longMatchAction( pd->curActionOrd++, lmi );
}
parts[i]->longMatchAction( pd->curActionOrd++, lmi );
}
+ /* Before we union the patterns we need to deal with leaving actions. They
+ * are transfered to error transitions out of the final states (like local
+ * error actions) and to eof actions. In the scanner we need to forbid
+ * on_last for any final state that has an leaving action. */
+ for ( int i = 0; i < longestMatchList->length(); i++ )
+ transferScannerLeavingActions( parts[i] );
+
/* Union machines one and up with machine zero. The grammar dictates that
* there will always be at least one part. */
FsmAp *rtnVal = parts[0];
/* Union machines one and up with machine zero. The grammar dictates that
* there will always be at least one part. */
FsmAp *rtnVal = parts[0];
afterOpMinimize( rtnVal );
}
afterOpMinimize( rtnVal );
}
- runLonestMatch( pd, rtnVal );
+ runLongestMatch( pd, rtnVal );
/* Pop the name scope. */
pd->popNameScope( nameFrame );
/* Pop the name scope. */
pd->popNameScope( nameFrame );
FsmAp *walk( ParseData *pd );
void makeNameTree( ParseData *pd );
void resolveNameRefs( ParseData *pd );
FsmAp *walk( ParseData *pd );
void makeNameTree( ParseData *pd );
void resolveNameRefs( ParseData *pd );
- void runLonestMatch( ParseData *pd, FsmAp *graph );
+ void transferScannerLeavingActions( FsmAp *graph );
+ void runLongestMatch( ParseData *pd, FsmAp *graph );
Action *newAction( ParseData *pd, const InputLoc &loc, const char *name,
InlineList *inlineList );
void makeActions( ParseData *pd );
Action *newAction( ParseData *pd, const InputLoc &loc, const char *name,
InlineList *inlineList );
void makeActions( ParseData *pd );