lm_switch needs to set p from tokend when there is no user action.
[ragel.git] / rlgen-java / javacodegen.cpp
blobfdd4899fbc65bbc24ff31eb2aef6b14911548904
1 /*
2 * Copyright 2006-2007 Adrian Thurston <thurston@cs.queensu.ca>
3 * 2007 Colin Fleming <colin.fleming@caverock.com>
4 */
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"
25 #include "redfsm.h"
26 #include "gendata.h"
27 #include <iomanip>
28 #include <sstream>
30 /* Integer array line length. */
31 #define IALL 12
33 /* Static array initialization item count
34 * (should be multiple of IALL). */
35 #define SAIIC 8184
37 #define _resume 1
38 #define _again 2
39 #define _eof_trans 3
40 #define _test_eof 4
41 #define _out 5
43 using std::setw;
44 using std::ios;
45 using std::ostringstream;
46 using std::string;
47 using std::cerr;
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++ ) {
54 if ( *pc == '\\' )
55 out << "\\\\";
56 else
57 out << *pc;
59 out << "\"\n";
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 ) {
85 ret << "{";
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 )
93 ret << "}";
96 void JavaTabCodeGen::CALL_EXPR( ostream &ret, InlineItem *ilItem, int targState, bool inFinish )
98 if ( prePushExpr != 0 ) {
99 ret << "{";
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 )
108 ret << "}";
111 void JavaTabCodeGen::RET( ostream &ret, bool inFinish )
113 ret << "{" << CS() << " = " << STACK() << "[--" << TOP() << "];";
115 if ( postPopExpr != 0 ) {
116 ret << "{";
117 INLINE_LIST( ret, postPopExpr, 0, false );
118 ret << "}";
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 );
139 ret << ");";
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 );
149 ret << "))-1;}";
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:
160 ret << item->data;
161 break;
162 case InlineItem::Goto:
163 GOTO( ret, item->targState->id, inFinish );
164 break;
165 case InlineItem::Call:
166 CALL( ret, item->targState->id, targState, inFinish );
167 break;
168 case InlineItem::Next:
169 NEXT( ret, item->targState->id, inFinish );
170 break;
171 case InlineItem::Ret:
172 RET( ret, inFinish );
173 break;
174 case InlineItem::PChar:
175 ret << P();
176 break;
177 case InlineItem::Char:
178 ret << GET_KEY();
179 break;
180 case InlineItem::Hold:
181 ret << P() << "--;";
182 break;
183 case InlineItem::Exec:
184 EXEC( ret, item, targState, inFinish );
185 break;
186 case InlineItem::Curs:
187 ret << "(_ps)";
188 break;
189 case InlineItem::Targs:
190 ret << "(" << CS() << ")";
191 break;
192 case InlineItem::Entry:
193 ret << item->targState->id;
194 break;
195 case InlineItem::GotoExpr:
196 GOTO_EXPR( ret, item, inFinish );
197 break;
198 case InlineItem::CallExpr:
199 CALL_EXPR( ret, item, targState, inFinish );
200 break;
201 case InlineItem::NextExpr:
202 NEXT_EXPR( ret, item, inFinish );
203 break;
204 case InlineItem::LmSwitch:
205 LM_SWITCH( ret, item, targState, inFinish );
206 break;
207 case InlineItem::LmSetActId:
208 SET_ACT( ret, item );
209 break;
210 case InlineItem::LmSetTokEnd:
211 SET_TOKEND( ret, item );
212 break;
213 case InlineItem::LmGetTokEnd:
214 GET_TOKEND( ret, item );
215 break;
216 case InlineItem::LmInitTokStart:
217 INIT_TOKSTART( ret, item );
218 break;
219 case InlineItem::LmInitAct:
220 INIT_ACT( ret, item );
221 break;
222 case InlineItem::LmSetTokStart:
223 SET_TOKSTART( ret, item );
224 break;
225 case InlineItem::SubAction:
226 SUB_ACTION( ret, item, targState, inFinish );
227 break;
228 case InlineItem::Break:
229 BREAK( ret, targState );
230 break;
235 string JavaTabCodeGen::DATA_PREFIX()
237 if ( dataPrefix )
238 return FSM_NAME() + "_";
239 return "";
242 /* Emit the alphabet data type. */
243 string JavaTabCodeGen::ALPH_TYPE()
245 string ret = keyOps->alphType->data1;
246 if ( keyOps->alphType->data2 != 0 ) {
247 ret += " ";
248 ret += + keyOps->alphType->data2;
250 return ret;
253 /* Emit the alphabet data type. */
254 string JavaTabCodeGen::WIDE_ALPH_TYPE()
256 string ret;
257 if ( redFsm->maxKey <= keyOps->maxKey )
258 ret = ALPH_TYPE();
259 else {
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 ) {
266 ret += " ";
267 ret += wideType->data2;
270 return ret;
275 void JavaTabCodeGen::COND_TRANSLATE()
277 out <<
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;"
283 " int _mid;\n"
284 " int _upper = _keys + (_klen<<1) - 2;\n"
285 " while (true) {\n"
286 " if ( _upper < _lower )\n"
287 " break;\n"
288 "\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"
294 " else {\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";
312 out <<
313 " break;\n"
314 " }\n";
317 out <<
318 " }\n"
319 " break;\n"
320 " }\n"
321 " }\n"
322 " }\n"
323 "\n";
327 void JavaTabCodeGen::LOCATE_TRANS()
329 out <<
330 " _match: do {\n"
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"
336 " int _mid;\n"
337 " int _upper = _keys + _klen - 1;\n"
338 " while (true) {\n"
339 " if ( _upper < _lower )\n"
340 " break;\n"
341 "\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"
347 " else {\n"
348 " _trans += (_mid - _keys);\n"
349 " break _match;\n"
350 " }\n"
351 " }\n"
352 " _keys += _klen;\n"
353 " _trans += _klen;\n"
354 " }\n"
355 "\n"
356 " _klen = " << RL() << "[" << CS() << "];\n"
357 " if ( _klen > 0 ) {\n"
358 " int _lower = _keys;\n"
359 " int _mid;\n"
360 " int _upper = _keys + (_klen<<1) - 2;\n"
361 " while (true) {\n"
362 " if ( _upper < _lower )\n"
363 " break;\n"
364 "\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"
370 " else {\n"
371 " _trans += ((_mid - _keys)>>1);\n"
372 " break _match;\n"
373 " }\n"
374 " }\n"
375 " _trans += _klen;\n"
376 " }\n"
377 " } while (false);\n"
378 "\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 )
411 int act = 0;
412 if ( state->toStateAction != 0 )
413 act = state->toStateAction->location+1;
414 return act;
417 int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
419 int act = 0;
420 if ( state->fromStateAction != 0 )
421 act = state->fromStateAction->location+1;
422 return act;
425 int JavaTabCodeGen::EOF_ACTION( RedStateAp *state )
427 int act = 0;
428 if ( state->eofAction != 0 )
429 act = state->eofAction->location+1;
430 return act;
434 int JavaTabCodeGen::TRANS_ACTION( RedTransAp *trans )
436 /* If there are actions, emit them. Otherwise emit zero. */
437 int act = 0;
438 if ( trans->action != 0 )
439 act = trans->action->location+1;
440 return act;
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 );
452 out << "\tbreak;\n";
456 genLineDirective( out );
457 return 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 );
469 out << "\tbreak;\n";
473 genLineDirective( out );
474 return 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 );
486 out << "\tbreak;\n";
490 genLineDirective( out );
491 return 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 );
504 out << "\tbreak;\n";
508 genLineDirective( out );
509 return 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();
522 return out;
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;
535 return out;
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 )
549 curIndOffset += 1;
551 return out;
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() );
560 return out;
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() );
570 return out;
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() );
579 return out;
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() );
588 return out;
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() );
597 return out;
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() );
606 return out;
609 std::ostream &JavaTabCodeGen::EOF_TRANS()
611 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
612 /* Write any eof action. */
613 long trans = 0;
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() );
622 return out;
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++ ) {
631 /* Lower key. */
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 );
640 return out;
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++ ) {
648 /* Cond Space id. */
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 );
656 return out;
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++ ) {
669 /* Lower key. */
670 ARRAY_ITEM( KEY( rtel->lowKey ), false );
672 /* Upper key. */
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 );
680 return out;
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 );
705 return out;
708 std::ostream &JavaTabCodeGen::TRANS_TARGS()
710 int totalTrans = 0;
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 );
716 totalTrans++;
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 );
723 totalTrans++;
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 );
730 totalTrans++;
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 );
745 return out;
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 );
781 return out;
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];
795 trans->pos = t;
797 /* Write out the target state. */
798 ARRAY_ITEM( INT(trans->targ->id), ( t >= redFsm->transSet.length()-1 ) );
800 delete[] transPtrs;
801 return out;
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 ) );
818 delete[] transPtrs;
819 return out;
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";
829 out << "\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() );
839 ACTIONS_ARRAY();
840 CLOSE_ARRAY() <<
841 "\n";
844 if ( redFsm->anyConditions() ) {
845 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
846 COND_OFFSETS();
847 CLOSE_ARRAY() <<
848 "\n";
850 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
851 COND_LENS();
852 CLOSE_ARRAY() <<
853 "\n";
855 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
856 COND_KEYS();
857 CLOSE_ARRAY() <<
858 "\n";
860 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
861 COND_SPACES();
862 CLOSE_ARRAY() <<
863 "\n";
866 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
867 KEY_OFFSETS();
868 CLOSE_ARRAY() <<
869 "\n";
871 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
872 KEYS();
873 CLOSE_ARRAY() <<
874 "\n";
876 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
877 SINGLE_LENS();
878 CLOSE_ARRAY() <<
879 "\n";
881 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
882 RANGE_LENS();
883 CLOSE_ARRAY() <<
884 "\n";
886 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
887 INDEX_OFFSETS();
888 CLOSE_ARRAY() <<
889 "\n";
891 if ( useIndicies ) {
892 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
893 INDICIES();
894 CLOSE_ARRAY() <<
895 "\n";
897 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
898 TRANS_TARGS_WI();
899 CLOSE_ARRAY() <<
900 "\n";
902 if ( redFsm->anyActions() ) {
903 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
904 TRANS_ACTIONS_WI();
905 CLOSE_ARRAY() <<
906 "\n";
909 else {
910 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
911 TRANS_TARGS();
912 CLOSE_ARRAY() <<
913 "\n";
915 if ( redFsm->anyActions() ) {
916 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
917 TRANS_ACTIONS();
918 CLOSE_ARRAY() <<
919 "\n";
923 if ( redFsm->anyToStateActions() ) {
924 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
925 TO_STATE_ACTIONS();
926 CLOSE_ARRAY() <<
927 "\n";
930 if ( redFsm->anyFromStateActions() ) {
931 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
932 FROM_STATE_ACTIONS();
933 CLOSE_ARRAY() <<
934 "\n";
937 if ( redFsm->anyEofActions() ) {
938 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
939 EOF_ACTIONS();
940 CLOSE_ARRAY() <<
941 "\n";
944 if ( redFsm->anyEofTrans() ) {
945 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
946 EOF_TRANS();
947 CLOSE_ARRAY() <<
948 "\n";
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";
957 if ( writeErr )
958 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
960 out << "\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";
967 out << "\n";
971 void JavaTabCodeGen::writeExec()
973 out <<
974 " {\n"
975 " int _klen";
977 if ( redFsm->anyRegCurStateRef() )
978 out << ", _ps";
980 out <<
981 ";\n"
982 " int _trans = 0;\n";
984 if ( redFsm->anyConditions() )
985 out << " int _widec;\n";
987 if ( redFsm->anyToStateActions() || redFsm->anyRegActions() ||
988 redFsm->anyFromStateActions() )
990 out <<
991 " int _acts;\n"
992 " int _nacts;\n";
995 out <<
996 " int _keys;\n"
997 " int _goto_targ = 0;\n"
998 "\n";
1000 out <<
1001 " _goto: while (true) {\n"
1002 " switch ( _goto_targ ) {\n"
1003 " case 0:\n";
1005 if ( hasEnd ) {
1006 out <<
1007 " if ( " << P() << " == " << PE() << " ) {\n"
1008 " _goto_targ = " << _test_eof << ";\n"
1009 " continue _goto;\n"
1010 " }\n";
1013 if ( redFsm->errState != 0 ) {
1014 out <<
1015 " if ( " << CS() << " == " << redFsm->errState->id << " ) {\n"
1016 " _goto_targ = " << _out << ";\n"
1017 " continue _goto;\n"
1018 " }\n";
1021 out << "case " << _resume << ":\n";
1023 if ( redFsm->anyFromStateActions() ) {
1024 out <<
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() <<
1030 " }\n"
1031 " }\n"
1032 "\n";
1035 if ( redFsm->anyConditions() )
1036 COND_TRANSLATE();
1038 LOCATE_TRANS();
1040 if ( useIndicies )
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";
1049 out <<
1050 " " << CS() << " = " << TT() << "[_trans];\n"
1051 "\n";
1053 if ( redFsm->anyRegActions() ) {
1054 out <<
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"
1060 " {\n";
1061 ACTION_SWITCH() <<
1062 " }\n"
1063 " }\n"
1064 " }\n"
1065 "\n";
1068 out << "case " << _again << ":\n";
1070 if ( redFsm->anyToStateActions() ) {
1071 out <<
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() <<
1077 " }\n"
1078 " }\n"
1079 "\n";
1082 if ( redFsm->errState != 0 ) {
1083 out <<
1084 " if ( " << CS() << " == " << redFsm->errState->id << " ) {\n"
1085 " _goto_targ = " << _out << ";\n"
1086 " continue _goto;\n"
1087 " }\n";
1090 if ( hasEnd ) {
1091 out <<
1092 " if ( ++" << P() << " != " << PE() << " ) {\n"
1093 " _goto_targ = " << _resume << ";\n"
1094 " continue _goto;\n"
1095 " }\n";
1097 else {
1098 out <<
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() ) {
1107 out <<
1108 " if ( " << P() << " == " << EOFV() << " )\n"
1109 " {\n";
1111 if ( redFsm->anyEofTrans() ) {
1112 out <<
1113 " if ( " << ET() << "[" << CS() << "] > 0 ) {\n"
1114 " _trans = " << ET() << "[" << CS() << "] - 1;\n"
1115 " _goto_targ = " << _eof_trans << ";\n"
1116 " continue _goto;\n"
1117 " }\n";
1120 if ( redFsm->anyEofActions() ) {
1121 out <<
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() <<
1127 " }\n"
1128 " }\n";
1131 out <<
1132 " }\n"
1133 "\n";
1136 out << "case " << _out << ":\n";
1138 /* The switch and goto loop. */
1139 out << " }\n";
1140 out << " break; }\n";
1142 /* The execute block. */
1143 out << " }\n";
1146 std::ostream &JavaTabCodeGen::OPEN_ARRAY( string type, string name )
1148 array_type = type;
1149 array_name = name;
1150 item_count = 0;
1151 div_count = 1;
1153 out << "private static " << type << "[] init_" << name << "_0()\n"
1154 "{\n\t"
1155 "return new " << type << " [] {\n\t";
1156 return out;
1159 std::ostream &JavaTabCodeGen::ARRAY_ITEM( string item, bool last )
1161 item_count++;
1163 out << setw(5) << setiosflags(ios::right) << item;
1165 if ( !last ) {
1166 if ( item_count % SAIIC == 0 ) {
1167 out << "\n\t};\n};\n"
1168 "private static "<< array_type << "[] init_" <<
1169 array_name << "_" << div_count << "()\n"
1170 "{\n\t"
1171 "return new " << array_type << " [] {\n\t";
1172 div_count++;
1173 } else if (item_count % IALL == 0) {
1174 out << ",\n\t";
1175 } else {
1176 out << ",";
1179 return out;
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";
1189 } else {
1190 out << "private static final " << array_type << " [] combine_" << array_name
1191 << "() {\n\t"
1192 << array_type << " [] combined = new " << array_type <<
1193 " [ " << item_count << " ];\n\t";
1194 int block = 0;
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 << "();";
1209 return out;
1213 std::ostream &JavaTabCodeGen::STATIC_VAR( string type, string name )
1215 out << "static final " << type << " " << name;
1216 return out;
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. */
1232 return "-1";
1235 string JavaTabCodeGen::GET_KEY()
1237 ostringstream ret;
1238 if ( getKeyExpr != 0 ) {
1239 /* Emit the user supplied method of retrieving the key. */
1240 ret << "(";
1241 INLINE_LIST( ret, getKeyExpr, 0, false );
1242 ret << ")";
1244 else {
1245 /* Expression for retrieving the key, use simple dereference. */
1246 ret << DATA() << "[" << P() << "]";
1248 return ret.str();
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 ) {
1272 ret += " ";
1273 ret += arrayType->data2;
1275 return ret;
1279 /* Write out the fsm name. */
1280 string JavaTabCodeGen::FSM_NAME()
1282 return fsmName;
1285 /* Emit the offset of the start state as a decimal integer. */
1286 string JavaTabCodeGen::START_STATE_ID()
1288 ostringstream ret;
1289 ret << redFsm->startState->id;
1290 return ret.str();
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()) );
1304 return out;
1308 string JavaTabCodeGen::ACCESS()
1310 ostringstream ret;
1311 if ( accessExpr != 0 )
1312 INLINE_LIST( ret, accessExpr, 0, false );
1313 return ret.str();
1316 string JavaTabCodeGen::P()
1318 ostringstream ret;
1319 if ( pExpr == 0 )
1320 ret << "p";
1321 else {
1322 ret << "(";
1323 INLINE_LIST( ret, pExpr, 0, false );
1324 ret << ")";
1326 return ret.str();
1329 string JavaTabCodeGen::PE()
1331 ostringstream ret;
1332 if ( peExpr == 0 )
1333 ret << "pe";
1334 else {
1335 ret << "(";
1336 INLINE_LIST( ret, peExpr, 0, false );
1337 ret << ")";
1339 return ret.str();
1342 string JavaTabCodeGen::EOFV()
1344 ostringstream ret;
1345 if ( eofExpr == 0 )
1346 ret << "eof";
1347 else {
1348 ret << "(";
1349 INLINE_LIST( ret, eofExpr, 0, false );
1350 ret << ")";
1352 return ret.str();
1355 string JavaTabCodeGen::CS()
1357 ostringstream ret;
1358 if ( csExpr == 0 )
1359 ret << ACCESS() << "cs";
1360 else {
1361 /* Emit the user supplied method of retrieving the key. */
1362 ret << "(";
1363 INLINE_LIST( ret, csExpr, 0, false );
1364 ret << ")";
1366 return ret.str();
1369 string JavaTabCodeGen::TOP()
1371 ostringstream ret;
1372 if ( topExpr == 0 )
1373 ret << ACCESS() + "top";
1374 else {
1375 ret << "(";
1376 INLINE_LIST( ret, topExpr, 0, false );
1377 ret << ")";
1379 return ret.str();
1382 string JavaTabCodeGen::STACK()
1384 ostringstream ret;
1385 if ( stackExpr == 0 )
1386 ret << ACCESS() + "stack";
1387 else {
1388 ret << "(";
1389 INLINE_LIST( ret, stackExpr, 0, false );
1390 ret << ")";
1392 return ret.str();
1395 string JavaTabCodeGen::ACT()
1397 ostringstream ret;
1398 if ( actExpr == 0 )
1399 ret << ACCESS() + "act";
1400 else {
1401 ret << "(";
1402 INLINE_LIST( ret, actExpr, 0, false );
1403 ret << ")";
1405 return ret.str();
1408 string JavaTabCodeGen::TOKSTART()
1410 ostringstream ret;
1411 if ( tokstartExpr == 0 )
1412 ret << ACCESS() + "ts";
1413 else {
1414 ret << "(";
1415 INLINE_LIST( ret, tokstartExpr, 0, false );
1416 ret << ")";
1418 return ret.str();
1421 string JavaTabCodeGen::TOKEND()
1423 ostringstream ret;
1424 if ( tokendExpr == 0 )
1425 ret << ACCESS() + "te";
1426 else {
1427 ret << "(";
1428 INLINE_LIST( ret, tokendExpr, 0, false );
1429 ret << ")";
1431 return ret.str();
1434 string JavaTabCodeGen::DATA()
1436 ostringstream ret;
1437 if ( dataExpr == 0 )
1438 ret << ACCESS() + "data";
1439 else {
1440 ret << "(";
1441 INLINE_LIST( ret, dataExpr, 0, false );
1442 ret << ")";
1444 return ret.str();
1448 string JavaTabCodeGen::GET_WIDE_KEY()
1450 if ( redFsm->anyConditions() )
1451 return "_widec";
1452 else
1453 return GET_KEY();
1456 string JavaTabCodeGen::GET_WIDE_KEY( RedStateAp *state )
1458 if ( state->stateCondList.length() > 0 )
1459 return "_widec";
1460 else
1461 return GET_KEY();
1464 /* Write out level number of tabs. Makes the nested binary search nice
1465 * looking. */
1466 string JavaTabCodeGen::TABS( int level )
1468 string result;
1469 while ( level-- > 0 )
1470 result += "\t";
1471 return result;
1474 string JavaTabCodeGen::KEY( Key key )
1476 ostringstream ret;
1477 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
1478 ret << key.getVal();
1479 else
1480 ret << (unsigned long) key.getVal();
1481 return ret.str();
1484 string JavaTabCodeGen::INT( int i )
1486 ostringstream ret;
1487 ret << i;
1488 return ret.str();
1491 void JavaTabCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
1492 int targState, int inFinish )
1494 ret <<
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";
1501 else
1502 ret << " case " << lma->lmId << ":\n";
1504 /* Write the block and close it off. */
1505 ret << " {";
1506 INLINE_LIST( ret, lma->children, targState, inFinish );
1507 ret << "}\n";
1509 ret << " break;\n";
1512 ret <<
1513 " }\n"
1514 "\t";
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;
1528 out << ";";
1531 void JavaTabCodeGen::GET_TOKEND( ostream &ret, InlineItem *item )
1533 ret << TOKEND();
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. */
1556 ret << "{";
1557 INLINE_LIST( ret, item->children, targState, inFinish );
1558 ret << "}";
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. */
1568 ret << "\t{";
1569 INLINE_LIST( ret, action->inlineList, targState, inFinish );
1570 ret << "}\n";
1573 void JavaTabCodeGen::CONDITION( ostream &ret, Action *condition )
1575 ret << "\n";
1576 lineDirective( ret, sourceFileName, condition->loc.line );
1577 INLINE_LIST( ret, condition->inlineList, 0, false );
1580 string JavaTabCodeGen::ERROR_STATE()
1582 ostringstream ret;
1583 if ( redFsm->errState != 0 )
1584 ret << redFsm->errState->id;
1585 else
1586 ret << "-1";
1587 return ret.str();
1590 string JavaTabCodeGen::FIRST_FINAL_STATE()
1592 ostringstream ret;
1593 if ( redFsm->firstFinState != 0 )
1594 ret << redFsm->firstFinState->id;
1595 else
1596 ret << redFsm->nextStateId;
1597 return ret.str();
1600 void JavaTabCodeGen::writeInit()
1602 out << " {\n";
1604 if ( writeCS )
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 ) {
1612 out <<
1613 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
1614 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
1615 " " << ACT() << " = 0;\n";
1617 out << " }\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 )
1634 return;
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. */
1639 analyzeMachine();
1641 /* Determine if we should use indicies. */
1642 calcIndexSize();
1645 ostream &JavaTabCodeGen::source_warning( const InputLoc &loc )
1647 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
1648 return cerr;
1651 ostream &JavaTabCodeGen::source_error( const InputLoc &loc )
1653 gblErrorCount += 1;
1654 assert( sourceFileName != 0 );
1655 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
1656 return cerr;