1 /*
2 * Copyright 2007 Victor Hugo Borja <vic@rubyforge.org>
3 * 2007 Adrian Thurston <thurston@complang.org>
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 <iomanip>
24 #include <sstream>
25 #include "redfsm.h"
26 #include "gendata.h"
27 #include "ragel.h"
28 #include "rubytable.h"
29
30 using std::ostream;
31 using std::ostringstream;
32 using std::string;
33 using std::cerr;
34 using std::endl;
35
36
37
GOTO(ostream & out,int gotoDest,bool inFinish)38 void RubyTabCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish )
39 {
40 out <<
41 " begin\n"
42 " " << vCS() << " = " << gotoDest << "\n"
43 " _trigger_goto = true\n"
44 " _goto_level = _again\n"
45 " break\n"
46 " end\n";
47 }
48
GOTO_EXPR(ostream & out,GenInlineItem * ilItem,bool inFinish)49 void RubyTabCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish )
50 {
51 out <<
52 " begin\n"
53 " " << vCS() << " = (";
54 INLINE_LIST( out, ilItem->children, 0, inFinish );
55 out << ")\n";
56 out <<
57 " _trigger_goto = true\n"
58 " _goto_level = _again\n"
59 " break\n"
60 " end\n";
61 }
62
CALL(ostream & out,int callDest,int targState,bool inFinish)63 void RubyTabCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish )
64 {
65 if ( prePushExpr != 0 ) {
66 out << "begin\n";
67 INLINE_LIST( out, prePushExpr, 0, false );
68 }
69
70 out <<
71 " begin\n"
72 " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
73 " " << TOP() << "+= 1\n"
74 " " << vCS() << " = " << callDest << "\n"
75 " _trigger_goto = true\n"
76 " _goto_level = _again\n"
77 " break\n"
78 " end\n";
79
80 if ( prePushExpr != 0 )
81 out << "end\n";
82 }
83
CALL_EXPR(ostream & out,GenInlineItem * ilItem,int targState,bool inFinish)84 void RubyTabCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem, int targState, bool inFinish )
85 {
86 if ( prePushExpr != 0 ) {
87 out << "begin\n";
88 INLINE_LIST( out, prePushExpr, 0, false );
89 }
90
91 out <<
92 " begin\n"
93 " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
94 " " << TOP() << " += 1\n"
95 " " << vCS() << " = (";
96 INLINE_LIST( out, ilItem->children, targState, inFinish );
97 out << ")\n";
98
99 out <<
100 " _trigger_goto = true\n"
101 " _goto_level = _again\n"
102 " break\n"
103 " end\n";
104
105 if ( prePushExpr != 0 )
106 out << "end\n";
107 }
108
RET(ostream & out,bool inFinish)109 void RubyTabCodeGen::RET( ostream &out, bool inFinish )
110 {
111 out <<
112 " begin\n"
113 " " << TOP() << " -= 1\n"
114 " " << vCS() << " = " << STACK() << "[" << TOP() << "]\n";
115
116 if ( postPopExpr != 0 ) {
117 out << "begin\n";
118 INLINE_LIST( out, postPopExpr, 0, false );
119 out << "end\n";
120 }
121
122 out <<
123 " _trigger_goto = true\n"
124 " _goto_level = _again\n"
125 " break\n"
126 " end\n";
127 }
128
BREAK(ostream & out,int targState)129 void RubyTabCodeGen::BREAK( ostream &out, int targState )
130 {
131 out <<
132 " begin\n"
133 " " << P() << " += 1\n"
134 " _trigger_goto = true\n"
135 " _goto_level = _out\n"
136 " break\n"
137 " end\n";
138 }
139
COND_TRANSLATE()140 void RubyTabCodeGen::COND_TRANSLATE()
141 {
142 out <<
143 " _widec = " << GET_KEY() << "\n"
144 " _keys = " << CO() << "[" << vCS() << "]*2\n"
145 " _klen = " << CL() << "[" << vCS() << "]\n"
146 " if _klen > 0\n"
147 " _lower = _keys\n"
148 " _upper = _keys + (_klen<<1) - 2\n"
149 " loop do\n"
150 " break if _upper < _lower\n"
151 " _mid = _lower + (((_upper-_lower) >> 1) & ~1)\n"
152 " if " << GET_WIDE_KEY() << " < " << CK() << "[_mid]\n"
153 " _upper = _mid - 2\n"
154 " elsif " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1]\n"
155 " _lower = _mid + 2\n"
156 " else\n"
157 " case " << C() << "[" << CO() << "[" << vCS() << "]"
158 " + ((_mid - _keys)>>1)]\n";
159
160 for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
161 GenCondSpace *condSpace = csi;
162 out << " when " << condSpace->condSpaceId << " then" ;
163 out << " _widec = " << KEY(condSpace->baseKey) <<
164 "+ (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ")\n";
165
166 for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
167 Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
168 out << " _widec += " << condValOffset << " if ( ";
169 CONDITION( out, *csi );
170 out << " )\n";
171 }
172 }
173
174 out <<
175 " end # case\n"
176 " end\n"
177 " end # loop\n"
178 " end\n";
179 }
180
181
LOCATE_TRANS()182 void RubyTabCodeGen::LOCATE_TRANS()
183 {
184 out <<
185 " _keys = " << KO() << "[" << vCS() << "]\n"
186 " _trans = " << IO() << "[" << vCS() << "]\n"
187 " _klen = " << SL() << "[" << vCS() << "]\n"
188 " _break_match = false\n"
189 " \n"
190 " begin\n"
191 " if _klen > 0\n"
192 " _lower = _keys\n"
193 " _upper = _keys + _klen - 1\n"
194 "\n"
195 " loop do\n"
196 " break if _upper < _lower\n"
197 " _mid = _lower + ( (_upper - _lower) >> 1 )\n"
198 "\n"
199 " if " << GET_WIDE_KEY() << " < " << K() << "[_mid]\n"
200 " _upper = _mid - 1\n"
201 " elsif " << GET_WIDE_KEY() << " > " << K() << "[_mid]\n"
202 " _lower = _mid + 1\n"
203 " else\n"
204 " _trans += (_mid - _keys)\n"
205 " _break_match = true\n"
206 " break\n"
207 " end\n"
208 " end # loop\n"
209 " break if _break_match\n"
210 " _keys += _klen\n"
211 " _trans += _klen\n"
212 " end"
213 "\n"
214 " _klen = " << RL() << "[" << vCS() << "]\n"
215 " if _klen > 0\n"
216 " _lower = _keys\n"
217 " _upper = _keys + (_klen << 1) - 2\n"
218 " loop do\n"
219 " break if _upper < _lower\n"
220 " _mid = _lower + (((_upper-_lower) >> 1) & ~1)\n"
221 " if " << GET_WIDE_KEY() << " < " << K() << "[_mid]\n"
222 " _upper = _mid - 2\n"
223 " elsif " << GET_WIDE_KEY() << " > " << K() << "[_mid+1]\n"
224 " _lower = _mid + 2\n"
225 " else\n"
226 " _trans += ((_mid - _keys) >> 1)\n"
227 " _break_match = true\n"
228 " break\n"
229 " end\n"
230 " end # loop\n"
231 " break if _break_match\n"
232 " _trans += _klen\n"
233 " end\n"
234 " end while false\n";
235 }
236
writeExec()237 void RubyTabCodeGen::writeExec()
238 {
239 out <<
240 "begin\n"
241 " _klen, _trans, _keys";
242
243 if ( redFsm->anyRegCurStateRef() )
244 out << ", _ps";
245 if ( redFsm->anyConditions() )
246 out << ", _widec";
247 if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
248 || redFsm->anyFromStateActions() )
249 out << ", _acts, _nacts";
250
251 out << " = nil\n";
252
253 out <<
254 " _goto_level = 0\n"
255 " _resume = 10\n"
256 " _eof_trans = 15\n"
257 " _again = 20\n"
258 " _test_eof = 30\n"
259 " _out = 40\n";
260
261 out <<
262 " while true\n"
263 " _trigger_goto = false\n"
264 " if _goto_level <= 0\n";
265
266 if ( !noEnd ) {
267 out <<
268 " if " << P() << " == " << PE() << "\n"
269 " _goto_level = _test_eof\n"
270 " next\n"
271 " end\n";
272 }
273
274 if ( redFsm->errState != 0 ) {
275 out <<
276 " if " << vCS() << " == " << redFsm->errState->id << "\n"
277 " _goto_level = _out\n"
278 " next\n"
279 " end\n";
280 }
281
282 /* The resume label. */
283 out <<
284 " end\n"
285 " if _goto_level <= _resume\n";
286
287 if ( redFsm->anyFromStateActions() ) {
288 out <<
289 " _acts = " << FSA() << "[" << vCS() << "]\n"
290 " _nacts = " << A() << "[_acts]\n"
291 " _acts += 1\n"
292 " while _nacts > 0\n"
293 " _nacts -= 1\n"
294 " _acts += 1\n"
295 " case " << A() << "[_acts - 1]\n";
296 FROM_STATE_ACTION_SWITCH();
297 out <<
298 " end # from state action switch\n"
299 " end\n"
300 " if _trigger_goto\n"
301 " next\n"
302 " end\n";
303 }
304
305 if ( redFsm->anyConditions() )
306 COND_TRANSLATE();
307
308 LOCATE_TRANS();
309
310 if ( useIndicies )
311 out << " _trans = " << I() << "[_trans]\n";
312
313 if ( redFsm->anyEofTrans() ) {
314 out <<
315 " end\n"
316 " if _goto_level <= _eof_trans\n";
317 }
318
319 if ( redFsm->anyRegCurStateRef() )
320 out << " _ps = " << vCS() << "\n";
321
322 out << " " << vCS() << " = " << TT() << "[_trans]\n";
323
324 if ( redFsm->anyRegActions() ) {
325 out <<
326 " if " << TA() << "[_trans] != 0\n"
327 " _acts = " << TA() << "[_trans]\n"
328 " _nacts = " << A() << "[_acts]\n"
329 " _acts += 1\n"
330 " while _nacts > 0\n"
331 " _nacts -= 1\n"
332 " _acts += 1\n"
333 " case " << A() << "[_acts - 1]\n";
334 ACTION_SWITCH();
335 out <<
336 " end # action switch\n"
337 " end\n"
338 " end\n"
339 " if _trigger_goto\n"
340 " next\n"
341 " end\n";
342 }
343
344 /* The again label. */
345 out <<
346 " end\n"
347 " if _goto_level <= _again\n";
348
349 if ( redFsm->anyToStateActions() ) {
350 out <<
351 " _acts = " << TSA() << "[" << vCS() << "]\n"
352 " _nacts = " << A() << "[_acts]\n"
353 " _acts += 1\n"
354 " while _nacts > 0\n"
355 " _nacts -= 1\n"
356 " _acts += 1\n"
357 " case " << A() << "[_acts - 1]\n";
358 TO_STATE_ACTION_SWITCH();
359 out <<
360 " end # to state action switch\n"
361 " end\n"
362 " if _trigger_goto\n"
363 " next\n"
364 " end\n";
365 }
366
367 if ( redFsm->errState != 0 ) {
368 out <<
369 " if " << vCS() << " == " << redFsm->errState->id << "\n"
370 " _goto_level = _out\n"
371 " next\n"
372 " end\n";
373 }
374
375 out << " " << P() << " += 1\n";
376
377 if ( !noEnd ) {
378 out <<
379 " if " << P() << " != " << PE() << "\n"
380 " _goto_level = _resume\n"
381 " next\n"
382 " end\n";
383 }
384 else {
385 out <<
386 " _goto_level = _resume\n"
387 " next\n";
388 }
389
390 /* The test_eof label. */
391 out <<
392 " end\n"
393 " if _goto_level <= _test_eof\n";
394
395 if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
396 out <<
397 " if " << P() << " == " << vEOF() << "\n";
398
399 if ( redFsm->anyEofTrans() ) {
400 out <<
401 " if " << ET() << "[" << vCS() << "] > 0\n"
402 " _trans = " << ET() << "[" << vCS() << "] - 1;\n"
403 " _goto_level = _eof_trans\n"
404 " next;\n"
405 " end\n";
406 }
407
408 if ( redFsm->anyEofActions() ) {
409 out <<
410 " __acts = " << EA() << "[" << vCS() << "]\n"
411 " __nacts = " << " " << A() << "[__acts]\n"
412 " __acts += 1\n"
413 " while __nacts > 0\n"
414 " __nacts -= 1\n"
415 " __acts += 1\n"
416 " case " << A() << "[__acts - 1]\n";
417 EOF_ACTION_SWITCH() <<
418 " end # eof action switch\n"
419 " end\n"
420 " if _trigger_goto\n"
421 " next\n"
422 " end\n";
423 }
424
425 out <<
426 "end\n";
427 }
428
429 out <<
430 " end\n"
431 " if _goto_level <= _out\n"
432 " break\n"
433 " end\n";
434
435 /* The loop for next. */
436 out <<
437 " end\n";
438
439 /* Wrapping the execute block. */
440 out <<
441 " end\n";
442 }
443
FROM_STATE_ACTION_SWITCH()444 std::ostream &RubyTabCodeGen::FROM_STATE_ACTION_SWITCH()
445 {
446 /* Walk the list of functions, printing the cases. */
447 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
448 /* Write out referenced actions. */
449 if ( act->numFromStateRefs > 0 ) {
450 /* Write the case label, the action */
451 out << " when " << act->actionId << " then\n";
452 ACTION( out, act, 0, false );
453 }
454 }
455
456 genLineDirective( out );
457 return out;
458 }
459
460
TO_STATE_ACTION_SWITCH()461 std::ostream &RubyTabCodeGen::TO_STATE_ACTION_SWITCH()
462 {
463 /* Walk the list of functions, printing the cases. */
464 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
465 /* Write out referenced actions. */
466 if ( act->numToStateRefs > 0 ) {
467 /* Write the case label, the action and the case break. */
468 out << "when " << act->actionId << " then\n";
469 ACTION( out, act, 0, false );
470 }
471 }
472
473 genLineDirective( out );
474 return out;
475 }
476
EOF_ACTION_SWITCH()477 std::ostream &RubyTabCodeGen::EOF_ACTION_SWITCH()
478 {
479 /* Walk the list of functions, printing the cases. */
480 for ( GenActionList::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 << "when " << act->actionId << " then\n";
485 ACTION( out, act, 0, true );
486 }
487 }
488
489 genLineDirective( out );
490 return out;
491 }
492
ACTION_SWITCH()493 std::ostream &RubyTabCodeGen::ACTION_SWITCH()
494 {
495 /* Walk the list of functions, printing the cases. */
496 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
497 /* Write out referenced actions. */
498 if ( act->numTransRefs > 0 ) {
499 /* Write the case label, the action and the case break. */
500 out << "when " << act->actionId << " then\n";
501 ACTION( out, act, 0, false );
502 }
503 }
504
505 genLineDirective( out );
506 return out;
507 }
508
509
NEXT(ostream & ret,int nextDest,bool inFinish)510 void RubyTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
511 {
512 ret << vCS() << " = " << nextDest << ";";
513 }
514
NEXT_EXPR(ostream & ret,GenInlineItem * ilItem,bool inFinish)515 void RubyTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
516 {
517 ret << vCS() << " = (";
518 INLINE_LIST( ret, ilItem->children, 0, inFinish );
519 ret << ");";
520 }
521
522
TO_STATE_ACTION(RedStateAp * state)523 int RubyTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
524 {
525 int act = 0;
526 if ( state->toStateAction != 0 )
527 act = state->toStateAction->location+1;
528 return act;
529 }
530
FROM_STATE_ACTION(RedStateAp * state)531 int RubyTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
532 {
533 int act = 0;
534 if ( state->fromStateAction != 0 )
535 act = state->fromStateAction->location+1;
536 return act;
537 }
538
EOF_ACTION(RedStateAp * state)539 int RubyTabCodeGen::EOF_ACTION( RedStateAp *state )
540 {
541 int act = 0;
542 if ( state->eofAction != 0 )
543 act = state->eofAction->location+1;
544 return act;
545 }
546
547
COND_OFFSETS()548 std::ostream &RubyTabCodeGen::COND_OFFSETS()
549 {
550 START_ARRAY_LINE();
551 int totalStateNum = 0, curKeyOffset = 0;
552 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
553 /* Write the key offset. */
554 ARRAY_ITEM( INT(curKeyOffset), ++totalStateNum, st.last() );
555
556 /* Move the key offset ahead. */
557 curKeyOffset += st->stateCondList.length();
558 }
559 END_ARRAY_LINE();
560 return out;
561 }
562
KEY_OFFSETS()563 std::ostream &RubyTabCodeGen::KEY_OFFSETS()
564 {
565 START_ARRAY_LINE();
566 int totalStateNum = 0, curKeyOffset = 0;
567 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
568 /* Write the key offset. */
569 ARRAY_ITEM( INT(curKeyOffset), ++totalStateNum, st.last() );
570
571 /* Move the key offset ahead. */
572 curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
573 }
574 END_ARRAY_LINE();
575 return out;
576 }
577
578
INDEX_OFFSETS()579 std::ostream &RubyTabCodeGen::INDEX_OFFSETS()
580 {
581 START_ARRAY_LINE();
582 int totalStateNum = 0, curIndOffset = 0;
583 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
584 /* Write the index offset. */
585 ARRAY_ITEM( INT(curIndOffset), ++totalStateNum, st.last() );
586
587 /* Move the index offset ahead. */
588 curIndOffset += st->outSingle.length() + st->outRange.length();
589 if ( st->defTrans != 0 )
590 curIndOffset += 1;
591 }
592 END_ARRAY_LINE();
593 return out;
594 }
595
COND_LENS()596 std::ostream &RubyTabCodeGen::COND_LENS()
597 {
598 START_ARRAY_LINE();
599 int totalStateNum = 0;
600 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
601 /* Write singles length. */
602 ARRAY_ITEM( INT(st->stateCondList.length()), ++totalStateNum, st.last() );
603 }
604 END_ARRAY_LINE();
605 return out;
606 }
607
608
SINGLE_LENS()609 std::ostream &RubyTabCodeGen::SINGLE_LENS()
610 {
611 START_ARRAY_LINE();
612 int totalStateNum = 0;
613 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
614 /* Write singles length. */
615 ARRAY_ITEM( INT(st->outSingle.length()), ++totalStateNum, st.last() );
616 }
617 END_ARRAY_LINE();
618 return out;
619 }
620
RANGE_LENS()621 std::ostream &RubyTabCodeGen::RANGE_LENS()
622 {
623 START_ARRAY_LINE();
624 int totalStateNum = 0;
625 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
626 /* Emit length of range index. */
627 ARRAY_ITEM( INT(st->outRange.length()), ++totalStateNum, st.last() );
628 }
629 END_ARRAY_LINE();
630 return out;
631 }
632
TO_STATE_ACTIONS()633 std::ostream &RubyTabCodeGen::TO_STATE_ACTIONS()
634 {
635 START_ARRAY_LINE();
636 int totalStateNum = 0;
637 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
638 /* Write any eof action. */
639 ARRAY_ITEM( INT(TO_STATE_ACTION(st)), ++totalStateNum, st.last() );
640 }
641 END_ARRAY_LINE();
642 return out;
643 }
644
FROM_STATE_ACTIONS()645 std::ostream &RubyTabCodeGen::FROM_STATE_ACTIONS()
646 {
647 START_ARRAY_LINE();
648 int totalStateNum = 0;
649 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
650 /* Write any eof action. */
651 ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), ++totalStateNum, st.last() );
652 }
653 END_ARRAY_LINE();
654 return out;
655 }
656
EOF_ACTIONS()657 std::ostream &RubyTabCodeGen::EOF_ACTIONS()
658 {
659 START_ARRAY_LINE();
660 int totalStateNum = 0;
661 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
662 /* Write any eof action. */
663 ARRAY_ITEM( INT(EOF_ACTION(st)), ++totalStateNum, st.last() );
664 }
665 END_ARRAY_LINE();
666 return out;
667 }
668
EOF_TRANS()669 std::ostream &RubyTabCodeGen::EOF_TRANS()
670 {
671 START_ARRAY_LINE();
672 int totalStateNum = 0;
673 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
674 /* Write any eof action. */
675 long trans = 0;
676 if ( st->eofTrans != 0 ) {
677 assert( st->eofTrans->pos >= 0 );
678 trans = st->eofTrans->pos+1;
679 }
680
681 /* Write any eof action. */
682 ARRAY_ITEM( INT(trans), ++totalStateNum, st.last() );
683 }
684 END_ARRAY_LINE();
685 return out;
686 }
687
COND_KEYS()688 std::ostream &RubyTabCodeGen::COND_KEYS()
689 {
690 START_ARRAY_LINE();
691 int totalTrans = 0;
692 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
693 /* Loop the state's transitions. */
694 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
695 /* Lower key. */
696 ARRAY_ITEM( KEY( sc->lowKey ), ++totalTrans, false );
697 ARRAY_ITEM( KEY( sc->highKey ), ++totalTrans, false );
698 }
699 }
700
701 /* Output one last number so we don't have to figure out when the last
702 * entry is and avoid writing a comma. */
703 ARRAY_ITEM( INT(0), ++totalTrans, true );
704 END_ARRAY_LINE();
705 return out;
706 }
707
COND_SPACES()708 std::ostream &RubyTabCodeGen::COND_SPACES()
709 {
710 START_ARRAY_LINE();
711 int totalTrans = 0;
712 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
713 /* Loop the state's transitions. */
714 for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
715 /* Cond Space id. */
716 ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), ++totalTrans, false );
717 }
718 }
719
720 /* Output one last number so we don't have to figure out when the last
721 * entry is and avoid writing a comma. */
722 ARRAY_ITEM( INT(0), ++totalTrans, true );
723 END_ARRAY_LINE();
724 return out;
725 }
726
KEYS()727 std::ostream &RubyTabCodeGen::KEYS()
728 {
729 START_ARRAY_LINE();
730 int totalTrans = 0;
731 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
732 /* Loop the singles. */
733 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
734 ARRAY_ITEM( KEY( stel->lowKey ), ++totalTrans, false );
735 }
736
737 /* Loop the state's transitions. */
738 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
739 /* Lower key. */
740 ARRAY_ITEM( KEY( rtel->lowKey ), ++totalTrans, false );
741
742 /* Upper key. */
743 ARRAY_ITEM( KEY( rtel->highKey ), ++totalTrans, false );
744 }
745 }
746
747 /* Output one last number so we don't have to figure out when the last
748 * entry is and avoid writing a comma. */
749 ARRAY_ITEM( INT(0), ++totalTrans, true );
750 END_ARRAY_LINE();
751 return out;
752 }
753
INDICIES()754 std::ostream &RubyTabCodeGen::INDICIES()
755 {
756 int totalTrans = 0;
757 START_ARRAY_LINE();
758 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
759 /* Walk the singles. */
760 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
761 ARRAY_ITEM( KEY( stel->value->id ), ++totalTrans, false );
762 }
763
764 /* Walk the ranges. */
765 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
766 ARRAY_ITEM( KEY( rtel->value->id ), ++totalTrans, false );
767 }
768
769 /* The state's default index goes next. */
770 if ( st->defTrans != 0 ) {
771 ARRAY_ITEM( KEY( st->defTrans->id ), ++totalTrans, false );
772 }
773 }
774
775 /* Output one last number so we don't have to figure out when the last
776 * entry is and avoid writing a comma. */
777 ARRAY_ITEM( INT(0), ++totalTrans, true );
778 END_ARRAY_LINE();
779 return out;
780 }
781
TRANS_TARGS()782 std::ostream &RubyTabCodeGen::TRANS_TARGS()
783 {
784 int totalTrans = 0;
785 START_ARRAY_LINE();
786 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
787 /* Walk the singles. */
788 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
789 RedTransAp *trans = stel->value;
790 ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
791 }
792
793 /* Walk the ranges. */
794 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
795 RedTransAp *trans = rtel->value;
796 ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
797 }
798
799 /* The state's default target state. */
800 if ( st->defTrans != 0 ) {
801 RedTransAp *trans = st->defTrans;
802 ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
803 }
804 }
805
806 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
807 if ( st->eofTrans != 0 ) {
808 RedTransAp *trans = st->eofTrans;
809 trans->pos = totalTrans;
810 ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
811 }
812 }
813
814 /* Output one last number so we don't have to figure out when the last
815 * entry is and avoid writing a comma. */
816 ARRAY_ITEM( INT(0), ++totalTrans, true );
817 END_ARRAY_LINE();
818 return out;
819 }
820
821
TRANS_ACTIONS()822 std::ostream &RubyTabCodeGen::TRANS_ACTIONS()
823 {
824 int totalTrans = 0;
825 START_ARRAY_LINE();
826 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
827 /* Walk the singles. */
828 for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
829 RedTransAp *trans = stel->value;
830 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
831 }
832
833 /* Walk the ranges. */
834 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
835 RedTransAp *trans = rtel->value;
836 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
837 }
838
839 /* The state's default index goes next. */
840 if ( st->defTrans != 0 ) {
841 RedTransAp *trans = st->defTrans;
842 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
843 }
844 }
845
846 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
847 if ( st->eofTrans != 0 ) {
848 RedTransAp *trans = st->eofTrans;
849 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
850 }
851 }
852
853 /* Output one last number so we don't have to figure out when the last
854 * entry is and avoid writing a comma. */
855 ARRAY_ITEM( INT(0), ++totalTrans, true );
856 END_ARRAY_LINE();
857 return out;
858 }
859
TRANS_TARGS_WI()860 std::ostream &RubyTabCodeGen::TRANS_TARGS_WI()
861 {
862 /* Transitions must be written ordered by their id. */
863 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
864 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
865 transPtrs[trans->id] = trans;
866
867 /* Keep a count of the num of items in the array written. */
868 START_ARRAY_LINE();
869 int totalStates = 0;
870 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
871 /* Save the position. Needed for eofTargs. */
872 RedTransAp *trans = transPtrs[t];
873 trans->pos = t;
874
875 /* Write out the target state. */
876 ARRAY_ITEM( INT(trans->targ->id), ++totalStates, ( t >= redFsm->transSet.length()-1 ) );
877 }
878 END_ARRAY_LINE();
879 delete[] transPtrs;
880 return out;
881 }
882
883
TRANS_ACTIONS_WI()884 std::ostream &RubyTabCodeGen::TRANS_ACTIONS_WI()
885 {
886 /* Transitions must be written ordered by their id. */
887 RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
888 for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
889 transPtrs[trans->id] = trans;
890
891 /* Keep a count of the num of items in the array written. */
892 START_ARRAY_LINE();
893 int totalAct = 0;
894 for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
895 /* Write the function for the transition. */
896 RedTransAp *trans = transPtrs[t];
897 ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalAct,
898 ( t >= redFsm->transSet.length()-1 ) );
899 }
900 END_ARRAY_LINE();
901 delete[] transPtrs;
902 return out;
903 }
904
905
writeData()906 void RubyTabCodeGen::writeData()
907 {
908 /* If there are any transtion functions then output the array. If there
909 * are none, don't bother emitting an empty array that won't be used. */
910 if ( redFsm->anyActions() ) {
911 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
912 ACTIONS_ARRAY();
913 CLOSE_ARRAY() <<
914 "\n";
915 }
916
917 if ( redFsm->anyConditions() ) {
918 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
919 COND_OFFSETS();
920 CLOSE_ARRAY() <<
921 "\n";
922
923 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
924 COND_LENS();
925 CLOSE_ARRAY() <<
926 "\n";
927
928 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
929 COND_KEYS();
930 CLOSE_ARRAY() <<
931 "\n";
932
933 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
934 COND_SPACES();
935 CLOSE_ARRAY() <<
936 "\n";
937 }
938
939 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
940 KEY_OFFSETS();
941 CLOSE_ARRAY() <<
942 "\n";
943
944 OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
945 KEYS();
946 CLOSE_ARRAY() <<
947 "\n";
948
949 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
950 SINGLE_LENS();
951 CLOSE_ARRAY() <<
952 "\n";
953
954 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
955 RANGE_LENS();
956 CLOSE_ARRAY() <<
957 "\n";
958
959 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
960 INDEX_OFFSETS();
961 CLOSE_ARRAY() <<
962 "\n";
963
964 if ( useIndicies ) {
965 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
966 INDICIES();
967 CLOSE_ARRAY() <<
968 "\n";
969
970 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
971 TRANS_TARGS_WI();
972 CLOSE_ARRAY() <<
973 "\n";
974
975 if ( redFsm->anyActions() ) {
976 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
977 TRANS_ACTIONS_WI();
978 CLOSE_ARRAY() <<
979 "\n";
980 }
981 }
982 else {
983 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
984 TRANS_TARGS();
985 CLOSE_ARRAY() <<
986 "\n";
987
988 if ( redFsm->anyActions() ) {
989 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
990 TRANS_ACTIONS();
991 CLOSE_ARRAY() <<
992 "\n";
993 }
994 }
995
996 if ( redFsm->anyToStateActions() ) {
997 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
998 TO_STATE_ACTIONS();
999 CLOSE_ARRAY() <<
1000 "\n";
1001 }
1002
1003 if ( redFsm->anyFromStateActions() ) {
1004 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
1005 FROM_STATE_ACTIONS();
1006 CLOSE_ARRAY() <<
1007 "\n";
1008 }
1009
1010 if ( redFsm->anyEofActions() ) {
1011 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
1012 EOF_ACTIONS();
1013 CLOSE_ARRAY() <<
1014 "\n";
1015 }
1016
1017 if ( redFsm->anyEofTrans() ) {
1018 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
1019 EOF_TRANS();
1020 CLOSE_ARRAY() <<
1021 "\n";
1022 }
1023
1024 STATE_IDS();
1025 }
1026
1027 /*
1028 Local Variables:
1029 mode: c++
1030 indent-tabs-mode: 1
1031 c-file-style: "bsd"
1032 End:
1033 */
1034