void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context )
{
- if ( isLmItem( context ) ) {
- out << "<sub_action>";
- out << "<exec><get_tokend></get_tokend></exec>";
- }
-
switch ( item->type ) {
case InlineItem::Goto:
writeGoto( item, context );
break;
default: break;
}
-
- if ( isLmItem( context ) )
- out << "</sub_action>";
}
-void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem * )
{
- if ( isLmItem( context ) ) {
- switch ( item->type ) {
- case InlineItem::Hold:
- out << "<holdte></holdte>";
- break;
- case InlineItem::Exec:
- writeActionExecTE( item );
- break;
- default: break;
- }
- }
- else {
- switch ( item->type ) {
- case InlineItem::Hold:
- out << "<hold></hold>";
- break;
- case InlineItem::Exec:
- writeActionExec( item );
- break;
- default: break;
- }
+ switch ( item->type ) {
+ case InlineItem::Hold:
+ out << "<hold></hold>";
+ break;
+ case InlineItem::Exec:
+ writeActionExec( item );
+ break;
+ default: break;
}
}
void XMLCodeGen::writeLmOnLast( InlineItem *item )
{
out << "<set_tokend>1</set_tokend>";
+
if ( item->longestMatchPart->action != 0 ) {
out << "<sub_action>";
writeInlineList( item->longestMatchPart->action->inlineList, item );
out << "</sub_action>";
}
- out << "<exec><get_tokend></get_tokend></exec>";
}
void XMLCodeGen::writeLmOnNext( InlineItem *item )
{
out << "<set_tokend>0</set_tokend>";
+ out << "<hold></hold>";
+
if ( item->longestMatchPart->action != 0 ) {
out << "<sub_action>";
writeInlineList( item->longestMatchPart->action->inlineList, item );
out << "</sub_action>";
}
- out << "<exec><get_tokend></get_tokend></exec>";
}
void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
{
+ out << "<exec><get_tokend></get_tokend></exec>";
+
if ( item->longestMatchPart->action != 0 ) {
out << "<sub_action>";
writeInlineList( item->longestMatchPart->action->inlineList, item );
out << "</sub_action>";
}
- out << "<exec><get_tokend></get_tokend></exec>";
}
void XMLCodeGen::writeLmSwitch( InlineItem *item )
{
+
LongestMatch *longestMatch = item->longestMatch;
+ out << "<lm_switch>\n";
- out << "<lm_switch";
- if ( longestMatch->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 << " <sub_action id=\"0\">";
+ out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
+ out << "</sub_action>\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 << " <sub_action id=\"" << lmi->longestMatchId << "\">";
+ out << "<exec><get_tokend></get_tokend></exec>";
writeInlineList( lmi->action->inlineList, item );
out << "</sub_action>\n";
}
}
- out << " </lm_switch><exec><get_tokend></get_tokend></exec>";
+ out << " </lm_switch>";
}
void XMLCodeGen::writeInlineList( InlineList *inlineList, InlineItem *context )
if ( item->type == InlineItem::Break )
redFsm->bAnyRegBreak = true;
-
- if ( item->type == InlineItem::LmSwitch && item->handlesError )
- redFsm->bAnyLmSwitchError = true;
}
if ( item->children != 0 )
bAnyRegNextStmt(false),
bAnyRegCurStateRef(false),
bAnyRegBreak(false),
- bAnyLmSwitchError(false),
bAnyConditions(false)
{
}
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;
int lmId;
InlineList *children;
int offset;
- bool handlesError;
Type type;
InlineItem *prev, *next;
bool bAnyRegNextStmt;
bool bAnyRegCurStateRef;
bool bAnyRegBreak;
- bool bAnyLmSwitchError;
bool bAnyConditions;
int maxState;
bool anyRegNextStmt() { return bAnyRegNextStmt; }
bool anyRegCurStateRef() { return bAnyRegCurStateRef; }
bool anyRegBreak() { return bAnyRegBreak; }
- bool anyLmSwitchError() { return bAnyLmSwitchError; }
bool anyConditions() { return bAnyConditions; }
# 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
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";
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
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++ )
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";
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 )
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 )
<< 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 )
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 )
<< 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 )
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";
--- /dev/null
+/*
+ * @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_____ */