Added name finding for backend executable. If any forward slash is found in
[ragel.git] / rlgen-java / javacodegen.cpp
blobf9b53a4075733d3114e4ba5d68af954414a8f179
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 8
33 /* Static array initialization item count
34 * (should be multiple of IALL). */
35 #define SAIIC 8192
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::ostream;
44 using std::ostringstream;
45 using std::string;
46 using std::cerr;
47 using std::endl;
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 << "{ _goto_targ = " << _out << "; " << CTRL_FLOW() << " continue _goto;}";
129 void JavaTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
131 ret << CS() << " = " << nextDest << ";";
134 void JavaTabCodeGen::NEXT_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish )
136 ret << CS() << " = (";
137 INLINE_LIST( ret, ilItem->children, 0, inFinish );
138 ret << ");";
141 void JavaTabCodeGen::EXEC( ostream &ret, InlineItem *item, int targState, int inFinish )
143 /* The parser gives fexec two children. The double brackets are for D
144 * code. If the inline list is a single word it will get interpreted as a
145 * C-style cast by the D compiler. */
146 ret << "{" << P() << " = ((";
147 INLINE_LIST( ret, item->children, targState, inFinish );
148 ret << "))-1;}";
151 /* Write out an inline tree structure. Walks the list and possibly calls out
152 * to virtual functions than handle language specific items in the tree. */
153 void JavaTabCodeGen::INLINE_LIST( ostream &ret, InlineList *inlineList,
154 int targState, bool inFinish )
156 for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
157 switch ( item->type ) {
158 case InlineItem::Text:
159 ret << item->data;
160 break;
161 case InlineItem::Goto:
162 GOTO( ret, item->targState->id, inFinish );
163 break;
164 case InlineItem::Call:
165 CALL( ret, item->targState->id, targState, inFinish );
166 break;
167 case InlineItem::Next:
168 NEXT( ret, item->targState->id, inFinish );
169 break;
170 case InlineItem::Ret:
171 RET( ret, inFinish );
172 break;
173 case InlineItem::PChar:
174 ret << P();
175 break;
176 case InlineItem::Char:
177 ret << GET_KEY();
178 break;
179 case InlineItem::Hold:
180 ret << P() << "--;";
181 break;
182 case InlineItem::Exec:
183 EXEC( ret, item, targState, inFinish );
184 break;
185 case InlineItem::Curs:
186 ret << "(_ps)";
187 break;
188 case InlineItem::Targs:
189 ret << "(" << CS() << ")";
190 break;
191 case InlineItem::Entry:
192 ret << item->targState->id;
193 break;
194 case InlineItem::GotoExpr:
195 GOTO_EXPR( ret, item, inFinish );
196 break;
197 case InlineItem::CallExpr:
198 CALL_EXPR( ret, item, targState, inFinish );
199 break;
200 case InlineItem::NextExpr:
201 NEXT_EXPR( ret, item, inFinish );
202 break;
203 case InlineItem::LmSwitch:
204 LM_SWITCH( ret, item, targState, inFinish );
205 break;
206 case InlineItem::LmSetActId:
207 SET_ACT( ret, item );
208 break;
209 case InlineItem::LmSetTokEnd:
210 SET_TOKEND( ret, item );
211 break;
212 case InlineItem::LmGetTokEnd:
213 GET_TOKEND( ret, item );
214 break;
215 case InlineItem::LmInitTokStart:
216 INIT_TOKSTART( ret, item );
217 break;
218 case InlineItem::LmInitAct:
219 INIT_ACT( ret, item );
220 break;
221 case InlineItem::LmSetTokStart:
222 SET_TOKSTART( ret, item );
223 break;
224 case InlineItem::SubAction:
225 SUB_ACTION( ret, item, targState, inFinish );
226 break;
227 case InlineItem::Break:
228 BREAK( ret, targState );
229 break;
234 string JavaTabCodeGen::DATA_PREFIX()
236 if ( dataPrefix )
237 return FSM_NAME() + "_";
238 return "";
241 /* Emit the alphabet data type. */
242 string JavaTabCodeGen::ALPH_TYPE()
244 string ret = keyOps->alphType->data1;
245 if ( keyOps->alphType->data2 != 0 ) {
246 ret += " ";
247 ret += + keyOps->alphType->data2;
249 return ret;
252 /* Emit the alphabet data type. */
253 string JavaTabCodeGen::WIDE_ALPH_TYPE()
255 string ret;
256 if ( redFsm->maxKey <= keyOps->maxKey )
257 ret = ALPH_TYPE();
258 else {
259 long long maxKeyVal = redFsm->maxKey.getLongLong();
260 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
261 assert( wideType != 0 );
263 ret = wideType->data1;
264 if ( wideType->data2 != 0 ) {
265 ret += " ";
266 ret += wideType->data2;
269 return ret;
274 void JavaTabCodeGen::COND_TRANSLATE()
276 out <<
277 " _widec = " << GET_KEY() << ";\n"
278 " _keys = " << CO() << "[" << CS() << "]*2\n;"
279 " _klen = " << CL() << "[" << CS() << "];\n"
280 " if ( _klen > 0 ) {\n"
281 " int _lower = _keys\n;"
282 " int _mid;\n"
283 " int _upper = _keys + (_klen<<1) - 2;\n"
284 " while (true) {\n"
285 " if ( _upper < _lower )\n"
286 " break;\n"
287 "\n"
288 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
289 " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n"
290 " _upper = _mid - 2;\n"
291 " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n"
292 " _lower = _mid + 2;\n"
293 " else {\n"
294 " switch ( " << C() << "[" << CO() << "[" << CS() << "]"
295 " + ((_mid - _keys)>>1)] ) {\n"
298 for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
299 CondSpace *condSpace = csi;
300 out << " case " << condSpace->condSpaceId << ": {\n";
301 out << TABS(2) << "_widec = " << KEY(condSpace->baseKey) <<
302 " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ");\n";
304 for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
305 out << TABS(2) << "if ( ";
306 CONDITION( out, *csi );
307 Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
308 out << " ) _widec += " << condValOffset << ";\n";
311 out <<
312 " break;\n"
313 " }\n";
316 out <<
317 " }\n"
318 " break;\n"
319 " }\n"
320 " }\n"
321 " }\n"
322 "\n";
326 void JavaTabCodeGen::LOCATE_TRANS()
328 out <<
329 " _match: do {\n"
330 " _keys = " << KO() << "[" << CS() << "]" << ";\n"
331 " _trans = " << IO() << "[" << CS() << "];\n"
332 " _klen = " << SL() << "[" << CS() << "];\n"
333 " if ( _klen > 0 ) {\n"
334 " int _lower = _keys;\n"
335 " int _mid;\n"
336 " int _upper = _keys + _klen - 1;\n"
337 " while (true) {\n"
338 " if ( _upper < _lower )\n"
339 " break;\n"
340 "\n"
341 " _mid = _lower + ((_upper-_lower) >> 1);\n"
342 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
343 " _upper = _mid - 1;\n"
344 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n"
345 " _lower = _mid + 1;\n"
346 " else {\n"
347 " _trans += (_mid - _keys);\n"
348 " break _match;\n"
349 " }\n"
350 " }\n"
351 " _keys += _klen;\n"
352 " _trans += _klen;\n"
353 " }\n"
354 "\n"
355 " _klen = " << RL() << "[" << CS() << "];\n"
356 " if ( _klen > 0 ) {\n"
357 " int _lower = _keys;\n"
358 " int _mid;\n"
359 " int _upper = _keys + (_klen<<1) - 2;\n"
360 " while (true) {\n"
361 " if ( _upper < _lower )\n"
362 " break;\n"
363 "\n"
364 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
365 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
366 " _upper = _mid - 2;\n"
367 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n"
368 " _lower = _mid + 2;\n"
369 " else {\n"
370 " _trans += ((_mid - _keys)>>1);\n"
371 " break _match;\n"
372 " }\n"
373 " }\n"
374 " _trans += _klen;\n"
375 " }\n"
376 " } while (false);\n"
377 "\n";
380 /* Determine if we should use indicies or not. */
381 void JavaTabCodeGen::calcIndexSize()
383 int sizeWithInds = 0, sizeWithoutInds = 0;
385 /* Calculate cost of using with indicies. */
386 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
387 int totalIndex = st->outSingle.length() + st->outRange.length() +
388 (st->defTrans == 0 ? 0 : 1);
389 sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
391 sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
392 if ( redFsm->anyActions() )
393 sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
395 /* Calculate the cost of not using indicies. */
396 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
397 int totalIndex = st->outSingle.length() + st->outRange.length() +
398 (st->defTrans == 0 ? 0 : 1);
399 sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
400 if ( redFsm->anyActions() )
401 sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
404 /* If using indicies reduces the size, use them. */
405 useIndicies = sizeWithInds < sizeWithoutInds;
408 int JavaTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
410 int act = 0;
411 if ( state->toStateAction != 0 )
412 act = state->toStateAction->location+1;
413 return act;
416 int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
418 int act = 0;
419 if ( state->fromStateAction != 0 )
420 act = state->fromStateAction->location+1;
421 return act;
424 int JavaTabCodeGen::EOF_ACTION( RedStateAp *state )
426 int act = 0;
427 if ( state->eofAction != 0 )
428 act = state->eofAction->location+1;
429 return act;
433 int JavaTabCodeGen::TRANS_ACTION( RedTransAp *trans )
435 /* If there are actions, emit them. Otherwise emit zero. */
436 int act = 0;
437 if ( trans->action != 0 )
438 act = trans->action->location+1;
439 return act;
442 std::ostream &JavaTabCodeGen::TO_STATE_ACTION_SWITCH()
444 /* Walk the list of functions, printing the cases. */
445 for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
446 /* Write out referenced actions. */
447 if ( act->numToStateRefs > 0 ) {
448 /* Write the case label, the action and the case break. */
449 out << "\tcase " << act->actionId << ":\n";
450 ACTION( out, act, 0, false );
451 out << "\tbreak;\n";
455 genLineDirective( out );
456 return out;
459 std::ostream &JavaTabCodeGen::FROM_STATE_ACTION_SWITCH()
461 /* Walk the list of functions, printing the cases. */
462 for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
463 /* Write out referenced actions. */
464 if ( act->numFromStateRefs > 0 ) {
465 /* Write the case label, the action and the case break. */
466 out << "\tcase " << act->actionId << ":\n";
467 ACTION( out, act, 0, false );
468 out << "\tbreak;\n";
472 genLineDirective( out );
473 return out;
476 std::ostream &JavaTabCodeGen::EOF_ACTION_SWITCH()
478 /* Walk the list of functions, printing the cases. */
479 for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
480 /* Write out referenced actions. */
481 if ( act->numEofRefs > 0 ) {
482 /* Write the case label, the action and the case break. */
483 out << "\tcase " << act->actionId << ":\n";
484 ACTION( out, act, 0, true );
485 out << "\tbreak;\n";
489 genLineDirective( out );
490 return out;
494 std::ostream &JavaTabCodeGen::ACTION_SWITCH()
496 /* Walk the list of functions, printing the cases. */
497 for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
498 /* Write out referenced actions. */
499 if ( act->numTransRefs > 0 ) {
500 /* Write the case label, the action and the case break. */
501 out << "\tcase " << act->actionId << ":\n";
502 ACTION( out, act, 0, false );
503 out << "\tbreak;\n";
507 genLineDirective( out );
508 return out;
511 std::ostream &JavaTabCodeGen::COND_OFFSETS()
513 int curKeyOffset = 0;
514 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
515 /* Write the key offset. */
516 ARRAY_ITEM( INT(curKeyOffset), st.last() );
518 /* Move the key offset ahead. */
519 curKeyOffset += st->stateCondList.length();
521 return out;
524 std::ostream &JavaTabCodeGen::KEY_OFFSETS()
526 int curKeyOffset = 0;
527 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
528 /* Write the key offset. */
529 ARRAY_ITEM( INT(curKeyOffset), st.last() );
531 /* Move the key offset ahead. */
532 curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
534 return out;
538 std::ostream &JavaTabCodeGen::INDEX_OFFSETS()
540 int curIndOffset = 0;
541 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
542 /* Write the index offset. */
543 ARRAY_ITEM( INT(curIndOffset), st.last() );
545 /* Move the index offset ahead. */
546 curIndOffset += st->outSingle.length() + st->outRange.length();
547 if ( st->defTrans != 0 )
548 curIndOffset += 1;
550 return out;
553 std::ostream &JavaTabCodeGen::COND_LENS()
555 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
556 /* Write singles length. */
557 ARRAY_ITEM( INT(st->stateCondList.length()), st.last() );
559 return out;
563 std::ostream &JavaTabCodeGen::SINGLE_LENS()
565 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
566 /* Write singles length. */
567 ARRAY_ITEM( INT(st->outSingle.length()), st.last() );
569 return out;
572 std::ostream &JavaTabCodeGen::RANGE_LENS()
574 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
575 /* Emit length of range index. */
576 ARRAY_ITEM( INT(st->outRange.length()), st.last() );
578 return out;
581 std::ostream &JavaTabCodeGen::TO_STATE_ACTIONS()
583 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
584 /* Write any eof action. */
585 ARRAY_ITEM( INT(TO_STATE_ACTION(st)), st.last() );
587 return out;
590 std::ostream &JavaTabCodeGen::FROM_STATE_ACTIONS()
592 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
593 /* Write any eof action. */
594 ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), st.last() );
596 return out;
599 std::ostream &JavaTabCodeGen::EOF_ACTIONS()
601 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
602 /* Write any eof action. */
603 ARRAY_ITEM( INT(EOF_ACTION(st)), st.last() );
605 return out;
608 std::ostream &JavaTabCodeGen::EOF_TRANS()
610 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
611 /* Write any eof action. */
612 long trans = 0;
613 if ( st->eofTrans != 0 )
614 trans = st->eofTrans->id+1;
616 /* Write any eof action. */
617 ARRAY_ITEM( INT(trans), st.last() );
619 return out;
623 std::ostream &JavaTabCodeGen::COND_KEYS()
625 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
626 /* Loop the state's transitions. */
627 for ( StateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
628 /* Lower key. */
629 ARRAY_ITEM( KEY( sc->lowKey ), false );
630 ARRAY_ITEM( KEY( sc->highKey ), false );
634 /* Output one last number so we don't have to figure out when the last
635 * entry is and avoid writing a comma. */
636 ARRAY_ITEM( INT(0), true );
637 return out;
640 std::ostream &JavaTabCodeGen::COND_SPACES()
642 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
643 /* Loop the state's transitions. */
644 for ( StateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
645 /* Cond Space id. */
646 ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), false );
650 /* Output one last number so we don't have to figure out when the last
651 * entry is and avoid writing a comma. */
652 ARRAY_ITEM( INT(0), true );
653 return out;
656 std::ostream &JavaTabCodeGen::KEYS()
658 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
659 /* Loop the singles. */
660 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
661 ARRAY_ITEM( KEY( stel->lowKey ), false );
664 /* Loop the state's transitions. */
665 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
666 /* Lower key. */
667 ARRAY_ITEM( KEY( rtel->lowKey ), false );
669 /* Upper key. */
670 ARRAY_ITEM( KEY( rtel->highKey ), false );
674 /* Output one last number so we don't have to figure out when the last
675 * entry is and avoid writing a comma. */
676 ARRAY_ITEM( INT(0), true );
677 return out;
680 std::ostream &JavaTabCodeGen::INDICIES()
682 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
683 /* Walk the singles. */
684 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
685 ARRAY_ITEM( KEY( stel->value->id ), false );
688 /* Walk the ranges. */
689 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
690 ARRAY_ITEM( KEY( rtel->value->id ), false );
693 /* The state's default index goes next. */
694 if ( st->defTrans != 0 ) {
695 ARRAY_ITEM( KEY( st->defTrans->id ), false );
699 /* Output one last number so we don't have to figure out when the last
700 * entry is and avoid writing a comma. */
701 ARRAY_ITEM( INT(0), true );
702 return out;
705 std::ostream &JavaTabCodeGen::TRANS_TARGS()
707 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
708 /* Walk the singles. */
709 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
710 RedTransAp *trans = stel->value;
711 ARRAY_ITEM( KEY( trans->targ->id ), false );
714 /* Walk the ranges. */
715 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
716 RedTransAp *trans = rtel->value;
717 ARRAY_ITEM( KEY( trans->targ->id ), false );
720 /* The state's default target state. */
721 if ( st->defTrans != 0 ) {
722 RedTransAp *trans = st->defTrans;
723 ARRAY_ITEM( KEY( trans->targ->id ), false );
727 /* Output one last number so we don't have to figure out when the last
728 * entry is and avoid writing a comma. */
729 ARRAY_ITEM( INT(0), true );
730 return out;
734 std::ostream &JavaTabCodeGen::TRANS_ACTIONS()
736 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
737 /* Walk the singles. */
738 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
739 RedTransAp *trans = stel->value;
740 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
743 /* Walk the ranges. */
744 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
745 RedTransAp *trans = rtel->value;
746 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
749 /* The state's default index goes next. */
750 if ( st->defTrans != 0 ) {
751 RedTransAp *trans = st->defTrans;
752 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
756 /* Output one last number so we don't have to figure out when the last
757 * entry is and avoid writing a comma. */
758 ARRAY_ITEM( INT(0), true );
759 return out;
762 std::ostream &JavaTabCodeGen::TRANS_TARGS_WI()
764 /* Transitions must be written ordered by their id. */
765 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
766 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
767 transPtrs[trans->id] = trans;
769 /* Keep a count of the num of items in the array written. */
770 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
771 /* Write out the target state. */
772 RedTransAp *trans = transPtrs[t];
773 ARRAY_ITEM( INT(trans->targ->id), ( t >= redFsm->transSet.length()-1 ) );
775 delete[] transPtrs;
776 return out;
780 std::ostream &JavaTabCodeGen::TRANS_ACTIONS_WI()
782 /* Transitions must be written ordered by their id. */
783 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
784 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
785 transPtrs[trans->id] = trans;
787 /* Keep a count of the num of items in the array written. */
788 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
789 /* Write the function for the transition. */
790 RedTransAp *trans = transPtrs[t];
791 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ( t >= redFsm->transSet.length()-1 ) );
793 delete[] transPtrs;
794 return out;
797 void JavaTabCodeGen::writeExports()
799 if ( exportList.length() > 0 ) {
800 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
801 STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name )
802 << " = " << KEY(ex->key) << ";\n";
804 out << "\n";
808 void JavaTabCodeGen::writeData()
810 /* If there are any transtion functions then output the array. If there
811 * are none, don't bother emitting an empty array that won't be used. */
812 if ( redFsm->anyActions() ) {
813 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
814 ACTIONS_ARRAY();
815 CLOSE_ARRAY() <<
816 "\n";
819 if ( redFsm->anyConditions() ) {
820 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
821 COND_OFFSETS();
822 CLOSE_ARRAY() <<
823 "\n";
825 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
826 COND_LENS();
827 CLOSE_ARRAY() <<
828 "\n";
830 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
831 COND_KEYS();
832 CLOSE_ARRAY() <<
833 "\n";
835 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
836 COND_SPACES();
837 CLOSE_ARRAY() <<
838 "\n";
841 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
842 KEY_OFFSETS();
843 CLOSE_ARRAY() <<
844 "\n";
846 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
847 KEYS();
848 CLOSE_ARRAY() <<
849 "\n";
851 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
852 SINGLE_LENS();
853 CLOSE_ARRAY() <<
854 "\n";
856 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
857 RANGE_LENS();
858 CLOSE_ARRAY() <<
859 "\n";
861 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
862 INDEX_OFFSETS();
863 CLOSE_ARRAY() <<
864 "\n";
866 if ( useIndicies ) {
867 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
868 INDICIES();
869 CLOSE_ARRAY() <<
870 "\n";
872 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
873 TRANS_TARGS_WI();
874 CLOSE_ARRAY() <<
875 "\n";
877 if ( redFsm->anyActions() ) {
878 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
879 TRANS_ACTIONS_WI();
880 CLOSE_ARRAY() <<
881 "\n";
884 else {
885 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
886 TRANS_TARGS();
887 CLOSE_ARRAY() <<
888 "\n";
890 if ( redFsm->anyActions() ) {
891 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
892 TRANS_ACTIONS();
893 CLOSE_ARRAY() <<
894 "\n";
898 if ( redFsm->anyToStateActions() ) {
899 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
900 TO_STATE_ACTIONS();
901 CLOSE_ARRAY() <<
902 "\n";
905 if ( redFsm->anyFromStateActions() ) {
906 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
907 FROM_STATE_ACTIONS();
908 CLOSE_ARRAY() <<
909 "\n";
912 if ( redFsm->anyEofActions() ) {
913 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
914 EOF_ACTIONS();
915 CLOSE_ARRAY() <<
916 "\n";
919 if ( redFsm->anyEofTrans() ) {
920 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex+1), ET() );
921 EOF_TRANS();
922 CLOSE_ARRAY() <<
923 "\n";
926 if ( redFsm->startState != 0 )
927 STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
929 if ( writeFirstFinal )
930 STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
932 if ( writeErr )
933 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
935 out << "\n";
937 if ( entryPointNames.length() > 0 ) {
938 for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
939 STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) <<
940 " = " << entryPointIds[en.pos()] << ";\n";
942 out << "\n";
946 void JavaTabCodeGen::writeExec()
948 out <<
949 " {\n"
950 " int _klen";
952 if ( redFsm->anyRegCurStateRef() )
953 out << ", _ps";
955 out <<
956 ";\n"
957 " int _trans = 0;\n";
959 if ( redFsm->anyConditions() )
960 out << " int _widec;\n";
962 if ( redFsm->anyToStateActions() || redFsm->anyRegActions() ||
963 redFsm->anyFromStateActions() )
965 out <<
966 " int _acts;\n"
967 " int _nacts;\n";
970 out <<
971 " int _keys;\n"
972 " int _goto_targ = 0;\n"
973 "\n";
975 out <<
976 " _goto: while (true) {\n"
977 " switch ( _goto_targ ) {\n"
978 " case 0:\n";
980 if ( hasEnd ) {
981 out <<
982 " if ( " << P() << " == " << PE() << " ) {\n"
983 " _goto_targ = " << _test_eof << ";\n"
984 " continue _goto;\n"
985 " }\n";
988 if ( redFsm->errState != 0 ) {
989 out <<
990 " if ( " << CS() << " == " << redFsm->errState->id << " ) {\n"
991 " _goto_targ = " << _out << ";\n"
992 " continue _goto;\n"
993 " }\n";
996 out << "case " << _resume << ":\n";
998 if ( redFsm->anyFromStateActions() ) {
999 out <<
1000 " _acts = " << FSA() << "[" << CS() << "]" << ";\n"
1001 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1002 " while ( _nacts-- > 0 ) {\n"
1003 " switch ( " << A() << "[_acts++] ) {\n";
1004 FROM_STATE_ACTION_SWITCH() <<
1005 " }\n"
1006 " }\n"
1007 "\n";
1010 if ( redFsm->anyConditions() )
1011 COND_TRANSLATE();
1013 LOCATE_TRANS();
1015 if ( useIndicies )
1016 out << " _trans = " << I() << "[_trans];\n";
1018 if ( redFsm->anyEofTrans() )
1019 out << "case " << _eof_trans << ":\n";
1021 if ( redFsm->anyRegCurStateRef() )
1022 out << " _ps = " << CS() << ";\n";
1024 out <<
1025 " " << CS() << " = " << TT() << "[_trans];\n"
1026 "\n";
1028 if ( redFsm->anyRegActions() ) {
1029 out <<
1030 " if ( " << TA() << "[_trans] != 0 ) {\n"
1031 " _acts = " << TA() << "[_trans]" << ";\n"
1032 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1033 " while ( _nacts-- > 0 )\n {\n"
1034 " switch ( " << A() << "[_acts++] )\n"
1035 " {\n";
1036 ACTION_SWITCH() <<
1037 " }\n"
1038 " }\n"
1039 " }\n"
1040 "\n";
1043 out << "case " << _again << ":\n";
1045 if ( redFsm->anyToStateActions() ) {
1046 out <<
1047 " _acts = " << TSA() << "[" << CS() << "]" << ";\n"
1048 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1049 " while ( _nacts-- > 0 ) {\n"
1050 " switch ( " << A() << "[_acts++] ) {\n";
1051 TO_STATE_ACTION_SWITCH() <<
1052 " }\n"
1053 " }\n"
1054 "\n";
1057 if ( redFsm->errState != 0 ) {
1058 out <<
1059 " if ( " << CS() << " == " << redFsm->errState->id << " ) {\n"
1060 " _goto_targ = " << _out << ";\n"
1061 " continue _goto;\n"
1062 " }\n";
1065 if ( hasEnd ) {
1066 out <<
1067 " if ( ++" << P() << " != " << PE() << " ) {\n"
1068 " _goto_targ = " << _resume << ";\n"
1069 " continue _goto;\n"
1070 " }\n";
1072 else {
1073 out <<
1074 " " << P() << " += 1;\n"
1075 " _goto_targ = " << _resume << ";\n"
1076 " continue _goto;\n";
1079 out << "case " << _test_eof << ":\n";
1081 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
1082 out <<
1083 " if ( " << P() << " == " << EOFV() << " )\n"
1084 " {\n";
1086 if ( redFsm->anyEofTrans() ) {
1087 out <<
1088 " if ( " << ET() << "[" << CS() << "] > 0 ) {\n"
1089 " _trans = " << ET() << "[" << CS() << "] - 1;\n"
1090 " _goto_targ = " << _eof_trans << ";\n"
1091 " continue _goto;\n"
1092 " }\n";
1095 if ( redFsm->anyEofActions() ) {
1096 out <<
1097 " int __acts = " << EA() << "[" << CS() << "]" << ";\n"
1098 " int __nacts = " << CAST("int") << " " << A() << "[__acts++];\n"
1099 " while ( __nacts-- > 0 ) {\n"
1100 " switch ( " << A() << "[__acts++] ) {\n";
1101 EOF_ACTION_SWITCH() <<
1102 " }\n"
1103 " }\n";
1106 out <<
1107 " }\n"
1108 "\n";
1111 out << "case " << _out << ":\n";
1113 /* The switch and goto loop. */
1114 out << " }\n";
1115 out << " break; }\n";
1117 /* The execute block. */
1118 out << " }\n";
1121 std::ostream &JavaTabCodeGen::OPEN_ARRAY( string type, string name )
1123 array_type = type;
1124 array_name = name;
1125 item_count = 0;
1126 div_count = 1;
1128 out <<
1129 "private static void init_" << name << "_0( " << type << "[] r )\n"
1130 "{\n\t";
1132 return out;
1135 std::ostream &JavaTabCodeGen::ARRAY_ITEM( string item, bool last )
1137 out << "r[" << item_count << "]=" << item << "; ";
1139 item_count += 1;
1141 if ( !last ) {
1142 if ( item_count % SAIIC == 0 ) {
1143 out << "\n}\n\n";
1144 out << "private static void init_" << array_name << "_" << div_count <<
1145 "( " << array_type << "[] r )\n{\n\t";
1146 div_count += 1;
1148 else if ( item_count % IALL == 0 )
1149 out << "\n\t";
1152 return out;
1155 std::ostream &JavaTabCodeGen::CLOSE_ARRAY()
1157 out << "\n}\n\n";
1159 out <<
1160 "private static " << array_type << "[] create_" << array_name << "( )\n"
1161 "{\n"
1162 " " << array_type << "[] r = new " << array_type << "[" << item_count << "];\n";
1164 for ( int i = 0; i < div_count; i++ )
1165 out << " init_" << array_name << "_" << i << "( r );\n";
1167 out <<
1168 " return r;\n"
1169 "}\n"
1170 "\n";
1172 out <<
1173 "private static final " << array_type << " " << array_name <<
1174 "[] = create_" << array_name << "();\n\n";
1176 return out;
1180 std::ostream &JavaTabCodeGen::STATIC_VAR( string type, string name )
1182 out << "static final " << type << " " << name;
1183 return out;
1186 string JavaTabCodeGen::ARR_OFF( string ptr, string offset )
1188 return ptr + " + " + offset;
1191 string JavaTabCodeGen::CAST( string type )
1193 return "(" + type + ")";
1196 string JavaTabCodeGen::NULL_ITEM()
1198 /* In java we use integers instead of pointers. */
1199 return "-1";
1202 string JavaTabCodeGen::GET_KEY()
1204 ostringstream ret;
1205 if ( getKeyExpr != 0 ) {
1206 /* Emit the user supplied method of retrieving the key. */
1207 ret << "(";
1208 INLINE_LIST( ret, getKeyExpr, 0, false );
1209 ret << ")";
1211 else {
1212 /* Expression for retrieving the key, use simple dereference. */
1213 ret << DATA() << "[" << P() << "]";
1215 return ret.str();
1218 string JavaTabCodeGen::CTRL_FLOW()
1220 return "if (true) ";
1223 unsigned int JavaTabCodeGen::arrayTypeSize( unsigned long maxVal )
1225 long long maxValLL = (long long) maxVal;
1226 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
1227 assert( arrayType != 0 );
1228 return arrayType->size;
1231 string JavaTabCodeGen::ARRAY_TYPE( unsigned long maxVal )
1233 long long maxValLL = (long long) maxVal;
1234 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
1235 assert( arrayType != 0 );
1237 string ret = arrayType->data1;
1238 if ( arrayType->data2 != 0 ) {
1239 ret += " ";
1240 ret += arrayType->data2;
1242 return ret;
1246 /* Write out the fsm name. */
1247 string JavaTabCodeGen::FSM_NAME()
1249 return fsmName;
1252 /* Emit the offset of the start state as a decimal integer. */
1253 string JavaTabCodeGen::START_STATE_ID()
1255 ostringstream ret;
1256 ret << redFsm->startState->id;
1257 return ret.str();
1260 /* Write out the array of actions. */
1261 std::ostream &JavaTabCodeGen::ACTIONS_ARRAY()
1263 ARRAY_ITEM( INT(0), false );
1264 for ( ActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
1265 /* Write out the length, which will never be the last character. */
1266 ARRAY_ITEM( INT(act->key.length()), false );
1268 for ( ActionTable::Iter item = act->key; item.lte(); item++ )
1269 ARRAY_ITEM( INT(item->value->actionId), (act.last() && item.last()) );
1271 return out;
1275 string JavaTabCodeGen::ACCESS()
1277 ostringstream ret;
1278 if ( accessExpr != 0 )
1279 INLINE_LIST( ret, accessExpr, 0, false );
1280 return ret.str();
1283 string JavaTabCodeGen::P()
1285 ostringstream ret;
1286 if ( pExpr == 0 )
1287 ret << "p";
1288 else {
1289 ret << "(";
1290 INLINE_LIST( ret, pExpr, 0, false );
1291 ret << ")";
1293 return ret.str();
1296 string JavaTabCodeGen::PE()
1298 ostringstream ret;
1299 if ( peExpr == 0 )
1300 ret << "pe";
1301 else {
1302 ret << "(";
1303 INLINE_LIST( ret, peExpr, 0, false );
1304 ret << ")";
1306 return ret.str();
1309 string JavaTabCodeGen::EOFV()
1311 ostringstream ret;
1312 if ( eofExpr == 0 )
1313 ret << "eof";
1314 else {
1315 ret << "(";
1316 INLINE_LIST( ret, eofExpr, 0, false );
1317 ret << ")";
1319 return ret.str();
1322 string JavaTabCodeGen::CS()
1324 ostringstream ret;
1325 if ( csExpr == 0 )
1326 ret << ACCESS() << "cs";
1327 else {
1328 /* Emit the user supplied method of retrieving the key. */
1329 ret << "(";
1330 INLINE_LIST( ret, csExpr, 0, false );
1331 ret << ")";
1333 return ret.str();
1336 string JavaTabCodeGen::TOP()
1338 ostringstream ret;
1339 if ( topExpr == 0 )
1340 ret << ACCESS() + "top";
1341 else {
1342 ret << "(";
1343 INLINE_LIST( ret, topExpr, 0, false );
1344 ret << ")";
1346 return ret.str();
1349 string JavaTabCodeGen::STACK()
1351 ostringstream ret;
1352 if ( stackExpr == 0 )
1353 ret << ACCESS() + "stack";
1354 else {
1355 ret << "(";
1356 INLINE_LIST( ret, stackExpr, 0, false );
1357 ret << ")";
1359 return ret.str();
1362 string JavaTabCodeGen::ACT()
1364 ostringstream ret;
1365 if ( actExpr == 0 )
1366 ret << ACCESS() + "act";
1367 else {
1368 ret << "(";
1369 INLINE_LIST( ret, actExpr, 0, false );
1370 ret << ")";
1372 return ret.str();
1375 string JavaTabCodeGen::TOKSTART()
1377 ostringstream ret;
1378 if ( tokstartExpr == 0 )
1379 ret << ACCESS() + "tokstart";
1380 else {
1381 ret << "(";
1382 INLINE_LIST( ret, tokstartExpr, 0, false );
1383 ret << ")";
1385 return ret.str();
1388 string JavaTabCodeGen::TOKEND()
1390 ostringstream ret;
1391 if ( tokendExpr == 0 )
1392 ret << ACCESS() + "tokend";
1393 else {
1394 ret << "(";
1395 INLINE_LIST( ret, tokendExpr, 0, false );
1396 ret << ")";
1398 return ret.str();
1401 string JavaTabCodeGen::DATA()
1403 ostringstream ret;
1404 if ( dataExpr == 0 )
1405 ret << ACCESS() + "data";
1406 else {
1407 ret << "(";
1408 INLINE_LIST( ret, dataExpr, 0, false );
1409 ret << ")";
1411 return ret.str();
1415 string JavaTabCodeGen::GET_WIDE_KEY()
1417 if ( redFsm->anyConditions() )
1418 return "_widec";
1419 else
1420 return GET_KEY();
1423 string JavaTabCodeGen::GET_WIDE_KEY( RedStateAp *state )
1425 if ( state->stateCondList.length() > 0 )
1426 return "_widec";
1427 else
1428 return GET_KEY();
1431 /* Write out level number of tabs. Makes the nested binary search nice
1432 * looking. */
1433 string JavaTabCodeGen::TABS( int level )
1435 string result;
1436 while ( level-- > 0 )
1437 result += "\t";
1438 return result;
1441 string JavaTabCodeGen::KEY( Key key )
1443 ostringstream ret;
1444 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
1445 ret << key.getVal();
1446 else
1447 ret << (unsigned long) key.getVal();
1448 return ret.str();
1451 string JavaTabCodeGen::INT( int i )
1453 ostringstream ret;
1454 ret << i;
1455 return ret.str();
1458 void JavaTabCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
1459 int targState, int inFinish )
1461 ret <<
1462 " switch( " << ACT() << " ) {\n";
1464 for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
1465 /* Write the case label, the action and the case break. */
1466 ret << " case " << lma->lmId << ":\n";
1468 /* Write the block and close it off. */
1469 ret << " {";
1470 INLINE_LIST( ret, lma->children, targState, inFinish );
1471 ret << "}\n";
1473 ret << " break;\n";
1475 /* Default required for D code. */
1476 ret <<
1477 " default: break;\n"
1478 " }\n"
1479 "\t";
1482 void JavaTabCodeGen::SET_ACT( ostream &ret, InlineItem *item )
1484 ret << ACT() << " = " << item->lmId << ";";
1487 void JavaTabCodeGen::SET_TOKEND( ostream &ret, InlineItem *item )
1489 /* The tokend action sets tokend. */
1490 ret << TOKEND() << " = " << P();
1491 if ( item->offset != 0 )
1492 out << "+" << item->offset;
1493 out << ";";
1496 void JavaTabCodeGen::GET_TOKEND( ostream &ret, InlineItem *item )
1498 ret << TOKEND();
1501 void JavaTabCodeGen::INIT_TOKSTART( ostream &ret, InlineItem *item )
1503 ret << TOKSTART() << " = " << NULL_ITEM() << ";";
1506 void JavaTabCodeGen::INIT_ACT( ostream &ret, InlineItem *item )
1508 ret << ACT() << " = 0;";
1511 void JavaTabCodeGen::SET_TOKSTART( ostream &ret, InlineItem *item )
1513 ret << TOKSTART() << " = " << P() << ";";
1516 void JavaTabCodeGen::SUB_ACTION( ostream &ret, InlineItem *item,
1517 int targState, bool inFinish )
1519 if ( item->children->length() > 0 ) {
1520 /* Write the block and close it off. */
1521 ret << "{";
1522 INLINE_LIST( ret, item->children, targState, inFinish );
1523 ret << "}";
1527 void JavaTabCodeGen::ACTION( ostream &ret, Action *action, int targState, bool inFinish )
1529 /* Write the preprocessor line info for going into the source file. */
1530 lineDirective( ret, sourceFileName, action->loc.line );
1532 /* Write the block and close it off. */
1533 ret << "\t{";
1534 INLINE_LIST( ret, action->inlineList, targState, inFinish );
1535 ret << "}\n";
1538 void JavaTabCodeGen::CONDITION( ostream &ret, Action *condition )
1540 ret << "\n";
1541 lineDirective( ret, sourceFileName, condition->loc.line );
1542 INLINE_LIST( ret, condition->inlineList, 0, false );
1545 string JavaTabCodeGen::ERROR_STATE()
1547 ostringstream ret;
1548 if ( redFsm->errState != 0 )
1549 ret << redFsm->errState->id;
1550 else
1551 ret << "-1";
1552 return ret.str();
1555 string JavaTabCodeGen::FIRST_FINAL_STATE()
1557 ostringstream ret;
1558 if ( redFsm->firstFinState != 0 )
1559 ret << redFsm->firstFinState->id;
1560 else
1561 ret << redFsm->nextStateId;
1562 return ret.str();
1565 void JavaTabCodeGen::writeInit()
1567 out << " {\n";
1569 if ( writeCS )
1570 out << "\t" << CS() << " = " << START() << ";\n";
1572 /* If there are any calls, then the stack top needs initialization. */
1573 if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
1574 out << "\t" << TOP() << " = 0;\n";
1576 if ( hasLongestMatch ) {
1577 out <<
1578 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
1579 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
1580 " " << ACT() << " = 0;\n";
1582 out << " }\n";
1585 void JavaTabCodeGen::finishRagelDef()
1587 /* The frontend will do this for us, but it may be a good idea to force it
1588 * if the intermediate file is edited. */
1589 redFsm->sortByStateId();
1591 /* Choose default transitions and the single transition. */
1592 redFsm->chooseDefaultSpan();
1594 /* Maybe do flat expand, otherwise choose single. */
1595 redFsm->chooseSingle();
1597 /* If any errors have occured in the input file then don't write anything. */
1598 if ( gblErrorCount > 0 )
1599 return;
1601 /* Anlayze Machine will find the final action reference counts, among
1602 * other things. We will use these in reporting the usage
1603 * of fsm directives in action code. */
1604 analyzeMachine();
1606 /* Determine if we should use indicies. */
1607 calcIndexSize();
1610 ostream &JavaTabCodeGen::source_warning( const InputLoc &loc )
1612 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
1613 return cerr;
1616 ostream &JavaTabCodeGen::source_error( const InputLoc &loc )
1618 gblErrorCount += 1;
1619 assert( sourceFileName != 0 );
1620 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
1621 return cerr;