2 * Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
5 /* This file is part of Ragel.
7 * Ragel is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * Ragel is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Ragel; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "xmlcodegen.h"
26 #include "parsedata.h"
33 XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm,
34 std::ostream &out, XmlParser &xmlParser )
46 void XMLCodeGen::writeActionList()
48 /* Determine which actions to write. */
50 for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
51 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
52 act->actionId = nextActionId++;
56 out << " <action_list length=\"" << nextActionId << "\">\n";
57 for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
58 if ( act->actionId >= 0 )
61 out << " </action_list>\n";
64 void XMLCodeGen::writeActionTableList()
66 /* Must first order the action tables based on their id. */
67 int numTables = nextActionTableId;
68 RedActionTable **tables = new RedActionTable*[numTables];
69 for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
72 out << " <action_table_list length=\"" << numTables << "\">\n";
73 for ( int t = 0; t < numTables; t++ ) {
74 out << " <action_table id=\"" << t << "\" length=\"" <<
75 tables[t]->key.length() << "\">";
76 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
77 out << atel->value->actionId;
81 out << "</action_table>\n";
83 out << " </action_table_list>\n";
88 void XMLCodeGen::reduceActionTables()
90 /* Reduce the actions tables to a set. */
91 for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
92 RedActionTable *actionTable = 0;
94 /* Reduce To State Actions. */
95 if ( st->toStateActionTable.length() > 0 ) {
96 if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
97 actionTable->id = nextActionTableId++;
100 /* Reduce From State Actions. */
101 if ( st->fromStateActionTable.length() > 0 ) {
102 if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
103 actionTable->id = nextActionTableId++;
106 /* Reduce EOF actions. */
107 if ( st->eofActionTable.length() > 0 ) {
108 if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
109 actionTable->id = nextActionTableId++;
112 /* Loop the transitions and reduce their actions. */
113 for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
114 if ( trans->actionTable.length() > 0 ) {
115 if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
116 actionTable->id = nextActionTableId++;
122 void XMLCodeGen::appendTrans( TransListVect &outList, Key lowKey,
123 Key highKey, TransAp *trans )
125 if ( trans->toState != 0 || trans->actionTable.length() > 0 )
126 outList.append( TransEl( lowKey, highKey, trans ) );
129 void XMLCodeGen::writeKey( Key key )
131 if ( keyOps->isSigned )
134 out << (unsigned long) key.getVal();
137 void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
139 /* First reduce the action. */
140 RedActionTable *actionTable = 0;
141 if ( trans->actionTable.length() > 0 )
142 actionTable = actionTableMap.find( trans->actionTable );
144 /* Write the transition. */
150 if ( trans->toState != 0 )
151 out << " " << trans->toState->alg.stateNum;
155 if ( actionTable != 0 )
156 out << " " << actionTable->id;
162 void XMLCodeGen::writeTransList( StateAp *state )
164 TransListVect outList;
166 /* If there is only are no ranges the task is simple. */
167 if ( state->outList.length() > 0 ) {
168 /* Loop each source range. */
169 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
170 /* Reduce the transition. If it reduced to anything then add it. */
171 appendTrans( outList, trans->lowKey, trans->highKey, trans );
175 out << " <trans_list length=\"" << outList.length() << "\">\n";
176 for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
177 writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
178 out << " </trans_list>\n";
181 void XMLCodeGen::writeEofTrans( StateAp *state )
183 RedActionTable *eofActions = 0;
184 if ( state->eofActionTable.length() > 0 )
185 eofActions = actionTableMap.find( state->eofActionTable );
187 /* The <eof_t> is used when there is an eof target, otherwise the eof
188 * action goes into state actions. */
189 if ( state->eofTarget != 0 ) {
190 out << " <eof_t>" << state->eofTarget->alg.stateNum;
192 if ( eofActions != 0 )
193 out << " " << eofActions->id;
197 out << "</eof_t>" << endl;
201 void XMLCodeGen::writeText( InlineItem *item )
203 if ( item->prev == 0 || item->prev->type != InlineItem::Text )
205 xmlEscapeHost( out, item->data, strlen(item->data) );
206 if ( item->next == 0 || item->next->type != InlineItem::Text )
210 void XMLCodeGen::writeGoto( InlineItem *item )
212 if ( pd->generatingSectionSubset )
213 out << "<goto>-1</goto>";
215 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
216 out << "<goto>" << targ->value->alg.stateNum << "</goto>";
220 void XMLCodeGen::writeCall( InlineItem *item )
222 if ( pd->generatingSectionSubset )
223 out << "<call>-1</call>";
225 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
226 out << "<call>" << targ->value->alg.stateNum << "</call>";
230 void XMLCodeGen::writeNext( InlineItem *item )
232 if ( pd->generatingSectionSubset )
233 out << "<next>-1</next>";
235 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
236 out << "<next>" << targ->value->alg.stateNum << "</next>";
240 void XMLCodeGen::writeGotoExpr( InlineItem *item )
242 out << "<goto_expr>";
243 writeInlineList( item->children );
244 out << "</goto_expr>";
247 void XMLCodeGen::writeCallExpr( InlineItem *item )
249 out << "<call_expr>";
250 writeInlineList( item->children );
251 out << "</call_expr>";
254 void XMLCodeGen::writeNextExpr( InlineItem *item )
256 out << "<next_expr>";
257 writeInlineList( item->children );
258 out << "</next_expr>";
261 void XMLCodeGen::writeEntry( InlineItem *item )
263 if ( pd->generatingSectionSubset )
264 out << "<entry>-1</entry>";
266 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
267 out << "<entry>" << targ->value->alg.stateNum << "</entry>";
271 void XMLCodeGen::writeActionExec( InlineItem *item )
274 writeInlineList( item->children );
278 void XMLCodeGen::writeLmOnLast( InlineItem *item )
280 out << "<set_tokend>1</set_tokend>";
282 if ( item->longestMatchPart->action != 0 ) {
283 out << "<sub_action>";
284 writeInlineList( item->longestMatchPart->action->inlineList );
285 out << "</sub_action>";
289 void XMLCodeGen::writeLmOnNext( InlineItem *item )
291 out << "<set_tokend>0</set_tokend>";
292 out << "<hold></hold>";
294 if ( item->longestMatchPart->action != 0 ) {
295 out << "<sub_action>";
296 writeInlineList( item->longestMatchPart->action->inlineList );
297 out << "</sub_action>";
301 void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
303 out << "<exec><get_tokend></get_tokend></exec>";
305 if ( item->longestMatchPart->action != 0 ) {
306 out << "<sub_action>";
307 writeInlineList( item->longestMatchPart->action->inlineList );
308 out << "</sub_action>";
312 void XMLCodeGen::writeLmSwitch( InlineItem *item )
314 LongestMatch *longestMatch = item->longestMatch;
315 out << "<lm_switch>\n";
317 /* We can't put the <exec> here because we may need to handle the error
318 * case and in that case p should not be changed. Instead use a default
319 * label in the switch to adjust p when user actions are not set. An id of
320 * -1 indicates the default. */
322 if ( longestMatch->lmSwitchHandlesError ) {
323 /* If the switch handles error then we should have also forced the
325 assert( fsm->errState != 0 );
327 out << " <sub_action id=\"0\">";
328 out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
329 out << "</sub_action>\n";
332 bool needDefault = false;
333 for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
334 if ( lmi->inLmSelect ) {
335 if ( lmi->action == 0 )
338 /* Open the action. Write it with the context that sets up _p
339 * when doing control flow changes from inside the machine. */
340 out << " <sub_action id=\"" << lmi->longestMatchId << "\">";
341 out << "<exec><get_tokend></get_tokend></exec>";
342 writeInlineList( lmi->action->inlineList );
343 out << "</sub_action>\n";
349 out << " <sub_action id=\"-1\"><exec><get_tokend>"
350 "</get_tokend></exec></sub_action>\n";
353 out << " </lm_switch>";
356 void XMLCodeGen::writeInlineList( InlineList *inlineList )
358 for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
359 switch ( item->type ) {
360 case InlineItem::Text:
363 case InlineItem::Goto:
366 case InlineItem::GotoExpr:
367 writeGotoExpr( item );
369 case InlineItem::Call:
372 case InlineItem::CallExpr:
373 writeCallExpr( item );
375 case InlineItem::Next:
378 case InlineItem::NextExpr:
379 writeNextExpr( item );
381 case InlineItem::Break:
382 out << "<break></break>";
384 case InlineItem::Ret:
385 out << "<ret></ret>";
387 case InlineItem::PChar:
388 out << "<pchar></pchar>";
390 case InlineItem::Char:
391 out << "<char></char>";
393 case InlineItem::Curs:
394 out << "<curs></curs>";
396 case InlineItem::Targs:
397 out << "<targs></targs>";
399 case InlineItem::Entry:
403 case InlineItem::Hold:
404 out << "<hold></hold>";
406 case InlineItem::Exec:
407 writeActionExec( item );
410 case InlineItem::LmSetActId:
411 out << "<set_act>" <<
412 item->longestMatchPart->longestMatchId <<
415 case InlineItem::LmSetTokEnd:
416 out << "<set_tokend>1</set_tokend>";
419 case InlineItem::LmOnLast:
420 writeLmOnLast( item );
422 case InlineItem::LmOnNext:
423 writeLmOnNext( item );
425 case InlineItem::LmOnLagBehind:
426 writeLmOnLagBehind( item );
428 case InlineItem::LmSwitch:
429 writeLmSwitch( item );
432 case InlineItem::LmInitAct:
433 out << "<init_act></init_act>";
435 case InlineItem::LmInitTokStart:
436 out << "<init_tokstart></init_tokstart>";
438 case InlineItem::LmSetTokStart:
439 out << "<set_tokstart></set_tokstart>";
445 void XMLCodeGen::makeKey( GenInlineList *outList, Key key )
449 void XMLCodeGen::makeText( GenInlineList *outList, InlineItem *item )
451 GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Text );
452 inlineItem->data = item->data;
454 outList->append( inlineItem );
457 void XMLCodeGen::makeTargetItem( GenInlineList *outList, long targetId, GenInlineItem::Type type )
460 if ( pd->generatingSectionSubset )
463 EntryMapEl *targ = fsm->entryPoints.find( targetId );
464 targetState = targ->value->alg.stateNum;
468 GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), type );
469 inlineItem->targId = targetState;
470 outList->append( inlineItem );
473 /* Make a sublist item with a given type. */
474 void XMLCodeGen::makeSubList( GenInlineList *outList,
475 InlineList *inlineList, GenInlineItem::Type type )
477 /* Fill the sub list. */
478 GenInlineList *subList = new GenInlineList;
479 makeGenInlineList( subList, inlineList );
482 GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), type );
483 inlineItem->children = subList;
484 outList->append( inlineItem );
487 void XMLCodeGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
489 makeSetTokend( outList, 1 );
491 if ( item->longestMatchPart->action != 0 ) {
492 makeSubList( outList,
493 item->longestMatchPart->action->inlineList,
494 GenInlineItem::SubAction );
498 void XMLCodeGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
500 makeSetTokend( outList, 0 );
501 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Hold ) );
503 if ( item->longestMatchPart->action != 0 ) {
504 makeSubList( outList,
505 item->longestMatchPart->action->inlineList,
506 GenInlineItem::SubAction );
510 void XMLCodeGen::makeExecGetTokend( GenInlineList *outList )
512 /* Make the Exec item. */
513 GenInlineItem *execItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Exec );
514 execItem->children = new GenInlineList;
516 /* Make the GetTokEnd */
517 GenInlineItem *getTokend = new GenInlineItem( GenInputLoc(), GenInlineItem::LmGetTokEnd );
518 execItem->children->append( getTokend );
520 outList->append( execItem );
523 void XMLCodeGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
525 /* Jump to the tokend. */
526 makeExecGetTokend( outList );
528 if ( item->longestMatchPart->action != 0 ) {
529 makeSubList( outList,
530 item->longestMatchPart->action->inlineList,
531 GenInlineItem::SubAction );
535 void XMLCodeGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
537 GenInlineItem *lmSwitch = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSwitch );
538 GenInlineList *lmList = lmSwitch->children = new GenInlineList;
539 LongestMatch *longestMatch = item->longestMatch;
541 /* We can't put the <exec> here because we may need to handle the error
542 * case and in that case p should not be changed. Instead use a default
543 * label in the switch to adjust p when user actions are not set. An id of
544 * -1 indicates the default. */
546 if ( longestMatch->lmSwitchHandlesError ) {
547 /* If the switch handles error then we should have also forced the
549 assert( fsm->errState != 0 );
551 GenInlineItem *errCase = new GenInlineItem( GenInputLoc(), GenInlineItem::SubAction );
553 errCase->children = new GenInlineList;
555 makeTargetItem( errCase->children,
556 fsm->errState->alg.stateNum, GenInlineItem::Goto );
558 lmList->append( errCase );
561 bool needDefault = false;
562 for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
563 if ( lmi->inLmSelect ) {
564 if ( lmi->action == 0 )
567 /* Open the action. Write it with the context that sets up _p
568 * when doing control flow changes from inside the machine. */
569 GenInlineItem *lmCase = new GenInlineItem( GenInputLoc(),
570 GenInlineItem::SubAction );
571 lmCase->lmId = lmi->longestMatchId;
572 lmCase->children = new GenInlineList;
574 makeExecGetTokend( lmCase->children );
575 makeGenInlineList( lmCase->children, lmi->action->inlineList );
577 lmList->append( lmCase );
583 GenInlineItem *defCase = new GenInlineItem( GenInputLoc(),
584 GenInlineItem::SubAction );
586 defCase->children = new GenInlineList;
588 makeExecGetTokend( defCase->children );
590 lmList->append( defCase );
593 outList->append( lmSwitch );
596 void XMLCodeGen::makeSetTokend( GenInlineList *outList, long offset )
598 GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokEnd );
599 inlineItem->offset = offset;
600 outList->append( inlineItem );
603 void XMLCodeGen::makeSetAct( GenInlineList *outList, long lmId )
605 GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetActId );
606 inlineItem->lmId = lmId;
607 outList->append( inlineItem );
610 void XMLCodeGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
612 for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
613 switch ( item->type ) {
614 case InlineItem::Text:
615 makeText( outList, item );
617 case InlineItem::Goto:
618 makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Goto );
620 case InlineItem::GotoExpr:
621 makeSubList( outList, item->children, GenInlineItem::GotoExpr );
623 case InlineItem::Call:
624 makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Call );
626 case InlineItem::CallExpr:
627 makeSubList( outList, item->children, GenInlineItem::CallExpr );
629 case InlineItem::Next:
630 makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Next );
632 case InlineItem::NextExpr:
633 makeSubList( outList, item->children, GenInlineItem::NextExpr );
635 case InlineItem::Break:
636 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Break ) );
638 case InlineItem::Ret:
639 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Ret ) );
641 case InlineItem::PChar:
642 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::PChar ) );
644 case InlineItem::Char:
645 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Char ) );
647 case InlineItem::Curs:
648 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Curs ) );
650 case InlineItem::Targs:
651 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Targs ) );
653 case InlineItem::Entry:
654 makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Entry );
657 case InlineItem::Hold:
658 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Hold ) );
660 case InlineItem::Exec:
661 makeSubList( outList, item->children, GenInlineItem::Exec );
664 case InlineItem::LmSetActId:
665 makeSetAct( outList, item->longestMatchPart->longestMatchId );
667 case InlineItem::LmSetTokEnd:
668 makeSetTokend( outList, 1 );
671 case InlineItem::LmOnLast:
672 makeLmOnLast( outList, item );
674 case InlineItem::LmOnNext:
675 makeLmOnNext( outList, item );
677 case InlineItem::LmOnLagBehind:
678 makeLmOnLagBehind( outList, item );
680 case InlineItem::LmSwitch:
681 makeLmSwitch( outList, item );
684 case InlineItem::LmInitAct:
685 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitAct ) );
687 case InlineItem::LmInitTokStart:
688 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitTokStart ) );
690 case InlineItem::LmSetTokStart:
691 outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokStart ) );
692 xmlParser.cgd->hasLongestMatch = true;
699 void XMLCodeGen::writeAction( Action *action )
701 out << " <action id=\"" << action->actionId << "\"";
702 if ( action->name != 0 )
703 out << " name=\"" << action->name << "\"";
704 out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
705 writeInlineList( action->inlineList );
706 out << "</action>\n";
709 void xmlEscapeHost( std::ostream &out, char *data, long len )
711 char *end = data + len;
712 while ( data != end ) {
714 case '<': out << "<"; break;
715 case '>': out << ">"; break;
716 case '&': out << "&"; break;
717 default: out << *data; break;
723 void XMLCodeGen::writeStateActions( StateAp *state )
725 RedActionTable *toStateActions = 0;
726 if ( state->toStateActionTable.length() > 0 )
727 toStateActions = actionTableMap.find( state->toStateActionTable );
729 RedActionTable *fromStateActions = 0;
730 if ( state->fromStateActionTable.length() > 0 )
731 fromStateActions = actionTableMap.find( state->fromStateActionTable );
733 /* EOF actions go out here only if the state has no eof target. If it has
734 * an eof target then an eof transition will be used instead. */
735 RedActionTable *eofActions = 0;
736 if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
737 eofActions = actionTableMap.find( state->eofActionTable );
739 if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
740 out << " <state_actions>";
741 if ( toStateActions != 0 )
742 out << toStateActions->id;
746 if ( fromStateActions != 0 )
747 out << " " << fromStateActions->id;
751 if ( eofActions != 0 )
752 out << " " << eofActions->id;
756 out << "</state_actions>\n";
760 void XMLCodeGen::writeStateConditions( StateAp *state )
762 if ( state->stateCondList.length() > 0 ) {
763 out << " <cond_list length=\"" << state->stateCondList.length() << "\">\n";
764 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
766 writeKey( scdi->lowKey );
768 writeKey( scdi->highKey );
770 out << scdi->condSpace->condSpaceId;
773 out << " </cond_list>\n";
777 void XMLCodeGen::writeStateList()
779 /* Write the list of states. */
780 out << " <state_list length=\"" << fsm->stateList.length() << "\">\n";
781 for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
782 out << " <state id=\"" << st->alg.stateNum << "\"";
783 if ( st->isFinState() )
784 out << " final=\"t\"";
787 writeStateActions( st );
789 writeStateConditions( st );
790 writeTransList( st );
792 out << " </state>\n";
797 out << " </state_list>\n";
800 bool XMLCodeGen::writeNameInst( NameInst *nameInst )
802 bool written = false;
803 if ( nameInst->parent != 0 )
804 written = writeNameInst( nameInst->parent );
806 if ( nameInst->name != 0 ) {
809 out << nameInst->name;
816 void XMLCodeGen::writeEntryPoints()
818 /* List of entry points other than start state. */
819 if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
820 out << " <entry_points";
821 if ( pd->lmRequiresErrorState )
822 out << " error=\"t\"";
824 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
825 /* Get the name instantiation from nameIndex. */
826 NameInst *nameInst = pd->nameIndex[en->key];
827 StateAp *state = en->value;
828 out << " <entry name=\"";
829 writeNameInst( nameInst );
830 out << "\">" << state->alg.stateNum << "</entry>\n";
832 out << " </entry_points>\n";
836 void XMLCodeGen::writeMachine()
838 /* Open the machine. */
839 out << " <machine>\n";
842 reduceActionTables();
845 writeActionTableList();
849 out << " <start_state>" << fsm->startState->alg.stateNum <<
853 if ( fsm->errState != 0 ) {
854 out << " <error_state>" << fsm->errState->alg.stateNum <<
861 out << " </machine>\n";
865 void XMLCodeGen::writeConditions()
867 if ( condData->condSpaceMap.length() > 0 ) {
868 long nextCondSpaceId = 0;
869 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
870 cs->condSpaceId = nextCondSpaceId++;
872 out << " <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
873 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
874 out << " <cond_space id=\"" << cs->condSpaceId <<
875 "\" length=\"" << cs->condSet.length() << "\">";
876 writeKey( cs->baseKey );
877 for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
878 out << " " << (*csi)->actionId;
879 out << "</cond_space>\n";
881 out << " </cond_space_list>\n";
885 void XMLCodeGen::writeExports()
887 if ( pd->exportList.length() > 0 ) {
888 out << " <exports>\n";
889 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
890 out << " <ex name=\"" << exp->name << "\">";
891 writeKey( exp->key );
894 out << " </exports>\n";
898 void XMLCodeGen::writeXML()
900 /* Open the definition. */
901 out << "<ragel_def name=\"" << fsmName << "\">\n";
904 out << " <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
906 /* Getkey expression. */
907 if ( pd->getKeyExpr != 0 ) {
909 writeInlineList( pd->getKeyExpr );
910 out << "</getkey>\n";
913 /* Access expression. */
914 if ( pd->accessExpr != 0 ) {
916 writeInlineList( pd->accessExpr );
917 out << "</access>\n";
920 /* PrePush expression. */
921 if ( pd->prePushExpr != 0 ) {
923 writeInlineList( pd->prePushExpr );
924 out << "</prepush>\n";
927 /* PostPop expression. */
928 if ( pd->postPopExpr != 0 ) {
930 writeInlineList( pd->postPopExpr );
931 out << "</postpop>\n";
935 * Variable expressions.
938 if ( pd->pExpr != 0 ) {
940 writeInlineList( pd->pExpr );
941 out << "</p_expr>\n";
944 if ( pd->peExpr != 0 ) {
946 writeInlineList( pd->peExpr );
947 out << "</pe_expr>\n";
950 if ( pd->eofExpr != 0 ) {
951 out << " <eof_expr>";
952 writeInlineList( pd->eofExpr );
953 out << "</eof_expr>\n";
956 if ( pd->csExpr != 0 ) {
958 writeInlineList( pd->csExpr );
959 out << "</cs_expr>\n";
962 if ( pd->topExpr != 0 ) {
963 out << " <top_expr>";
964 writeInlineList( pd->topExpr );
965 out << "</top_expr>\n";
968 if ( pd->stackExpr != 0 ) {
969 out << " <stack_expr>";
970 writeInlineList( pd->stackExpr );
971 out << "</stack_expr>\n";
974 if ( pd->actExpr != 0 ) {
975 out << " <act_expr>";
976 writeInlineList( pd->actExpr );
977 out << "</act_expr>\n";
980 if ( pd->tokstartExpr != 0 ) {
981 out << " <tokstart_expr>";
982 writeInlineList( pd->tokstartExpr );
983 out << "</tokstart_expr>\n";
986 if ( pd->tokendExpr != 0 ) {
987 out << " <tokend_expr>";
988 writeInlineList( pd->tokendExpr );
989 out << "</tokend_expr>\n";
992 if ( pd->dataExpr != 0 ) {
993 out << " <data_expr>";
994 writeInlineList( pd->dataExpr );
995 out << "</data_expr>\n";
1006 void XMLCodeGen::makeExports()
1008 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
1009 xmlParser.cgd->exportList.append( new Export( exp->name, exp->key ) );
1012 void XMLCodeGen::makeAction( Action *action )
1014 GenInlineList *genList = new GenInlineList;
1015 makeGenInlineList( genList, action->inlineList );
1017 xmlParser.cgd->newAction( xmlParser.curAction++, action->name,
1018 action->loc.line, action->loc.col, genList );
1022 void XMLCodeGen::makeActionList()
1024 /* Determine which actions to write. */
1025 int nextActionId = 0;
1026 for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1027 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
1028 act->actionId = nextActionId++;
1031 /* Write the list. */
1032 xmlParser.cgd->initActionList( nextActionId );
1033 xmlParser.curAction = 0;
1035 for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1036 if ( act->actionId >= 0 )
1041 void XMLCodeGen::makeActionTableList()
1043 /* Must first order the action tables based on their id. */
1044 int numTables = nextActionTableId;
1045 RedActionTable **tables = new RedActionTable*[numTables];
1046 for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
1047 tables[at->id] = at;
1049 xmlParser.cgd->initActionTableList( numTables );
1050 xmlParser.curActionTable = 0;
1052 for ( int t = 0; t < numTables; t++ ) {
1053 long length = tables[t]->key.length();
1055 /* Collect the action table. */
1056 RedAction *redAct = xmlParser.cgd->allActionTables + xmlParser.curActionTable;
1057 redAct->actListId = xmlParser.curActionTable;
1058 redAct->key.setAsNew( length );
1060 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
1061 redAct->key[atel.pos()].key = 0;
1062 redAct->key[atel.pos()].value = xmlParser.cgd->allActions +
1063 atel->value->actionId;
1066 xmlParser.curActionTable += 1;
1072 void XMLCodeGen::makeConditions()
1074 if ( condData->condSpaceMap.length() > 0 ) {
1075 long nextCondSpaceId = 0;
1076 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
1077 cs->condSpaceId = nextCondSpaceId++;
1079 long listLength = condData->condSpaceMap.length();
1080 xmlParser.cgd->initCondSpaceList( listLength );
1081 xmlParser.curCondSpace = 0;
1083 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
1084 long id = cs->condSpaceId;
1085 xmlParser.cgd->newCondSpace( xmlParser.curCondSpace, id, cs->baseKey );
1086 for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
1087 xmlParser.cgd->condSpaceItem( xmlParser.curCondSpace, (*csi)->actionId );
1088 xmlParser.curCondSpace += 1;
1093 bool XMLCodeGen::makeNameInst( std::string &res, NameInst *nameInst )
1095 bool written = false;
1096 if ( nameInst->parent != 0 )
1097 written = makeNameInst( res, nameInst->parent );
1099 if ( nameInst->name != 0 ) {
1102 res += nameInst->name;
1109 void XMLCodeGen::makeEntryPoints()
1111 /* List of entry points other than start state. */
1112 if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
1113 if ( pd->lmRequiresErrorState )
1114 xmlParser.cgd->setForcedErrorState();
1116 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
1117 /* Get the name instantiation from nameIndex. */
1118 NameInst *nameInst = pd->nameIndex[en->key];
1120 makeNameInst( name, nameInst );
1121 StateAp *state = en->value;
1122 xmlParser.cgd->addEntryPoint( strdup(name.c_str()), state->alg.stateNum );
1127 void XMLCodeGen::makeStateActions( StateAp *state )
1129 RedActionTable *toStateActions = 0;
1130 if ( state->toStateActionTable.length() > 0 )
1131 toStateActions = actionTableMap.find( state->toStateActionTable );
1133 RedActionTable *fromStateActions = 0;
1134 if ( state->fromStateActionTable.length() > 0 )
1135 fromStateActions = actionTableMap.find( state->fromStateActionTable );
1137 /* EOF actions go out here only if the state has no eof target. If it has
1138 * an eof target then an eof transition will be used instead. */
1139 RedActionTable *eofActions = 0;
1140 if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
1141 eofActions = actionTableMap.find( state->eofActionTable );
1143 if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
1145 if ( toStateActions != 0 )
1146 to = toStateActions->id;
1149 if ( fromStateActions != 0 )
1150 from = fromStateActions->id;
1153 if ( eofActions != 0 )
1154 eof = eofActions->id;
1156 xmlParser.cgd->setStateActions( xmlParser.curState, to, from, eof );
1160 void XMLCodeGen::makeEofTrans( StateAp *state )
1162 RedActionTable *eofActions = 0;
1163 if ( state->eofActionTable.length() > 0 )
1164 eofActions = actionTableMap.find( state->eofActionTable );
1166 /* The EOF trans is used when there is an eof target, otherwise the eof
1167 * action goes into state actions. */
1168 if ( state->eofTarget != 0 ) {
1169 long targ = state->eofTarget->alg.stateNum;
1171 if ( eofActions != 0 )
1172 action = eofActions->id;
1174 xmlParser.cgd->setEofTrans( xmlParser.curState, targ, action );
1178 void XMLCodeGen::makeStateConditions( StateAp *state )
1180 if ( state->stateCondList.length() > 0 ) {
1181 long length = state->stateCondList.length();
1182 xmlParser.cgd->initStateCondList( xmlParser.curState, length );
1183 xmlParser.curStateCond = 0;
1185 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
1186 xmlParser.cgd->addStateCond( xmlParser.curState, scdi->lowKey, scdi->highKey,
1187 scdi->condSpace->condSpaceId );
1192 void XMLCodeGen::makeTrans( Key lowKey, Key highKey, TransAp *trans )
1194 /* First reduce the action. */
1195 RedActionTable *actionTable = 0;
1196 if ( trans->actionTable.length() > 0 )
1197 actionTable = actionTableMap.find( trans->actionTable );
1200 if ( trans->toState != 0 )
1201 targ = trans->toState->alg.stateNum;
1204 if ( actionTable != 0 )
1205 action = actionTable->id;
1207 xmlParser.cgd->newTrans( xmlParser.curState, xmlParser.curTrans++, lowKey, highKey, targ, action );
1211 void XMLCodeGen::makeTransList( StateAp *state )
1213 TransListVect outList;
1215 /* If there is only are no ranges the task is simple. */
1216 if ( state->outList.length() > 0 ) {
1217 /* Loop each source range. */
1218 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
1219 /* Reduce the transition. If it reduced to anything then add it. */
1220 appendTrans( outList, trans->lowKey, trans->highKey, trans );
1224 xmlParser.cgd->initTransList( xmlParser.curState, outList.length() );
1225 xmlParser.curTrans = 0;
1227 for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
1228 makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
1230 xmlParser.cgd->finishTransList( xmlParser.curState );
1234 void XMLCodeGen::makeStateList()
1236 /* Write the list of states. */
1237 long length = fsm->stateList.length();
1238 xmlParser.cgd->initStateList( length );
1239 xmlParser.curState = 0;
1240 for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
1241 makeStateActions( st );
1243 makeStateConditions( st );
1244 makeTransList( st );
1246 long id = st->alg.stateNum;
1247 xmlParser.cgd->setId( xmlParser.curState, id );
1249 if ( st->isFinState() )
1250 xmlParser.cgd->setFinal( xmlParser.curState );
1252 xmlParser.curState += 1;
1257 void XMLCodeGen::makeMachine()
1259 xmlParser.cgd->createMachine();
1261 /* Action tables. */
1262 reduceActionTables();
1265 makeActionTableList();
1269 xmlParser.cgd->setStartState( fsm->startState->alg.stateNum );
1272 if ( fsm->errState != 0 )
1273 xmlParser.cgd->setErrorState( fsm->errState->alg.stateNum );
1279 void XMLCodeGen::makeBackend()
1281 /* Open the definition. */
1282 xmlParser.open_ragel_def( fsmName );
1284 /* Alphabet type. */
1285 xmlParser.cgd->setAlphType( keyOps->alphType->internalName );
1287 /* Getkey expression. */
1288 if ( pd->getKeyExpr != 0 ) {
1289 xmlParser.cgd->getKeyExpr = new GenInlineList;
1290 makeGenInlineList( xmlParser.cgd->getKeyExpr, pd->getKeyExpr );
1293 /* Access expression. */
1294 if ( pd->accessExpr != 0 ) {
1295 xmlParser.cgd->accessExpr = new GenInlineList;
1296 makeGenInlineList( xmlParser.cgd->accessExpr, pd->accessExpr );
1299 /* PrePush expression. */
1300 if ( pd->prePushExpr != 0 ) {
1301 xmlParser.cgd->prePushExpr = new GenInlineList;
1302 makeGenInlineList( xmlParser.cgd->prePushExpr, pd->prePushExpr );
1305 /* PostPop expression. */
1306 if ( pd->postPopExpr != 0 ) {
1307 xmlParser.cgd->postPopExpr = new GenInlineList;
1308 makeGenInlineList( xmlParser.cgd->postPopExpr, pd->postPopExpr );
1312 * Variable expressions.
1315 if ( pd->pExpr != 0 ) {
1316 xmlParser.cgd->pExpr = new GenInlineList;
1317 makeGenInlineList( xmlParser.cgd->pExpr, pd->pExpr );
1320 if ( pd->peExpr != 0 ) {
1321 xmlParser.cgd->peExpr = new GenInlineList;
1322 makeGenInlineList( xmlParser.cgd->peExpr, pd->peExpr );
1325 if ( pd->eofExpr != 0 ) {
1326 xmlParser.cgd->eofExpr = new GenInlineList;
1327 makeGenInlineList( xmlParser.cgd->eofExpr, pd->eofExpr );
1330 if ( pd->csExpr != 0 ) {
1331 xmlParser.cgd->csExpr = new GenInlineList;
1332 makeGenInlineList( xmlParser.cgd->csExpr, pd->csExpr );
1335 if ( pd->topExpr != 0 ) {
1336 xmlParser.cgd->topExpr = new GenInlineList;
1337 makeGenInlineList( xmlParser.cgd->topExpr, pd->topExpr );
1340 if ( pd->stackExpr != 0 ) {
1341 xmlParser.cgd->stackExpr = new GenInlineList;
1342 makeGenInlineList( xmlParser.cgd->stackExpr, pd->stackExpr );
1345 if ( pd->actExpr != 0 ) {
1346 xmlParser.cgd->actExpr = new GenInlineList;
1347 makeGenInlineList( xmlParser.cgd->actExpr, pd->actExpr );
1350 if ( pd->tokstartExpr != 0 ) {
1351 xmlParser.cgd->tokstartExpr = new GenInlineList;
1352 makeGenInlineList( xmlParser.cgd->tokstartExpr, pd->tokstartExpr );
1355 if ( pd->tokendExpr != 0 ) {
1356 xmlParser.cgd->tokendExpr = new GenInlineList;
1357 makeGenInlineList( xmlParser.cgd->tokendExpr, pd->tokendExpr );
1360 if ( pd->dataExpr != 0 ) {
1361 xmlParser.cgd->dataExpr = new GenInlineList;
1362 makeGenInlineList( xmlParser.cgd->dataExpr, pd->dataExpr );