"Fossies" - the Fresh Open Source Software Archive 
Member "ragel-6.10/ragel/rubycodegen.cpp" (24 Mar 2017, 18410 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 "rubycodegen.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 * 2007 Victor Hugo Borja <vic@rubyforge.org>
3 * Copyright 2001-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 "rubycodegen.h"
29 #include "pcheck.h"
30 #include "vector.h"
31 #include "version.h"
32 #include "common.h"
33
34 #include "ragel.h"
35 #include "rubytable.h"
36 #include "rubyftable.h"
37 #include "rubyflat.h"
38 #include "rubyfflat.h"
39 #include "rbxgoto.h"
40
41 using std::ostream;
42 using std::ostringstream;
43 using std::string;
44 using std::cerr;
45 using std::endl;
46 using std::istream;
47 using std::ifstream;
48 using std::ostream;
49 using std::ios;
50 using std::cin;
51 using std::cout;
52 using std::cerr;
53 using std::endl;
54
55 /* Target ruby impl */
56
57 /* Target language and output style. */
58 extern CodeStyle codeStyle;
59
60 extern int numSplitPartitions;
61 extern bool noLineDirectives;
62
63 /*
64 * Callbacks invoked by the XML data parser.
65 */
66
67
68 void rubyLineDirective( ostream &out, const char *fileName, int line )
69 {
70 if ( noLineDirectives )
71 return;
72
73 /* Write a comment containing line info. */
74 out << "# line " << line << " \"";
75 for ( const char *pc = fileName; *pc != 0; pc++ ) {
76 if ( *pc == '\\' )
77 out << "\\\\";
78 else
79 out << *pc;
80 }
81 out << "\"\n";
82 }
83
84 void RubyCodeGen::genLineDirective( ostream &out )
85 {
86 std::streambuf *sbuf = out.rdbuf();
87 output_filter *filter = static_cast<output_filter*>(sbuf);
88 rubyLineDirective( out, filter->fileName, filter->line + 1 );
89 }
90
91 string RubyCodeGen::DATA_PREFIX()
92 {
93 if ( !noPrefix )
94 return FSM_NAME() + "_";
95 return "";
96 }
97
98 std::ostream &RubyCodeGen::STATIC_VAR( string type, string name )
99 {
100 out <<
101 "class << self\n"
102 " attr_accessor :" << name << "\n"
103 "end\n"
104 "self." << name;
105 return out;
106 }
107
108
109 std::ostream &RubyCodeGen::OPEN_ARRAY( string type, string name )
110 {
111 out <<
112 "class << self\n"
113 " attr_accessor :" << name << "\n"
114 " private :" << name << ", :" << name << "=\n"
115 "end\n"
116 "self." << name << " = [\n";
117 return out;
118 }
119
120 std::ostream &RubyCodeGen::CLOSE_ARRAY()
121 {
122 out << "]\n";
123 return out;
124 }
125
126
127 string RubyCodeGen::ARR_OFF( string ptr, string offset )
128 {
129 return ptr + "[" + offset + "]";
130 }
131
132 string RubyCodeGen::NULL_ITEM()
133 {
134 return "nil";
135 }
136
137
138 string RubyCodeGen::P()
139 {
140 ostringstream ret;
141 if ( pExpr == 0 )
142 ret << "p";
143 else {
144 //ret << "(";
145 INLINE_LIST( ret, pExpr, 0, false );
146 //ret << ")";
147 }
148 return ret.str();
149 }
150
151 string RubyCodeGen::PE()
152 {
153 ostringstream ret;
154 if ( peExpr == 0 )
155 ret << "pe";
156 else {
157 //ret << "(";
158 INLINE_LIST( ret, peExpr, 0, false );
159 //ret << ")";
160 }
161 return ret.str();
162 }
163
164 string RubyCodeGen::vEOF()
165 {
166 ostringstream ret;
167 if ( eofExpr == 0 )
168 ret << "eof";
169 else {
170 //ret << "(";
171 INLINE_LIST( ret, eofExpr, 0, false );
172 //ret << ")";
173 }
174 return ret.str();
175 }
176
177 string RubyCodeGen::vCS()
178 {
179 ostringstream ret;
180 if ( csExpr == 0 )
181 ret << ACCESS() << "cs";
182 else {
183 //ret << "(";
184 INLINE_LIST( ret, csExpr, 0, false );
185 //ret << ")";
186 }
187 return ret.str();
188 }
189
190 string RubyCodeGen::TOP()
191 {
192 ostringstream ret;
193 if ( topExpr == 0 )
194 ret << ACCESS() + "top";
195 else {
196 //ret << "(";
197 INLINE_LIST( ret, topExpr, 0, false );
198 //ret << ")";
199 }
200 return ret.str();
201 }
202
203 string RubyCodeGen::STACK()
204 {
205 ostringstream ret;
206 if ( stackExpr == 0 )
207 ret << ACCESS() + "stack";
208 else {
209 //ret << "(";
210 INLINE_LIST( ret, stackExpr, 0, false );
211 //ret << ")";
212 }
213 return ret.str();
214 }
215
216 string RubyCodeGen::ACT()
217 {
218 ostringstream ret;
219 if ( actExpr == 0 )
220 ret << ACCESS() + "act";
221 else {
222 //ret << "(";
223 INLINE_LIST( ret, actExpr, 0, false );
224 //ret << ")";
225 }
226 return ret.str();
227 }
228
229 string RubyCodeGen::TOKSTART()
230 {
231 ostringstream ret;
232 if ( tokstartExpr == 0 )
233 ret << ACCESS() + "ts";
234 else {
235 //ret << "(";
236 INLINE_LIST( ret, tokstartExpr, 0, false );
237 //ret << ")";
238 }
239 return ret.str();
240 }
241
242 string RubyCodeGen::TOKEND()
243 {
244 ostringstream ret;
245 if ( tokendExpr == 0 )
246 ret << ACCESS() + "te";
247 else {
248 //ret << "(";
249 INLINE_LIST( ret, tokendExpr, 0, false );
250 //ret << ")";
251 }
252 return ret.str();
253 }
254
255 string RubyCodeGen::DATA()
256 {
257 ostringstream ret;
258 if ( dataExpr == 0 )
259 ret << ACCESS() + "data";
260 else {
261 //ret << "(";
262 INLINE_LIST( ret, dataExpr, 0, false );
263 //ret << ")";
264 }
265 return ret.str();
266 }
267
268 /* Write out the fsm name. */
269 string RubyCodeGen::FSM_NAME()
270 {
271 return fsmName;
272 }
273
274
275 void RubyCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish )
276 {
277 /* Write the preprocessor line info for going into the source file. */
278 rubyLineDirective( ret, action->loc.fileName, action->loc.line );
279
280 /* Write the block and close it off. */
281 ret << " begin\n";
282 INLINE_LIST( ret, action->inlineList, targState, inFinish );
283 ret << " end\n";
284 }
285
286
287
288 string RubyCodeGen::GET_WIDE_KEY()
289 {
290 if ( redFsm->anyConditions() )
291 return "_widec";
292 else
293 return GET_KEY();
294 }
295
296 string RubyCodeGen::GET_WIDE_KEY( RedStateAp *state )
297 {
298 if ( state->stateCondList.length() > 0 )
299 return "_widec";
300 else
301 return GET_KEY();
302 }
303
304 string RubyCodeGen::GET_KEY()
305 {
306 ostringstream ret;
307 if ( getKeyExpr != 0 ) {
308 /* Emit the user supplied method of retrieving the key. */
309 ret << "(";
310 INLINE_LIST( ret, getKeyExpr, 0, false );
311 ret << ")";
312 }
313 else {
314 /* Expression for retrieving the key, use dereference and read ordinal,
315 * for compatibility with Ruby 1.9. */
316 ret << DATA() << "[" << P() << "].ord";
317 }
318 return ret.str();
319 }
320
321 string RubyCodeGen::KEY( Key key )
322 {
323 ostringstream ret;
324 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
325 ret << key.getVal();
326 else
327 ret << (unsigned long) key.getVal();
328 return ret.str();
329 }
330
331
332 /* Write out level number of tabs. Makes the nested binary search nice
333 * looking. */
334 string RubyCodeGen::TABS( int level )
335 {
336 string result;
337 while ( level-- > 0 )
338 result += "\t";
339 return result;
340 }
341
342 string RubyCodeGen::INT( int i )
343 {
344 ostringstream ret;
345 ret << i;
346 return ret.str();
347 }
348
349 void RubyCodeGen::CONDITION( ostream &ret, GenAction *condition )
350 {
351 ret << "\n";
352 rubyLineDirective( ret, condition->loc.fileName, condition->loc.line );
353 INLINE_LIST( ret, condition->inlineList, 0, false );
354 }
355
356 /* Emit the alphabet data type. */
357 string RubyCodeGen::ALPH_TYPE()
358 {
359 string ret = keyOps->alphType->data1;
360 if ( keyOps->alphType->data2 != 0 ) {
361 ret += " ";
362 ret += + keyOps->alphType->data2;
363 }
364 return ret;
365 }
366
367 /* Emit the alphabet data type. */
368 string RubyCodeGen::WIDE_ALPH_TYPE()
369 {
370 string ret;
371 if ( redFsm->maxKey <= keyOps->maxKey )
372 ret = ALPH_TYPE();
373 else {
374 long long maxKeyVal = redFsm->maxKey.getLongLong();
375 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
376 assert( wideType != 0 );
377
378 ret = wideType->data1;
379 if ( wideType->data2 != 0 ) {
380 ret += " ";
381 ret += wideType->data2;
382 }
383 }
384 return ret;
385 }
386
387
388 string RubyCodeGen::ARRAY_TYPE( unsigned long maxVal )
389 {
390 long long maxValLL = (long long) maxVal;
391 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
392 assert( arrayType != 0 );
393
394 string ret = arrayType->data1;
395 if ( arrayType->data2 != 0 ) {
396 ret += " ";
397 ret += arrayType->data2;
398 }
399 return ret;
400 }
401
402 /* Write out the array of actions. */
403 std::ostream &RubyCodeGen::ACTIONS_ARRAY()
404 {
405 START_ARRAY_LINE();
406 int totalActions = 0;
407 ARRAY_ITEM( INT(0), ++totalActions, false );
408 for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
409 /* Write out the length, which will never be the last character. */
410 ARRAY_ITEM( INT(act->key.length()), ++totalActions, false );
411
412 for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) {
413 ARRAY_ITEM( INT(item->value->actionId), ++totalActions, (act.last() && item.last()) );
414 }
415 }
416 END_ARRAY_LINE();
417 return out;
418 }
419
420 void RubyCodeGen::STATE_IDS()
421 {
422 if ( redFsm->startState != 0 )
423 STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
424
425 if ( !noFinal )
426 STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
427
428 if ( !noError )
429 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
430
431 out << "\n";
432
433 if ( !noEntry && entryPointNames.length() > 0 ) {
434 for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
435 STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) <<
436 " = " << entryPointIds[en.pos()] << ";\n";
437 }
438 out << "\n";
439 }
440 }
441
442 std::ostream &RubyCodeGen::START_ARRAY_LINE()
443 {
444 out << "\t";
445 return out;
446 }
447
448 std::ostream &RubyCodeGen::ARRAY_ITEM( string item, int count, bool last )
449 {
450 out << item;
451 if ( !last )
452 {
453 out << ", ";
454 if ( count % IALL == 0 )
455 {
456 END_ARRAY_LINE();
457 START_ARRAY_LINE();
458 }
459 }
460 return out;
461 }
462
463 std::ostream &RubyCodeGen::END_ARRAY_LINE()
464 {
465 out << "\n";
466 return out;
467 }
468
469 /* Emit the offset of the start state as a decimal integer. */
470 string RubyCodeGen::START_STATE_ID()
471 {
472 ostringstream ret;
473 ret << redFsm->startState->id;
474 return ret.str();
475 };
476
477 string RubyCodeGen::ERROR_STATE()
478 {
479 ostringstream ret;
480 if ( redFsm->errState != 0 )
481 ret << redFsm->errState->id;
482 else
483 ret << "-1";
484 return ret.str();
485 }
486
487 string RubyCodeGen::FIRST_FINAL_STATE()
488 {
489 ostringstream ret;
490 if ( redFsm->firstFinState != 0 )
491 ret << redFsm->firstFinState->id;
492 else
493 ret << redFsm->nextStateId;
494 return ret.str();
495 }
496
497 string RubyCodeGen::ACCESS()
498 {
499 ostringstream ret;
500 if ( accessExpr != 0 )
501 INLINE_LIST( ret, accessExpr, 0, false );
502 return ret.str();
503 }
504
505 /* Write out an inline tree structure. Walks the list and possibly calls out
506 * to virtual functions than handle language specific items in the tree. */
507 void RubyCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList,
508 int targState, bool inFinish )
509 {
510 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
511 switch ( item->type ) {
512 case GenInlineItem::Text:
513 ret << item->data;
514 break;
515 case GenInlineItem::Goto:
516 GOTO( ret, item->targState->id, inFinish );
517 break;
518 case GenInlineItem::Call:
519 CALL( ret, item->targState->id, targState, inFinish );
520 break;
521 case GenInlineItem::Next:
522 NEXT( ret, item->targState->id, inFinish );
523 break;
524 case GenInlineItem::Ret:
525 RET( ret, inFinish );
526 break;
527 case GenInlineItem::PChar:
528 ret << P();
529 break;
530 case GenInlineItem::Char:
531 ret << GET_KEY();
532 break;
533 case GenInlineItem::Hold:
534 ret << P() << " = " << P() << " - 1;";
535 break;
536 case GenInlineItem::Exec:
537 EXEC( ret, item, targState, inFinish );
538 break;
539 case GenInlineItem::Curs:
540 ret << "(_ps)";
541 break;
542 case GenInlineItem::Targs:
543 ret << "(" << vCS() << ")";
544 break;
545 case GenInlineItem::Entry:
546 ret << item->targState->id;
547 break;
548 case GenInlineItem::GotoExpr:
549 GOTO_EXPR( ret, item, inFinish );
550 break;
551 case GenInlineItem::CallExpr:
552 CALL_EXPR( ret, item, targState, inFinish );
553 break;
554 case GenInlineItem::NextExpr:
555 NEXT_EXPR( ret, item, inFinish );
556 break;
557 case GenInlineItem::LmSwitch:
558 LM_SWITCH( ret, item, targState, inFinish );
559 break;
560 case GenInlineItem::LmSetActId:
561 SET_ACT( ret, item );
562 break;
563 case GenInlineItem::LmSetTokEnd:
564 SET_TOKEND( ret, item );
565 break;
566 case GenInlineItem::LmGetTokEnd:
567 GET_TOKEND( ret, item );
568 break;
569 case GenInlineItem::LmInitTokStart:
570 INIT_TOKSTART( ret, item );
571 break;
572 case GenInlineItem::LmInitAct:
573 INIT_ACT( ret, item );
574 break;
575 case GenInlineItem::LmSetTokStart:
576 SET_TOKSTART( ret, item );
577 break;
578 case GenInlineItem::SubAction:
579 SUB_ACTION( ret, item, targState, inFinish );
580 break;
581 case GenInlineItem::Break:
582 BREAK( ret, targState );
583 break;
584 }
585 }
586 }
587
588
589 void RubyCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
590 {
591 /* The parser gives fexec two children. The double brackets are for D
592 * code. If the inline list is a single word it will get interpreted as a
593 * C-style cast by the D compiler. */
594 ret << " begin " << P() << " = ((";
595 INLINE_LIST( ret, item->children, targState, inFinish );
596 ret << "))-1; end\n";
597 }
598
599 void RubyCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item,
600 int targState, int inFinish )
601 {
602 ret <<
603 " case " << ACT() << "\n";
604
605 for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
606 /* Write the case label, the action and the case break. */
607 if ( lma->lmId < 0 )
608 ret << " else\n";
609 else
610 ret << " when " << lma->lmId << " then\n";
611
612
613 /* Write the block and close it off. */
614 ret << " begin";
615 INLINE_LIST( ret, lma->children, targState, inFinish );
616 ret << "end\n";
617 }
618
619 ret << "end \n\t";
620 }
621
622 void RubyCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
623 {
624 ret << ACT() << " = " << item->lmId << ";";
625 }
626
627 void RubyCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
628 {
629 ret << TOKSTART() << " = " << NULL_ITEM() << ";";
630 }
631
632 void RubyCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
633 {
634 ret << ACT() << " = 0\n";
635 }
636
637 void RubyCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
638 {
639 ret << TOKSTART() << " = " << P() << "\n";
640 }
641
642 void RubyCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
643 {
644 /* The tokend action sets tokend. */
645 ret << TOKEND() << " = " << P();
646 if ( item->offset != 0 )
647 out << "+" << item->offset;
648 out << "\n";
649 }
650
651 void RubyCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
652 {
653 ret << TOKEND();
654 }
655
656 void RubyCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item,
657 int targState, bool inFinish )
658 {
659 if ( item->children->length() > 0 ) {
660 /* Write the block and close it off. */
661 ret << " begin ";
662 INLINE_LIST( ret, item->children, targState, inFinish );
663 ret << " end\n";
664 }
665 }
666
667 int RubyCodeGen::TRANS_ACTION( RedTransAp *trans )
668 {
669 /* If there are actions, emit them. Otherwise emit zero. */
670 int act = 0;
671 if ( trans->action != 0 )
672 act = trans->action->location+1;
673 return act;
674 }
675
676 ostream &RubyCodeGen::source_warning( const InputLoc &loc )
677 {
678 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
679 return cerr;
680 }
681
682 ostream &RubyCodeGen::source_error( const InputLoc &loc )
683 {
684 gblErrorCount += 1;
685 assert( sourceFileName != 0 );
686 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
687 return cerr;
688 }
689
690 void RubyCodeGen::finishRagelDef()
691 {
692 if ( codeStyle == GenGoto || codeStyle == GenFGoto ||
693 codeStyle == GenIpGoto || codeStyle == GenSplit )
694 {
695 /* For directly executable machines there is no required state
696 * ordering. Choose a depth-first ordering to increase the
697 * potential for fall-throughs. */
698 redFsm->depthFirstOrdering();
699 }
700 else {
701 /* The frontend will do this for us, but it may be a good idea to
702 * force it if the intermediate file is edited. */
703 redFsm->sortByStateId();
704 }
705
706 /* Choose default transitions and the single transition. */
707 redFsm->chooseDefaultSpan();
708
709 /* Maybe do flat expand, otherwise choose single. */
710 if ( codeStyle == GenFlat || codeStyle == GenFFlat )
711 redFsm->makeFlat();
712 else
713 redFsm->chooseSingle();
714
715 /* If any errors have occured in the input file then don't write anything. */
716 if ( gblErrorCount > 0 )
717 return;
718
719 if ( codeStyle == GenSplit )
720 redFsm->partitionFsm( numSplitPartitions );
721
722 if ( codeStyle == GenIpGoto || codeStyle == GenSplit )
723 redFsm->setInTrans();
724
725 /* Anlayze Machine will find the final action reference counts, among
726 * other things. We will use these in reporting the usage
727 * of fsm directives in action code. */
728 analyzeMachine();
729
730 /* Determine if we should use indicies. */
731 calcIndexSize();
732 }
733
734
735 /* Determine if we should use indicies or not. */
736 void RubyCodeGen::calcIndexSize()
737 {
738 int sizeWithInds = 0, sizeWithoutInds = 0;
739
740 /* Calculate cost of using with indicies. */
741 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
742 int totalIndex = st->outSingle.length() + st->outRange.length() +
743 (st->defTrans == 0 ? 0 : 1);
744 sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
745 }
746 sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
747 if ( redFsm->anyActions() )
748 sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
749
750 /* Calculate the cost of not using indicies. */
751 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
752 int totalIndex = st->outSingle.length() + st->outRange.length() +
753 (st->defTrans == 0 ? 0 : 1);
754 sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
755 if ( redFsm->anyActions() )
756 sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
757 }
758
759 /* If using indicies reduces the size, use them. */
760 useIndicies = sizeWithInds < sizeWithoutInds;
761 }
762
763 unsigned int RubyCodeGen::arrayTypeSize( unsigned long maxVal )
764 {
765 long long maxValLL = (long long) maxVal;
766 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
767 assert( arrayType != 0 );
768 return arrayType->size;
769 }
770
771
772 void RubyCodeGen::writeInit()
773 {
774 out << "begin\n";
775
776 out << " " << P() << " ||= 0\n";
777
778 if ( !noEnd )
779 out << " " << PE() << " ||= " << DATA() << ".length\n";
780
781 if ( !noCS )
782 out << " " << vCS() << " = " << START() << "\n";
783
784 /* If there are any calls, then the stack top needs initialization. */
785 if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
786 out << " " << TOP() << " = 0\n";
787
788 if ( hasLongestMatch ) {
789 out <<
790 " " << TOKSTART() << " = " << NULL_ITEM() << "\n"
791 " " << TOKEND() << " = " << NULL_ITEM() << "\n"
792 " " << ACT() << " = 0\n";
793 }
794
795 out << "end\n";
796 }
797
798 void RubyCodeGen::writeExports()
799 {
800 if ( exportList.length() > 0 ) {
801 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
802 STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name )
803 << " = " << KEY(ex->key) << "\n";
804 }
805 out << "\n";
806 }
807 }
808
809 void RubyCodeGen::writeStart()
810 {
811 out << START_STATE_ID();
812 }
813
814 void RubyCodeGen::writeFirstFinal()
815 {
816 out << FIRST_FINAL_STATE();
817 }
818
819 void RubyCodeGen::writeError()
820 {
821 out << ERROR_STATE();
822 }
823
824
825 /*
826 * Local Variables:
827 * mode: c++
828 * indent-tabs-mode: 1
829 * c-file-style: "bsd"
830 * End:
831 */