"Fossies" - the Fresh Open Source Software Archive 
Member "ragel-6.10/ragel/javacodegen.cpp" (24 Mar 2017, 40555 Bytes) of package /linux/misc/ragel-6.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "javacodegen.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
6.9_vs_6.10.
1 /*
2 * Copyright 2006-2007 Adrian Thurston <thurston@complang.org>
3 * 2007 Colin Fleming <colin.fleming@caverock.com>
4 */
5
6 /* This file is part of Ragel.
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "ragel.h"
24 #include "javacodegen.h"
25 #include "redfsm.h"
26 #include "gendata.h"
27 #include <iomanip>
28 #include <sstream>
29
30 /* Integer array line length. */
31 #define IALL 12
32
33 /* Static array initialization item count
34 * (should be multiple of IALL). */
35 #define SAIIC 8184
36
37 #define _resume 1
38 #define _again 2
39 #define _eof_trans 3
40 #define _test_eof 4
41 #define _out 5
42
43 using std::setw;
44 using std::ios;
45 using std::ostringstream;
46 using std::string;
47 using std::cerr;
48
49 using std::istream;
50 using std::ifstream;
51 using std::ostream;
52 using std::ios;
53 using std::cin;
54 using std::cout;
55 using std::cerr;
56 using std::endl;
57 using std::setiosflags;
58
59 void javaLineDirective( ostream &out, const char *fileName, int line )
60 {
61 /* Write the preprocessor line info for to the input file. */
62 out << "// line " << line << " \"";
63 for ( const char *pc = fileName; *pc != 0; pc++ ) {
64 if ( *pc == '\\' )
65 out << "\\\\";
66 else
67 out << *pc;
68 }
69 out << "\"\n";
70 }
71
72 void JavaTabCodeGen::genLineDirective( ostream &out )
73 {
74 std::streambuf *sbuf = out.rdbuf();
75 output_filter *filter = static_cast<output_filter*>(sbuf);
76 javaLineDirective( out, filter->fileName, filter->line + 1 );
77 }
78
79 void JavaTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
80 {
81 ret << "{" << vCS() << " = " << gotoDest << "; _goto_targ = " << _again << "; " <<
82 CTRL_FLOW() << "continue _goto;}";
83 }
84
85 void JavaTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
86 {
87 ret << "{" << vCS() << " = (";
88 INLINE_LIST( ret, ilItem->children, 0, inFinish );
89 ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
90 }
91
92 void JavaTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
93 {
94 if ( prePushExpr != 0 ) {
95 ret << "{";
96 INLINE_LIST( ret, prePushExpr, 0, false );
97 }
98
99 ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " <<
100 callDest << "; _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
101
102 if ( prePushExpr != 0 )
103 ret << "}";
104 }
105
106 void JavaTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
107 {
108 if ( prePushExpr != 0 ) {
109 ret << "{";
110 INLINE_LIST( ret, prePushExpr, 0, false );
111 }
112
113 ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
114 INLINE_LIST( ret, ilItem->children, targState, inFinish );
115 ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
116
117 if ( prePushExpr != 0 )
118 ret << "}";
119 }
120
121 void JavaTabCodeGen::RET( ostream &ret, bool inFinish )
122 {
123 ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];";
124
125 if ( postPopExpr != 0 ) {
126 ret << "{";
127 INLINE_LIST( ret, postPopExpr, 0, false );
128 ret << "}";
129 }
130
131 ret << "_goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
132 }
133
134 void JavaTabCodeGen::BREAK( ostream &ret, int targState )
135 {
136 ret << "{ " << P() << " += 1; _goto_targ = " << _out << "; " <<
137 CTRL_FLOW() << " continue _goto;}";
138 }
139
140 void JavaTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
141 {
142 ret << vCS() << " = " << nextDest << ";";
143 }
144
145 void JavaTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
146 {
147 ret << vCS() << " = (";
148 INLINE_LIST( ret, ilItem->children, 0, inFinish );
149 ret << ");";
150 }
151
152 void JavaTabCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
153 {
154 /* The parser gives fexec two children. The double brackets are for D
155 * code. If the inline list is a single word it will get interpreted as a
156 * C-style cast by the D compiler. */
157 ret << "{" << P() << " = ((";
158 INLINE_LIST( ret, item->children, targState, inFinish );
159 ret << "))-1;}";
160 }
161
162 /* Write out an inline tree structure. Walks the list and possibly calls out
163 * to virtual functions than handle language specific items in the tree. */
164 void JavaTabCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList,
165 int targState, bool inFinish )
166 {
167 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
168 switch ( item->type ) {
169 case GenInlineItem::Text:
170 ret << item->data;
171 break;
172 case GenInlineItem::Goto:
173 GOTO( ret, item->targState->id, inFinish );
174 break;
175 case GenInlineItem::Call:
176 CALL( ret, item->targState->id, targState, inFinish );
177 break;
178 case GenInlineItem::Next:
179 NEXT( ret, item->targState->id, inFinish );
180 break;
181 case GenInlineItem::Ret:
182 RET( ret, inFinish );
183 break;
184 case GenInlineItem::PChar:
185 ret << P();
186 break;
187 case GenInlineItem::Char:
188 ret << GET_KEY();
189 break;
190 case GenInlineItem::Hold:
191 ret << P() << "--;";
192 break;
193 case GenInlineItem::Exec:
194 EXEC( ret, item, targState, inFinish );
195 break;
196 case GenInlineItem::Curs:
197 ret << "(_ps)";
198 break;
199 case GenInlineItem::Targs:
200 ret << "(" << vCS() << ")";
201 break;
202 case GenInlineItem::Entry:
203 ret << item->targState->id;
204 break;
205 case GenInlineItem::GotoExpr:
206 GOTO_EXPR( ret, item, inFinish );
207 break;
208 case GenInlineItem::CallExpr:
209 CALL_EXPR( ret, item, targState, inFinish );
210 break;
211 case GenInlineItem::NextExpr:
212 NEXT_EXPR( ret, item, inFinish );
213 break;
214 case GenInlineItem::LmSwitch:
215 LM_SWITCH( ret, item, targState, inFinish );
216 break;
217 case GenInlineItem::LmSetActId:
218 SET_ACT( ret, item );
219 break;
220 case GenInlineItem::LmSetTokEnd:
221 SET_TOKEND( ret, item );
222 break;
223 case GenInlineItem::LmGetTokEnd:
224 GET_TOKEND( ret, item );
225 break;
226 case GenInlineItem::LmInitTokStart:
227 INIT_TOKSTART( ret, item );
228 break;
229 case GenInlineItem::LmInitAct:
230 INIT_ACT( ret, item );
231 break;
232 case GenInlineItem::LmSetTokStart:
233 SET_TOKSTART( ret, item );
234 break;
235 case GenInlineItem::SubAction:
236 SUB_ACTION( ret, item, targState, inFinish );
237 break;
238 case GenInlineItem::Break:
239 BREAK( ret, targState );
240 break;
241 }
242 }
243 }
244
245 string JavaTabCodeGen::DATA_PREFIX()
246 {
247 if ( !noPrefix )
248 return FSM_NAME() + "_";
249 return "";
250 }
251
252 /* Emit the alphabet data type. */
253 string JavaTabCodeGen::ALPH_TYPE()
254 {
255 string ret = keyOps->alphType->data1;
256 if ( keyOps->alphType->data2 != 0 ) {
257 ret += " ";
258 ret += + keyOps->alphType->data2;
259 }
260 return ret;
261 }
262
263 /* Emit the alphabet data type. */
264 string JavaTabCodeGen::WIDE_ALPH_TYPE()
265 {
266 string ret;
267 if ( redFsm->maxKey <= keyOps->maxKey )
268 ret = ALPH_TYPE();
269 else {
270 long long maxKeyVal = redFsm->maxKey.getLongLong();
271 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
272 assert( wideType != 0 );
273
274 ret = wideType->data1;
275 if ( wideType->data2 != 0 ) {
276 ret += " ";
277 ret += wideType->data2;
278 }
279 }
280 return ret;
281 }
282
283
284
285 void JavaTabCodeGen::COND_TRANSLATE()
286 {
287 out <<
288 " _widec = " << GET_KEY() << ";\n"
289 " _keys = " << CO() << "[" << vCS() << "]*2\n;"
290 " _klen = " << CL() << "[" << vCS() << "];\n"
291 " if ( _klen > 0 ) {\n"
292 " int _lower = _keys\n;"
293 " int _mid;\n"
294 " int _upper = _keys + (_klen<<1) - 2;\n"
295 " while (true) {\n"
296 " if ( _upper < _lower )\n"
297 " break;\n"
298 "\n"
299 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
300 " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n"
301 " _upper = _mid - 2;\n"
302 " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n"
303 " _lower = _mid + 2;\n"
304 " else {\n"
305 " switch ( " << C() << "[" << CO() << "[" << vCS() << "]"
306 " + ((_mid - _keys)>>1)] ) {\n"
307 ;
308
309 for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
310 GenCondSpace *condSpace = csi;
311 out << " case " << condSpace->condSpaceId << ": {\n";
312 out << TABS(2) << "_widec = " << KEY(condSpace->baseKey) <<
313 " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ");\n";
314
315 for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
316 out << TABS(2) << "if ( ";
317 CONDITION( out, *csi );
318 Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
319 out << " ) _widec += " << condValOffset << ";\n";
320 }
321
322 out <<
323 " break;\n"
324 " }\n";
325 }
326
327 out <<
328 " }\n"
329 " break;\n"
330 " }\n"
331 " }\n"
332 " }\n"
333 "\n";
334 }
335
336
337 void JavaTabCodeGen::LOCATE_TRANS()
338 {
339 out <<
340 " _match: do {\n"
341 " _keys = " << KO() << "[" << vCS() << "]" << ";\n"
342 " _trans = " << IO() << "[" << vCS() << "];\n"
343 " _klen = " << SL() << "[" << vCS() << "];\n"
344 " if ( _klen > 0 ) {\n"
345 " int _lower = _keys;\n"
346 " int _mid;\n"
347 " int _upper = _keys + _klen - 1;\n"
348 " while (true) {\n"
349 " if ( _upper < _lower )\n"
350 " break;\n"
351 "\n"
352 " _mid = _lower + ((_upper-_lower) >> 1);\n"
353 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
354 " _upper = _mid - 1;\n"
355 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n"
356 " _lower = _mid + 1;\n"
357 " else {\n"
358 " _trans += (_mid - _keys);\n"
359 " break _match;\n"
360 " }\n"
361 " }\n"
362 " _keys += _klen;\n"
363 " _trans += _klen;\n"
364 " }\n"
365 "\n"
366 " _klen = " << RL() << "[" << vCS() << "];\n"
367 " if ( _klen > 0 ) {\n"
368 " int _lower = _keys;\n"
369 " int _mid;\n"
370 " int _upper = _keys + (_klen<<1) - 2;\n"
371 " while (true) {\n"
372 " if ( _upper < _lower )\n"
373 " break;\n"
374 "\n"
375 " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
376 " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
377 " _upper = _mid - 2;\n"
378 " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n"
379 " _lower = _mid + 2;\n"
380 " else {\n"
381 " _trans += ((_mid - _keys)>>1);\n"
382 " break _match;\n"
383 " }\n"
384 " }\n"
385 " _trans += _klen;\n"
386 " }\n"
387 " } while (false);\n"
388 "\n";
389 }
390
391 /* Determine if we should use indicies or not. */
392 void JavaTabCodeGen::calcIndexSize()
393 {
394 int sizeWithInds = 0, sizeWithoutInds = 0;
395
396 /* Calculate cost of using with 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 sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
401 }
402 sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
403 if ( redFsm->anyActions() )
404 sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
405
406 /* Calculate the cost of not using indicies. */
407 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
408 int totalIndex = st->outSingle.length() + st->outRange.length() +
409 (st->defTrans == 0 ? 0 : 1);
410 sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
411 if ( redFsm->anyActions() )
412 sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
413 }
414
415 /* If using indicies reduces the size, use them. */
416 useIndicies = sizeWithInds < sizeWithoutInds;
417 }
418
419 int JavaTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
420 {
421 int act = 0;
422 if ( state->toStateAction != 0 )
423 act = state->toStateAction->location+1;
424 return act;
425 }
426
427 int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
428 {
429 int act = 0;
430 if ( state->fromStateAction != 0 )
431 act = state->fromStateAction->location+1;
432 return act;
433 }
434
435 int JavaTabCodeGen::EOF_ACTION( RedStateAp *state )
436 {
437 int act = 0;
438 if ( state->eofAction != 0 )
439 act = state->eofAction->location+1;
440 return act;
441 }
442
443
444 int JavaTabCodeGen::TRANS_ACTION( RedTransAp *trans )
445 {
446 /* If there are actions, emit them. Otherwise emit zero. */
447 int act = 0;
448 if ( trans->action != 0 )
449 act = trans->action->location+1;
450 return act;
451 }
452
453 std::ostream &JavaTabCodeGen::TO_STATE_ACTION_SWITCH()
454 {
455 /* Walk the list of functions, printing the cases. */
456 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
457 /* Write out referenced actions. */
458 if ( act->numToStateRefs > 0 ) {
459 /* Write the case label, the action and the case break. */
460 out << "\tcase " << act->actionId << ":\n";
461 ACTION( out, act, 0, false );
462 out << "\tbreak;\n";
463 }
464 }
465
466 genLineDirective( out );
467 return out;
468 }
469
470 std::ostream &JavaTabCodeGen::FROM_STATE_ACTION_SWITCH()
471 {
472 /* Walk the list of functions, printing the cases. */
473 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
474 /* Write out referenced actions. */
475 if ( act->numFromStateRefs > 0 ) {
476 /* Write the case label, the action and the case break. */
477 out << "\tcase " << act->actionId << ":\n";
478 ACTION( out, act, 0, false );
479 out << "\tbreak;\n";
480 }
481 }
482
483 genLineDirective( out );
484 return out;
485 }
486
487 std::ostream &JavaTabCodeGen::EOF_ACTION_SWITCH()
488 {
489 /* Walk the list of functions, printing the cases. */
490 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
491 /* Write out referenced actions. */
492 if ( act->numEofRefs > 0 ) {
493 /* Write the case label, the action and the case break. */
494 out << "\tcase " << act->actionId << ":\n";
495 ACTION( out, act, 0, true );
496 out << "\tbreak;\n";
497 }
498 }
499
500 genLineDirective( out );
501 return out;
502 }
503
504
505 std::ostream &JavaTabCodeGen::ACTION_SWITCH()
506 {
507 /* Walk the list of functions, printing the cases. */
508 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
509 /* Write out referenced actions. */
510 if ( act->numTransRefs > 0 ) {
511 /* Write the case label, the action and the case break. */
512 out << "\tcase " << act->actionId << ":\n";
513 ACTION( out, act, 0, false );
514 out << "\tbreak;\n";
515 }
516 }
517
518 genLineDirective( out );
519 return out;
520 }
521
522 std::ostream &JavaTabCodeGen::COND_OFFSETS()
523 {
524 int curKeyOffset = 0;
525 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
526 /* Write the key offset. */
527 ARRAY_ITEM( INT(curKeyOffset), st.last() );
528
529 /* Move the key offset ahead. */
530 curKeyOffset += st->stateCondList.length();
531 }
532 return out;
533 }
534
535 std::ostream &JavaTabCodeGen::KEY_OFFSETS()
536 {
537 int curKeyOffset = 0;
538 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
539 /* Write the key offset. */
540 ARRAY_ITEM( INT(curKeyOffset), st.last() );
541
542 /* Move the key offset ahead. */
543 curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
544 }
545 return out;
546 }
547
548
549 std::ostream &JavaTabCodeGen::INDEX_OFFSETS()
550 {
551 int curIndOffset = 0;
552 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
553 /* Write the index offset. */
554 ARRAY_ITEM( INT(curIndOffset), st.last() );
555
556 /* Move the index offset ahead. */
557 curIndOffset += st->outSingle.length() + st->outRange.length();
558 if ( st->defTrans != 0 )
559 curIndOffset += 1;
560 }
561 return out;
562 }
563
564 std::ostream &JavaTabCodeGen::COND_LENS()
565 {
566 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
567 /* Write singles length. */
568 ARRAY_ITEM( INT(st->stateCondList.length()), st.last() );
569 }
570 return out;
571 }
572
573
574 std::ostream &JavaTabCodeGen::SINGLE_LENS()
575 {
576 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
577 /* Write singles length. */
578 ARRAY_ITEM( INT(st->outSingle.length()), st.last() );
579 }
580 return out;
581 }
582
583 std::ostream &JavaTabCodeGen::RANGE_LENS()
584 {
585 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
586 /* Emit length of range index. */
587 ARRAY_ITEM( INT(st->outRange.length()), st.last() );
588 }
589 return out;
590 }
591
592 std::ostream &JavaTabCodeGen::TO_STATE_ACTIONS()
593 {
594 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
595 /* Write any eof action. */
596 ARRAY_ITEM( INT(TO_STATE_ACTION(st)), st.last() );
597 }
598 return out;
599 }
600
601 std::ostream &JavaTabCodeGen::FROM_STATE_ACTIONS()
602 {
603 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
604 /* Write any eof action. */
605 ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), st.last() );
606 }
607 return out;
608 }
609
610 std::ostream &JavaTabCodeGen::EOF_ACTIONS()
611 {
612 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
613 /* Write any eof action. */
614 ARRAY_ITEM( INT(EOF_ACTION(st)), st.last() );
615 }
616 return out;
617 }
618
619 std::ostream &JavaTabCodeGen::EOF_TRANS()
620 {
621 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
622 /* Write any eof action. */
623 long trans = 0;
624 if ( st->eofTrans != 0 ) {
625 assert( st->eofTrans->pos >= 0 );
626 trans = st->eofTrans->pos+1;
627 }
628
629 /* Write any eof action. */
630 ARRAY_ITEM( INT(trans), st.last() );
631 }
632 return out;
633 }
634
635
636 std::ostream &JavaTabCodeGen::COND_KEYS()
637 {
638 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
639 /* Loop the state's transitions. */
640 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
641 /* Lower key. */
642 ARRAY_ITEM( KEY( sc->lowKey ), false );
643 ARRAY_ITEM( KEY( sc->highKey ), false );
644 }
645 }
646
647 /* Output one last number so we don't have to figure out when the last
648 * entry is and avoid writing a comma. */
649 ARRAY_ITEM( INT(0), true );
650 return out;
651 }
652
653 std::ostream &JavaTabCodeGen::COND_SPACES()
654 {
655 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
656 /* Loop the state's transitions. */
657 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
658 /* Cond Space id. */
659 ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), false );
660 }
661 }
662
663 /* Output one last number so we don't have to figure out when the last
664 * entry is and avoid writing a comma. */
665 ARRAY_ITEM( INT(0), true );
666 return out;
667 }
668
669 std::ostream &JavaTabCodeGen::KEYS()
670 {
671 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
672 /* Loop the singles. */
673 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
674 ARRAY_ITEM( KEY( stel->lowKey ), false );
675 }
676
677 /* Loop the state's transitions. */
678 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
679 /* Lower key. */
680 ARRAY_ITEM( KEY( rtel->lowKey ), false );
681
682 /* Upper key. */
683 ARRAY_ITEM( KEY( rtel->highKey ), false );
684 }
685 }
686
687 /* Output one last number so we don't have to figure out when the last
688 * entry is and avoid writing a comma. */
689 ARRAY_ITEM( INT(0), true );
690 return out;
691 }
692
693 std::ostream &JavaTabCodeGen::INDICIES()
694 {
695 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
696 /* Walk the singles. */
697 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
698 ARRAY_ITEM( KEY( stel->value->id ), false );
699 }
700
701 /* Walk the ranges. */
702 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
703 ARRAY_ITEM( KEY( rtel->value->id ), false );
704 }
705
706 /* The state's default index goes next. */
707 if ( st->defTrans != 0 ) {
708 ARRAY_ITEM( KEY( st->defTrans->id ), false );
709 }
710 }
711
712 /* Output one last number so we don't have to figure out when the last
713 * entry is and avoid writing a comma. */
714 ARRAY_ITEM( INT(0), true );
715 return out;
716 }
717
718 std::ostream &JavaTabCodeGen::TRANS_TARGS()
719 {
720 int totalTrans = 0;
721 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
722 /* Walk the singles. */
723 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
724 RedTransAp *trans = stel->value;
725 ARRAY_ITEM( KEY( trans->targ->id ), false );
726 totalTrans++;
727 }
728
729 /* Walk the ranges. */
730 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
731 RedTransAp *trans = rtel->value;
732 ARRAY_ITEM( KEY( trans->targ->id ), false );
733 totalTrans++;
734 }
735
736 /* The state's default target state. */
737 if ( st->defTrans != 0 ) {
738 RedTransAp *trans = st->defTrans;
739 ARRAY_ITEM( KEY( trans->targ->id ), false );
740 totalTrans++;
741 }
742 }
743
744 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
745 if ( st->eofTrans != 0 ) {
746 RedTransAp *trans = st->eofTrans;
747 trans->pos = totalTrans++;
748 ARRAY_ITEM( KEY( trans->targ->id ), false );
749 }
750 }
751
752 /* Output one last number so we don't have to figure out when the last
753 * entry is and avoid writing a comma. */
754 ARRAY_ITEM( INT(0), true );
755 return out;
756 }
757
758
759 std::ostream &JavaTabCodeGen::TRANS_ACTIONS()
760 {
761 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
762 /* Walk the singles. */
763 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
764 RedTransAp *trans = stel->value;
765 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
766 }
767
768 /* Walk the ranges. */
769 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
770 RedTransAp *trans = rtel->value;
771 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
772 }
773
774 /* The state's default index goes next. */
775 if ( st->defTrans != 0 ) {
776 RedTransAp *trans = st->defTrans;
777 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
778 }
779 }
780
781 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
782 if ( st->eofTrans != 0 ) {
783 RedTransAp *trans = st->eofTrans;
784 ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
785 }
786 }
787
788 /* Output one last number so we don't have to figure out when the last
789 * entry is and avoid writing a comma. */
790 ARRAY_ITEM( INT(0), true );
791 return out;
792 }
793
794 std::ostream &JavaTabCodeGen::TRANS_TARGS_WI()
795 {
796 /* Transitions must be written ordered by their id. */
797 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
798 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
799 transPtrs[trans->id] = trans;
800
801 /* Keep a count of the num of items in the array written. */
802 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
803 /* Save the position. Needed for eofTargs. */
804 RedTransAp *trans = transPtrs[t];
805 trans->pos = t;
806
807 /* Write out the target state. */
808 ARRAY_ITEM( INT(trans->targ->id), ( t >= redFsm->transSet.length()-1 ) );
809 }
810 delete[] transPtrs;
811 return out;
812 }
813
814
815 std::ostream &JavaTabCodeGen::TRANS_ACTIONS_WI()
816 {
817 /* Transitions must be written ordered by their id. */
818 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
819 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
820 transPtrs[trans->id] = trans;
821
822 /* Keep a count of the num of items in the array written. */
823 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
824 /* Write the function for the transition. */
825 RedTransAp *trans = transPtrs[t];
826 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ( t >= redFsm->transSet.length()-1 ) );
827 }
828 delete[] transPtrs;
829 return out;
830 }
831
832 void JavaTabCodeGen::writeExports()
833 {
834 if ( exportList.length() > 0 ) {
835 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
836 STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name )
837 << " = " << KEY(ex->key) << ";\n";
838 }
839 out << "\n";
840 }
841 }
842
843 void JavaTabCodeGen::writeStart()
844 {
845 out << START_STATE_ID();
846 }
847
848 void JavaTabCodeGen::writeFirstFinal()
849 {
850 out << FIRST_FINAL_STATE();
851 }
852
853 void JavaTabCodeGen::writeError()
854 {
855 out << ERROR_STATE();
856 }
857
858 void JavaTabCodeGen::writeData()
859 {
860 /* If there are any transtion functions then output the array. If there
861 * are none, don't bother emitting an empty array that won't be used. */
862 if ( redFsm->anyActions() ) {
863 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
864 ACTIONS_ARRAY();
865 CLOSE_ARRAY() <<
866 "\n";
867 }
868
869 if ( redFsm->anyConditions() ) {
870 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
871 COND_OFFSETS();
872 CLOSE_ARRAY() <<
873 "\n";
874
875 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
876 COND_LENS();
877 CLOSE_ARRAY() <<
878 "\n";
879
880 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
881 COND_KEYS();
882 CLOSE_ARRAY() <<
883 "\n";
884
885 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
886 COND_SPACES();
887 CLOSE_ARRAY() <<
888 "\n";
889 }
890
891 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
892 KEY_OFFSETS();
893 CLOSE_ARRAY() <<
894 "\n";
895
896 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
897 KEYS();
898 CLOSE_ARRAY() <<
899 "\n";
900
901 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
902 SINGLE_LENS();
903 CLOSE_ARRAY() <<
904 "\n";
905
906 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
907 RANGE_LENS();
908 CLOSE_ARRAY() <<
909 "\n";
910
911 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
912 INDEX_OFFSETS();
913 CLOSE_ARRAY() <<
914 "\n";
915
916 if ( useIndicies ) {
917 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
918 INDICIES();
919 CLOSE_ARRAY() <<
920 "\n";
921
922 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
923 TRANS_TARGS_WI();
924 CLOSE_ARRAY() <<
925 "\n";
926
927 if ( redFsm->anyActions() ) {
928 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
929 TRANS_ACTIONS_WI();
930 CLOSE_ARRAY() <<
931 "\n";
932 }
933 }
934 else {
935 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
936 TRANS_TARGS();
937 CLOSE_ARRAY() <<
938 "\n";
939
940 if ( redFsm->anyActions() ) {
941 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
942 TRANS_ACTIONS();
943 CLOSE_ARRAY() <<
944 "\n";
945 }
946 }
947
948 if ( redFsm->anyToStateActions() ) {
949 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
950 TO_STATE_ACTIONS();
951 CLOSE_ARRAY() <<
952 "\n";
953 }
954
955 if ( redFsm->anyFromStateActions() ) {
956 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
957 FROM_STATE_ACTIONS();
958 CLOSE_ARRAY() <<
959 "\n";
960 }
961
962 if ( redFsm->anyEofActions() ) {
963 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
964 EOF_ACTIONS();
965 CLOSE_ARRAY() <<
966 "\n";
967 }
968
969 if ( redFsm->anyEofTrans() ) {
970 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
971 EOF_TRANS();
972 CLOSE_ARRAY() <<
973 "\n";
974 }
975
976 if ( redFsm->startState != 0 )
977 STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
978
979 if ( !noFinal )
980 STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
981
982 if ( !noError )
983 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
984
985 out << "\n";
986
987 if ( !noEntry && entryPointNames.length() > 0 ) {
988 for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
989 STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) <<
990 " = " << entryPointIds[en.pos()] << ";\n";
991 }
992 out << "\n";
993 }
994 }
995
996 void JavaTabCodeGen::writeExec()
997 {
998 out <<
999 " {\n"
1000 " int _klen";
1001
1002 if ( redFsm->anyRegCurStateRef() )
1003 out << ", _ps";
1004
1005 out <<
1006 ";\n"
1007 " int _trans = 0;\n";
1008
1009 if ( redFsm->anyConditions() )
1010 out << " int _widec;\n";
1011
1012 if ( redFsm->anyToStateActions() || redFsm->anyRegActions() ||
1013 redFsm->anyFromStateActions() )
1014 {
1015 out <<
1016 " int _acts;\n"
1017 " int _nacts;\n";
1018 }
1019
1020 out <<
1021 " int _keys;\n"
1022 " int _goto_targ = 0;\n"
1023 "\n";
1024
1025 out <<
1026 " _goto: while (true) {\n"
1027 " switch ( _goto_targ ) {\n"
1028 " case 0:\n";
1029
1030 if ( !noEnd ) {
1031 out <<
1032 " if ( " << P() << " == " << PE() << " ) {\n"
1033 " _goto_targ = " << _test_eof << ";\n"
1034 " continue _goto;\n"
1035 " }\n";
1036 }
1037
1038 if ( redFsm->errState != 0 ) {
1039 out <<
1040 " if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n"
1041 " _goto_targ = " << _out << ";\n"
1042 " continue _goto;\n"
1043 " }\n";
1044 }
1045
1046 out << "case " << _resume << ":\n";
1047
1048 if ( redFsm->anyFromStateActions() ) {
1049 out <<
1050 " _acts = " << FSA() << "[" << vCS() << "]" << ";\n"
1051 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1052 " while ( _nacts-- > 0 ) {\n"
1053 " switch ( " << A() << "[_acts++] ) {\n";
1054 FROM_STATE_ACTION_SWITCH() <<
1055 " }\n"
1056 " }\n"
1057 "\n";
1058 }
1059
1060 if ( redFsm->anyConditions() )
1061 COND_TRANSLATE();
1062
1063 LOCATE_TRANS();
1064
1065 if ( useIndicies )
1066 out << " _trans = " << I() << "[_trans];\n";
1067
1068 if ( redFsm->anyEofTrans() )
1069 out << "case " << _eof_trans << ":\n";
1070
1071 if ( redFsm->anyRegCurStateRef() )
1072 out << " _ps = " << vCS() << ";\n";
1073
1074 out <<
1075 " " << vCS() << " = " << TT() << "[_trans];\n"
1076 "\n";
1077
1078 if ( redFsm->anyRegActions() ) {
1079 out <<
1080 " if ( " << TA() << "[_trans] != 0 ) {\n"
1081 " _acts = " << TA() << "[_trans]" << ";\n"
1082 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1083 " while ( _nacts-- > 0 )\n {\n"
1084 " switch ( " << A() << "[_acts++] )\n"
1085 " {\n";
1086 ACTION_SWITCH() <<
1087 " }\n"
1088 " }\n"
1089 " }\n"
1090 "\n";
1091 }
1092
1093 out << "case " << _again << ":\n";
1094
1095 if ( redFsm->anyToStateActions() ) {
1096 out <<
1097 " _acts = " << TSA() << "[" << vCS() << "]" << ";\n"
1098 " _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
1099 " while ( _nacts-- > 0 ) {\n"
1100 " switch ( " << A() << "[_acts++] ) {\n";
1101 TO_STATE_ACTION_SWITCH() <<
1102 " }\n"
1103 " }\n"
1104 "\n";
1105 }
1106
1107 if ( redFsm->errState != 0 ) {
1108 out <<
1109 " if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n"
1110 " _goto_targ = " << _out << ";\n"
1111 " continue _goto;\n"
1112 " }\n";
1113 }
1114
1115 if ( !noEnd ) {
1116 out <<
1117 " if ( ++" << P() << " != " << PE() << " ) {\n"
1118 " _goto_targ = " << _resume << ";\n"
1119 " continue _goto;\n"
1120 " }\n";
1121 }
1122 else {
1123 out <<
1124 " " << P() << " += 1;\n"
1125 " _goto_targ = " << _resume << ";\n"
1126 " continue _goto;\n";
1127 }
1128
1129 out << "case " << _test_eof << ":\n";
1130
1131 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
1132 out <<
1133 " if ( " << P() << " == " << vEOF() << " )\n"
1134 " {\n";
1135
1136 if ( redFsm->anyEofTrans() ) {
1137 out <<
1138 " if ( " << ET() << "[" << vCS() << "] > 0 ) {\n"
1139 " _trans = " << ET() << "[" << vCS() << "] - 1;\n"
1140 " _goto_targ = " << _eof_trans << ";\n"
1141 " continue _goto;\n"
1142 " }\n";
1143 }
1144
1145 if ( redFsm->anyEofActions() ) {
1146 out <<
1147 " int __acts = " << EA() << "[" << vCS() << "]" << ";\n"
1148 " int __nacts = " << CAST("int") << " " << A() << "[__acts++];\n"
1149 " while ( __nacts-- > 0 ) {\n"
1150 " switch ( " << A() << "[__acts++] ) {\n";
1151 EOF_ACTION_SWITCH() <<
1152 " }\n"
1153 " }\n";
1154 }
1155
1156 out <<
1157 " }\n"
1158 "\n";
1159 }
1160
1161 out << "case " << _out << ":\n";
1162
1163 /* The switch and goto loop. */
1164 out << " }\n";
1165 out << " break; }\n";
1166
1167 /* The execute block. */
1168 out << " }\n";
1169 }
1170
1171 std::ostream &JavaTabCodeGen::OPEN_ARRAY( string type, string name )
1172 {
1173 array_type = type;
1174 array_name = name;
1175 item_count = 0;
1176 div_count = 1;
1177
1178 out << "private static " << type << "[] init_" << name << "_0()\n"
1179 "{\n\t"
1180 "return new " << type << " [] {\n\t";
1181 return out;
1182 }
1183
1184 std::ostream &JavaTabCodeGen::ARRAY_ITEM( string item, bool last )
1185 {
1186 item_count++;
1187
1188 out << setw(5) << setiosflags(ios::right) << item;
1189
1190 if ( !last ) {
1191 if ( item_count % SAIIC == 0 ) {
1192 out << "\n\t};\n};\n"
1193 "private static "<< array_type << "[] init_" <<
1194 array_name << "_" << div_count << "()\n"
1195 "{\n\t"
1196 "return new " << array_type << " [] {\n\t";
1197 div_count++;
1198 } else if (item_count % IALL == 0) {
1199 out << ",\n\t";
1200 } else {
1201 out << ",";
1202 }
1203 }
1204 return out;
1205 }
1206
1207 std::ostream &JavaTabCodeGen::CLOSE_ARRAY()
1208 {
1209 out << "\n\t};\n}\n\n";
1210
1211 if (item_count < SAIIC) {
1212 out << "private static final " << array_type << " " << array_name <<
1213 "[] = init_" << array_name << "_0();\n\n";
1214 } else {
1215 out << "private static final " << array_type << " [] combine_" << array_name
1216 << "() {\n\t"
1217 << array_type << " [] combined = new " << array_type <<
1218 " [ " << item_count << " ];\n\t";
1219 int block = 0;
1220 int full_blocks = item_count / SAIIC;
1221 for (;block < full_blocks; ++block) {
1222 out << "System.arraycopy ( init_" << array_name << "_" << block <<
1223 "(), 0, combined, " << SAIIC * block << ", " << SAIIC << " );\n\t";
1224 }
1225 if ( (item_count % SAIIC) > 0 ) {
1226 out << "System.arraycopy ( init_" << array_name << "_" << block <<
1227 "(), 0, combined, " << SAIIC * block << ", " <<
1228 (item_count % SAIIC) << " );\n\t";
1229 }
1230 out << "return combined;\n}\n";
1231 out << "private static final " << array_type << " [] " << array_name <<
1232 " = combine_" << array_name << "();";
1233 }
1234 return out;
1235 }
1236
1237
1238 std::ostream &JavaTabCodeGen::STATIC_VAR( string type, string name )
1239 {
1240 out << "static final " << type << " " << name;
1241 return out;
1242 }
1243
1244 string JavaTabCodeGen::ARR_OFF( string ptr, string offset )
1245 {
1246 return ptr + " + " + offset;
1247 }
1248
1249 string JavaTabCodeGen::CAST( string type )
1250 {
1251 return "(" + type + ")";
1252 }
1253
1254 string JavaTabCodeGen::NULL_ITEM()
1255 {
1256 /* In java we use integers instead of pointers. */
1257 return "-1";
1258 }
1259
1260 string JavaTabCodeGen::GET_KEY()
1261 {
1262 ostringstream ret;
1263 if ( getKeyExpr != 0 ) {
1264 /* Emit the user supplied method of retrieving the key. */
1265 ret << "(";
1266 INLINE_LIST( ret, getKeyExpr, 0, false );
1267 ret << ")";
1268 }
1269 else {
1270 /* Expression for retrieving the key, use simple dereference. */
1271 ret << DATA() << "[" << P() << "]";
1272 }
1273 return ret.str();
1274 }
1275
1276 string JavaTabCodeGen::CTRL_FLOW()
1277 {
1278 return "if (true) ";
1279 }
1280
1281 unsigned int JavaTabCodeGen::arrayTypeSize( unsigned long maxVal )
1282 {
1283 long long maxValLL = (long long) maxVal;
1284 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
1285 assert( arrayType != 0 );
1286 return arrayType->size;
1287 }
1288
1289 string JavaTabCodeGen::ARRAY_TYPE( unsigned long maxVal )
1290 {
1291 long long maxValLL = (long long) maxVal;
1292 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
1293 assert( arrayType != 0 );
1294
1295 string ret = arrayType->data1;
1296 if ( arrayType->data2 != 0 ) {
1297 ret += " ";
1298 ret += arrayType->data2;
1299 }
1300 return ret;
1301 }
1302
1303
1304 /* Write out the fsm name. */
1305 string JavaTabCodeGen::FSM_NAME()
1306 {
1307 return fsmName;
1308 }
1309
1310 /* Emit the offset of the start state as a decimal integer. */
1311 string JavaTabCodeGen::START_STATE_ID()
1312 {
1313 ostringstream ret;
1314 ret << redFsm->startState->id;
1315 return ret.str();
1316 };
1317
1318 /* Write out the array of actions. */
1319 std::ostream &JavaTabCodeGen::ACTIONS_ARRAY()
1320 {
1321 ARRAY_ITEM( INT(0), false );
1322 for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
1323 /* Write out the length, which will never be the last character. */
1324 ARRAY_ITEM( INT(act->key.length()), false );
1325
1326 for ( GenActionTable::Iter item = act->key; item.lte(); item++ )
1327 ARRAY_ITEM( INT(item->value->actionId), (act.last() && item.last()) );
1328 }
1329 return out;
1330 }
1331
1332
1333 string JavaTabCodeGen::ACCESS()
1334 {
1335 ostringstream ret;
1336 if ( accessExpr != 0 )
1337 INLINE_LIST( ret, accessExpr, 0, false );
1338 return ret.str();
1339 }
1340
1341 string JavaTabCodeGen::P()
1342 {
1343 ostringstream ret;
1344 if ( pExpr == 0 )
1345 ret << "p";
1346 else {
1347 ret << "(";
1348 INLINE_LIST( ret, pExpr, 0, false );
1349 ret << ")";
1350 }
1351 return ret.str();
1352 }
1353
1354 string JavaTabCodeGen::PE()
1355 {
1356 ostringstream ret;
1357 if ( peExpr == 0 )
1358 ret << "pe";
1359 else {
1360 ret << "(";
1361 INLINE_LIST( ret, peExpr, 0, false );
1362 ret << ")";
1363 }
1364 return ret.str();
1365 }
1366
1367 string JavaTabCodeGen::vEOF()
1368 {
1369 ostringstream ret;
1370 if ( eofExpr == 0 )
1371 ret << "eof";
1372 else {
1373 ret << "(";
1374 INLINE_LIST( ret, eofExpr, 0, false );
1375 ret << ")";
1376 }
1377 return ret.str();
1378 }
1379
1380 string JavaTabCodeGen::vCS()
1381 {
1382 ostringstream ret;
1383 if ( csExpr == 0 )
1384 ret << ACCESS() << "cs";
1385 else {
1386 /* Emit the user supplied method of retrieving the key. */
1387 ret << "(";
1388 INLINE_LIST( ret, csExpr, 0, false );
1389 ret << ")";
1390 }
1391 return ret.str();
1392 }
1393
1394 string JavaTabCodeGen::TOP()
1395 {
1396 ostringstream ret;
1397 if ( topExpr == 0 )
1398 ret << ACCESS() + "top";
1399 else {
1400 ret << "(";
1401 INLINE_LIST( ret, topExpr, 0, false );
1402 ret << ")";
1403 }
1404 return ret.str();
1405 }
1406
1407 string JavaTabCodeGen::STACK()
1408 {
1409 ostringstream ret;
1410 if ( stackExpr == 0 )
1411 ret << ACCESS() + "stack";
1412 else {
1413 ret << "(";
1414 INLINE_LIST( ret, stackExpr, 0, false );
1415 ret << ")";
1416 }
1417 return ret.str();
1418 }
1419
1420 string JavaTabCodeGen::ACT()
1421 {
1422 ostringstream ret;
1423 if ( actExpr == 0 )
1424 ret << ACCESS() + "act";
1425 else {
1426 ret << "(";
1427 INLINE_LIST( ret, actExpr, 0, false );
1428 ret << ")";
1429 }
1430 return ret.str();
1431 }
1432
1433 string JavaTabCodeGen::TOKSTART()
1434 {
1435 ostringstream ret;
1436 if ( tokstartExpr == 0 )
1437 ret << ACCESS() + "ts";
1438 else {
1439 ret << "(";
1440 INLINE_LIST( ret, tokstartExpr, 0, false );
1441 ret << ")";
1442 }
1443 return ret.str();
1444 }
1445
1446 string JavaTabCodeGen::TOKEND()
1447 {
1448 ostringstream ret;
1449 if ( tokendExpr == 0 )
1450 ret << ACCESS() + "te";
1451 else {
1452 ret << "(";
1453 INLINE_LIST( ret, tokendExpr, 0, false );
1454 ret << ")";
1455 }
1456 return ret.str();
1457 }
1458
1459 string JavaTabCodeGen::DATA()
1460 {
1461 ostringstream ret;
1462 if ( dataExpr == 0 )
1463 ret << ACCESS() + "data";
1464 else {
1465 ret << "(";
1466 INLINE_LIST( ret, dataExpr, 0, false );
1467 ret << ")";
1468 }
1469 return ret.str();
1470 }
1471
1472
1473 string JavaTabCodeGen::GET_WIDE_KEY()
1474 {
1475 if ( redFsm->anyConditions() )
1476 return "_widec";
1477 else
1478 return GET_KEY();
1479 }
1480
1481 string JavaTabCodeGen::GET_WIDE_KEY( RedStateAp *state )
1482 {
1483 if ( state->stateCondList.length() > 0 )
1484 return "_widec";
1485 else
1486 return GET_KEY();
1487 }
1488
1489 /* Write out level number of tabs. Makes the nested binary search nice
1490 * looking. */
1491 string JavaTabCodeGen::TABS( int level )
1492 {
1493 string result;
1494 while ( level-- > 0 )
1495 result += "\t";
1496 return result;
1497 }
1498
1499 string JavaTabCodeGen::KEY( Key key )
1500 {
1501 ostringstream ret;
1502 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
1503 ret << key.getVal();
1504 else
1505 ret << (unsigned long) key.getVal();
1506 return ret.str();
1507 }
1508
1509 string JavaTabCodeGen::INT( int i )
1510 {
1511 ostringstream ret;
1512 ret << i;
1513 return ret.str();
1514 }
1515
1516 void JavaTabCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item,
1517 int targState, int inFinish )
1518 {
1519 ret <<
1520 " switch( " << ACT() << " ) {\n";
1521
1522 for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
1523 /* Write the case label, the action and the case break. */
1524 if ( lma->lmId < 0 )
1525 ret << " default:\n";
1526 else
1527 ret << " case " << lma->lmId << ":\n";
1528
1529 /* Write the block and close it off. */
1530 ret << " {";
1531 INLINE_LIST( ret, lma->children, targState, inFinish );
1532 ret << "}\n";
1533
1534 ret << " break;\n";
1535 }
1536
1537 ret <<
1538 " }\n"
1539 "\t";
1540 }
1541
1542 void JavaTabCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
1543 {
1544 ret << ACT() << " = " << item->lmId << ";";
1545 }
1546
1547 void JavaTabCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
1548 {
1549 /* The tokend action sets tokend. */
1550 ret << TOKEND() << " = " << P();
1551 if ( item->offset != 0 )
1552 out << "+" << item->offset;
1553 out << ";";
1554 }
1555
1556 void JavaTabCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
1557 {
1558 ret << TOKEND();
1559 }
1560
1561 void JavaTabCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
1562 {
1563 ret << TOKSTART() << " = " << NULL_ITEM() << ";";
1564 }
1565
1566 void JavaTabCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
1567 {
1568 ret << ACT() << " = 0;";
1569 }
1570
1571 void JavaTabCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
1572 {
1573 ret << TOKSTART() << " = " << P() << ";";
1574 }
1575
1576 void JavaTabCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item,
1577 int targState, bool inFinish )
1578 {
1579 if ( item->children->length() > 0 ) {
1580 /* Write the block and close it off. */
1581 ret << "{";
1582 INLINE_LIST( ret, item->children, targState, inFinish );
1583 ret << "}";
1584 }
1585 }
1586
1587 void JavaTabCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish )
1588 {
1589 /* Write the preprocessor line info for going into the source file. */
1590 javaLineDirective( ret, action->loc.fileName, action->loc.line );
1591
1592 /* Write the block and close it off. */
1593 ret << "\t{";
1594 INLINE_LIST( ret, action->inlineList, targState, inFinish );
1595 ret << "}\n";
1596 }
1597
1598 void JavaTabCodeGen::CONDITION( ostream &ret, GenAction *condition )
1599 {
1600 ret << "\n";
1601 javaLineDirective( ret, condition->loc.fileName, condition->loc.line );
1602 INLINE_LIST( ret, condition->inlineList, 0, false );
1603 }
1604
1605 string JavaTabCodeGen::ERROR_STATE()
1606 {
1607 ostringstream ret;
1608 if ( redFsm->errState != 0 )
1609 ret << redFsm->errState->id;
1610 else
1611 ret << "-1";
1612 return ret.str();
1613 }
1614
1615 string JavaTabCodeGen::FIRST_FINAL_STATE()
1616 {
1617 ostringstream ret;
1618 if ( redFsm->firstFinState != 0 )
1619 ret << redFsm->firstFinState->id;
1620 else
1621 ret << redFsm->nextStateId;
1622 return ret.str();
1623 }
1624
1625 void JavaTabCodeGen::writeInit()
1626 {
1627 out << " {\n";
1628
1629 if ( !noCS )
1630 out << "\t" << vCS() << " = " << START() << ";\n";
1631
1632 /* If there are any calls, then the stack top needs initialization. */
1633 if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
1634 out << "\t" << TOP() << " = 0;\n";
1635
1636 if ( hasLongestMatch ) {
1637 out <<
1638 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
1639 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
1640 " " << ACT() << " = 0;\n";
1641 }
1642 out << " }\n";
1643 }
1644
1645 void JavaTabCodeGen::finishRagelDef()
1646 {
1647 /* The frontend will do this for us, but it may be a good idea to force it
1648 * if the intermediate file is edited. */
1649 redFsm->sortByStateId();
1650
1651 /* Choose default transitions and the single transition. */
1652 redFsm->chooseDefaultSpan();
1653
1654 /* Maybe do flat expand, otherwise choose single. */
1655 redFsm->chooseSingle();
1656
1657 /* If any errors have occured in the input file then don't write anything. */
1658 if ( gblErrorCount > 0 )
1659 return;
1660
1661 /* Anlayze Machine will find the final action reference counts, among
1662 * other things. We will use these in reporting the usage
1663 * of fsm directives in action code. */
1664 analyzeMachine();
1665
1666 /* Determine if we should use indicies. */
1667 calcIndexSize();
1668 }
1669
1670 ostream &JavaTabCodeGen::source_warning( const InputLoc &loc )
1671 {
1672 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
1673 return cerr;
1674 }
1675
1676 ostream &JavaTabCodeGen::source_error( const InputLoc &loc )
1677 {
1678 gblErrorCount += 1;
1679 assert( sourceFileName != 0 );
1680 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
1681 return cerr;
1682 }
1683
1684