From 650d76495fcc15ca96cd99d1372b2f8acdad7ac3 Mon Sep 17 00:00:00 2001 From: thurston Date: Sat, 9 Jun 2007 22:01:46 +0000 Subject: [PATCH] The p varialbe is now set up at the beginning of a scanner action, rather than at the end. This leaves scanner actions free to manipulate p and removes the need for the special holdTE and execTE (TE for tokend) versions of hold and exec. It also removes the need to set p = tokend-1 immediately before any control flow. The error handler in LmSwitch actions is now generated by the frontend, rather than the backend. This became possible when the creation of the error state was moved to the frontend. git-svn-id: http://svn.complang.org/ragel/trunk@238 052ea7fc-9027-0410-9066-f65837a77df0 --- ragel/xmlcodegen.cpp | 65 +++++++++++++++++++--------------------------- redfsm/gendata.cpp | 3 --- redfsm/redfsm.cpp | 1 - redfsm/redfsm.h | 5 +--- redfsm/xmlparse.kl | 6 ----- rlgen-cd/fsmcodegen.cpp | 8 ------ rlgen-cd/ipgotocodegen.cpp | 3 --- rlgen-cd/splitcodegen.cpp | 3 --- rlgen-java/javacodegen.cpp | 8 ------ rlgen-ruby/rubycodegen.cpp | 18 ++++--------- test/scan1.rl | 64 +++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 97 insertions(+), 87 deletions(-) create mode 100644 test/scan1.rl diff --git a/ragel/xmlcodegen.cpp b/ragel/xmlcodegen.cpp index a12c56b..f5d210a 100644 --- a/ragel/xmlcodegen.cpp +++ b/ragel/xmlcodegen.cpp @@ -195,11 +195,6 @@ bool isLmItem( InlineItem *context ) void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context ) { - if ( isLmItem( context ) ) { - out << ""; - out << ""; - } - switch ( item->type ) { case InlineItem::Goto: writeGoto( item, context ); @@ -227,34 +222,18 @@ void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context ) break; default: break; } - - if ( isLmItem( context ) ) - out << ""; } -void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem *context ) +void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem * ) { - if ( isLmItem( context ) ) { - switch ( item->type ) { - case InlineItem::Hold: - out << ""; - break; - case InlineItem::Exec: - writeActionExecTE( item ); - break; - default: break; - } - } - else { - switch ( item->type ) { - case InlineItem::Hold: - out << ""; - break; - case InlineItem::Exec: - writeActionExec( item ); - break; - default: break; - } + switch ( item->type ) { + case InlineItem::Hold: + out << ""; + break; + case InlineItem::Exec: + writeActionExec( item ); + break; + default: break; } } @@ -337,55 +316,65 @@ void XMLCodeGen::writeActionExecTE( InlineItem *item ) void XMLCodeGen::writeLmOnLast( InlineItem *item ) { out << "1"; + if ( item->longestMatchPart->action != 0 ) { out << ""; writeInlineList( item->longestMatchPart->action->inlineList, item ); out << ""; } - out << ""; } void XMLCodeGen::writeLmOnNext( InlineItem *item ) { out << "0"; + out << ""; + if ( item->longestMatchPart->action != 0 ) { out << ""; writeInlineList( item->longestMatchPart->action->inlineList, item ); out << ""; } - out << ""; } void XMLCodeGen::writeLmOnLagBehind( InlineItem *item ) { + out << ""; + if ( item->longestMatchPart->action != 0 ) { out << ""; writeInlineList( item->longestMatchPart->action->inlineList, item ); out << ""; } - out << ""; } void XMLCodeGen::writeLmSwitch( InlineItem *item ) { + LongestMatch *longestMatch = item->longestMatch; + out << "\n"; - out << "lmSwitchHandlesError ) - out << " handles_error=\"t\""; - out << ">\n"; + if ( longestMatch->lmSwitchHandlesError ) { + /* If the switch handles error then we should have also forced the + * error state. */ + assert( fsm->errState != 0 ); + + out << " "; + out << "" << fsm->errState->alg.stateNum << ""; + out << "\n"; + } for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) { if ( lmi->inLmSelect && lmi->action != 0 ) { /* Open the action. Write it with the context that sets up _p * when doing control flow changes from inside the machine. */ out << " longestMatchId << "\">"; + out << ""; writeInlineList( lmi->action->inlineList, item ); out << "\n"; } } - out << " "; + out << " "; } void XMLCodeGen::writeInlineList( InlineList *inlineList, InlineItem *context ) diff --git a/redfsm/gendata.cpp b/redfsm/gendata.cpp index 8f06de0..dac4f6b 100644 --- a/redfsm/gendata.cpp +++ b/redfsm/gendata.cpp @@ -451,9 +451,6 @@ void CodeGenData::analyzeAction( Action *act, InlineList *inlineList ) if ( item->type == InlineItem::Break ) redFsm->bAnyRegBreak = true; - - if ( item->type == InlineItem::LmSwitch && item->handlesError ) - redFsm->bAnyLmSwitchError = true; } if ( item->children != 0 ) diff --git a/redfsm/redfsm.cpp b/redfsm/redfsm.cpp index 73e3b7e..2eadcd2 100644 --- a/redfsm/redfsm.cpp +++ b/redfsm/redfsm.cpp @@ -62,7 +62,6 @@ RedFsmAp::RedFsmAp() bAnyRegNextStmt(false), bAnyRegCurStateRef(false), bAnyRegBreak(false), - bAnyLmSwitchError(false), bAnyConditions(false) { } diff --git a/redfsm/redfsm.h b/redfsm/redfsm.h index 8098a3c..85e49f4 100644 --- a/redfsm/redfsm.h +++ b/redfsm/redfsm.h @@ -73,7 +73,7 @@ struct InlineItem InlineItem( const InputLoc &loc, Type type ) : loc(loc), data(0), targId(0), targState(0), lmId(0), children(0), offset(0), - handlesError(false), type(type) { } + type(type) { } InputLoc loc; char *data; @@ -82,7 +82,6 @@ struct InlineItem int lmId; InlineList *children; int offset; - bool handlesError; Type type; InlineItem *prev, *next; @@ -429,7 +428,6 @@ struct RedFsmAp bool bAnyRegNextStmt; bool bAnyRegCurStateRef; bool bAnyRegBreak; - bool bAnyLmSwitchError; bool bAnyConditions; int maxState; @@ -464,7 +462,6 @@ struct RedFsmAp bool anyRegNextStmt() { return bAnyRegNextStmt; } bool anyRegCurStateRef() { return bAnyRegCurStateRef; } bool anyRegBreak() { return bAnyRegBreak; } - bool anyLmSwitchError() { return bAnyLmSwitchError; } bool anyConditions() { return bAnyConditions; } diff --git a/redfsm/xmlparse.kl b/redfsm/xmlparse.kl index 30f6d3a..cf3be17 100644 --- a/redfsm/xmlparse.kl +++ b/redfsm/xmlparse.kl @@ -717,14 +717,8 @@ tag_sub_action: TAG_sub_action inline_list '/' TAG_sub_action # Action switches. tag_lm_switch: TAG_lm_switch lm_action_list '/' TAG_lm_switch final { - bool handlesError = false; - Attribute *handlesErrorAttr = $1->tag->findAttr( "handles_error" ); - if ( handlesErrorAttr != 0 ) - handlesError = true; - $$->inlineItem = new InlineItem( InputLoc(), InlineItem::LmSwitch ); $$->inlineItem->children = $2->inlineList; - $$->inlineItem->handlesError = handlesError; }; nonterm lm_action_list diff --git a/rlgen-cd/fsmcodegen.cpp b/rlgen-cd/fsmcodegen.cpp index 7fc8d5e..93a5150 100644 --- a/rlgen-cd/fsmcodegen.cpp +++ b/rlgen-cd/fsmcodegen.cpp @@ -333,14 +333,6 @@ void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item, ret << " switch( " << ACT() << " ) {\n"; - /* If the switch handles error then we also forced the error state. It - * will exist. */ - if ( item->handlesError ) { - ret << " case 0: " << TOKEND() << " = " << TOKSTART() << "; "; - GOTO( ret, redFsm->errState->id, inFinish ); - ret << "\n"; - } - for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) { /* Write the case label, the action and the case break. */ ret << " case " << lma->lmId << ":\n"; diff --git a/rlgen-cd/ipgotocodegen.cpp b/rlgen-cd/ipgotocodegen.cpp index ed65be5..4e55e1f 100644 --- a/rlgen-cd/ipgotocodegen.cpp +++ b/rlgen-cd/ipgotocodegen.cpp @@ -293,9 +293,6 @@ void IpGotoCodeGen::setLabelsNeeded() for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) st->labelNeeded = false; - if ( redFsm->errState != 0 && redFsm->anyLmSwitchError() ) - redFsm->errState->labelNeeded = true; - /* Walk all transitions and set only those that have targs. */ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { /* If there is no action with a next statement, then the label will be diff --git a/rlgen-cd/splitcodegen.cpp b/rlgen-cd/splitcodegen.cpp index d703b37..f43362e 100644 --- a/rlgen-cd/splitcodegen.cpp +++ b/rlgen-cd/splitcodegen.cpp @@ -486,9 +486,6 @@ void SplitCodeGen::setLabelsNeeded() for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) trans->labelNeeded = false; - if ( redFsm->errState != 0 && redFsm->anyLmSwitchError() ) - redFsm->errState->labelNeeded = true; - /* Walk all transitions and set only those that have targs. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) diff --git a/rlgen-java/javacodegen.cpp b/rlgen-java/javacodegen.cpp index bbce5bb..c941ea7 100644 --- a/rlgen-java/javacodegen.cpp +++ b/rlgen-java/javacodegen.cpp @@ -1369,14 +1369,6 @@ void JavaTabCodeGen::LM_SWITCH( ostream &ret, InlineItem *item, ret << " switch( " << ACT() << " ) {\n"; - /* If the switch handles error then we also forced the error state. It - * will exist. */ - if ( item->handlesError ) { - ret << " case 0: " << TOKEND() << " = " << TOKSTART() << "; "; - GOTO( ret, redFsm->errState->id, inFinish ); - ret << "\n"; - } - for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) { /* Write the case label, the action and the case break. */ ret << " case " << lma->lmId << ":\n"; diff --git a/rlgen-ruby/rubycodegen.cpp b/rlgen-ruby/rubycodegen.cpp index bd556b1..1f68925 100644 --- a/rlgen-ruby/rubycodegen.cpp +++ b/rlgen-ruby/rubycodegen.cpp @@ -61,7 +61,7 @@ void RubyCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish ) out << INDENT_U() << "begin" << INDENT_S() << CS() << " = " << gotoDest << INDENT_S() << "_again.call " << CTRL_FLOW() - << INDENT_D() << "end"; + << INDENT_D() << "end "; } void RubyCodeGen::GOTO_EXPR( ostream &out, InlineItem *ilItem, bool inFinish ) @@ -71,7 +71,7 @@ void RubyCodeGen::GOTO_EXPR( ostream &out, InlineItem *ilItem, bool inFinish ) INLINE_LIST( out, ilItem->children, 0, inFinish ); out << ")" << INDENT_S() << "_again.call " << CTRL_FLOW() - << INDENT_D() << "end"; + << INDENT_D() << "end "; } void RubyCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish ) @@ -81,7 +81,7 @@ void RubyCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish << INDENT_S() << TOP() << "+= 1" << INDENT_S() << CS() << " = " << callDest << INDENT_S() << "_again.call " << CTRL_FLOW() - << INDENT_D() << "end"; + << INDENT_D() << "end "; } void RubyCodeGen::CALL_EXPR(ostream &out, InlineItem *ilItem, int targState, bool inFinish ) @@ -93,7 +93,7 @@ void RubyCodeGen::CALL_EXPR(ostream &out, InlineItem *ilItem, int targState, boo INLINE_LIST( out, ilItem->children, targState, inFinish ); out << ")" << INDENT_S() << "_again.call " << CTRL_FLOW() - << INDENT_D() << "end"; + << INDENT_D() << "end "; } void RubyCodeGen::RET( ostream &out, bool inFinish ) @@ -102,7 +102,7 @@ void RubyCodeGen::RET( ostream &out, bool inFinish ) << INDENT_S() << TOP() << " -= 1" << INDENT_S() << CS() << " = " << STACK() << "[" << TOP() << "]" << INDENT_S() << "_again.call " << CTRL_FLOW() - << INDENT_D() << "end"; + << INDENT_D() << "end "; } void RubyCodeGen::BREAK( ostream &out, int targState ) @@ -1411,14 +1411,6 @@ void RubyCodeGen::LM_SWITCH( ostream &ret, InlineItem *item, ret << " case " << ACT() << "\n"; - /* If the switch handles error then we also forced the error state. It - * will exist. */ - if ( item->handlesError ) { - ret << " when 0: " << TOKEND() << " = " << TOKSTART() << "; "; - GOTO( ret, redFsm->errState->id, inFinish ); - ret << "\n"; - } - for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) { /* Write the case label, the action and the case break. */ ret << " when " << lma->lmId << ":\n"; diff --git a/test/scan1.rl b/test/scan1.rl new file mode 100644 index 0000000..5b32e89 --- /dev/null +++ b/test/scan1.rl @@ -0,0 +1,64 @@ +/* + * @LANG: indep + */ +ptr tokstart; +ptr tokend; +int act; +int token; +%% +%%{ + machine scanner; + + # Warning: changing the patterns or the input string will affect the + # coverage of the scanner action types. + main := |* + 'a' => { + prints "on last "; + if ( p+1 == tokend ) + prints "yes"; + prints "\n"; + }; + + 'b'+ => { + prints "on next "; + if ( p+1 == tokend ) + prints "yes"; + prints "\n"; + }; + + 'c1' 'dxxx'? => { + prints "on lag "; + if ( p+1 == tokend ) + prints "yes"; + prints "\n"; + }; + + 'd1' => { + prints "lm switch1 "; + if ( p+1 == tokend ) + prints "yes"; + prints "\n"; + }; + 'd2' => { + prints "lm switch2 "; + if ( p+1 == tokend ) + prints "yes"; + prints "\n"; + }; + + [d0-9]+ '.'; + + '\n'; + *|; +}%% +/* _____INPUT_____ +"abbc1d1d2\n" +_____INPUT_____ */ +/* _____OUTPUT_____ +on last yes +on next yes +on lag yes +lm switch1 yes +lm switch2 yes +ACCEPT +_____OUTPUT_____ */ -- 2.7.4