2 * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca>
3 * 2004 Eric Ocean <eric.ocean@ampede.com>
4 * 2005 Alan West <alan@alanz.com>
7 /* This file is part of Ragel.
9 * Ragel is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * Ragel is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Ragel; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "rlcodegen.h"
25 #include "fsmcodegen.h"
33 using std::ostringstream;
39 /* Determine if a string is only whitespace. Code blocks that are only
40 * whitespace need not be output. */
41 bool onlyWhitespace( char *str )
44 if ( *str != ' ' && *str != '\t' && *str != '\n' &&
45 *str != '\v' && *str != '\f' && *str != '\r' )
52 /* Init code gen with in parameters. */
53 FsmCodeGen::FsmCodeGen( ostream &out )
59 bAnyToStateActions(false),
60 bAnyFromStateActions(false),
61 bAnyRegActions(false),
62 bAnyEofActions(false),
63 bAnyActionGotos(false),
64 bAnyActionCalls(false),
65 bAnyActionRets(false),
66 bAnyRegActionRets(false),
67 bAnyRegActionByValControl(false),
68 bAnyRegNextStmt(false),
69 bAnyRegCurStateRef(false),
71 bAnyLmSwitchError(false),
76 /* Does the machine have any actions. */
77 bool FsmCodeGen::anyActions()
79 return redFsm->actionMap.length() > 0;
82 void FsmCodeGen::findFinalActionRefs()
84 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
85 /* Rerence count out of single transitions. */
86 for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) {
87 if ( rtel->value->action != 0 ) {
88 rtel->value->action->numTransRefs += 1;
89 for ( ActionTable::Iter item = rtel->value->action->key; item.lte(); item++ )
90 item->value->numTransRefs += 1;
94 /* Reference count out of range transitions. */
95 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
96 if ( rtel->value->action != 0 ) {
97 rtel->value->action->numTransRefs += 1;
98 for ( ActionTable::Iter item = rtel->value->action->key; item.lte(); item++ )
99 item->value->numTransRefs += 1;
103 /* Reference count default transition. */
104 if ( st->defTrans != 0 && st->defTrans->action != 0 ) {
105 st->defTrans->action->numTransRefs += 1;
106 for ( ActionTable::Iter item = st->defTrans->action->key; item.lte(); item++ )
107 item->value->numTransRefs += 1;
110 /* Reference count to state actions. */
111 if ( st->toStateAction != 0 ) {
112 st->toStateAction->numToStateRefs += 1;
113 for ( ActionTable::Iter item = st->toStateAction->key; item.lte(); item++ )
114 item->value->numToStateRefs += 1;
117 /* Reference count from state actions. */
118 if ( st->fromStateAction != 0 ) {
119 st->fromStateAction->numFromStateRefs += 1;
120 for ( ActionTable::Iter item = st->fromStateAction->key; item.lte(); item++ )
121 item->value->numFromStateRefs += 1;
124 /* Reference count EOF actions. */
125 if ( st->eofAction != 0 ) {
126 st->eofAction->numEofRefs += 1;
127 for ( ActionTable::Iter item = st->eofAction->key; item.lte(); item++ )
128 item->value->numEofRefs += 1;
133 /* Assign ids to referenced actions. */
134 void FsmCodeGen::assignActionIds()
136 int nextActionId = 0;
137 for ( ActionList::Iter act = cgd->actionList; act.lte(); act++ ) {
138 /* Only ever interested in referenced actions. */
139 if ( act->numRefs() > 0 )
140 act->actionId = nextActionId++;
144 void FsmCodeGen::setValueLimits()
155 maxFlatIndexOffset = 0;
159 maxCondIndexOffset = 0;
161 /* In both of these cases the 0 index is reserved for no value, so the max
162 * is one more than it would be if they started at 0. */
163 maxIndex = redFsm->transSet.length();
164 maxCond = cgd->condSpaceList.length();
166 /* The nextStateId - 1 is the last state id assigned. */
167 maxState = redFsm->nextStateId - 1;
169 for ( CondSpaceList::Iter csi = cgd->condSpaceList; csi.lte(); csi++ ) {
170 if ( csi->condSpaceId > maxCondSpaceId )
171 maxCondSpaceId = csi->condSpaceId;
174 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
175 /* Maximum cond length. */
176 if ( st->stateCondList.length() > maxCondLen )
177 maxCondLen = st->stateCondList.length();
179 /* Maximum single length. */
180 if ( st->outSingle.length() > maxSingleLen )
181 maxSingleLen = st->outSingle.length();
183 /* Maximum range length. */
184 if ( st->outRange.length() > maxRangeLen )
185 maxRangeLen = st->outRange.length();
187 /* The key offset index offset for the state after last is not used, skip it.. */
189 maxCondOffset += st->stateCondList.length();
190 maxKeyOffset += st->outSingle.length() + st->outRange.length()*2;
191 maxIndexOffset += st->outSingle.length() + st->outRange.length() + 1;
195 if ( st->condList != 0 ) {
196 unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
197 if ( span > maxCondSpan )
202 if ( st->transList != 0 ) {
203 unsigned long long span = keyOps->span( st->lowKey, st->highKey );
204 if ( span > maxSpan )
208 /* Max cond index offset. */
210 if ( st->condList != 0 )
211 maxCondIndexOffset += keyOps->span( st->condLowKey, st->condHighKey );
214 /* Max flat index offset. */
216 if ( st->transList != 0 )
217 maxFlatIndexOffset += keyOps->span( st->lowKey, st->highKey );
218 maxFlatIndexOffset += 1;
222 for ( ActionTableMap::Iter at = redFsm->actionMap; at.lte(); at++ ) {
223 /* Maximum id of action lists. */
224 if ( at->actListId+1 > maxActListId )
225 maxActListId = at->actListId+1;
227 /* Maximum location of items in action array. */
228 if ( at->location+1 > maxActionLoc )
229 maxActionLoc = at->location+1;
231 /* Maximum values going into the action array. */
232 if ( at->key.length() > maxActArrItem )
233 maxActArrItem = at->key.length();
234 for ( ActionTable::Iter item = at->key; item.lte(); item++ ) {
235 if ( item->value->actionId > maxActArrItem )
236 maxActArrItem = item->value->actionId;
241 void FsmCodeGen::analyzeAction( Action *act, InlineList *inlineList )
243 for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
244 /* Only consider actions that are referenced. */
245 if ( act->numRefs() > 0 ) {
246 if ( item->type == InlineItem::Goto || item->type == InlineItem::GotoExpr )
247 bAnyActionGotos = true;
248 else if ( item->type == InlineItem::Call || item->type == InlineItem::CallExpr )
249 bAnyActionCalls = true;
250 else if ( item->type == InlineItem::Ret )
251 bAnyActionRets = true;
254 /* Check for various things in regular actions. */
255 if ( act->numTransRefs > 0 || act->numToStateRefs > 0 || act->numFromStateRefs > 0 ) {
256 /* Any returns in regular actions? */
257 if ( item->type == InlineItem::Ret )
258 bAnyRegActionRets = true;
260 /* Any next statements in the regular actions? */
261 if ( item->type == InlineItem::Next || item->type == InlineItem::NextExpr )
262 bAnyRegNextStmt = true;
264 /* Any by value control in regular actions? */
265 if ( item->type == InlineItem::CallExpr || item->type == InlineItem::GotoExpr )
266 bAnyRegActionByValControl = true;
268 /* Any references to the current state in regular actions? */
269 if ( item->type == InlineItem::Curs )
270 bAnyRegCurStateRef = true;
272 if ( item->type == InlineItem::Break )
275 if ( item->type == InlineItem::LmSwitch && item->handlesError )
276 bAnyLmSwitchError = true;
279 if ( item->children != 0 )
280 analyzeAction( act, item->children );
284 void FsmCodeGen::analyzeActionList( RedAction *redAct, InlineList *inlineList )
286 for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
287 /* Any next statements in the action table? */
288 if ( item->type == InlineItem::Next || item->type == InlineItem::NextExpr )
289 redAct->bAnyNextStmt = true;
291 /* Any references to the current state. */
292 if ( item->type == InlineItem::Curs )
293 redAct->bAnyCurStateRef = true;
295 if ( item->type == InlineItem::Break )
296 redAct->bAnyBreakStmt = true;
298 if ( item->children != 0 )
299 analyzeActionList( redAct, item->children );
303 /* Gather various info on the machine. */
304 void FsmCodeGen::analyzeMachine()
306 /* Find the true count of action references. */
307 findFinalActionRefs();
309 /* Check if there are any calls in action code. */
310 for ( ActionList::Iter act = cgd->actionList; act.lte(); act++ ) {
311 /* Record the occurrence of various kinds of actions. */
312 if ( act->numToStateRefs > 0 )
313 bAnyToStateActions = true;
314 if ( act->numFromStateRefs > 0 )
315 bAnyFromStateActions = true;
316 if ( act->numEofRefs > 0 )
317 bAnyEofActions = true;
318 if ( act->numTransRefs > 0 )
319 bAnyRegActions = true;
321 /* Recurse through the action's parse tree looking for various things. */
322 analyzeAction( act, act->inlineList );
325 /* Analyze reduced action lists. */
326 for ( ActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
327 for ( ActionTable::Iter act = redAct->key; act.lte(); act++ )
328 analyzeActionList( redAct, act->value->inlineList );
331 /* Find states that have transitions with actions that have next
333 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
334 /* Check any actions out of outSinge. */
335 for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) {
336 if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() )
337 st->bAnyRegCurStateRef = true;
340 /* Check any actions out of outRange. */
341 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
342 if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() )
343 st->bAnyRegCurStateRef = true;
346 /* Check any action out of default. */
347 if ( st->defTrans != 0 && st->defTrans->action != 0 &&
348 st->defTrans->action->anyCurStateRef() )
349 st->bAnyRegCurStateRef = true;
351 if ( st->stateCondList.length() > 0 )
352 bAnyConditions = true;
355 /* Assign ids to actions that are referenced. */
358 /* Set the maximums of various values used for deciding types. */
361 /* Determine if we should use indicies. */
365 unsigned int FsmCodeGen::arrayTypeSize( unsigned long maxVal )
367 long long maxValLL = (long long) maxVal;
368 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
369 assert( arrayType != 0 );
370 return arrayType->size;
373 string FsmCodeGen::ARRAY_TYPE( unsigned long maxVal )
375 long long maxValLL = (long long) maxVal;
376 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
377 assert( arrayType != 0 );
379 string ret = arrayType->data1;
380 if ( arrayType->data2 != 0 ) {
382 ret += arrayType->data2;
388 /* Write out the fsm name. */
389 string FsmCodeGen::FSM_NAME()
394 /* Emit the offset of the start state as a decimal integer. */
395 string FsmCodeGen::START_STATE_ID()
398 ret << redFsm->startState->id;
402 /* Write out the array of actions. */
403 std::ostream &FsmCodeGen::ACTIONS_ARRAY()
406 int totalActions = 1;
407 for ( ActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
408 /* Write out the length, which will never be the last character. */
409 out << act->key.length() << ", ";
410 /* Put in a line break every 8 */
411 if ( totalActions++ % 8 == 7 )
414 for ( ActionTable::Iter item = act->key; item.lte(); item++ ) {
415 out << item->value->actionId;
416 if ( ! (act.last() && item.last()) )
419 /* Put in a line break every 8 */
420 if ( totalActions++ % 8 == 7 )
429 string FsmCodeGen::CS()
432 if ( cgd->curStateExpr != 0 ) {
433 /* Emit the user supplied method of retrieving the key. */
435 INLINE_LIST( ret, cgd->curStateExpr, 0, false );
439 /* Expression for retrieving the key, use simple dereference. */
440 ret << ACCESS() << "cs";
445 string FsmCodeGen::ACCESS()
448 if ( cgd->accessExpr != 0 )
449 INLINE_LIST( ret, cgd->accessExpr, 0, false );
453 string FsmCodeGen::GET_WIDE_KEY()
455 if ( anyConditions() )
461 string FsmCodeGen::GET_WIDE_KEY( RedStateAp *state )
463 if ( state->stateCondList.length() > 0 )
469 string FsmCodeGen::GET_KEY()
472 if ( cgd->getKeyExpr != 0 ) {
473 /* Emit the user supplied method of retrieving the key. */
475 INLINE_LIST( ret, cgd->getKeyExpr, 0, false );
479 /* Expression for retrieving the key, use simple dereference. */
480 ret << "(*" << P() << ")";
485 /* Write out level number of tabs. Makes the nested binary search nice
487 string FsmCodeGen::TABS( int level )
490 while ( level-- > 0 )
495 /* Write out a key from the fsm code gen. Depends on wether or not the key is
497 string FsmCodeGen::KEY( Key key )
500 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
503 ret << (unsigned long) key.getVal() << 'u';
507 void FsmCodeGen::EXEC( ostream &ret, InlineItem *item, int targState, int inFinish )
509 /* The parser gives fexec two children. The double brackets are for D
510 * code. If the inline list is a single word it will get interpreted as a
511 * C-style cast by the D compiler. */
512 ret << "{" << P() << " = ((";
513 INLINE_LIST( ret, item->children, targState, inFinish );
517 void FsmCodeGen::EXECTE( ostream &ret, InlineItem *item, int targState, int inFinish )
519 /* Tokend version of exec. */
521 /* The parser gives fexec two children. The double brackets are for D
522 * code. If the inline list is a single word it will get interpreted as a
523 * C-style cast by the D compiler. */
524 ret << "{" << TOKEND() << " = ((";
525 INLINE_LIST( ret, item->children, targState, inFinish );
530 void FsmCodeGen::LM_SWITCH( ostream &ret, InlineItem *item,
531 int targState, int inFinish )
534 " switch( act ) {\n";
536 /* If the switch handles error then we also forced the error state. It
538 if ( item->handlesError ) {
539 ret << " case 0: " << TOKEND() << " = " << TOKSTART() << "; ";
540 GOTO( ret, redFsm->errState->id, inFinish );
544 for ( InlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
545 /* Write the case label, the action and the case break. */
546 ret << " case " << lma->lmId << ":\n";
548 /* Write the block and close it off. */
550 INLINE_LIST( ret, lma->children, targState, inFinish );
555 /* Default required for D code. */
562 void FsmCodeGen::SET_ACT( ostream &ret, InlineItem *item )
564 ret << ACT() << " = " << item->lmId << ";";
567 void FsmCodeGen::SET_TOKEND( ostream &ret, InlineItem *item )
569 /* The tokend action sets tokend. */
570 ret << TOKEND() << " = " << P();
571 if ( item->offset != 0 )
572 out << "+" << item->offset;
576 void FsmCodeGen::GET_TOKEND( ostream &ret, InlineItem *item )
581 void FsmCodeGen::INIT_TOKSTART( ostream &ret, InlineItem *item )
583 ret << TOKSTART() << " = " << NULL_ITEM() << ";";
586 void FsmCodeGen::INIT_ACT( ostream &ret, InlineItem *item )
588 ret << ACT() << " = 0;";
591 void FsmCodeGen::SET_TOKSTART( ostream &ret, InlineItem *item )
593 ret << TOKSTART() << " = " << P() << ";";
596 void FsmCodeGen::SUB_ACTION( ostream &ret, InlineItem *item,
597 int targState, bool inFinish )
599 if ( item->children->length() > 0 ) {
600 /* Write the block and close it off. */
602 INLINE_LIST( ret, item->children, targState, inFinish );
608 /* Write out an inline tree structure. Walks the list and possibly calls out
609 * to virtual functions than handle language specific items in the tree. */
610 void FsmCodeGen::INLINE_LIST( ostream &ret, InlineList *inlineList,
611 int targState, bool inFinish )
613 for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
614 switch ( item->type ) {
615 case InlineItem::Text:
618 case InlineItem::Goto:
619 GOTO( ret, item->targState->id, inFinish );
621 case InlineItem::Call:
622 CALL( ret, item->targState->id, targState, inFinish );
624 case InlineItem::Next:
625 NEXT( ret, item->targState->id, inFinish );
627 case InlineItem::Ret:
628 RET( ret, inFinish );
630 case InlineItem::PChar:
633 case InlineItem::Char:
636 case InlineItem::Hold:
639 case InlineItem::Exec:
640 EXEC( ret, item, targState, inFinish );
642 case InlineItem::HoldTE:
643 ret << TOKEND() << "--;";
645 case InlineItem::ExecTE:
646 EXECTE( ret, item, targState, inFinish );
648 case InlineItem::Curs:
649 CURS( ret, inFinish );
651 case InlineItem::Targs:
652 TARGS( ret, inFinish, targState );
654 case InlineItem::Entry:
655 ret << item->targState->id;
657 case InlineItem::GotoExpr:
658 GOTO_EXPR( ret, item, inFinish );
660 case InlineItem::CallExpr:
661 CALL_EXPR( ret, item, targState, inFinish );
663 case InlineItem::NextExpr:
664 NEXT_EXPR( ret, item, inFinish );
666 case InlineItem::LmSwitch:
667 LM_SWITCH( ret, item, targState, inFinish );
669 case InlineItem::LmSetActId:
670 SET_ACT( ret, item );
672 case InlineItem::LmSetTokEnd:
673 SET_TOKEND( ret, item );
675 case InlineItem::LmGetTokEnd:
676 GET_TOKEND( ret, item );
678 case InlineItem::LmInitTokStart:
679 INIT_TOKSTART( ret, item );
681 case InlineItem::LmInitAct:
682 INIT_ACT( ret, item );
684 case InlineItem::LmSetTokStart:
685 SET_TOKSTART( ret, item );
687 case InlineItem::SubAction:
688 SUB_ACTION( ret, item, targState, inFinish );
690 case InlineItem::Break:
691 BREAK( ret, targState );
696 /* Write out paths in line directives. Escapes any special characters. */
697 string FsmCodeGen::LDIR_PATH( char *path )
700 for ( char *pc = path; *pc != 0; pc++ ) {
709 void FsmCodeGen::ACTION( ostream &ret, Action *action, int targState, bool inFinish )
711 /* Write the preprocessor line info for going into the source file. */
712 lineDirective( ret, cgd->fileName, action->loc.line );
714 /* Write the block and close it off. */
716 INLINE_LIST( ret, action->inlineList, targState, inFinish );
720 void FsmCodeGen::CONDITION( ostream &ret, Action *condition )
723 lineDirective( ret, cgd->fileName, condition->loc.line );
724 INLINE_LIST( ret, condition->inlineList, 0, false );
727 string FsmCodeGen::ERROR_STATE()
730 if ( redFsm->errState != 0 )
731 ret << redFsm->errState->id;
737 string FsmCodeGen::FIRST_FINAL_STATE()
740 if ( redFsm->firstFinState != 0 )
741 ret << redFsm->firstFinState->id;
743 ret << redFsm->nextStateId;
747 void FsmCodeGen::writeOutInit()
750 out << "\t" << CS() << " = " << START() << ";\n";
752 /* If there are any calls, then the stack top needs initialization. */
753 if ( anyActionCalls() || anyActionRets() )
754 out << "\t" << TOP() << " = 0;\n";
756 if ( cgd->hasLongestMatch ) {
758 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
759 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
760 " " << ACT() << " = 0;\n";
765 string FsmCodeGen::DATA_PREFIX()
767 if ( cgd->dataPrefix )
768 return FSM_NAME() + "_";
772 /* Emit the alphabet data type. */
773 string FsmCodeGen::ALPH_TYPE()
775 string ret = keyOps->alphType->data1;
776 if ( keyOps->alphType->data2 != 0 ) {
778 ret += + keyOps->alphType->data2;
783 /* Emit the alphabet data type. */
784 string FsmCodeGen::WIDE_ALPH_TYPE()
787 if ( maxKey <= keyOps->maxKey )
790 long long maxKeyVal = maxKey.getLongLong();
791 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
792 assert( wideType != 0 );
794 ret = wideType->data1;
795 if ( wideType->data2 != 0 ) {
797 ret += wideType->data2;
805 * Language specific, but style independent code generators functions.
808 string CCodeGen::PTR_CONST()
813 std::ostream &CCodeGen::OPEN_ARRAY( string type, string name )
815 out << "static const " << type << " " << name << "[] = {\n";
819 std::ostream &CCodeGen::CLOSE_ARRAY()
821 return out << "};\n";
824 std::ostream &CCodeGen::STATIC_VAR( string type, string name )
826 out << "static const " << type << " " << name;
830 string CCodeGen::UINT( )
832 return "unsigned int";
835 string CCodeGen::ARR_OFF( string ptr, string offset )
837 return ptr + " + " + offset;
840 string CCodeGen::CAST( string type )
842 return "(" + type + ")";
845 string CCodeGen::NULL_ITEM()
850 string CCodeGen::POINTER()
855 std::ostream &CCodeGen::SWITCH_DEFAULT()
860 string CCodeGen::CTRL_FLOW()
869 string DCodeGen::NULL_ITEM()
874 string DCodeGen::POINTER()
876 // multiple items seperated by commas can also be pointer types.
880 string DCodeGen::PTR_CONST()
885 std::ostream &DCodeGen::OPEN_ARRAY( string type, string name )
887 out << "static const " << type << "[] " << name << " = [\n";
891 std::ostream &DCodeGen::CLOSE_ARRAY()
893 return out << "];\n";
896 std::ostream &DCodeGen::STATIC_VAR( string type, string name )
898 out << "static const " << type << " " << name;
902 string DCodeGen::ARR_OFF( string ptr, string offset )
904 return "&" + ptr + "[" + offset + "]";
907 string DCodeGen::CAST( string type )
909 return "cast(" + type + ")";
912 string DCodeGen::UINT( )
917 std::ostream &DCodeGen::SWITCH_DEFAULT()
919 out << " default: break;\n";
923 string DCodeGen::CTRL_FLOW()
933 string JavaCodeGen::PTR_CONST()
935 /* Not used in Java code. */
940 std::ostream &JavaCodeGen::OPEN_ARRAY( string type, string name )
942 out << "static final " << type << "[] " << name << " = {\n";
946 std::ostream &JavaCodeGen::CLOSE_ARRAY()
948 return out << "};\n";
951 std::ostream &JavaCodeGen::STATIC_VAR( string type, string name )
953 out << "static final " << type << " " << name;
957 string JavaCodeGen::UINT( )
964 string JavaCodeGen::ARR_OFF( string ptr, string offset )
966 return ptr + " + " + offset;
969 string JavaCodeGen::CAST( string type )
971 return "(" + type + ")";
974 string JavaCodeGen::NULL_ITEM()
976 /* In java we use integers instead of pointers. */
980 string JavaCodeGen::POINTER()
987 std::ostream &JavaCodeGen::SWITCH_DEFAULT()
992 string JavaCodeGen::GET_KEY()
995 if ( cgd->getKeyExpr != 0 ) {
996 /* Emit the user supplied method of retrieving the key. */
998 INLINE_LIST( ret, cgd->getKeyExpr, 0, false );
1002 /* Expression for retrieving the key, use simple dereference. */
1003 ret << "data[" << P() << "]";
1008 string JavaCodeGen::CTRL_FLOW()
1010 return "if (true) ";