2 * Copyright 2006-2007 Adrian Thurston <thurston@cs.queensu.ca>
3 * 2007 Colin Fleming <colin.fleming@caverock.com>
6 /* This file is part of Ragel.
8 * Ragel is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * Ragel is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Ragel; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "rlgen-java.h"
24 #include "javacodegen.h"
30 /* Integer array line length. */
33 /* Static array initialization item count
34 * (should be multiple of IALL). */
45 using std::ostringstream
;
49 void lineDirective( ostream
&out
, char *fileName
, int line
)
51 /* Write the preprocessor line info for to the input file. */
52 out
<< "// line " << line
<< " \"";
53 for ( char *pc
= fileName
; *pc
!= 0; pc
++ ) {
62 void genLineDirective( ostream
&out
)
64 std::streambuf
*sbuf
= out
.rdbuf();
65 output_filter
*filter
= static_cast<output_filter
*>(sbuf
);
66 lineDirective( out
, filter
->fileName
, filter
->line
+ 1 );
69 void JavaTabCodeGen::GOTO( ostream
&ret
, int gotoDest
, bool inFinish
)
71 ret
<< "{" << CS() << " = " << gotoDest
<< "; _goto_targ = " << _again
<< "; " <<
72 CTRL_FLOW() << "continue _goto;}";
75 void JavaTabCodeGen::GOTO_EXPR( ostream
&ret
, InlineItem
*ilItem
, bool inFinish
)
77 ret
<< "{" << CS() << " = (";
78 INLINE_LIST( ret
, ilItem
->children
, 0, inFinish
);
79 ret
<< "); _goto_targ = " << _again
<< "; " << CTRL_FLOW() << "continue _goto;}";
82 void JavaTabCodeGen::CALL( ostream
&ret
, int callDest
, int targState
, bool inFinish
)
84 if ( prePushExpr
!= 0 ) {
86 INLINE_LIST( ret
, prePushExpr
, 0, false );
89 ret
<< "{" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = " <<
90 callDest
<< "; _goto_targ = " << _again
<< "; " << CTRL_FLOW() << "continue _goto;}";
92 if ( prePushExpr
!= 0 )
96 void JavaTabCodeGen::CALL_EXPR( ostream
&ret
, InlineItem
*ilItem
, int targState
, bool inFinish
)
98 if ( prePushExpr
!= 0 ) {
100 INLINE_LIST( ret
, prePushExpr
, 0, false );
103 ret
<< "{" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = (";
104 INLINE_LIST( ret
, ilItem
->children
, targState
, inFinish
);
105 ret
<< "); _goto_targ = " << _again
<< "; " << CTRL_FLOW() << "continue _goto;}";
107 if ( prePushExpr
!= 0 )
111 void JavaTabCodeGen::RET( ostream
&ret
, bool inFinish
)
113 ret
<< "{" << CS() << " = " << STACK() << "[--" << TOP() << "];";
115 if ( postPopExpr
!= 0 ) {
117 INLINE_LIST( ret
, postPopExpr
, 0, false );
121 ret
<< "_goto_targ = " << _again
<< "; " << CTRL_FLOW() << "continue _goto;}";
124 void JavaTabCodeGen::BREAK( ostream
&ret
, int targState
)
126 ret
<< "{ " << P() << " += 1; _goto_targ = " << _out
<< "; " <<
127 CTRL_FLOW() << " continue _goto;}";
130 void JavaTabCodeGen::NEXT( ostream
&ret
, int nextDest
, bool inFinish
)
132 ret
<< CS() << " = " << nextDest
<< ";";
135 void JavaTabCodeGen::NEXT_EXPR( ostream
&ret
, InlineItem
*ilItem
, bool inFinish
)
137 ret
<< CS() << " = (";
138 INLINE_LIST( ret
, ilItem
->children
, 0, inFinish
);
142 void JavaTabCodeGen::EXEC( ostream
&ret
, InlineItem
*item
, int targState
, int inFinish
)
144 /* The parser gives fexec two children. The double brackets are for D
145 * code. If the inline list is a single word it will get interpreted as a
146 * C-style cast by the D compiler. */
147 ret
<< "{" << P() << " = ((";
148 INLINE_LIST( ret
, item
->children
, targState
, inFinish
);
152 /* Write out an inline tree structure. Walks the list and possibly calls out
153 * to virtual functions than handle language specific items in the tree. */
154 void JavaTabCodeGen::INLINE_LIST( ostream
&ret
, InlineList
*inlineList
,
155 int targState
, bool inFinish
)
157 for ( InlineList::Iter item
= *inlineList
; item
.lte(); item
++ ) {
158 switch ( item
->type
) {
159 case InlineItem::Text
:
162 case InlineItem::Goto
:
163 GOTO( ret
, item
->targState
->id
, inFinish
);
165 case InlineItem::Call
:
166 CALL( ret
, item
->targState
->id
, targState
, inFinish
);
168 case InlineItem::Next
:
169 NEXT( ret
, item
->targState
->id
, inFinish
);
171 case InlineItem::Ret
:
172 RET( ret
, inFinish
);
174 case InlineItem::PChar
:
177 case InlineItem::Char
:
180 case InlineItem::Hold
:
183 case InlineItem::Exec
:
184 EXEC( ret
, item
, targState
, inFinish
);
186 case InlineItem::Curs
:
189 case InlineItem::Targs
:
190 ret
<< "(" << CS() << ")";
192 case InlineItem::Entry
:
193 ret
<< item
->targState
->id
;
195 case InlineItem::GotoExpr
:
196 GOTO_EXPR( ret
, item
, inFinish
);
198 case InlineItem::CallExpr
:
199 CALL_EXPR( ret
, item
, targState
, inFinish
);
201 case InlineItem::NextExpr
:
202 NEXT_EXPR( ret
, item
, inFinish
);
204 case InlineItem::LmSwitch
:
205 LM_SWITCH( ret
, item
, targState
, inFinish
);
207 case InlineItem::LmSetActId
:
208 SET_ACT( ret
, item
);
210 case InlineItem::LmSetTokEnd
:
211 SET_TOKEND( ret
, item
);
213 case InlineItem::LmGetTokEnd
:
214 GET_TOKEND( ret
, item
);
216 case InlineItem::LmInitTokStart
:
217 INIT_TOKSTART( ret
, item
);
219 case InlineItem::LmInitAct
:
220 INIT_ACT( ret
, item
);
222 case InlineItem::LmSetTokStart
:
223 SET_TOKSTART( ret
, item
);
225 case InlineItem::SubAction
:
226 SUB_ACTION( ret
, item
, targState
, inFinish
);
228 case InlineItem::Break
:
229 BREAK( ret
, targState
);
235 string
JavaTabCodeGen::DATA_PREFIX()
238 return FSM_NAME() + "_";
242 /* Emit the alphabet data type. */
243 string
JavaTabCodeGen::ALPH_TYPE()
245 string ret
= keyOps
->alphType
->data1
;
246 if ( keyOps
->alphType
->data2
!= 0 ) {
248 ret
+= + keyOps
->alphType
->data2
;
253 /* Emit the alphabet data type. */
254 string
JavaTabCodeGen::WIDE_ALPH_TYPE()
257 if ( redFsm
->maxKey
<= keyOps
->maxKey
)
260 long long maxKeyVal
= redFsm
->maxKey
.getLongLong();
261 HostType
*wideType
= keyOps
->typeSubsumes( keyOps
->isSigned
, maxKeyVal
);
262 assert( wideType
!= 0 );
264 ret
= wideType
->data1
;
265 if ( wideType
->data2
!= 0 ) {
267 ret
+= wideType
->data2
;
275 void JavaTabCodeGen::COND_TRANSLATE()
278 " _widec = " << GET_KEY() << ";\n"
279 " _keys = " << CO() << "[" << CS() << "]*2\n;"
280 " _klen = " << CL() << "[" << CS() << "];\n"
281 " if ( _klen > 0 ) {\n"
282 " int _lower = _keys\n;"
284 " int _upper = _keys + (_klen<<1) - 2;\n"
286 " if ( _upper < _lower )\n"
289 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
290 " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n"
291 " _upper = _mid - 2;\n"
292 " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n"
293 " _lower = _mid + 2;\n"
295 " switch ( " << C() << "[" << CO() << "[" << CS() << "]"
296 " + ((_mid - _keys)>>1)] ) {\n"
299 for ( CondSpaceList::Iter csi
= condSpaceList
; csi
.lte(); csi
++ ) {
300 CondSpace
*condSpace
= csi
;
301 out
<< " case " << condSpace
->condSpaceId
<< ": {\n";
302 out
<< TABS(2) << "_widec = " << KEY(condSpace
->baseKey
) <<
303 " + (" << GET_KEY() << " - " << KEY(keyOps
->minKey
) << ");\n";
305 for ( CondSet::Iter csi
= condSpace
->condSet
; csi
.lte(); csi
++ ) {
306 out
<< TABS(2) << "if ( ";
307 CONDITION( out
, *csi
);
308 Size condValOffset
= ((1 << csi
.pos()) * keyOps
->alphSize());
309 out
<< " ) _widec += " << condValOffset
<< ";\n";
327 void JavaTabCodeGen::LOCATE_TRANS()
331 " _keys = " << KO() << "[" << CS() << "]" << ";\n"
332 " _trans = " << IO() << "[" << CS() << "];\n"
333 " _klen = " << SL() << "[" << CS() << "];\n"
334 " if ( _klen > 0 ) {\n"
335 " int _lower = _keys;\n"
337 " int _upper = _keys + _klen - 1;\n"
339 " if ( _upper < _lower )\n"
342 " _mid = _lower + ((_upper-_lower) >> 1);\n"
343 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
344 " _upper = _mid - 1;\n"
345 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n"
346 " _lower = _mid + 1;\n"
348 " _trans += (_mid - _keys);\n"
353 " _trans += _klen;\n"
356 " _klen = " << RL() << "[" << CS() << "];\n"
357 " if ( _klen > 0 ) {\n"
358 " int _lower = _keys;\n"
360 " int _upper = _keys + (_klen<<1) - 2;\n"
362 " if ( _upper < _lower )\n"
365 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
366 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
367 " _upper = _mid - 2;\n"
368 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n"
369 " _lower = _mid + 2;\n"
371 " _trans += ((_mid - _keys)>>1);\n"
375 " _trans += _klen;\n"
377 " } while (false);\n"
381 /* Determine if we should use indicies or not. */
382 void JavaTabCodeGen::calcIndexSize()
384 int sizeWithInds
= 0, sizeWithoutInds
= 0;
386 /* Calculate cost of using with indicies. */
387 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
388 int totalIndex
= st
->outSingle
.length() + st
->outRange
.length() +
389 (st
->defTrans
== 0 ? 0 : 1);
390 sizeWithInds
+= arrayTypeSize(redFsm
->maxIndex
) * totalIndex
;
392 sizeWithInds
+= arrayTypeSize(redFsm
->maxState
) * redFsm
->transSet
.length();
393 if ( redFsm
->anyActions() )
394 sizeWithInds
+= arrayTypeSize(redFsm
->maxActionLoc
) * redFsm
->transSet
.length();
396 /* Calculate the cost of not using indicies. */
397 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
398 int totalIndex
= st
->outSingle
.length() + st
->outRange
.length() +
399 (st
->defTrans
== 0 ? 0 : 1);
400 sizeWithoutInds
+= arrayTypeSize(redFsm
->maxState
) * totalIndex
;
401 if ( redFsm
->anyActions() )
402 sizeWithoutInds
+= arrayTypeSize(redFsm
->maxActionLoc
) * totalIndex
;
405 /* If using indicies reduces the size, use them. */
406 useIndicies
= sizeWithInds
< sizeWithoutInds
;
409 int JavaTabCodeGen::TO_STATE_ACTION( RedStateAp
*state
)
412 if ( state
->toStateAction
!= 0 )
413 act
= state
->toStateAction
->location
+1;
417 int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp
*state
)
420 if ( state
->fromStateAction
!= 0 )
421 act
= state
->fromStateAction
->location
+1;
425 int JavaTabCodeGen::EOF_ACTION( RedStateAp
*state
)
428 if ( state
->eofAction
!= 0 )
429 act
= state
->eofAction
->location
+1;
434 int JavaTabCodeGen::TRANS_ACTION( RedTransAp
*trans
)
436 /* If there are actions, emit them. Otherwise emit zero. */
438 if ( trans
->action
!= 0 )
439 act
= trans
->action
->location
+1;
443 std::ostream
&JavaTabCodeGen::TO_STATE_ACTION_SWITCH()
445 /* Walk the list of functions, printing the cases. */
446 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
447 /* Write out referenced actions. */
448 if ( act
->numToStateRefs
> 0 ) {
449 /* Write the case label, the action and the case break. */
450 out
<< "\tcase " << act
->actionId
<< ":\n";
451 ACTION( out
, act
, 0, false );
456 genLineDirective( out
);
460 std::ostream
&JavaTabCodeGen::FROM_STATE_ACTION_SWITCH()
462 /* Walk the list of functions, printing the cases. */
463 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
464 /* Write out referenced actions. */
465 if ( act
->numFromStateRefs
> 0 ) {
466 /* Write the case label, the action and the case break. */
467 out
<< "\tcase " << act
->actionId
<< ":\n";
468 ACTION( out
, act
, 0, false );
473 genLineDirective( out
);
477 std::ostream
&JavaTabCodeGen::EOF_ACTION_SWITCH()
479 /* Walk the list of functions, printing the cases. */
480 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
481 /* Write out referenced actions. */
482 if ( act
->numEofRefs
> 0 ) {
483 /* Write the case label, the action and the case break. */
484 out
<< "\tcase " << act
->actionId
<< ":\n";
485 ACTION( out
, act
, 0, true );
490 genLineDirective( out
);
495 std::ostream
&JavaTabCodeGen::ACTION_SWITCH()
497 /* Walk the list of functions, printing the cases. */
498 for ( ActionList::Iter act
= actionList
; act
.lte(); act
++ ) {
499 /* Write out referenced actions. */
500 if ( act
->numTransRefs
> 0 ) {
501 /* Write the case label, the action and the case break. */
502 out
<< "\tcase " << act
->actionId
<< ":\n";
503 ACTION( out
, act
, 0, false );
508 genLineDirective( out
);
512 std::ostream
&JavaTabCodeGen::COND_OFFSETS()
514 int curKeyOffset
= 0;
515 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
516 /* Write the key offset. */
517 ARRAY_ITEM( INT(curKeyOffset
), st
.last() );
519 /* Move the key offset ahead. */
520 curKeyOffset
+= st
->stateCondList
.length();
525 std::ostream
&JavaTabCodeGen::KEY_OFFSETS()
527 int curKeyOffset
= 0;
528 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
529 /* Write the key offset. */
530 ARRAY_ITEM( INT(curKeyOffset
), st
.last() );
532 /* Move the key offset ahead. */
533 curKeyOffset
+= st
->outSingle
.length() + st
->outRange
.length()*2;
539 std::ostream
&JavaTabCodeGen::INDEX_OFFSETS()
541 int curIndOffset
= 0;
542 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
543 /* Write the index offset. */
544 ARRAY_ITEM( INT(curIndOffset
), st
.last() );
546 /* Move the index offset ahead. */
547 curIndOffset
+= st
->outSingle
.length() + st
->outRange
.length();
548 if ( st
->defTrans
!= 0 )
554 std::ostream
&JavaTabCodeGen::COND_LENS()
556 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
557 /* Write singles length. */
558 ARRAY_ITEM( INT(st
->stateCondList
.length()), st
.last() );
564 std::ostream
&JavaTabCodeGen::SINGLE_LENS()
566 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
567 /* Write singles length. */
568 ARRAY_ITEM( INT(st
->outSingle
.length()), st
.last() );
573 std::ostream
&JavaTabCodeGen::RANGE_LENS()
575 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
576 /* Emit length of range index. */
577 ARRAY_ITEM( INT(st
->outRange
.length()), st
.last() );
582 std::ostream
&JavaTabCodeGen::TO_STATE_ACTIONS()
584 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
585 /* Write any eof action. */
586 ARRAY_ITEM( INT(TO_STATE_ACTION(st
)), st
.last() );
591 std::ostream
&JavaTabCodeGen::FROM_STATE_ACTIONS()
593 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
594 /* Write any eof action. */
595 ARRAY_ITEM( INT(FROM_STATE_ACTION(st
)), st
.last() );
600 std::ostream
&JavaTabCodeGen::EOF_ACTIONS()
602 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
603 /* Write any eof action. */
604 ARRAY_ITEM( INT(EOF_ACTION(st
)), st
.last() );
609 std::ostream
&JavaTabCodeGen::EOF_TRANS()
611 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
612 /* Write any eof action. */
614 if ( st
->eofTrans
!= 0 ) {
615 assert( st
->eofTrans
->pos
>= 0 );
616 trans
= st
->eofTrans
->pos
+1;
619 /* Write any eof action. */
620 ARRAY_ITEM( INT(trans
), st
.last() );
626 std::ostream
&JavaTabCodeGen::COND_KEYS()
628 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
629 /* Loop the state's transitions. */
630 for ( StateCondList::Iter sc
= st
->stateCondList
; sc
.lte(); sc
++ ) {
632 ARRAY_ITEM( KEY( sc
->lowKey
), false );
633 ARRAY_ITEM( KEY( sc
->highKey
), false );
637 /* Output one last number so we don't have to figure out when the last
638 * entry is and avoid writing a comma. */
639 ARRAY_ITEM( INT(0), true );
643 std::ostream
&JavaTabCodeGen::COND_SPACES()
645 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
646 /* Loop the state's transitions. */
647 for ( StateCondList::Iter sc
= st
->stateCondList
; sc
.lte(); sc
++ ) {
649 ARRAY_ITEM( KEY( sc
->condSpace
->condSpaceId
), false );
653 /* Output one last number so we don't have to figure out when the last
654 * entry is and avoid writing a comma. */
655 ARRAY_ITEM( INT(0), true );
659 std::ostream
&JavaTabCodeGen::KEYS()
661 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
662 /* Loop the singles. */
663 for ( RedTransList::Iter stel
= st
->outSingle
; stel
.lte(); stel
++ ) {
664 ARRAY_ITEM( KEY( stel
->lowKey
), false );
667 /* Loop the state's transitions. */
668 for ( RedTransList::Iter rtel
= st
->outRange
; rtel
.lte(); rtel
++ ) {
670 ARRAY_ITEM( KEY( rtel
->lowKey
), false );
673 ARRAY_ITEM( KEY( rtel
->highKey
), false );
677 /* Output one last number so we don't have to figure out when the last
678 * entry is and avoid writing a comma. */
679 ARRAY_ITEM( INT(0), true );
683 std::ostream
&JavaTabCodeGen::INDICIES()
685 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
686 /* Walk the singles. */
687 for ( RedTransList::Iter stel
= st
->outSingle
; stel
.lte(); stel
++ ) {
688 ARRAY_ITEM( KEY( stel
->value
->id
), false );
691 /* Walk the ranges. */
692 for ( RedTransList::Iter rtel
= st
->outRange
; rtel
.lte(); rtel
++ ) {
693 ARRAY_ITEM( KEY( rtel
->value
->id
), false );
696 /* The state's default index goes next. */
697 if ( st
->defTrans
!= 0 ) {
698 ARRAY_ITEM( KEY( st
->defTrans
->id
), false );
702 /* Output one last number so we don't have to figure out when the last
703 * entry is and avoid writing a comma. */
704 ARRAY_ITEM( INT(0), true );
708 std::ostream
&JavaTabCodeGen::TRANS_TARGS()
711 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
712 /* Walk the singles. */
713 for ( RedTransList::Iter stel
= st
->outSingle
; stel
.lte(); stel
++ ) {
714 RedTransAp
*trans
= stel
->value
;
715 ARRAY_ITEM( KEY( trans
->targ
->id
), false );
719 /* Walk the ranges. */
720 for ( RedTransList::Iter rtel
= st
->outRange
; rtel
.lte(); rtel
++ ) {
721 RedTransAp
*trans
= rtel
->value
;
722 ARRAY_ITEM( KEY( trans
->targ
->id
), false );
726 /* The state's default target state. */
727 if ( st
->defTrans
!= 0 ) {
728 RedTransAp
*trans
= st
->defTrans
;
729 ARRAY_ITEM( KEY( trans
->targ
->id
), false );
734 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
735 if ( st
->eofTrans
!= 0 ) {
736 RedTransAp
*trans
= st
->eofTrans
;
737 trans
->pos
= totalTrans
++;
738 ARRAY_ITEM( KEY( trans
->targ
->id
), false );
742 /* Output one last number so we don't have to figure out when the last
743 * entry is and avoid writing a comma. */
744 ARRAY_ITEM( INT(0), true );
749 std::ostream
&JavaTabCodeGen::TRANS_ACTIONS()
751 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
752 /* Walk the singles. */
753 for ( RedTransList::Iter stel
= st
->outSingle
; stel
.lte(); stel
++ ) {
754 RedTransAp
*trans
= stel
->value
;
755 ARRAY_ITEM( INT(TRANS_ACTION( trans
)), false );
758 /* Walk the ranges. */
759 for ( RedTransList::Iter rtel
= st
->outRange
; rtel
.lte(); rtel
++ ) {
760 RedTransAp
*trans
= rtel
->value
;
761 ARRAY_ITEM( INT(TRANS_ACTION( trans
)), false );
764 /* The state's default index goes next. */
765 if ( st
->defTrans
!= 0 ) {
766 RedTransAp
*trans
= st
->defTrans
;
767 ARRAY_ITEM( INT(TRANS_ACTION( trans
)), false );
771 for ( RedStateList::Iter st
= redFsm
->stateList
; st
.lte(); st
++ ) {
772 if ( st
->eofTrans
!= 0 ) {
773 RedTransAp
*trans
= st
->eofTrans
;
774 ARRAY_ITEM( INT(TRANS_ACTION( trans
)), false );
778 /* Output one last number so we don't have to figure out when the last
779 * entry is and avoid writing a comma. */
780 ARRAY_ITEM( INT(0), true );
784 std::ostream
&JavaTabCodeGen::TRANS_TARGS_WI()
786 /* Transitions must be written ordered by their id. */
787 RedTransAp
**transPtrs
= new RedTransAp
*[redFsm
->transSet
.length()];
788 for ( TransApSet::Iter trans
= redFsm
->transSet
; trans
.lte(); trans
++ )
789 transPtrs
[trans
->id
] = trans
;
791 /* Keep a count of the num of items in the array written. */
792 for ( int t
= 0; t
< redFsm
->transSet
.length(); t
++ ) {
793 /* Save the position. Needed for eofTargs. */
794 RedTransAp
*trans
= transPtrs
[t
];
797 /* Write out the target state. */
798 ARRAY_ITEM( INT(trans
->targ
->id
), ( t
>= redFsm
->transSet
.length()-1 ) );
805 std::ostream
&JavaTabCodeGen::TRANS_ACTIONS_WI()
807 /* Transitions must be written ordered by their id. */
808 RedTransAp
**transPtrs
= new RedTransAp
*[redFsm
->transSet
.length()];
809 for ( TransApSet::Iter trans
= redFsm
->transSet
; trans
.lte(); trans
++ )
810 transPtrs
[trans
->id
] = trans
;
812 /* Keep a count of the num of items in the array written. */
813 for ( int t
= 0; t
< redFsm
->transSet
.length(); t
++ ) {
814 /* Write the function for the transition. */
815 RedTransAp
*trans
= transPtrs
[t
];
816 ARRAY_ITEM( INT(TRANS_ACTION( trans
)), ( t
>= redFsm
->transSet
.length()-1 ) );
822 void JavaTabCodeGen::writeExports()
824 if ( exportList
.length() > 0 ) {
825 for ( ExportList::Iter ex
= exportList
; ex
.lte(); ex
++ ) {
826 STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex
->name
)
827 << " = " << KEY(ex
->key
) << ";\n";
833 void JavaTabCodeGen::writeData()
835 /* If there are any transtion functions then output the array. If there
836 * are none, don't bother emitting an empty array that won't be used. */
837 if ( redFsm
->anyActions() ) {
838 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActArrItem
), A() );
844 if ( redFsm
->anyConditions() ) {
845 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxCondOffset
), CO() );
850 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxCondLen
), CL() );
855 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
860 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxCondSpaceId
), C() );
866 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxKeyOffset
), KO() );
871 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
876 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxSingleLen
), SL() );
881 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxRangeLen
), RL() );
886 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxIndexOffset
), IO() );
892 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxIndex
), I() );
897 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxState
), TT() );
902 if ( redFsm
->anyActions() ) {
903 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), TA() );
910 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxState
), TT() );
915 if ( redFsm
->anyActions() ) {
916 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), TA() );
923 if ( redFsm
->anyToStateActions() ) {
924 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), TSA() );
930 if ( redFsm
->anyFromStateActions() ) {
931 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), FSA() );
932 FROM_STATE_ACTIONS();
937 if ( redFsm
->anyEofActions() ) {
938 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxActionLoc
), EA() );
944 if ( redFsm
->anyEofTrans() ) {
945 OPEN_ARRAY( ARRAY_TYPE(redFsm
->maxIndexOffset
+1), ET() );
951 if ( redFsm
->startState
!= 0 )
952 STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
954 if ( writeFirstFinal
)
955 STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
958 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
962 if ( entryPointNames
.length() > 0 ) {
963 for ( EntryNameVect::Iter en
= entryPointNames
; en
.lte(); en
++ ) {
964 STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en
) <<
965 " = " << entryPointIds
[en
.pos()] << ";\n";
971 void JavaTabCodeGen::writeExec()
977 if ( redFsm
->anyRegCurStateRef() )
982 " int _trans = 0;\n";
984 if ( redFsm
->anyConditions() )
985 out
<< " int _widec;\n";
987 if ( redFsm
->anyToStateActions() || redFsm
->anyRegActions() ||
988 redFsm
->anyFromStateActions() )
997 " int _goto_targ = 0;\n"
1001 " _goto: while (true) {\n"
1002 " switch ( _goto_targ ) {\n"
1007 " if ( " << P() << " == " << PE() << " ) {\n"
1008 " _goto_targ = " << _test_eof
<< ";\n"
1009 " continue _goto;\n"
1013 if ( redFsm
->errState
!= 0 ) {
1015 " if ( " << CS() << " == " << redFsm
->errState
->id
<< " ) {\n"
1016 " _goto_targ = " << _out
<< ";\n"
1017 " continue _goto;\n"
1021 out
<< "case " << _resume
<< ":\n";
1023 if ( redFsm
->anyFromStateActions() ) {
1025 " _acts = " << FSA() << "[" << CS() << "]" << ";\n"
1026 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1027 " while ( _nacts-- > 0 ) {\n"
1028 " switch ( " << A() << "[_acts++] ) {\n";
1029 FROM_STATE_ACTION_SWITCH() <<
1035 if ( redFsm
->anyConditions() )
1041 out
<< " _trans = " << I() << "[_trans];\n";
1043 if ( redFsm
->anyEofTrans() )
1044 out
<< "case " << _eof_trans
<< ":\n";
1046 if ( redFsm
->anyRegCurStateRef() )
1047 out
<< " _ps = " << CS() << ";\n";
1050 " " << CS() << " = " << TT() << "[_trans];\n"
1053 if ( redFsm
->anyRegActions() ) {
1055 " if ( " << TA() << "[_trans] != 0 ) {\n"
1056 " _acts = " << TA() << "[_trans]" << ";\n"
1057 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1058 " while ( _nacts-- > 0 )\n {\n"
1059 " switch ( " << A() << "[_acts++] )\n"
1068 out
<< "case " << _again
<< ":\n";
1070 if ( redFsm
->anyToStateActions() ) {
1072 " _acts = " << TSA() << "[" << CS() << "]" << ";\n"
1073 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1074 " while ( _nacts-- > 0 ) {\n"
1075 " switch ( " << A() << "[_acts++] ) {\n";
1076 TO_STATE_ACTION_SWITCH() <<
1082 if ( redFsm
->errState
!= 0 ) {
1084 " if ( " << CS() << " == " << redFsm
->errState
->id
<< " ) {\n"
1085 " _goto_targ = " << _out
<< ";\n"
1086 " continue _goto;\n"
1092 " if ( ++" << P() << " != " << PE() << " ) {\n"
1093 " _goto_targ = " << _resume
<< ";\n"
1094 " continue _goto;\n"
1099 " " << P() << " += 1;\n"
1100 " _goto_targ = " << _resume
<< ";\n"
1101 " continue _goto;\n";
1104 out
<< "case " << _test_eof
<< ":\n";
1106 if ( redFsm
->anyEofTrans() || redFsm
->anyEofActions() ) {
1108 " if ( " << P() << " == " << EOFV() << " )\n"
1111 if ( redFsm
->anyEofTrans() ) {
1113 " if ( " << ET() << "[" << CS() << "] > 0 ) {\n"
1114 " _trans = " << ET() << "[" << CS() << "] - 1;\n"
1115 " _goto_targ = " << _eof_trans
<< ";\n"
1116 " continue _goto;\n"
1120 if ( redFsm
->anyEofActions() ) {
1122 " int __acts = " << EA() << "[" << CS() << "]" << ";\n"
1123 " int __nacts = " << CAST("int") << " " << A() << "[__acts++];\n"
1124 " while ( __nacts-- > 0 ) {\n"
1125 " switch ( " << A() << "[__acts++] ) {\n";
1126 EOF_ACTION_SWITCH() <<
1136 out
<< "case " << _out
<< ":\n";
1138 /* The switch and goto loop. */
1140 out
<< " break; }\n";
1142 /* The execute block. */
1146 std::ostream
&JavaTabCodeGen::OPEN_ARRAY( string type
, string name
)
1153 out
<< "private static " << type
<< "[] init_" << name
<< "_0()\n"
1155 "return new " << type
<< " [] {\n\t";
1159 std::ostream
&JavaTabCodeGen::ARRAY_ITEM( string item
, bool last
)
1163 out
<< setw(5) << setiosflags(ios::right
) << item
;
1166 if ( item_count
% SAIIC
== 0 ) {
1167 out
<< "\n\t};\n};\n"
1168 "private static "<< array_type
<< "[] init_" <<
1169 array_name
<< "_" << div_count
<< "()\n"
1171 "return new " << array_type
<< " [] {\n\t";
1173 } else if (item_count
% IALL
== 0) {
1182 std::ostream
&JavaTabCodeGen::CLOSE_ARRAY()
1184 out
<< "\n\t};\n}\n\n";
1186 if (item_count
< SAIIC
) {
1187 out
<< "private static final " << array_type
<< " " << array_name
<<
1188 "[] = init_" << array_name
<< "_0();\n\n";
1190 out
<< "private static final " << array_type
<< " [] combine_" << array_name
1192 << array_type
<< " [] combined = new " << array_type
<<
1193 " [ " << item_count
<< " ];\n\t";
1195 int full_blocks
= item_count
/ SAIIC
;
1196 for (;block
< full_blocks
; ++block
) {
1197 out
<< "System.arraycopy ( init_" << array_name
<< "_" << block
<<
1198 "(), 0, combined, " << SAIIC
* block
<< ", " << SAIIC
<< " );\n\t";
1200 if ( (item_count
% SAIIC
) > 0 ) {
1201 out
<< "System.arraycopy ( init_" << array_name
<< "_" << block
<<
1202 "(), 0, combined, " << SAIIC
* block
<< ", " <<
1203 (item_count
% SAIIC
) << " );\n\t";
1205 out
<< "return combined;\n}\n";
1206 out
<< "private static final " << array_type
<< " [] " << array_name
<<
1207 " = combine_" << array_name
<< "();";
1213 std::ostream
&JavaTabCodeGen::STATIC_VAR( string type
, string name
)
1215 out
<< "static final " << type
<< " " << name
;
1219 string
JavaTabCodeGen::ARR_OFF( string ptr
, string offset
)
1221 return ptr
+ " + " + offset
;
1224 string
JavaTabCodeGen::CAST( string type
)
1226 return "(" + type
+ ")";
1229 string
JavaTabCodeGen::NULL_ITEM()
1231 /* In java we use integers instead of pointers. */
1235 string
JavaTabCodeGen::GET_KEY()
1238 if ( getKeyExpr
!= 0 ) {
1239 /* Emit the user supplied method of retrieving the key. */
1241 INLINE_LIST( ret
, getKeyExpr
, 0, false );
1245 /* Expression for retrieving the key, use simple dereference. */
1246 ret
<< DATA() << "[" << P() << "]";
1251 string
JavaTabCodeGen::CTRL_FLOW()
1253 return "if (true) ";
1256 unsigned int JavaTabCodeGen::arrayTypeSize( unsigned long maxVal
)
1258 long long maxValLL
= (long long) maxVal
;
1259 HostType
*arrayType
= keyOps
->typeSubsumes( maxValLL
);
1260 assert( arrayType
!= 0 );
1261 return arrayType
->size
;
1264 string
JavaTabCodeGen::ARRAY_TYPE( unsigned long maxVal
)
1266 long long maxValLL
= (long long) maxVal
;
1267 HostType
*arrayType
= keyOps
->typeSubsumes( maxValLL
);
1268 assert( arrayType
!= 0 );
1270 string ret
= arrayType
->data1
;
1271 if ( arrayType
->data2
!= 0 ) {
1273 ret
+= arrayType
->data2
;
1279 /* Write out the fsm name. */
1280 string
JavaTabCodeGen::FSM_NAME()
1285 /* Emit the offset of the start state as a decimal integer. */
1286 string
JavaTabCodeGen::START_STATE_ID()
1289 ret
<< redFsm
->startState
->id
;
1293 /* Write out the array of actions. */
1294 std::ostream
&JavaTabCodeGen::ACTIONS_ARRAY()
1296 ARRAY_ITEM( INT(0), false );
1297 for ( ActionTableMap::Iter act
= redFsm
->actionMap
; act
.lte(); act
++ ) {
1298 /* Write out the length, which will never be the last character. */
1299 ARRAY_ITEM( INT(act
->key
.length()), false );
1301 for ( ActionTable::Iter item
= act
->key
; item
.lte(); item
++ )
1302 ARRAY_ITEM( INT(item
->value
->actionId
), (act
.last() && item
.last()) );
1308 string
JavaTabCodeGen::ACCESS()
1311 if ( accessExpr
!= 0 )
1312 INLINE_LIST( ret
, accessExpr
, 0, false );
1316 string
JavaTabCodeGen::P()
1323 INLINE_LIST( ret
, pExpr
, 0, false );
1329 string
JavaTabCodeGen::PE()
1336 INLINE_LIST( ret
, peExpr
, 0, false );
1342 string
JavaTabCodeGen::EOFV()
1349 INLINE_LIST( ret
, eofExpr
, 0, false );
1355 string
JavaTabCodeGen::CS()
1359 ret
<< ACCESS() << "cs";
1361 /* Emit the user supplied method of retrieving the key. */
1363 INLINE_LIST( ret
, csExpr
, 0, false );
1369 string
JavaTabCodeGen::TOP()
1373 ret
<< ACCESS() + "top";
1376 INLINE_LIST( ret
, topExpr
, 0, false );
1382 string
JavaTabCodeGen::STACK()
1385 if ( stackExpr
== 0 )
1386 ret
<< ACCESS() + "stack";
1389 INLINE_LIST( ret
, stackExpr
, 0, false );
1395 string
JavaTabCodeGen::ACT()
1399 ret
<< ACCESS() + "act";
1402 INLINE_LIST( ret
, actExpr
, 0, false );
1408 string
JavaTabCodeGen::TOKSTART()
1411 if ( tokstartExpr
== 0 )
1412 ret
<< ACCESS() + "ts";
1415 INLINE_LIST( ret
, tokstartExpr
, 0, false );
1421 string
JavaTabCodeGen::TOKEND()
1424 if ( tokendExpr
== 0 )
1425 ret
<< ACCESS() + "te";
1428 INLINE_LIST( ret
, tokendExpr
, 0, false );
1434 string
JavaTabCodeGen::DATA()
1437 if ( dataExpr
== 0 )
1438 ret
<< ACCESS() + "data";
1441 INLINE_LIST( ret
, dataExpr
, 0, false );
1448 string
JavaTabCodeGen::GET_WIDE_KEY()
1450 if ( redFsm
->anyConditions() )
1456 string
JavaTabCodeGen::GET_WIDE_KEY( RedStateAp
*state
)
1458 if ( state
->stateCondList
.length() > 0 )
1464 /* Write out level number of tabs. Makes the nested binary search nice
1466 string
JavaTabCodeGen::TABS( int level
)
1469 while ( level
-- > 0 )
1474 string
JavaTabCodeGen::KEY( Key key
)
1477 if ( keyOps
->isSigned
|| !hostLang
->explicitUnsigned
)
1478 ret
<< key
.getVal();
1480 ret
<< (unsigned long) key
.getVal();
1484 string
JavaTabCodeGen::INT( int i
)
1491 void JavaTabCodeGen::LM_SWITCH( ostream
&ret
, InlineItem
*item
,
1492 int targState
, int inFinish
)
1495 " switch( " << ACT() << " ) {\n";
1497 for ( InlineList::Iter lma
= *item
->children
; lma
.lte(); lma
++ ) {
1498 /* Write the case label, the action and the case break. */
1499 if ( lma
->lmId
< 0 )
1500 ret
<< " default:\n";
1502 ret
<< " case " << lma
->lmId
<< ":\n";
1504 /* Write the block and close it off. */
1506 INLINE_LIST( ret
, lma
->children
, targState
, inFinish
);
1517 void JavaTabCodeGen::SET_ACT( ostream
&ret
, InlineItem
*item
)
1519 ret
<< ACT() << " = " << item
->lmId
<< ";";
1522 void JavaTabCodeGen::SET_TOKEND( ostream
&ret
, InlineItem
*item
)
1524 /* The tokend action sets tokend. */
1525 ret
<< TOKEND() << " = " << P();
1526 if ( item
->offset
!= 0 )
1527 out
<< "+" << item
->offset
;
1531 void JavaTabCodeGen::GET_TOKEND( ostream
&ret
, InlineItem
*item
)
1536 void JavaTabCodeGen::INIT_TOKSTART( ostream
&ret
, InlineItem
*item
)
1538 ret
<< TOKSTART() << " = " << NULL_ITEM() << ";";
1541 void JavaTabCodeGen::INIT_ACT( ostream
&ret
, InlineItem
*item
)
1543 ret
<< ACT() << " = 0;";
1546 void JavaTabCodeGen::SET_TOKSTART( ostream
&ret
, InlineItem
*item
)
1548 ret
<< TOKSTART() << " = " << P() << ";";
1551 void JavaTabCodeGen::SUB_ACTION( ostream
&ret
, InlineItem
*item
,
1552 int targState
, bool inFinish
)
1554 if ( item
->children
->length() > 0 ) {
1555 /* Write the block and close it off. */
1557 INLINE_LIST( ret
, item
->children
, targState
, inFinish
);
1562 void JavaTabCodeGen::ACTION( ostream
&ret
, Action
*action
, int targState
, bool inFinish
)
1564 /* Write the preprocessor line info for going into the source file. */
1565 lineDirective( ret
, sourceFileName
, action
->loc
.line
);
1567 /* Write the block and close it off. */
1569 INLINE_LIST( ret
, action
->inlineList
, targState
, inFinish
);
1573 void JavaTabCodeGen::CONDITION( ostream
&ret
, Action
*condition
)
1576 lineDirective( ret
, sourceFileName
, condition
->loc
.line
);
1577 INLINE_LIST( ret
, condition
->inlineList
, 0, false );
1580 string
JavaTabCodeGen::ERROR_STATE()
1583 if ( redFsm
->errState
!= 0 )
1584 ret
<< redFsm
->errState
->id
;
1590 string
JavaTabCodeGen::FIRST_FINAL_STATE()
1593 if ( redFsm
->firstFinState
!= 0 )
1594 ret
<< redFsm
->firstFinState
->id
;
1596 ret
<< redFsm
->nextStateId
;
1600 void JavaTabCodeGen::writeInit()
1605 out
<< "\t" << CS() << " = " << START() << ";\n";
1607 /* If there are any calls, then the stack top needs initialization. */
1608 if ( redFsm
->anyActionCalls() || redFsm
->anyActionRets() )
1609 out
<< "\t" << TOP() << " = 0;\n";
1611 if ( hasLongestMatch
) {
1613 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
1614 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
1615 " " << ACT() << " = 0;\n";
1620 void JavaTabCodeGen::finishRagelDef()
1622 /* The frontend will do this for us, but it may be a good idea to force it
1623 * if the intermediate file is edited. */
1624 redFsm
->sortByStateId();
1626 /* Choose default transitions and the single transition. */
1627 redFsm
->chooseDefaultSpan();
1629 /* Maybe do flat expand, otherwise choose single. */
1630 redFsm
->chooseSingle();
1632 /* If any errors have occured in the input file then don't write anything. */
1633 if ( gblErrorCount
> 0 )
1636 /* Anlayze Machine will find the final action reference counts, among
1637 * other things. We will use these in reporting the usage
1638 * of fsm directives in action code. */
1641 /* Determine if we should use indicies. */
1645 ostream
&JavaTabCodeGen::source_warning( const InputLoc
&loc
)
1647 cerr
<< sourceFileName
<< ":" << loc
.line
<< ":" << loc
.col
<< ": warning: ";
1651 ostream
&JavaTabCodeGen::source_error( const InputLoc
&loc
)
1654 assert( sourceFileName
!= 0 );
1655 cerr
<< sourceFileName
<< ":" << loc
.line
<< ":" << loc
.col
<< ": ";