/*
- * Copyright 2005, 2006 Adrian Thurston <thurston@cs.queensu.ca>
+ * Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
*/
/* This file is part of Ragel.
out << " </trans_list>\n";
}
-void XMLCodeGen::writeLmSwitch( InlineItem *item )
+void XMLCodeGen::writeEofTrans( StateAp *state )
{
- LongestMatch *longestMatch = item->longestMatch;
-
- out << "<lm_switch";
- if ( longestMatch->lmSwitchHandlesError )
- out << " handles_error=\"t\"";
- out << ">\n";
+ RedActionTable *eofActions = 0;
+ if ( state->eofActionTable.length() > 0 )
+ eofActions = actionTableMap.find( state->eofActionTable );
- 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 << "\">";
- writeInlineList( lmi->action->inlineList, item );
- out << "</sub_action>\n";
- }
- }
+ /* The <eof_t> is used when there is an eof target, otherwise the eof
+ * action goes into state actions. */
+ if ( state->eofTarget != 0 ) {
+ out << " <eof_t>" << state->eofTarget->alg.stateNum;
- out << " </lm_switch><exec><get_tokend></get_tokend></exec>";
+ if ( eofActions != 0 )
+ out << " " << eofActions->id;
+ else
+ out << " x";
+
+ out << "</eof_t>" << endl;
+ }
}
void XMLCodeGen::writeText( InlineItem *item )
out << "</text>";
}
-void XMLCodeGen::writeCtrlFlow( InlineItem *item, InlineItem *context )
-{
- if ( context != 0 ) {
- out << "<sub_action>";
-
- switch ( context->type ) {
- case InlineItem::LmOnLast:
- out << "<exec><get_tokend></get_tokend></exec>";
- break;
- case InlineItem::LmOnNext:
- out << "<exec><get_tokend></get_tokend></exec>";
- break;
- case InlineItem::LmOnLagBehind:
- out << "<exec><get_tokend></get_tokend></exec>";
- break;
- case InlineItem::LmSwitch:
- out << "<exec><get_tokend></get_tokend></exec>";
- break;
- default: break;
- }
- }
-
- switch ( item->type ) {
- case InlineItem::Goto:
- writeGoto( item, context );
- break;
- case InlineItem::GotoExpr:
- writeGotoExpr( item, context );
- break;
- case InlineItem::Call:
- writeCall( item, context );
- break;
- case InlineItem::CallExpr:
- writeCallExpr( item, context );
- break;
- case InlineItem::Next:
- writeNext( item, context );
- break;
- case InlineItem::NextExpr:
- writeNextExpr( item, context );
- break;
- case InlineItem::Break:
- out << "<break></break>";
- break;
- case InlineItem::Ret:
- out << "<ret></ret>";
- break;
- default: break;
- }
-
- if ( context != 0 )
- out << "</sub_action>";
-}
-
-void XMLCodeGen::writePtrMod( InlineItem *item, InlineItem *context )
-{
- if ( context != 0 && ( context->type == InlineItem::LmOnNext ||
- context->type == InlineItem::LmOnLagBehind ||
- context->type == InlineItem::LmSwitch ) )
- {
- 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;
- }
- }
-}
-
-
-void XMLCodeGen::writeGoto( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeGoto( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<goto>-1</goto>";
}
}
-void XMLCodeGen::writeCall( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeCall( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<call>-1</call>";
}
}
-void XMLCodeGen::writeNext( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeNext( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<next>-1</next>";
}
}
-void XMLCodeGen::writeGotoExpr( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeGotoExpr( InlineItem *item )
{
out << "<goto_expr>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</goto_expr>";
}
-void XMLCodeGen::writeCallExpr( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeCallExpr( InlineItem *item )
{
out << "<call_expr>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</call_expr>";
}
-void XMLCodeGen::writeNextExpr( InlineItem *item, InlineItem *context )
+void XMLCodeGen::writeNextExpr( InlineItem *item )
{
out << "<next_expr>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</next_expr>";
}
-void XMLCodeGen::writeEntry( InlineItem * item )
+void XMLCodeGen::writeEntry( InlineItem *item )
{
if ( pd->generatingSectionSubset )
out << "<entry>-1</entry>";
void XMLCodeGen::writeActionExec( InlineItem *item )
{
out << "<exec>";
- writeInlineList( item->children, 0 );
+ writeInlineList( item->children );
out << "</exec>";
}
-void XMLCodeGen::writeActionExecTE( InlineItem *item )
-{
- out << "<execte>";
- writeInlineList( item->children, 0 );
- out << "</execte>";
-}
-
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 );
+ writeInlineList( item->longestMatchPart->action->inlineList );
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 );
+ writeInlineList( item->longestMatchPart->action->inlineList );
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 );
+ writeInlineList( item->longestMatchPart->action->inlineList );
out << "</sub_action>";
}
- out << "<exec><get_tokend></get_tokend></exec>";
}
+void XMLCodeGen::writeLmSwitch( InlineItem *item )
+{
+ LongestMatch *longestMatch = item->longestMatch;
+ out << "<lm_switch>\n";
+
+ /* We can't put the <exec> here because we may need to handle the error
+ * case and in that case p should not be changed. Instead use a default
+ * label in the switch to adjust p when user actions are not set. An id of
+ * -1 indicates the default. */
-void XMLCodeGen::writeInlineList( InlineList *inlineList, InlineItem *context )
+ 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";
+ }
+
+ bool needDefault = false;
+ for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
+ if ( lmi->inLmSelect ) {
+ if ( lmi->action == 0 )
+ needDefault = true;
+ else {
+ /* 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 );
+ out << "</sub_action>\n";
+ }
+ }
+ }
+
+ if ( needDefault ) {
+ out << " <sub_action id=\"-1\"><exec><get_tokend>"
+ "</get_tokend></exec></sub_action>\n";
+ }
+
+ out << " </lm_switch>";
+}
+
+void XMLCodeGen::writeInlineList( InlineList *inlineList )
{
for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
switch ( item->type ) {
case InlineItem::Text:
writeText( item );
break;
- case InlineItem::Goto: case InlineItem::GotoExpr:
- case InlineItem::Call: case InlineItem::CallExpr:
- case InlineItem::Next: case InlineItem::NextExpr:
- case InlineItem::Break: case InlineItem::Ret:
- writeCtrlFlow( item, context );
+ case InlineItem::Goto:
+ writeGoto( item );
+ break;
+ case InlineItem::GotoExpr:
+ writeGotoExpr( item );
+ break;
+ case InlineItem::Call:
+ writeCall( item );
+ break;
+ case InlineItem::CallExpr:
+ writeCallExpr( item );
+ break;
+ case InlineItem::Next:
+ writeNext( item );
+ break;
+ case InlineItem::NextExpr:
+ writeNextExpr( item );
+ break;
+ case InlineItem::Break:
+ out << "<break></break>";
+ break;
+ case InlineItem::Ret:
+ out << "<ret></ret>";
break;
case InlineItem::PChar:
out << "<pchar></pchar>";
break;
case InlineItem::Hold:
+ out << "<hold></hold>";
+ break;
case InlineItem::Exec:
- writePtrMod( item, context );
+ writeActionExec( item );
break;
- case InlineItem::LmSwitch:
- writeLmSwitch( item );
- break;
case InlineItem::LmSetActId:
out << "<set_act>" <<
item->longestMatchPart->longestMatchId <<
case InlineItem::LmSetTokEnd:
out << "<set_tokend>1</set_tokend>";
break;
+
case InlineItem::LmOnLast:
writeLmOnLast( item );
break;
case InlineItem::LmOnLagBehind:
writeLmOnLagBehind( item );
break;
+ case InlineItem::LmSwitch:
+ writeLmSwitch( item );
+ break;
+
case InlineItem::LmInitAct:
out << "<init_act></init_act>";
break;
if ( action->name != 0 )
out << " name=\"" << action->name << "\"";
out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
- writeInlineList( action->inlineList, 0 );
+ writeInlineList( action->inlineList );
out << "</action>\n";
}
-void xmlEscapeHost( std::ostream &out, char *data, int len )
+void xmlEscapeHost( std::ostream &out, char *data, long len )
{
char *end = data + len;
while ( data != end ) {
if ( state->fromStateActionTable.length() > 0 )
fromStateActions = actionTableMap.find( state->fromStateActionTable );
+ /* EOF actions go out here only if the state has no eof target. If it has
+ * an eof target then an eof transition will be used instead. */
RedActionTable *eofActions = 0;
- if ( state->eofActionTable.length() > 0 )
+ if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
eofActions = actionTableMap.find( state->eofActionTable );
if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
if ( eofActions != 0 )
out << " " << eofActions->id;
else
- out << " x"; out << "</state_actions>\n";
+ out << " x";
+
+ out << "</state_actions>\n";
}
}
out << ">\n";
writeStateActions( st );
+ writeEofTrans( st );
writeStateConditions( st );
writeTransList( st );
writeConditions();
/* Start state. */
- GraphDictEl *mainEl = pd->graphDict.find( mainMachine );
- if ( mainEl != 0 ) {
- out << " <start_state>" << fsm->startState->alg.stateNum <<
+ out << " <start_state>" << fsm->startState->alg.stateNum <<
"</start_state>\n";
- }
/* Error state. */
if ( fsm->errState != 0 ) {
out << " </machine>\n";
}
-void XMLCodeGen::writeAlphType()
-{
- out << " <alphtype>" <<
- (keyOps->alphType - hostLang->hostTypes) << "</alphtype>\n";
-}
-
-void XMLCodeGen::writeGetKeyExpr()
-{
- out << " <getkey>";
- writeInlineList( pd->getKeyExpr, 0 );
- out << "</getkey>\n";
-}
-
-void XMLCodeGen::writeAccessExpr()
-{
- out << " <access>";
- writeInlineList( pd->accessExpr, 0 );
- out << "</access>\n";
-}
-
-void XMLCodeGen::writeCurStateExpr()
-{
- out << " <curstate>";
- writeInlineList( pd->curStateExpr, 0 );
- out << "</curstate>\n";
-}
void XMLCodeGen::writeConditions()
{
{
/* Open the definition. */
out << "<ragel_def name=\"" << fsmName << "\">\n";
- writeAlphType();
+
+ /* Alphabet type. */
+ out << " <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
- if ( pd->getKeyExpr != 0 )
- writeGetKeyExpr();
+ /* Getkey expression. */
+ if ( pd->getKeyExpr != 0 ) {
+ out << " <getkey>";
+ writeInlineList( pd->getKeyExpr );
+ out << "</getkey>\n";
+ }
- if ( pd->accessExpr != 0 )
- writeAccessExpr();
+ /* Access expression. */
+ if ( pd->accessExpr != 0 ) {
+ out << " <access>";
+ writeInlineList( pd->accessExpr );
+ out << "</access>\n";
+ }
+
+ /* PrePush expression. */
+ if ( pd->prePushExpr != 0 ) {
+ out << " <prepush>";
+ writeInlineList( pd->prePushExpr );
+ out << "</prepush>\n";
+ }
+
+ /* PostPop expression. */
+ if ( pd->postPopExpr != 0 ) {
+ out << " <postpop>";
+ writeInlineList( pd->postPopExpr );
+ out << "</postpop>\n";
+ }
+
+ /*
+ * Variable expressions.
+ */
+
+ if ( pd->pExpr != 0 ) {
+ out << " <p_expr>";
+ writeInlineList( pd->pExpr );
+ out << "</p_expr>\n";
+ }
+
+ if ( pd->peExpr != 0 ) {
+ out << " <pe_expr>";
+ writeInlineList( pd->peExpr );
+ out << "</pe_expr>\n";
+ }
- if ( pd->curStateExpr != 0 )
- writeCurStateExpr();
+ if ( pd->eofExpr != 0 ) {
+ out << " <eof_expr>";
+ writeInlineList( pd->eofExpr );
+ out << "</eof_expr>\n";
+ }
+
+ if ( pd->csExpr != 0 ) {
+ out << " <cs_expr>";
+ writeInlineList( pd->csExpr );
+ out << "</cs_expr>\n";
+ }
+
+ if ( pd->topExpr != 0 ) {
+ out << " <top_expr>";
+ writeInlineList( pd->topExpr );
+ out << "</top_expr>\n";
+ }
+
+ if ( pd->stackExpr != 0 ) {
+ out << " <stack_expr>";
+ writeInlineList( pd->stackExpr );
+ out << "</stack_expr>\n";
+ }
+
+ if ( pd->actExpr != 0 ) {
+ out << " <act_expr>";
+ writeInlineList( pd->actExpr );
+ out << "</act_expr>\n";
+ }
+
+ if ( pd->tokstartExpr != 0 ) {
+ out << " <tokstart_expr>";
+ writeInlineList( pd->tokstartExpr );
+ out << "</tokstart_expr>\n";
+ }
+
+ if ( pd->tokendExpr != 0 ) {
+ out << " <tokend_expr>";
+ writeInlineList( pd->tokendExpr );
+ out << "</tokend_expr>\n";
+ }
+
+ if ( pd->dataExpr != 0 ) {
+ out << " <data_expr>";
+ writeInlineList( pd->dataExpr );
+ out << "</data_expr>\n";
+ }
writeExports();