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"
25 #include "parsedata.h"
28 #include "inputdata.h"
35 GenBase::GenBase( char *fsmName
, ParseData
*pd
, FsmAp
*fsm
)
44 void GenBase::appendTrans( TransListVect
&outList
, Key lowKey
,
45 Key highKey
, TransAp
*trans
)
47 if ( trans
->toState
!= 0 || trans
->actionTable
.length() > 0 )
48 outList
.append( TransEl( lowKey
, highKey
, trans
) );
51 void GenBase::reduceActionTables()
53 /* Reduce the actions tables to a set. */
54 for ( StateList::Iter st
= fsm
->stateList
; st
.lte(); st
++ ) {
55 RedActionTable
*actionTable
= 0;
57 /* Reduce To State Actions. */
58 if ( st
->toStateActionTable
.length() > 0 ) {
59 if ( actionTableMap
.insert( st
->toStateActionTable
, &actionTable
) )
60 actionTable
->id
= nextActionTableId
++;
63 /* Reduce From State Actions. */
64 if ( st
->fromStateActionTable
.length() > 0 ) {
65 if ( actionTableMap
.insert( st
->fromStateActionTable
, &actionTable
) )
66 actionTable
->id
= nextActionTableId
++;
69 /* Reduce EOF actions. */
70 if ( st
->eofActionTable
.length() > 0 ) {
71 if ( actionTableMap
.insert( st
->eofActionTable
, &actionTable
) )
72 actionTable
->id
= nextActionTableId
++;
75 /* Loop the transitions and reduce their actions. */
76 for ( TransList::Iter trans
= st
->outList
; trans
.lte(); trans
++ ) {
77 if ( trans
->actionTable
.length() > 0 ) {
78 if ( actionTableMap
.insert( trans
->actionTable
, &actionTable
) )
79 actionTable
->id
= nextActionTableId
++;
85 XMLCodeGen::XMLCodeGen( char *fsmName
, ParseData
*pd
, FsmAp
*fsm
, std::ostream
&out
)
87 GenBase(fsmName
, pd
, fsm
),
93 void XMLCodeGen::writeActionList()
95 /* Determine which actions to write. */
97 for ( ActionList::Iter act
= pd
->actionList
; act
.lte(); act
++ ) {
98 if ( act
->numRefs() > 0 || act
->numCondRefs
> 0 )
99 act
->actionId
= nextActionId
++;
102 /* Write the list. */
103 out
<< " <action_list length=\"" << nextActionId
<< "\">\n";
104 for ( ActionList::Iter act
= pd
->actionList
; act
.lte(); act
++ ) {
105 if ( act
->actionId
>= 0 )
108 out
<< " </action_list>\n";
111 void XMLCodeGen::writeActionTableList()
113 /* Must first order the action tables based on their id. */
114 int numTables
= nextActionTableId
;
115 RedActionTable
**tables
= new RedActionTable
*[numTables
];
116 for ( ActionTableMap::Iter at
= actionTableMap
; at
.lte(); at
++ )
119 out
<< " <action_table_list length=\"" << numTables
<< "\">\n";
120 for ( int t
= 0; t
< numTables
; t
++ ) {
121 out
<< " <action_table id=\"" << t
<< "\" length=\"" <<
122 tables
[t
]->key
.length() << "\">";
123 for ( ActionTable::Iter atel
= tables
[t
]->key
; atel
.lte(); atel
++ ) {
124 out
<< atel
->value
->actionId
;
128 out
<< "</action_table>\n";
130 out
<< " </action_table_list>\n";
135 void XMLCodeGen::writeKey( Key key
)
137 if ( keyOps
->isSigned
)
140 out
<< (unsigned long) key
.getVal();
143 void XMLCodeGen::writeTrans( Key lowKey
, Key highKey
, TransAp
*trans
)
145 /* First reduce the action. */
146 RedActionTable
*actionTable
= 0;
147 if ( trans
->actionTable
.length() > 0 )
148 actionTable
= actionTableMap
.find( trans
->actionTable
);
150 /* Write the transition. */
156 if ( trans
->toState
!= 0 )
157 out
<< " " << trans
->toState
->alg
.stateNum
;
161 if ( actionTable
!= 0 )
162 out
<< " " << actionTable
->id
;
168 void XMLCodeGen::writeTransList( StateAp
*state
)
170 TransListVect outList
;
172 /* If there is only are no ranges the task is simple. */
173 if ( state
->outList
.length() > 0 ) {
174 /* Loop each source range. */
175 for ( TransList::Iter trans
= state
->outList
; trans
.lte(); trans
++ ) {
176 /* Reduce the transition. If it reduced to anything then add it. */
177 appendTrans( outList
, trans
->lowKey
, trans
->highKey
, trans
);
181 out
<< " <trans_list length=\"" << outList
.length() << "\">\n";
182 for ( TransListVect::Iter tvi
= outList
; tvi
.lte(); tvi
++ )
183 writeTrans( tvi
->lowKey
, tvi
->highKey
, tvi
->value
);
184 out
<< " </trans_list>\n";
187 void XMLCodeGen::writeEofTrans( StateAp
*state
)
189 RedActionTable
*eofActions
= 0;
190 if ( state
->eofActionTable
.length() > 0 )
191 eofActions
= actionTableMap
.find( state
->eofActionTable
);
193 /* The <eof_t> is used when there is an eof target, otherwise the eof
194 * action goes into state actions. */
195 if ( state
->eofTarget
!= 0 ) {
196 out
<< " <eof_t>" << state
->eofTarget
->alg
.stateNum
;
198 if ( eofActions
!= 0 )
199 out
<< " " << eofActions
->id
;
203 out
<< "</eof_t>" << endl
;
207 void XMLCodeGen::writeText( InlineItem
*item
)
209 if ( item
->prev
== 0 || item
->prev
->type
!= InlineItem::Text
)
211 xmlEscapeHost( out
, item
->data
, strlen(item
->data
) );
212 if ( item
->next
== 0 || item
->next
->type
!= InlineItem::Text
)
216 void XMLCodeGen::writeGoto( InlineItem
*item
)
218 if ( pd
->generatingSectionSubset
)
219 out
<< "<goto>-1</goto>";
221 EntryMapEl
*targ
= fsm
->entryPoints
.find( item
->nameTarg
->id
);
222 out
<< "<goto>" << targ
->value
->alg
.stateNum
<< "</goto>";
226 void XMLCodeGen::writeCall( InlineItem
*item
)
228 if ( pd
->generatingSectionSubset
)
229 out
<< "<call>-1</call>";
231 EntryMapEl
*targ
= fsm
->entryPoints
.find( item
->nameTarg
->id
);
232 out
<< "<call>" << targ
->value
->alg
.stateNum
<< "</call>";
236 void XMLCodeGen::writeNext( InlineItem
*item
)
238 if ( pd
->generatingSectionSubset
)
239 out
<< "<next>-1</next>";
241 EntryMapEl
*targ
= fsm
->entryPoints
.find( item
->nameTarg
->id
);
242 out
<< "<next>" << targ
->value
->alg
.stateNum
<< "</next>";
246 void XMLCodeGen::writeGotoExpr( InlineItem
*item
)
248 out
<< "<goto_expr>";
249 writeInlineList( item
->children
);
250 out
<< "</goto_expr>";
253 void XMLCodeGen::writeCallExpr( InlineItem
*item
)
255 out
<< "<call_expr>";
256 writeInlineList( item
->children
);
257 out
<< "</call_expr>";
260 void XMLCodeGen::writeNextExpr( InlineItem
*item
)
262 out
<< "<next_expr>";
263 writeInlineList( item
->children
);
264 out
<< "</next_expr>";
267 void XMLCodeGen::writeEntry( InlineItem
*item
)
269 if ( pd
->generatingSectionSubset
)
270 out
<< "<entry>-1</entry>";
272 EntryMapEl
*targ
= fsm
->entryPoints
.find( item
->nameTarg
->id
);
273 out
<< "<entry>" << targ
->value
->alg
.stateNum
<< "</entry>";
277 void XMLCodeGen::writeActionExec( InlineItem
*item
)
280 writeInlineList( item
->children
);
284 void XMLCodeGen::writeLmOnLast( InlineItem
*item
)
286 out
<< "<set_tokend>1</set_tokend>";
288 if ( item
->longestMatchPart
->action
!= 0 ) {
289 out
<< "<sub_action>";
290 writeInlineList( item
->longestMatchPart
->action
->inlineList
);
291 out
<< "</sub_action>";
295 void XMLCodeGen::writeLmOnNext( InlineItem
*item
)
297 out
<< "<set_tokend>0</set_tokend>";
298 out
<< "<hold></hold>";
300 if ( item
->longestMatchPart
->action
!= 0 ) {
301 out
<< "<sub_action>";
302 writeInlineList( item
->longestMatchPart
->action
->inlineList
);
303 out
<< "</sub_action>";
307 void XMLCodeGen::writeLmOnLagBehind( InlineItem
*item
)
309 out
<< "<exec><get_tokend></get_tokend></exec>";
311 if ( item
->longestMatchPart
->action
!= 0 ) {
312 out
<< "<sub_action>";
313 writeInlineList( item
->longestMatchPart
->action
->inlineList
);
314 out
<< "</sub_action>";
318 void XMLCodeGen::writeLmSwitch( InlineItem
*item
)
320 LongestMatch
*longestMatch
= item
->longestMatch
;
321 out
<< "<lm_switch>\n";
323 /* We can't put the <exec> here because we may need to handle the error
324 * case and in that case p should not be changed. Instead use a default
325 * label in the switch to adjust p when user actions are not set. An id of
326 * -1 indicates the default. */
328 if ( longestMatch
->lmSwitchHandlesError
) {
329 /* If the switch handles error then we should have also forced the
331 assert( fsm
->errState
!= 0 );
333 out
<< " <sub_action id=\"0\">";
334 out
<< "<goto>" << fsm
->errState
->alg
.stateNum
<< "</goto>";
335 out
<< "</sub_action>\n";
338 bool needDefault
= false;
339 for ( LmPartList::Iter lmi
= *longestMatch
->longestMatchList
; lmi
.lte(); lmi
++ ) {
340 if ( lmi
->inLmSelect
) {
341 if ( lmi
->action
== 0 )
344 /* Open the action. Write it with the context that sets up _p
345 * when doing control flow changes from inside the machine. */
346 out
<< " <sub_action id=\"" << lmi
->longestMatchId
<< "\">";
347 out
<< "<exec><get_tokend></get_tokend></exec>";
348 writeInlineList( lmi
->action
->inlineList
);
349 out
<< "</sub_action>\n";
355 out
<< " <sub_action id=\"-1\"><exec><get_tokend>"
356 "</get_tokend></exec></sub_action>\n";
359 out
<< " </lm_switch>";
362 void XMLCodeGen::writeInlineList( InlineList
*inlineList
)
364 for ( InlineList::Iter item
= *inlineList
; item
.lte(); item
++ ) {
365 switch ( item
->type
) {
366 case InlineItem::Text
:
369 case InlineItem::Goto
:
372 case InlineItem::GotoExpr
:
373 writeGotoExpr( item
);
375 case InlineItem::Call
:
378 case InlineItem::CallExpr
:
379 writeCallExpr( item
);
381 case InlineItem::Next
:
384 case InlineItem::NextExpr
:
385 writeNextExpr( item
);
387 case InlineItem::Break
:
388 out
<< "<break></break>";
390 case InlineItem::Ret
:
391 out
<< "<ret></ret>";
393 case InlineItem::PChar
:
394 out
<< "<pchar></pchar>";
396 case InlineItem::Char
:
397 out
<< "<char></char>";
399 case InlineItem::Curs
:
400 out
<< "<curs></curs>";
402 case InlineItem::Targs
:
403 out
<< "<targs></targs>";
405 case InlineItem::Entry
:
409 case InlineItem::Hold
:
410 out
<< "<hold></hold>";
412 case InlineItem::Exec
:
413 writeActionExec( item
);
416 case InlineItem::LmSetActId
:
417 out
<< "<set_act>" <<
418 item
->longestMatchPart
->longestMatchId
<<
421 case InlineItem::LmSetTokEnd
:
422 out
<< "<set_tokend>1</set_tokend>";
425 case InlineItem::LmOnLast
:
426 writeLmOnLast( item
);
428 case InlineItem::LmOnNext
:
429 writeLmOnNext( item
);
431 case InlineItem::LmOnLagBehind
:
432 writeLmOnLagBehind( item
);
434 case InlineItem::LmSwitch
:
435 writeLmSwitch( item
);
438 case InlineItem::LmInitAct
:
439 out
<< "<init_act></init_act>";
441 case InlineItem::LmInitTokStart
:
442 out
<< "<init_tokstart></init_tokstart>";
444 case InlineItem::LmSetTokStart
:
445 out
<< "<set_tokstart></set_tokstart>";
451 BackendGen::BackendGen( char *fsmName
, ParseData
*pd
, FsmAp
*fsm
, CodeGenData
*cgd
)
453 GenBase(fsmName
, pd
, fsm
),
459 void BackendGen::makeText( GenInlineList
*outList
, InlineItem
*item
)
461 GenInlineItem
*inlineItem
= new GenInlineItem( InputLoc(), GenInlineItem::Text
);
462 inlineItem
->data
= item
->data
;
464 outList
->append( inlineItem
);
467 void BackendGen::makeTargetItem( GenInlineList
*outList
, NameInst
*nameTarg
,
468 GenInlineItem::Type type
)
471 if ( pd
->generatingSectionSubset
)
474 EntryMapEl
*targ
= fsm
->entryPoints
.find( nameTarg
->id
);
475 targetState
= targ
->value
->alg
.stateNum
;
479 GenInlineItem
*inlineItem
= new GenInlineItem( InputLoc(), type
);
480 inlineItem
->targId
= targetState
;
481 outList
->append( inlineItem
);
484 /* Make a sublist item with a given type. */
485 void BackendGen::makeSubList( GenInlineList
*outList
,
486 InlineList
*inlineList
, GenInlineItem::Type type
)
488 /* Fill the sub list. */
489 GenInlineList
*subList
= new GenInlineList
;
490 makeGenInlineList( subList
, inlineList
);
493 GenInlineItem
*inlineItem
= new GenInlineItem( InputLoc(), type
);
494 inlineItem
->children
= subList
;
495 outList
->append( inlineItem
);
498 void BackendGen::makeLmOnLast( GenInlineList
*outList
, InlineItem
*item
)
500 makeSetTokend( outList
, 1 );
502 if ( item
->longestMatchPart
->action
!= 0 ) {
503 makeSubList( outList
,
504 item
->longestMatchPart
->action
->inlineList
,
505 GenInlineItem::SubAction
);
509 void BackendGen::makeLmOnNext( GenInlineList
*outList
, InlineItem
*item
)
511 makeSetTokend( outList
, 0 );
512 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold
) );
514 if ( item
->longestMatchPart
->action
!= 0 ) {
515 makeSubList( outList
,
516 item
->longestMatchPart
->action
->inlineList
,
517 GenInlineItem::SubAction
);
521 void BackendGen::makeExecGetTokend( GenInlineList
*outList
)
523 /* Make the Exec item. */
524 GenInlineItem
*execItem
= new GenInlineItem( InputLoc(), GenInlineItem::Exec
);
525 execItem
->children
= new GenInlineList
;
527 /* Make the GetTokEnd */
528 GenInlineItem
*getTokend
= new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd
);
529 execItem
->children
->append( getTokend
);
531 outList
->append( execItem
);
534 void BackendGen::makeLmOnLagBehind( GenInlineList
*outList
, InlineItem
*item
)
536 /* Jump to the tokend. */
537 makeExecGetTokend( outList
);
539 if ( item
->longestMatchPart
->action
!= 0 ) {
540 makeSubList( outList
,
541 item
->longestMatchPart
->action
->inlineList
,
542 GenInlineItem::SubAction
);
546 void BackendGen::makeLmSwitch( GenInlineList
*outList
, InlineItem
*item
)
548 GenInlineItem
*lmSwitch
= new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch
);
549 GenInlineList
*lmList
= lmSwitch
->children
= new GenInlineList
;
550 LongestMatch
*longestMatch
= item
->longestMatch
;
552 /* We can't put the <exec> here because we may need to handle the error
553 * case and in that case p should not be changed. Instead use a default
554 * label in the switch to adjust p when user actions are not set. An id of
555 * -1 indicates the default. */
557 if ( longestMatch
->lmSwitchHandlesError
) {
558 /* If the switch handles error then we should have also forced the
560 assert( fsm
->errState
!= 0 );
562 GenInlineItem
*errCase
= new GenInlineItem( InputLoc(), GenInlineItem::SubAction
);
564 errCase
->children
= new GenInlineList
;
567 GenInlineItem
*gotoItem
= new GenInlineItem( InputLoc(), GenInlineItem::Goto
);
568 gotoItem
->targId
= fsm
->errState
->alg
.stateNum
;
569 errCase
->children
->append( gotoItem
);
571 lmList
->append( errCase
);
574 bool needDefault
= false;
575 for ( LmPartList::Iter lmi
= *longestMatch
->longestMatchList
; lmi
.lte(); lmi
++ ) {
576 if ( lmi
->inLmSelect
) {
577 if ( lmi
->action
== 0 )
580 /* Open the action. Write it with the context that sets up _p
581 * when doing control flow changes from inside the machine. */
582 GenInlineItem
*lmCase
= new GenInlineItem( InputLoc(),
583 GenInlineItem::SubAction
);
584 lmCase
->lmId
= lmi
->longestMatchId
;
585 lmCase
->children
= new GenInlineList
;
587 makeExecGetTokend( lmCase
->children
);
588 makeGenInlineList( lmCase
->children
, lmi
->action
->inlineList
);
590 lmList
->append( lmCase
);
596 GenInlineItem
*defCase
= new GenInlineItem( InputLoc(),
597 GenInlineItem::SubAction
);
599 defCase
->children
= new GenInlineList
;
601 makeExecGetTokend( defCase
->children
);
603 lmList
->append( defCase
);
606 outList
->append( lmSwitch
);
609 void BackendGen::makeSetTokend( GenInlineList
*outList
, long offset
)
611 GenInlineItem
*inlineItem
= new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd
);
612 inlineItem
->offset
= offset
;
613 outList
->append( inlineItem
);
616 void BackendGen::makeSetAct( GenInlineList
*outList
, long lmId
)
618 GenInlineItem
*inlineItem
= new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId
);
619 inlineItem
->lmId
= lmId
;
620 outList
->append( inlineItem
);
623 void BackendGen::makeGenInlineList( GenInlineList
*outList
, InlineList
*inList
)
625 for ( InlineList::Iter item
= *inList
; item
.lte(); item
++ ) {
626 switch ( item
->type
) {
627 case InlineItem::Text
:
628 makeText( outList
, item
);
630 case InlineItem::Goto
:
631 makeTargetItem( outList
, item
->nameTarg
, GenInlineItem::Goto
);
633 case InlineItem::GotoExpr
:
634 makeSubList( outList
, item
->children
, GenInlineItem::GotoExpr
);
636 case InlineItem::Call
:
637 makeTargetItem( outList
, item
->nameTarg
, GenInlineItem::Call
);
639 case InlineItem::CallExpr
:
640 makeSubList( outList
, item
->children
, GenInlineItem::CallExpr
);
642 case InlineItem::Next
:
643 makeTargetItem( outList
, item
->nameTarg
, GenInlineItem::Next
);
645 case InlineItem::NextExpr
:
646 makeSubList( outList
, item
->children
, GenInlineItem::NextExpr
);
648 case InlineItem::Break
:
649 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Break
) );
651 case InlineItem::Ret
:
652 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Ret
) );
654 case InlineItem::PChar
:
655 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::PChar
) );
657 case InlineItem::Char
:
658 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Char
) );
660 case InlineItem::Curs
:
661 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Curs
) );
663 case InlineItem::Targs
:
664 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Targs
) );
666 case InlineItem::Entry
:
667 makeTargetItem( outList
, item
->nameTarg
, GenInlineItem::Entry
);
670 case InlineItem::Hold
:
671 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold
) );
673 case InlineItem::Exec
:
674 makeSubList( outList
, item
->children
, GenInlineItem::Exec
);
677 case InlineItem::LmSetActId
:
678 makeSetAct( outList
, item
->longestMatchPart
->longestMatchId
);
680 case InlineItem::LmSetTokEnd
:
681 makeSetTokend( outList
, 1 );
684 case InlineItem::LmOnLast
:
685 makeLmOnLast( outList
, item
);
687 case InlineItem::LmOnNext
:
688 makeLmOnNext( outList
, item
);
690 case InlineItem::LmOnLagBehind
:
691 makeLmOnLagBehind( outList
, item
);
693 case InlineItem::LmSwitch
:
694 makeLmSwitch( outList
, item
);
697 case InlineItem::LmInitAct
:
698 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct
) );
700 case InlineItem::LmInitTokStart
:
701 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart
) );
703 case InlineItem::LmSetTokStart
:
704 outList
->append( new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart
) );
705 cgd
->hasLongestMatch
= true;
712 void XMLCodeGen::writeAction( Action
*action
)
714 out
<< " <action id=\"" << action
->actionId
<< "\"";
715 if ( action
->name
!= 0 )
716 out
<< " name=\"" << action
->name
<< "\"";
717 out
<< " line=\"" << action
->loc
.line
<< "\" col=\"" << action
->loc
.col
<< "\">";
718 writeInlineList( action
->inlineList
);
719 out
<< "</action>\n";
722 void xmlEscapeHost( std::ostream
&out
, char *data
, long len
)
724 char *end
= data
+ len
;
725 while ( data
!= end
) {
727 case '<': out
<< "<"; break;
728 case '>': out
<< ">"; break;
729 case '&': out
<< "&"; break;
730 default: out
<< *data
; break;
736 void XMLCodeGen::writeStateActions( StateAp
*state
)
738 RedActionTable
*toStateActions
= 0;
739 if ( state
->toStateActionTable
.length() > 0 )
740 toStateActions
= actionTableMap
.find( state
->toStateActionTable
);
742 RedActionTable
*fromStateActions
= 0;
743 if ( state
->fromStateActionTable
.length() > 0 )
744 fromStateActions
= actionTableMap
.find( state
->fromStateActionTable
);
746 /* EOF actions go out here only if the state has no eof target. If it has
747 * an eof target then an eof transition will be used instead. */
748 RedActionTable
*eofActions
= 0;
749 if ( state
->eofTarget
== 0 && state
->eofActionTable
.length() > 0 )
750 eofActions
= actionTableMap
.find( state
->eofActionTable
);
752 if ( toStateActions
!= 0 || fromStateActions
!= 0 || eofActions
!= 0 ) {
753 out
<< " <state_actions>";
754 if ( toStateActions
!= 0 )
755 out
<< toStateActions
->id
;
759 if ( fromStateActions
!= 0 )
760 out
<< " " << fromStateActions
->id
;
764 if ( eofActions
!= 0 )
765 out
<< " " << eofActions
->id
;
769 out
<< "</state_actions>\n";
773 void XMLCodeGen::writeStateConditions( StateAp
*state
)
775 if ( state
->stateCondList
.length() > 0 ) {
776 out
<< " <cond_list length=\"" << state
->stateCondList
.length() << "\">\n";
777 for ( StateCondList::Iter scdi
= state
->stateCondList
; scdi
.lte(); scdi
++ ) {
779 writeKey( scdi
->lowKey
);
781 writeKey( scdi
->highKey
);
783 out
<< scdi
->condSpace
->condSpaceId
;
786 out
<< " </cond_list>\n";
790 void XMLCodeGen::writeStateList()
792 /* Write the list of states. */
793 out
<< " <state_list length=\"" << fsm
->stateList
.length() << "\">\n";
794 for ( StateList::Iter st
= fsm
->stateList
; st
.lte(); st
++ ) {
795 out
<< " <state id=\"" << st
->alg
.stateNum
<< "\"";
796 if ( st
->isFinState() )
797 out
<< " final=\"t\"";
800 writeStateActions( st
);
802 writeStateConditions( st
);
803 writeTransList( st
);
805 out
<< " </state>\n";
810 out
<< " </state_list>\n";
813 bool XMLCodeGen::writeNameInst( NameInst
*nameInst
)
815 bool written
= false;
816 if ( nameInst
->parent
!= 0 )
817 written
= writeNameInst( nameInst
->parent
);
819 if ( nameInst
->name
!= 0 ) {
822 out
<< nameInst
->name
;
829 void XMLCodeGen::writeEntryPoints()
831 /* List of entry points other than start state. */
832 if ( fsm
->entryPoints
.length() > 0 || pd
->lmRequiresErrorState
) {
833 out
<< " <entry_points";
834 if ( pd
->lmRequiresErrorState
)
835 out
<< " error=\"t\"";
837 for ( EntryMap::Iter en
= fsm
->entryPoints
; en
.lte(); en
++ ) {
838 /* Get the name instantiation from nameIndex. */
839 NameInst
*nameInst
= pd
->nameIndex
[en
->key
];
840 StateAp
*state
= en
->value
;
841 out
<< " <entry name=\"";
842 writeNameInst( nameInst
);
843 out
<< "\">" << state
->alg
.stateNum
<< "</entry>\n";
845 out
<< " </entry_points>\n";
849 void XMLCodeGen::writeMachine()
851 /* Open the machine. */
852 out
<< " <machine>\n";
855 reduceActionTables();
858 writeActionTableList();
862 out
<< " <start_state>" << fsm
->startState
->alg
.stateNum
<<
866 if ( fsm
->errState
!= 0 ) {
867 out
<< " <error_state>" << fsm
->errState
->alg
.stateNum
<<
874 out
<< " </machine>\n";
878 void XMLCodeGen::writeConditions()
880 if ( condData
->condSpaceMap
.length() > 0 ) {
881 long nextCondSpaceId
= 0;
882 for ( CondSpaceMap::Iter cs
= condData
->condSpaceMap
; cs
.lte(); cs
++ )
883 cs
->condSpaceId
= nextCondSpaceId
++;
885 out
<< " <cond_space_list length=\"" << condData
->condSpaceMap
.length() << "\">\n";
886 for ( CondSpaceMap::Iter cs
= condData
->condSpaceMap
; cs
.lte(); cs
++ ) {
887 out
<< " <cond_space id=\"" << cs
->condSpaceId
<<
888 "\" length=\"" << cs
->condSet
.length() << "\">";
889 writeKey( cs
->baseKey
);
890 for ( CondSet::Iter csi
= cs
->condSet
; csi
.lte(); csi
++ )
891 out
<< " " << (*csi
)->actionId
;
892 out
<< "</cond_space>\n";
894 out
<< " </cond_space_list>\n";
898 void XMLCodeGen::writeExports()
900 if ( pd
->exportList
.length() > 0 ) {
901 out
<< " <exports>\n";
902 for ( ExportList::Iter exp
= pd
->exportList
; exp
.lte(); exp
++ ) {
903 out
<< " <ex name=\"" << exp
->name
<< "\">";
904 writeKey( exp
->key
);
907 out
<< " </exports>\n";
911 void XMLCodeGen::writeXML()
913 /* Open the definition. */
914 out
<< "<ragel_def name=\"" << fsmName
<< "\">\n";
917 out
<< " <alphtype>" << keyOps
->alphType
->internalName
<< "</alphtype>\n";
919 /* Getkey expression. */
920 if ( pd
->getKeyExpr
!= 0 ) {
922 writeInlineList( pd
->getKeyExpr
);
923 out
<< "</getkey>\n";
926 /* Access expression. */
927 if ( pd
->accessExpr
!= 0 ) {
929 writeInlineList( pd
->accessExpr
);
930 out
<< "</access>\n";
933 /* PrePush expression. */
934 if ( pd
->prePushExpr
!= 0 ) {
936 writeInlineList( pd
->prePushExpr
);
937 out
<< "</prepush>\n";
940 /* PostPop expression. */
941 if ( pd
->postPopExpr
!= 0 ) {
943 writeInlineList( pd
->postPopExpr
);
944 out
<< "</postpop>\n";
948 * Variable expressions.
951 if ( pd
->pExpr
!= 0 ) {
953 writeInlineList( pd
->pExpr
);
954 out
<< "</p_expr>\n";
957 if ( pd
->peExpr
!= 0 ) {
959 writeInlineList( pd
->peExpr
);
960 out
<< "</pe_expr>\n";
963 if ( pd
->eofExpr
!= 0 ) {
964 out
<< " <eof_expr>";
965 writeInlineList( pd
->eofExpr
);
966 out
<< "</eof_expr>\n";
969 if ( pd
->csExpr
!= 0 ) {
971 writeInlineList( pd
->csExpr
);
972 out
<< "</cs_expr>\n";
975 if ( pd
->topExpr
!= 0 ) {
976 out
<< " <top_expr>";
977 writeInlineList( pd
->topExpr
);
978 out
<< "</top_expr>\n";
981 if ( pd
->stackExpr
!= 0 ) {
982 out
<< " <stack_expr>";
983 writeInlineList( pd
->stackExpr
);
984 out
<< "</stack_expr>\n";
987 if ( pd
->actExpr
!= 0 ) {
988 out
<< " <act_expr>";
989 writeInlineList( pd
->actExpr
);
990 out
<< "</act_expr>\n";
993 if ( pd
->tokstartExpr
!= 0 ) {
994 out
<< " <tokstart_expr>";
995 writeInlineList( pd
->tokstartExpr
);
996 out
<< "</tokstart_expr>\n";
999 if ( pd
->tokendExpr
!= 0 ) {
1000 out
<< " <tokend_expr>";
1001 writeInlineList( pd
->tokendExpr
);
1002 out
<< "</tokend_expr>\n";
1005 if ( pd
->dataExpr
!= 0 ) {
1006 out
<< " <data_expr>";
1007 writeInlineList( pd
->dataExpr
);
1008 out
<< "</data_expr>\n";
1019 void BackendGen::makeExports()
1021 for ( ExportList::Iter exp
= pd
->exportList
; exp
.lte(); exp
++ )
1022 cgd
->exportList
.append( new Export( exp
->name
, exp
->key
) );
1025 void BackendGen::makeAction( Action
*action
)
1027 GenInlineList
*genList
= new GenInlineList
;
1028 makeGenInlineList( genList
, action
->inlineList
);
1030 cgd
->newAction( curAction
++, action
->name
, action
->loc
, genList
);
1034 void BackendGen::makeActionList()
1036 /* Determine which actions to write. */
1037 int nextActionId
= 0;
1038 for ( ActionList::Iter act
= pd
->actionList
; act
.lte(); act
++ ) {
1039 if ( act
->numRefs() > 0 || act
->numCondRefs
> 0 )
1040 act
->actionId
= nextActionId
++;
1043 /* Write the list. */
1044 cgd
->initActionList( nextActionId
);
1047 for ( ActionList::Iter act
= pd
->actionList
; act
.lte(); act
++ ) {
1048 if ( act
->actionId
>= 0 )
1053 void BackendGen::makeActionTableList()
1055 /* Must first order the action tables based on their id. */
1056 int numTables
= nextActionTableId
;
1057 RedActionTable
**tables
= new RedActionTable
*[numTables
];
1058 for ( ActionTableMap::Iter at
= actionTableMap
; at
.lte(); at
++ )
1059 tables
[at
->id
] = at
;
1061 cgd
->initActionTableList( numTables
);
1064 for ( int t
= 0; t
< numTables
; t
++ ) {
1065 long length
= tables
[t
]->key
.length();
1067 /* Collect the action table. */
1068 RedAction
*redAct
= cgd
->allActionTables
+ curActionTable
;
1069 redAct
->actListId
= curActionTable
;
1070 redAct
->key
.setAsNew( length
);
1072 for ( ActionTable::Iter atel
= tables
[t
]->key
; atel
.lte(); atel
++ ) {
1073 redAct
->key
[atel
.pos()].key
= 0;
1074 redAct
->key
[atel
.pos()].value
= cgd
->allActions
+
1075 atel
->value
->actionId
;
1078 /* Insert into the action table map. */
1079 cgd
->redFsm
->actionMap
.insert( redAct
);
1081 curActionTable
+= 1;
1087 void BackendGen::makeConditions()
1089 if ( condData
->condSpaceMap
.length() > 0 ) {
1090 long nextCondSpaceId
= 0;
1091 for ( CondSpaceMap::Iter cs
= condData
->condSpaceMap
; cs
.lte(); cs
++ )
1092 cs
->condSpaceId
= nextCondSpaceId
++;
1094 long listLength
= condData
->condSpaceMap
.length();
1095 cgd
->initCondSpaceList( listLength
);
1098 for ( CondSpaceMap::Iter cs
= condData
->condSpaceMap
; cs
.lte(); cs
++ ) {
1099 long id
= cs
->condSpaceId
;
1100 cgd
->newCondSpace( curCondSpace
, id
, cs
->baseKey
);
1101 for ( CondSet::Iter csi
= cs
->condSet
; csi
.lte(); csi
++ )
1102 cgd
->condSpaceItem( curCondSpace
, (*csi
)->actionId
);
1108 bool BackendGen::makeNameInst( std::string
&res
, NameInst
*nameInst
)
1110 bool written
= false;
1111 if ( nameInst
->parent
!= 0 )
1112 written
= makeNameInst( res
, nameInst
->parent
);
1114 if ( nameInst
->name
!= 0 ) {
1117 res
+= nameInst
->name
;
1124 void BackendGen::makeEntryPoints()
1126 /* List of entry points other than start state. */
1127 if ( fsm
->entryPoints
.length() > 0 || pd
->lmRequiresErrorState
) {
1128 if ( pd
->lmRequiresErrorState
)
1129 cgd
->setForcedErrorState();
1131 for ( EntryMap::Iter en
= fsm
->entryPoints
; en
.lte(); en
++ ) {
1132 /* Get the name instantiation from nameIndex. */
1133 NameInst
*nameInst
= pd
->nameIndex
[en
->key
];
1135 makeNameInst( name
, nameInst
);
1136 StateAp
*state
= en
->value
;
1137 cgd
->addEntryPoint( strdup(name
.c_str()), state
->alg
.stateNum
);
1142 void BackendGen::makeStateActions( StateAp
*state
)
1144 RedActionTable
*toStateActions
= 0;
1145 if ( state
->toStateActionTable
.length() > 0 )
1146 toStateActions
= actionTableMap
.find( state
->toStateActionTable
);
1148 RedActionTable
*fromStateActions
= 0;
1149 if ( state
->fromStateActionTable
.length() > 0 )
1150 fromStateActions
= actionTableMap
.find( state
->fromStateActionTable
);
1152 /* EOF actions go out here only if the state has no eof target. If it has
1153 * an eof target then an eof transition will be used instead. */
1154 RedActionTable
*eofActions
= 0;
1155 if ( state
->eofTarget
== 0 && state
->eofActionTable
.length() > 0 )
1156 eofActions
= actionTableMap
.find( state
->eofActionTable
);
1158 if ( toStateActions
!= 0 || fromStateActions
!= 0 || eofActions
!= 0 ) {
1160 if ( toStateActions
!= 0 )
1161 to
= toStateActions
->id
;
1164 if ( fromStateActions
!= 0 )
1165 from
= fromStateActions
->id
;
1168 if ( eofActions
!= 0 )
1169 eof
= eofActions
->id
;
1171 cgd
->setStateActions( curState
, to
, from
, eof
);
1175 void BackendGen::makeEofTrans( StateAp
*state
)
1177 RedActionTable
*eofActions
= 0;
1178 if ( state
->eofActionTable
.length() > 0 )
1179 eofActions
= actionTableMap
.find( state
->eofActionTable
);
1181 /* The EOF trans is used when there is an eof target, otherwise the eof
1182 * action goes into state actions. */
1183 if ( state
->eofTarget
!= 0 ) {
1184 long targ
= state
->eofTarget
->alg
.stateNum
;
1186 if ( eofActions
!= 0 )
1187 action
= eofActions
->id
;
1189 cgd
->setEofTrans( curState
, targ
, action
);
1193 void BackendGen::makeStateConditions( StateAp
*state
)
1195 if ( state
->stateCondList
.length() > 0 ) {
1196 long length
= state
->stateCondList
.length();
1197 cgd
->initStateCondList( curState
, length
);
1200 for ( StateCondList::Iter scdi
= state
->stateCondList
; scdi
.lte(); scdi
++ ) {
1201 cgd
->addStateCond( curState
, scdi
->lowKey
, scdi
->highKey
,
1202 scdi
->condSpace
->condSpaceId
);
1207 void BackendGen::makeTrans( Key lowKey
, Key highKey
, TransAp
*trans
)
1209 /* First reduce the action. */
1210 RedActionTable
*actionTable
= 0;
1211 if ( trans
->actionTable
.length() > 0 )
1212 actionTable
= actionTableMap
.find( trans
->actionTable
);
1215 if ( trans
->toState
!= 0 )
1216 targ
= trans
->toState
->alg
.stateNum
;
1219 if ( actionTable
!= 0 )
1220 action
= actionTable
->id
;
1222 cgd
->newTrans( curState
, curTrans
++, lowKey
, highKey
, targ
, action
);
1225 void BackendGen::makeTransList( StateAp
*state
)
1227 TransListVect outList
;
1229 /* If there is only are no ranges the task is simple. */
1230 if ( state
->outList
.length() > 0 ) {
1231 /* Loop each source range. */
1232 for ( TransList::Iter trans
= state
->outList
; trans
.lte(); trans
++ ) {
1233 /* Reduce the transition. If it reduced to anything then add it. */
1234 appendTrans( outList
, trans
->lowKey
, trans
->highKey
, trans
);
1238 cgd
->initTransList( curState
, outList
.length() );
1241 for ( TransListVect::Iter tvi
= outList
; tvi
.lte(); tvi
++ )
1242 makeTrans( tvi
->lowKey
, tvi
->highKey
, tvi
->value
);
1244 cgd
->finishTransList( curState
);
1248 void BackendGen::makeStateList()
1250 /* Write the list of states. */
1251 long length
= fsm
->stateList
.length();
1252 cgd
->initStateList( length
);
1254 for ( StateList::Iter st
= fsm
->stateList
; st
.lte(); st
++ ) {
1255 makeStateActions( st
);
1257 makeStateConditions( st
);
1258 makeTransList( st
);
1260 long id
= st
->alg
.stateNum
;
1261 cgd
->setId( curState
, id
);
1263 if ( st
->isFinState() )
1264 cgd
->setFinal( curState
);
1271 void BackendGen::makeMachine()
1273 cgd
->createMachine();
1275 /* Action tables. */
1276 reduceActionTables();
1279 makeActionTableList();
1283 cgd
->setStartState( fsm
->startState
->alg
.stateNum
);
1286 if ( fsm
->errState
!= 0 )
1287 cgd
->setErrorState( fsm
->errState
->alg
.stateNum
);
1292 cgd
->closeMachine();
1295 void BackendGen::close_ragel_def()
1297 /* Do this before distributing transitions out to singles and defaults
1298 * makes life easier. */
1299 cgd
->redFsm
->maxKey
= cgd
->findMaxKey();
1301 cgd
->redFsm
->assignActionLocs();
1303 /* Find the first final state (The final state with the lowest id). */
1304 cgd
->redFsm
->findFirstFinState();
1306 /* Call the user's callback. */
1307 cgd
->finishRagelDef();
1311 void BackendGen::makeBackend()
1313 /* Alphabet type. */
1314 cgd
->setAlphType( keyOps
->alphType
->internalName
);
1316 /* Getkey expression. */
1317 if ( pd
->getKeyExpr
!= 0 ) {
1318 cgd
->getKeyExpr
= new GenInlineList
;
1319 makeGenInlineList( cgd
->getKeyExpr
, pd
->getKeyExpr
);
1322 /* Access expression. */
1323 if ( pd
->accessExpr
!= 0 ) {
1324 cgd
->accessExpr
= new GenInlineList
;
1325 makeGenInlineList( cgd
->accessExpr
, pd
->accessExpr
);
1328 /* PrePush expression. */
1329 if ( pd
->prePushExpr
!= 0 ) {
1330 cgd
->prePushExpr
= new GenInlineList
;
1331 makeGenInlineList( cgd
->prePushExpr
, pd
->prePushExpr
);
1334 /* PostPop expression. */
1335 if ( pd
->postPopExpr
!= 0 ) {
1336 cgd
->postPopExpr
= new GenInlineList
;
1337 makeGenInlineList( cgd
->postPopExpr
, pd
->postPopExpr
);
1341 * Variable expressions.
1344 if ( pd
->pExpr
!= 0 ) {
1345 cgd
->pExpr
= new GenInlineList
;
1346 makeGenInlineList( cgd
->pExpr
, pd
->pExpr
);
1349 if ( pd
->peExpr
!= 0 ) {
1350 cgd
->peExpr
= new GenInlineList
;
1351 makeGenInlineList( cgd
->peExpr
, pd
->peExpr
);
1354 if ( pd
->eofExpr
!= 0 ) {
1355 cgd
->eofExpr
= new GenInlineList
;
1356 makeGenInlineList( cgd
->eofExpr
, pd
->eofExpr
);
1359 if ( pd
->csExpr
!= 0 ) {
1360 cgd
->csExpr
= new GenInlineList
;
1361 makeGenInlineList( cgd
->csExpr
, pd
->csExpr
);
1364 if ( pd
->topExpr
!= 0 ) {
1365 cgd
->topExpr
= new GenInlineList
;
1366 makeGenInlineList( cgd
->topExpr
, pd
->topExpr
);
1369 if ( pd
->stackExpr
!= 0 ) {
1370 cgd
->stackExpr
= new GenInlineList
;
1371 makeGenInlineList( cgd
->stackExpr
, pd
->stackExpr
);
1374 if ( pd
->actExpr
!= 0 ) {
1375 cgd
->actExpr
= new GenInlineList
;
1376 makeGenInlineList( cgd
->actExpr
, pd
->actExpr
);
1379 if ( pd
->tokstartExpr
!= 0 ) {
1380 cgd
->tokstartExpr
= new GenInlineList
;
1381 makeGenInlineList( cgd
->tokstartExpr
, pd
->tokstartExpr
);
1384 if ( pd
->tokendExpr
!= 0 ) {
1385 cgd
->tokendExpr
= new GenInlineList
;
1386 makeGenInlineList( cgd
->tokendExpr
, pd
->tokendExpr
);
1389 if ( pd
->dataExpr
!= 0 ) {
1390 cgd
->dataExpr
= new GenInlineList
;
1391 makeGenInlineList( cgd
->dataExpr
, pd
->dataExpr
);
1400 void InputData::writeLanguage( std::ostream
&out
)
1403 switch ( hostLang
->lang
) {
1404 case HostLang::C
: out
<< "C"; break;
1405 case HostLang::D
: out
<< "D"; break;
1406 case HostLang::D2
: out
<< "D2"; break;
1407 case HostLang::Go
: out
<< "Go"; break;
1408 case HostLang::Java
: out
<< "Java"; break;
1409 case HostLang::Ruby
: out
<< "Ruby"; break;
1410 case HostLang::CSharp
: out
<< "C#"; break;
1411 case HostLang::OCaml
: out
<< "OCaml"; break;
1416 void InputData::writeXML( std::ostream
&out
)
1418 out
<< "<ragel version=\"" VERSION
"\" filename=\"" << inputFileName
<< "\"";
1419 writeLanguage( out
);
1422 for ( ParserDict::Iter parser
= parserDict
; parser
.lte(); parser
++ ) {
1423 ParseData
*pd
= parser
->value
->pd
;
1424 if ( pd
->instanceList
.length() > 0 )
1425 pd
->generateXML( *outStream
);
1428 out
<< "</ragel>\n";