/*
- * Copyright 2005-2007 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::writeEofTrans( StateAp *state )
+{
+ RedActionTable *eofActions = 0;
+ if ( state->eofActionTable.length() > 0 )
+ eofActions = actionTableMap.find( state->eofActionTable );
+
+ /* 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;
+
+ if ( eofActions != 0 )
+ out << " " << eofActions->id;
+ else
+ out << " x";
+
+ out << "</eof_t>" << endl;
+ }
+}
+
void XMLCodeGen::writeText( InlineItem *item )
{
if ( item->prev == 0 || item->prev->type != InlineItem::Text )
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. */
+
if ( longestMatch->lmSwitchHandlesError ) {
/* If the switch handles error then we should have also forced the
* error state. */
out << "</sub_action>\n";
}
+ bool needDefault = false;
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 );
- out << "</sub_action>\n";
+ 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>";
}
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 );
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.
*/
writeInlineList( pd->peExpr );
out << "</pe_expr>\n";
}
+
+ if ( pd->eofExpr != 0 ) {
+ out << " <eof_expr>";
+ writeInlineList( pd->eofExpr );
+ out << "</eof_expr>\n";
+ }
if ( pd->csExpr != 0 ) {
out << " <cs_expr>";
out << "</tokend_expr>\n";
}
+ if ( pd->dataExpr != 0 ) {
+ out << " <data_expr>";
+ writeInlineList( pd->dataExpr );
+ out << "</data_expr>\n";
+ }
+
writeExports();
writeMachine();