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>";
}
ret <<
" switch( " << ACT() << " ) {\n";
+ bool haveDefault = false;
for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
/* Write the case label, the action and the case break. */
- ret << " case " << lma->lmId << ":\n";
+ if ( lma->lmId < 0 ) {
+ ret << " default:\n";
+ haveDefault = true;
+ }
+ else
+ ret << " case " << lma->lmId << ":\n";
/* Write the block and close it off. */
ret << " {";
ret << " break;\n";
}
- /* Default required for D code. */
+
+ if ( hostLang->lang == HostLang::D && !haveDefault )
+ ret << " default: break;";
+
ret <<
- " default: break;\n"
" }\n"
"\t";
}
for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
/* Write the case label, the action and the case break. */
- ret << " case " << lma->lmId << ":\n";
+ if ( lma->lmId < 0 )
+ ret << " default:\n";
+ else
+ ret << " case " << lma->lmId << ":\n";
/* Write the block and close it off. */
ret << " {";
ret << " break;\n";
}
- /* Default required for D code. */
+
ret <<
- " default: break;\n"
" }\n"
"\t";
}
for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
/* Write the case label, the action and the case break. */
- ret << " case " << lma->lmId << ":\n";
+ if ( lma->lmId < 0 )
+ ret << " default:\n";
+ else
+ ret << " case " << lma->lmId << ":\n";
/* Write the block and close it off. */
ret << " {";
ret << " break;\n";
}
- /* Default required for D code. */
+
ret <<
- " default: break;\n"
" }\n"
"\t";
}
for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
/* Write the case label, the action and the case break. */
- ret << " when " << lma->lmId << " then\n";
+ if ( lma->lmId < 0 )
+ ret << " else\n";
+ else
+ ret << " when " << lma->lmId << " then\n";
+
/* Write the block and close it off. */
ret << " begin";
--- /dev/null
+/*
+ * @LANG: indep
+ */
+ptr ts;
+ptr te;
+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 "pat1\n";
+ };
+
+ [ab]+ . 'c' => {
+ prints "pat2\n";
+ };
+
+ any;
+ *|;
+}%%
+/* _____INPUT_____
+"ba a"
+_____INPUT_____ */
+/* _____OUTPUT_____
+pat1
+pat1
+ACCEPT
+_____OUTPUT_____ */