xmlcodegen.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429
  1. /*
  2. * Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
  3. */
  4. /* This file is part of Ragel.
  5. *
  6. * Ragel is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Ragel is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Ragel; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include "ragel.h"
  21. #include "xmlcodegen.h"
  22. #include "parsedata.h"
  23. #include "fsmgraph.h"
  24. #include "gendata.h"
  25. #include "inputdata.h"
  26. #include <string.h>
  27. #include "rlparse.h"
  28. #include "version.h"
  29. using namespace std;
  30. GenBase::GenBase( char *fsmName, ParseData *pd, FsmAp *fsm )
  31. :
  32. fsmName(fsmName),
  33. pd(pd),
  34. fsm(fsm),
  35. nextActionTableId(0)
  36. {
  37. }
  38. void GenBase::appendTrans( TransListVect &outList, Key lowKey,
  39. Key highKey, TransAp *trans )
  40. {
  41. if ( trans->toState != 0 || trans->actionTable.length() > 0 )
  42. outList.append( TransEl( lowKey, highKey, trans ) );
  43. }
  44. void GenBase::reduceActionTables()
  45. {
  46. /* Reduce the actions tables to a set. */
  47. for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
  48. RedActionTable *actionTable = 0;
  49. /* Reduce To State Actions. */
  50. if ( st->toStateActionTable.length() > 0 ) {
  51. if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
  52. actionTable->id = nextActionTableId++;
  53. }
  54. /* Reduce From State Actions. */
  55. if ( st->fromStateActionTable.length() > 0 ) {
  56. if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
  57. actionTable->id = nextActionTableId++;
  58. }
  59. /* Reduce EOF actions. */
  60. if ( st->eofActionTable.length() > 0 ) {
  61. if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
  62. actionTable->id = nextActionTableId++;
  63. }
  64. /* Loop the transitions and reduce their actions. */
  65. for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
  66. if ( trans->actionTable.length() > 0 ) {
  67. if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
  68. actionTable->id = nextActionTableId++;
  69. }
  70. }
  71. }
  72. }
  73. XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, std::ostream &out )
  74. :
  75. GenBase(fsmName, pd, fsm),
  76. out(out)
  77. {
  78. }
  79. void XMLCodeGen::writeActionList()
  80. {
  81. /* Determine which actions to write. */
  82. int nextActionId = 0;
  83. for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
  84. if ( act->numRefs() > 0 || act->numCondRefs > 0 )
  85. act->actionId = nextActionId++;
  86. }
  87. /* Write the list. */
  88. out << " <action_list length=\"" << nextActionId << "\">\n";
  89. for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
  90. if ( act->actionId >= 0 )
  91. writeAction( act );
  92. }
  93. out << " </action_list>\n";
  94. }
  95. void XMLCodeGen::writeActionTableList()
  96. {
  97. /* Must first order the action tables based on their id. */
  98. int numTables = nextActionTableId;
  99. RedActionTable **tables = new RedActionTable*[numTables];
  100. for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
  101. tables[at->id] = at;
  102. out << " <action_table_list length=\"" << numTables << "\">\n";
  103. for ( int t = 0; t < numTables; t++ ) {
  104. out << " <action_table id=\"" << t << "\" length=\"" <<
  105. tables[t]->key.length() << "\">";
  106. for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
  107. out << atel->value->actionId;
  108. if ( ! atel.last() )
  109. out << " ";
  110. }
  111. out << "</action_table>\n";
  112. }
  113. out << " </action_table_list>\n";
  114. delete[] tables;
  115. }
  116. void XMLCodeGen::writeKey( Key key )
  117. {
  118. if ( keyOps->isSigned )
  119. out << key.getVal();
  120. else
  121. out << (unsigned long) key.getVal();
  122. }
  123. void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
  124. {
  125. /* First reduce the action. */
  126. RedActionTable *actionTable = 0;
  127. if ( trans->actionTable.length() > 0 )
  128. actionTable = actionTableMap.find( trans->actionTable );
  129. /* Write the transition. */
  130. out << " <t>";
  131. writeKey( lowKey );
  132. out << " ";
  133. writeKey( highKey );
  134. if ( trans->toState != 0 )
  135. out << " " << trans->toState->alg.stateNum;
  136. else
  137. out << " x";
  138. if ( actionTable != 0 )
  139. out << " " << actionTable->id;
  140. else
  141. out << " x";
  142. out << "</t>\n";
  143. }
  144. void XMLCodeGen::writeTransList( StateAp *state )
  145. {
  146. TransListVect outList;
  147. /* If there is only are no ranges the task is simple. */
  148. if ( state->outList.length() > 0 ) {
  149. /* Loop each source range. */
  150. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  151. /* Reduce the transition. If it reduced to anything then add it. */
  152. appendTrans( outList, trans->lowKey, trans->highKey, trans );
  153. }
  154. }
  155. out << " <trans_list length=\"" << outList.length() << "\">\n";
  156. for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
  157. writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
  158. out << " </trans_list>\n";
  159. }
  160. void XMLCodeGen::writeEofTrans( StateAp *state )
  161. {
  162. RedActionTable *eofActions = 0;
  163. if ( state->eofActionTable.length() > 0 )
  164. eofActions = actionTableMap.find( state->eofActionTable );
  165. /* The <eof_t> is used when there is an eof target, otherwise the eof
  166. * action goes into state actions. */
  167. if ( state->eofTarget != 0 ) {
  168. out << " <eof_t>" << state->eofTarget->alg.stateNum;
  169. if ( eofActions != 0 )
  170. out << " " << eofActions->id;
  171. else
  172. out << " x";
  173. out << "</eof_t>" << endl;
  174. }
  175. }
  176. void XMLCodeGen::writeText( InlineItem *item )
  177. {
  178. if ( item->prev == 0 || item->prev->type != InlineItem::Text )
  179. out << "<text>";
  180. xmlEscapeHost( out, item->data, strlen(item->data) );
  181. if ( item->next == 0 || item->next->type != InlineItem::Text )
  182. out << "</text>";
  183. }
  184. void XMLCodeGen::writeGoto( InlineItem *item )
  185. {
  186. if ( pd->generatingSectionSubset )
  187. out << "<goto>-1</goto>";
  188. else {
  189. EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
  190. out << "<goto>" << targ->value->alg.stateNum << "</goto>";
  191. }
  192. }
  193. void XMLCodeGen::writeCall( InlineItem *item )
  194. {
  195. if ( pd->generatingSectionSubset )
  196. out << "<call>-1</call>";
  197. else {
  198. EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
  199. out << "<call>" << targ->value->alg.stateNum << "</call>";
  200. }
  201. }
  202. void XMLCodeGen::writeNext( InlineItem *item )
  203. {
  204. if ( pd->generatingSectionSubset )
  205. out << "<next>-1</next>";
  206. else {
  207. EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
  208. out << "<next>" << targ->value->alg.stateNum << "</next>";
  209. }
  210. }
  211. void XMLCodeGen::writeGotoExpr( InlineItem *item )
  212. {
  213. out << "<goto_expr>";
  214. writeInlineList( item->children );
  215. out << "</goto_expr>";
  216. }
  217. void XMLCodeGen::writeCallExpr( InlineItem *item )
  218. {
  219. out << "<call_expr>";
  220. writeInlineList( item->children );
  221. out << "</call_expr>";
  222. }
  223. void XMLCodeGen::writeNextExpr( InlineItem *item )
  224. {
  225. out << "<next_expr>";
  226. writeInlineList( item->children );
  227. out << "</next_expr>";
  228. }
  229. void XMLCodeGen::writeEntry( InlineItem *item )
  230. {
  231. if ( pd->generatingSectionSubset )
  232. out << "<entry>-1</entry>";
  233. else {
  234. EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
  235. out << "<entry>" << targ->value->alg.stateNum << "</entry>";
  236. }
  237. }
  238. void XMLCodeGen::writeActionExec( InlineItem *item )
  239. {
  240. out << "<exec>";
  241. writeInlineList( item->children );
  242. out << "</exec>";
  243. }
  244. void XMLCodeGen::writeLmOnLast( InlineItem *item )
  245. {
  246. out << "<set_tokend>1</set_tokend>";
  247. if ( item->longestMatchPart->action != 0 ) {
  248. out << "<sub_action>";
  249. writeInlineList( item->longestMatchPart->action->inlineList );
  250. out << "</sub_action>";
  251. }
  252. }
  253. void XMLCodeGen::writeLmOnNext( InlineItem *item )
  254. {
  255. out << "<set_tokend>0</set_tokend>";
  256. out << "<hold></hold>";
  257. if ( item->longestMatchPart->action != 0 ) {
  258. out << "<sub_action>";
  259. writeInlineList( item->longestMatchPart->action->inlineList );
  260. out << "</sub_action>";
  261. }
  262. }
  263. void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
  264. {
  265. out << "<exec><get_tokend></get_tokend></exec>";
  266. if ( item->longestMatchPart->action != 0 ) {
  267. out << "<sub_action>";
  268. writeInlineList( item->longestMatchPart->action->inlineList );
  269. out << "</sub_action>";
  270. }
  271. }
  272. void XMLCodeGen::writeLmSwitch( InlineItem *item )
  273. {
  274. LongestMatch *longestMatch = item->longestMatch;
  275. out << "<lm_switch>\n";
  276. /* We can't put the <exec> here because we may need to handle the error
  277. * case and in that case p should not be changed. Instead use a default
  278. * label in the switch to adjust p when user actions are not set. An id of
  279. * -1 indicates the default. */
  280. if ( longestMatch->lmSwitchHandlesError ) {
  281. /* If the switch handles error then we should have also forced the
  282. * error state. */
  283. assert( fsm->errState != 0 );
  284. out << " <sub_action id=\"0\">";
  285. out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
  286. out << "</sub_action>\n";
  287. }
  288. bool needDefault = false;
  289. for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
  290. if ( lmi->inLmSelect ) {
  291. if ( lmi->action == 0 )
  292. needDefault = true;
  293. else {
  294. /* Open the action. Write it with the context that sets up _p
  295. * when doing control flow changes from inside the machine. */
  296. out << " <sub_action id=\"" << lmi->longestMatchId << "\">";
  297. out << "<exec><get_tokend></get_tokend></exec>";
  298. writeInlineList( lmi->action->inlineList );
  299. out << "</sub_action>\n";
  300. }
  301. }
  302. }
  303. if ( needDefault ) {
  304. out << " <sub_action id=\"-1\"><exec><get_tokend>"
  305. "</get_tokend></exec></sub_action>\n";
  306. }
  307. out << " </lm_switch>";
  308. }
  309. void XMLCodeGen::writeInlineList( InlineList *inlineList )
  310. {
  311. for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
  312. switch ( item->type ) {
  313. case InlineItem::Text:
  314. writeText( item );
  315. break;
  316. case InlineItem::Goto:
  317. writeGoto( item );
  318. break;
  319. case InlineItem::GotoExpr:
  320. writeGotoExpr( item );
  321. break;
  322. case InlineItem::Call:
  323. writeCall( item );
  324. break;
  325. case InlineItem::CallExpr:
  326. writeCallExpr( item );
  327. break;
  328. case InlineItem::Next:
  329. writeNext( item );
  330. break;
  331. case InlineItem::NextExpr:
  332. writeNextExpr( item );
  333. break;
  334. case InlineItem::Break:
  335. out << "<break></break>";
  336. break;
  337. case InlineItem::Ret:
  338. out << "<ret></ret>";
  339. break;
  340. case InlineItem::PChar:
  341. out << "<pchar></pchar>";
  342. break;
  343. case InlineItem::Char:
  344. out << "<char></char>";
  345. break;
  346. case InlineItem::Curs:
  347. out << "<curs></curs>";
  348. break;
  349. case InlineItem::Targs:
  350. out << "<targs></targs>";
  351. break;
  352. case InlineItem::Entry:
  353. writeEntry( item );
  354. break;
  355. case InlineItem::Hold:
  356. out << "<hold></hold>";
  357. break;
  358. case InlineItem::Exec:
  359. writeActionExec( item );
  360. break;
  361. case InlineItem::LmSetActId:
  362. out << "<set_act>" <<
  363. item->longestMatchPart->longestMatchId <<
  364. "</set_act>";
  365. break;
  366. case InlineItem::LmSetTokEnd:
  367. out << "<set_tokend>1</set_tokend>";
  368. break;
  369. case InlineItem::LmOnLast:
  370. writeLmOnLast( item );
  371. break;
  372. case InlineItem::LmOnNext:
  373. writeLmOnNext( item );
  374. break;
  375. case InlineItem::LmOnLagBehind:
  376. writeLmOnLagBehind( item );
  377. break;
  378. case InlineItem::LmSwitch:
  379. writeLmSwitch( item );
  380. break;
  381. case InlineItem::LmInitAct:
  382. out << "<init_act></init_act>";
  383. break;
  384. case InlineItem::LmInitTokStart:
  385. out << "<init_tokstart></init_tokstart>";
  386. break;
  387. case InlineItem::LmSetTokStart:
  388. out << "<set_tokstart></set_tokstart>";
  389. break;
  390. }
  391. }
  392. }
  393. BackendGen::BackendGen( char *fsmName, ParseData *pd, FsmAp *fsm, CodeGenData *cgd )
  394. :
  395. GenBase(fsmName, pd, fsm),
  396. cgd(cgd)
  397. {
  398. }
  399. void BackendGen::makeText( GenInlineList *outList, InlineItem *item )
  400. {
  401. GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Text );
  402. inlineItem->data = item->data;
  403. outList->append( inlineItem );
  404. }
  405. void BackendGen::makeTargetItem( GenInlineList *outList, NameInst *nameTarg,
  406. GenInlineItem::Type type )
  407. {
  408. long targetState;
  409. if ( pd->generatingSectionSubset )
  410. targetState = -1;
  411. else {
  412. EntryMapEl *targ = fsm->entryPoints.find( nameTarg->id );
  413. targetState = targ->value->alg.stateNum;
  414. }
  415. /* Make the item. */
  416. GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
  417. inlineItem->targId = targetState;
  418. outList->append( inlineItem );
  419. }
  420. /* Make a sublist item with a given type. */
  421. void BackendGen::makeSubList( GenInlineList *outList,
  422. InlineList *inlineList, GenInlineItem::Type type )
  423. {
  424. /* Fill the sub list. */
  425. GenInlineList *subList = new GenInlineList;
  426. makeGenInlineList( subList, inlineList );
  427. /* Make the item. */
  428. GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), type );
  429. inlineItem->children = subList;
  430. outList->append( inlineItem );
  431. }
  432. void BackendGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
  433. {
  434. makeSetTokend( outList, 1 );
  435. if ( item->longestMatchPart->action != 0 ) {
  436. makeSubList( outList,
  437. item->longestMatchPart->action->inlineList,
  438. GenInlineItem::SubAction );
  439. }
  440. }
  441. void BackendGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
  442. {
  443. makeSetTokend( outList, 0 );
  444. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
  445. if ( item->longestMatchPart->action != 0 ) {
  446. makeSubList( outList,
  447. item->longestMatchPart->action->inlineList,
  448. GenInlineItem::SubAction );
  449. }
  450. }
  451. void BackendGen::makeExecGetTokend( GenInlineList *outList )
  452. {
  453. /* Make the Exec item. */
  454. GenInlineItem *execItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec );
  455. execItem->children = new GenInlineList;
  456. /* Make the GetTokEnd */
  457. GenInlineItem *getTokend = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd );
  458. execItem->children->append( getTokend );
  459. outList->append( execItem );
  460. }
  461. void BackendGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
  462. {
  463. /* Jump to the tokend. */
  464. makeExecGetTokend( outList );
  465. if ( item->longestMatchPart->action != 0 ) {
  466. makeSubList( outList,
  467. item->longestMatchPart->action->inlineList,
  468. GenInlineItem::SubAction );
  469. }
  470. }
  471. void BackendGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
  472. {
  473. GenInlineItem *lmSwitch = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch );
  474. GenInlineList *lmList = lmSwitch->children = new GenInlineList;
  475. LongestMatch *longestMatch = item->longestMatch;
  476. /* We can't put the <exec> here because we may need to handle the error
  477. * case and in that case p should not be changed. Instead use a default
  478. * label in the switch to adjust p when user actions are not set. An id of
  479. * -1 indicates the default. */
  480. if ( longestMatch->lmSwitchHandlesError ) {
  481. /* If the switch handles error then we should have also forced the
  482. * error state. */
  483. assert( fsm->errState != 0 );
  484. GenInlineItem *errCase = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
  485. errCase->lmId = 0;
  486. errCase->children = new GenInlineList;
  487. /* Make the item. */
  488. GenInlineItem *gotoItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto );
  489. gotoItem->targId = fsm->errState->alg.stateNum;
  490. errCase->children->append( gotoItem );
  491. lmList->append( errCase );
  492. }
  493. bool needDefault = false;
  494. for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
  495. if ( lmi->inLmSelect ) {
  496. if ( lmi->action == 0 )
  497. needDefault = true;
  498. else {
  499. /* Open the action. Write it with the context that sets up _p
  500. * when doing control flow changes from inside the machine. */
  501. GenInlineItem *lmCase = new GenInlineItem( InputLoc(),
  502. GenInlineItem::SubAction );
  503. lmCase->lmId = lmi->longestMatchId;
  504. lmCase->children = new GenInlineList;
  505. makeExecGetTokend( lmCase->children );
  506. makeGenInlineList( lmCase->children, lmi->action->inlineList );
  507. lmList->append( lmCase );
  508. }
  509. }
  510. }
  511. if ( needDefault ) {
  512. GenInlineItem *defCase = new GenInlineItem( InputLoc(),
  513. GenInlineItem::SubAction );
  514. defCase->lmId = -1;
  515. defCase->children = new GenInlineList;
  516. makeExecGetTokend( defCase->children );
  517. lmList->append( defCase );
  518. }
  519. outList->append( lmSwitch );
  520. }
  521. void BackendGen::makeSetTokend( GenInlineList *outList, long offset )
  522. {
  523. GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd );
  524. inlineItem->offset = offset;
  525. outList->append( inlineItem );
  526. }
  527. void BackendGen::makeSetAct( GenInlineList *outList, long lmId )
  528. {
  529. GenInlineItem *inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId );
  530. inlineItem->lmId = lmId;
  531. outList->append( inlineItem );
  532. }
  533. void BackendGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
  534. {
  535. for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
  536. switch ( item->type ) {
  537. case InlineItem::Text:
  538. makeText( outList, item );
  539. break;
  540. case InlineItem::Goto:
  541. makeTargetItem( outList, item->nameTarg, GenInlineItem::Goto );
  542. break;
  543. case InlineItem::GotoExpr:
  544. makeSubList( outList, item->children, GenInlineItem::GotoExpr );
  545. break;
  546. case InlineItem::Call:
  547. makeTargetItem( outList, item->nameTarg, GenInlineItem::Call );
  548. break;
  549. case InlineItem::CallExpr:
  550. makeSubList( outList, item->children, GenInlineItem::CallExpr );
  551. break;
  552. case InlineItem::Next:
  553. makeTargetItem( outList, item->nameTarg, GenInlineItem::Next );
  554. break;
  555. case InlineItem::NextExpr:
  556. makeSubList( outList, item->children, GenInlineItem::NextExpr );
  557. break;
  558. case InlineItem::Break:
  559. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Break ) );
  560. break;
  561. case InlineItem::Ret:
  562. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Ret ) );
  563. break;
  564. case InlineItem::PChar:
  565. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::PChar ) );
  566. break;
  567. case InlineItem::Char:
  568. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Char ) );
  569. break;
  570. case InlineItem::Curs:
  571. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Curs ) );
  572. break;
  573. case InlineItem::Targs:
  574. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Targs ) );
  575. break;
  576. case InlineItem::Entry:
  577. makeTargetItem( outList, item->nameTarg, GenInlineItem::Entry );
  578. break;
  579. case InlineItem::Hold:
  580. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::Hold ) );
  581. break;
  582. case InlineItem::Exec:
  583. makeSubList( outList, item->children, GenInlineItem::Exec );
  584. break;
  585. case InlineItem::LmSetActId:
  586. makeSetAct( outList, item->longestMatchPart->longestMatchId );
  587. break;
  588. case InlineItem::LmSetTokEnd:
  589. makeSetTokend( outList, 1 );
  590. break;
  591. case InlineItem::LmOnLast:
  592. makeLmOnLast( outList, item );
  593. break;
  594. case InlineItem::LmOnNext:
  595. makeLmOnNext( outList, item );
  596. break;
  597. case InlineItem::LmOnLagBehind:
  598. makeLmOnLagBehind( outList, item );
  599. break;
  600. case InlineItem::LmSwitch:
  601. makeLmSwitch( outList, item );
  602. break;
  603. case InlineItem::LmInitAct:
  604. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct ) );
  605. break;
  606. case InlineItem::LmInitTokStart:
  607. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart ) );
  608. break;
  609. case InlineItem::LmSetTokStart:
  610. outList->append( new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart ) );
  611. cgd->hasLongestMatch = true;
  612. break;
  613. }
  614. }
  615. }
  616. void XMLCodeGen::writeAction( Action *action )
  617. {
  618. out << " <action id=\"" << action->actionId << "\"";
  619. if ( action->name != 0 )
  620. out << " name=\"" << action->name << "\"";
  621. out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
  622. writeInlineList( action->inlineList );
  623. out << "</action>\n";
  624. }
  625. void xmlEscapeHost( std::ostream &out, char *data, long len )
  626. {
  627. char *end = data + len;
  628. while ( data != end ) {
  629. switch ( *data ) {
  630. case '<': out << "&lt;"; break;
  631. case '>': out << "&gt;"; break;
  632. case '&': out << "&amp;"; break;
  633. default: out << *data; break;
  634. }
  635. data += 1;
  636. }
  637. }
  638. void XMLCodeGen::writeStateActions( StateAp *state )
  639. {
  640. RedActionTable *toStateActions = 0;
  641. if ( state->toStateActionTable.length() > 0 )
  642. toStateActions = actionTableMap.find( state->toStateActionTable );
  643. RedActionTable *fromStateActions = 0;
  644. if ( state->fromStateActionTable.length() > 0 )
  645. fromStateActions = actionTableMap.find( state->fromStateActionTable );
  646. /* EOF actions go out here only if the state has no eof target. If it has
  647. * an eof target then an eof transition will be used instead. */
  648. RedActionTable *eofActions = 0;
  649. if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
  650. eofActions = actionTableMap.find( state->eofActionTable );
  651. if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
  652. out << " <state_actions>";
  653. if ( toStateActions != 0 )
  654. out << toStateActions->id;
  655. else
  656. out << "x";
  657. if ( fromStateActions != 0 )
  658. out << " " << fromStateActions->id;
  659. else
  660. out << " x";
  661. if ( eofActions != 0 )
  662. out << " " << eofActions->id;
  663. else
  664. out << " x";
  665. out << "</state_actions>\n";
  666. }
  667. }
  668. void XMLCodeGen::writeStateConditions( StateAp *state )
  669. {
  670. if ( state->stateCondList.length() > 0 ) {
  671. out << " <cond_list length=\"" << state->stateCondList.length() << "\">\n";
  672. for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
  673. out << " <c>";
  674. writeKey( scdi->lowKey );
  675. out << " ";
  676. writeKey( scdi->highKey );
  677. out << " ";
  678. out << scdi->condSpace->condSpaceId;
  679. out << "</c>\n";
  680. }
  681. out << " </cond_list>\n";
  682. }
  683. }
  684. void XMLCodeGen::writeStateList()
  685. {
  686. /* Write the list of states. */
  687. out << " <state_list length=\"" << fsm->stateList.length() << "\">\n";
  688. for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
  689. out << " <state id=\"" << st->alg.stateNum << "\"";
  690. if ( st->isFinState() )
  691. out << " final=\"t\"";
  692. out << ">\n";
  693. writeStateActions( st );
  694. writeEofTrans( st );
  695. writeStateConditions( st );
  696. writeTransList( st );
  697. out << " </state>\n";
  698. if ( !st.last() )
  699. out << "\n";
  700. }
  701. out << " </state_list>\n";
  702. }
  703. bool XMLCodeGen::writeNameInst( NameInst *nameInst )
  704. {
  705. bool written = false;
  706. if ( nameInst->parent != 0 )
  707. written = writeNameInst( nameInst->parent );
  708. if ( nameInst->name != 0 ) {
  709. if ( written )
  710. out << '_';
  711. out << nameInst->name;
  712. written = true;
  713. }
  714. return written;
  715. }
  716. void XMLCodeGen::writeEntryPoints()
  717. {
  718. /* List of entry points other than start state. */
  719. if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
  720. out << " <entry_points";
  721. if ( pd->lmRequiresErrorState )
  722. out << " error=\"t\"";
  723. out << ">\n";
  724. for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
  725. /* Get the name instantiation from nameIndex. */
  726. NameInst *nameInst = pd->nameIndex[en->key];
  727. StateAp *state = en->value;
  728. out << " <entry name=\"";
  729. writeNameInst( nameInst );
  730. out << "\">" << state->alg.stateNum << "</entry>\n";
  731. }
  732. out << " </entry_points>\n";
  733. }
  734. }
  735. void XMLCodeGen::writeMachine()
  736. {
  737. /* Open the machine. */
  738. out << " <machine>\n";
  739. /* Action tables. */
  740. reduceActionTables();
  741. writeActionList();
  742. writeActionTableList();
  743. writeConditions();
  744. /* Start state. */
  745. out << " <start_state>" << fsm->startState->alg.stateNum <<
  746. "</start_state>\n";
  747. /* Error state. */
  748. if ( fsm->errState != 0 ) {
  749. out << " <error_state>" << fsm->errState->alg.stateNum <<
  750. "</error_state>\n";
  751. }
  752. writeEntryPoints();
  753. writeStateList();
  754. out << " </machine>\n";
  755. }
  756. void XMLCodeGen::writeConditions()
  757. {
  758. if ( condData->condSpaceMap.length() > 0 ) {
  759. long nextCondSpaceId = 0;
  760. for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
  761. cs->condSpaceId = nextCondSpaceId++;
  762. out << " <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
  763. for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
  764. out << " <cond_space id=\"" << cs->condSpaceId <<
  765. "\" length=\"" << cs->condSet.length() << "\">";
  766. writeKey( cs->baseKey );
  767. for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
  768. out << " " << (*csi)->actionId;
  769. out << "</cond_space>\n";
  770. }
  771. out << " </cond_space_list>\n";
  772. }
  773. }
  774. void XMLCodeGen::writeExports()
  775. {
  776. if ( pd->exportList.length() > 0 ) {
  777. out << " <exports>\n";
  778. for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
  779. out << " <ex name=\"" << exp->name << "\">";
  780. writeKey( exp->key );
  781. out << "</ex>\n";
  782. }
  783. out << " </exports>\n";
  784. }
  785. }
  786. void XMLCodeGen::writeXML()
  787. {
  788. /* Open the definition. */
  789. out << "<ragel_def name=\"" << fsmName << "\">\n";
  790. /* Alphabet type. */
  791. out << " <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
  792. /* Getkey expression. */
  793. if ( pd->getKeyExpr != 0 ) {
  794. out << " <getkey>";
  795. writeInlineList( pd->getKeyExpr );
  796. out << "</getkey>\n";
  797. }
  798. /* Access expression. */
  799. if ( pd->accessExpr != 0 ) {
  800. out << " <access>";
  801. writeInlineList( pd->accessExpr );
  802. out << "</access>\n";
  803. }
  804. /* PrePush expression. */
  805. if ( pd->prePushExpr != 0 ) {
  806. out << " <prepush>";
  807. writeInlineList( pd->prePushExpr );
  808. out << "</prepush>\n";
  809. }
  810. /* PostPop expression. */
  811. if ( pd->postPopExpr != 0 ) {
  812. out << " <postpop>";
  813. writeInlineList( pd->postPopExpr );
  814. out << "</postpop>\n";
  815. }
  816. /*
  817. * Variable expressions.
  818. */
  819. if ( pd->pExpr != 0 ) {
  820. out << " <p_expr>";
  821. writeInlineList( pd->pExpr );
  822. out << "</p_expr>\n";
  823. }
  824. if ( pd->peExpr != 0 ) {
  825. out << " <pe_expr>";
  826. writeInlineList( pd->peExpr );
  827. out << "</pe_expr>\n";
  828. }
  829. if ( pd->eofExpr != 0 ) {
  830. out << " <eof_expr>";
  831. writeInlineList( pd->eofExpr );
  832. out << "</eof_expr>\n";
  833. }
  834. if ( pd->csExpr != 0 ) {
  835. out << " <cs_expr>";
  836. writeInlineList( pd->csExpr );
  837. out << "</cs_expr>\n";
  838. }
  839. if ( pd->topExpr != 0 ) {
  840. out << " <top_expr>";
  841. writeInlineList( pd->topExpr );
  842. out << "</top_expr>\n";
  843. }
  844. if ( pd->stackExpr != 0 ) {
  845. out << " <stack_expr>";
  846. writeInlineList( pd->stackExpr );
  847. out << "</stack_expr>\n";
  848. }
  849. if ( pd->actExpr != 0 ) {
  850. out << " <act_expr>";
  851. writeInlineList( pd->actExpr );
  852. out << "</act_expr>\n";
  853. }
  854. if ( pd->tokstartExpr != 0 ) {
  855. out << " <tokstart_expr>";
  856. writeInlineList( pd->tokstartExpr );
  857. out << "</tokstart_expr>\n";
  858. }
  859. if ( pd->tokendExpr != 0 ) {
  860. out << " <tokend_expr>";
  861. writeInlineList( pd->tokendExpr );
  862. out << "</tokend_expr>\n";
  863. }
  864. if ( pd->dataExpr != 0 ) {
  865. out << " <data_expr>";
  866. writeInlineList( pd->dataExpr );
  867. out << "</data_expr>\n";
  868. }
  869. writeExports();
  870. writeMachine();
  871. out <<
  872. "</ragel_def>\n";
  873. }
  874. void BackendGen::makeExports()
  875. {
  876. for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
  877. cgd->exportList.append( new Export( exp->name, exp->key ) );
  878. }
  879. void BackendGen::makeAction( Action *action )
  880. {
  881. GenInlineList *genList = new GenInlineList;
  882. makeGenInlineList( genList, action->inlineList );
  883. cgd->newAction( curAction++, action->name, action->loc, genList );
  884. }
  885. void BackendGen::makeActionList()
  886. {
  887. /* Determine which actions to write. */
  888. int nextActionId = 0;
  889. for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
  890. if ( act->numRefs() > 0 || act->numCondRefs > 0 )
  891. act->actionId = nextActionId++;
  892. }
  893. /* Write the list. */
  894. cgd->initActionList( nextActionId );
  895. curAction = 0;
  896. for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
  897. if ( act->actionId >= 0 )
  898. makeAction( act );
  899. }
  900. }
  901. void BackendGen::makeActionTableList()
  902. {
  903. /* Must first order the action tables based on their id. */
  904. int numTables = nextActionTableId;
  905. RedActionTable **tables = new RedActionTable*[numTables];
  906. for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
  907. tables[at->id] = at;
  908. cgd->initActionTableList( numTables );
  909. curActionTable = 0;
  910. for ( int t = 0; t < numTables; t++ ) {
  911. long length = tables[t]->key.length();
  912. /* Collect the action table. */
  913. RedAction *redAct = cgd->allActionTables + curActionTable;
  914. redAct->actListId = curActionTable;
  915. redAct->key.setAsNew( length );
  916. for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
  917. redAct->key[atel.pos()].key = 0;
  918. redAct->key[atel.pos()].value = cgd->allActions +
  919. atel->value->actionId;
  920. }
  921. /* Insert into the action table map. */
  922. cgd->redFsm->actionMap.insert( redAct );
  923. curActionTable += 1;
  924. }
  925. delete[] tables;
  926. }
  927. void BackendGen::makeConditions()
  928. {
  929. if ( condData->condSpaceMap.length() > 0 ) {
  930. long nextCondSpaceId = 0;
  931. for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
  932. cs->condSpaceId = nextCondSpaceId++;
  933. long listLength = condData->condSpaceMap.length();
  934. cgd->initCondSpaceList( listLength );
  935. curCondSpace = 0;
  936. for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
  937. long id = cs->condSpaceId;
  938. cgd->newCondSpace( curCondSpace, id, cs->baseKey );
  939. for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
  940. cgd->condSpaceItem( curCondSpace, (*csi)->actionId );
  941. curCondSpace += 1;
  942. }
  943. }
  944. }
  945. bool BackendGen::makeNameInst( std::string &res, NameInst *nameInst )
  946. {
  947. bool written = false;
  948. if ( nameInst->parent != 0 )
  949. written = makeNameInst( res, nameInst->parent );
  950. if ( nameInst->name != 0 ) {
  951. if ( written )
  952. res += '_';
  953. res += nameInst->name;
  954. written = true;
  955. }
  956. return written;
  957. }
  958. void BackendGen::makeEntryPoints()
  959. {
  960. /* List of entry points other than start state. */
  961. if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
  962. if ( pd->lmRequiresErrorState )
  963. cgd->setForcedErrorState();
  964. for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
  965. /* Get the name instantiation from nameIndex. */
  966. NameInst *nameInst = pd->nameIndex[en->key];
  967. std::string name;
  968. makeNameInst( name, nameInst );
  969. StateAp *state = en->value;
  970. cgd->addEntryPoint( strdup(name.c_str()), state->alg.stateNum );
  971. }
  972. }
  973. }
  974. void BackendGen::makeStateActions( StateAp *state )
  975. {
  976. RedActionTable *toStateActions = 0;
  977. if ( state->toStateActionTable.length() > 0 )
  978. toStateActions = actionTableMap.find( state->toStateActionTable );
  979. RedActionTable *fromStateActions = 0;
  980. if ( state->fromStateActionTable.length() > 0 )
  981. fromStateActions = actionTableMap.find( state->fromStateActionTable );
  982. /* EOF actions go out here only if the state has no eof target. If it has
  983. * an eof target then an eof transition will be used instead. */
  984. RedActionTable *eofActions = 0;
  985. if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
  986. eofActions = actionTableMap.find( state->eofActionTable );
  987. if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
  988. long to = -1;
  989. if ( toStateActions != 0 )
  990. to = toStateActions->id;
  991. long from = -1;
  992. if ( fromStateActions != 0 )
  993. from = fromStateActions->id;
  994. long eof = -1;
  995. if ( eofActions != 0 )
  996. eof = eofActions->id;
  997. cgd->setStateActions( curState, to, from, eof );
  998. }
  999. }
  1000. void BackendGen::makeEofTrans( StateAp *state )
  1001. {
  1002. RedActionTable *eofActions = 0;
  1003. if ( state->eofActionTable.length() > 0 )
  1004. eofActions = actionTableMap.find( state->eofActionTable );
  1005. /* The EOF trans is used when there is an eof target, otherwise the eof
  1006. * action goes into state actions. */
  1007. if ( state->eofTarget != 0 ) {
  1008. long targ = state->eofTarget->alg.stateNum;
  1009. long action = -1;
  1010. if ( eofActions != 0 )
  1011. action = eofActions->id;
  1012. cgd->setEofTrans( curState, targ, action );
  1013. }
  1014. }
  1015. void BackendGen::makeStateConditions( StateAp *state )
  1016. {
  1017. if ( state->stateCondList.length() > 0 ) {
  1018. long length = state->stateCondList.length();
  1019. cgd->initStateCondList( curState, length );
  1020. curStateCond = 0;
  1021. for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
  1022. cgd->addStateCond( curState, scdi->lowKey, scdi->highKey,
  1023. scdi->condSpace->condSpaceId );
  1024. }
  1025. }
  1026. }
  1027. void BackendGen::makeTrans( Key lowKey, Key highKey, TransAp *trans )
  1028. {
  1029. /* First reduce the action. */
  1030. RedActionTable *actionTable = 0;
  1031. if ( trans->actionTable.length() > 0 )
  1032. actionTable = actionTableMap.find( trans->actionTable );
  1033. long targ = -1;
  1034. if ( trans->toState != 0 )
  1035. targ = trans->toState->alg.stateNum;
  1036. long action = -1;
  1037. if ( actionTable != 0 )
  1038. action = actionTable->id;
  1039. cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action );
  1040. }
  1041. void BackendGen::makeTransList( StateAp *state )
  1042. {
  1043. TransListVect outList;
  1044. /* If there is only are no ranges the task is simple. */
  1045. if ( state->outList.length() > 0 ) {
  1046. /* Loop each source range. */
  1047. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  1048. /* Reduce the transition. If it reduced to anything then add it. */
  1049. appendTrans( outList, trans->lowKey, trans->highKey, trans );
  1050. }
  1051. }
  1052. cgd->initTransList( curState, outList.length() );
  1053. curTrans = 0;
  1054. for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
  1055. makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
  1056. cgd->finishTransList( curState );
  1057. }
  1058. void BackendGen::makeStateList()
  1059. {
  1060. /* Write the list of states. */
  1061. long length = fsm->stateList.length();
  1062. cgd->initStateList( length );
  1063. curState = 0;
  1064. for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
  1065. makeStateActions( st );
  1066. makeEofTrans( st );
  1067. makeStateConditions( st );
  1068. makeTransList( st );
  1069. long id = st->alg.stateNum;
  1070. cgd->setId( curState, id );
  1071. if ( st->isFinState() )
  1072. cgd->setFinal( curState );
  1073. curState += 1;
  1074. }
  1075. }
  1076. void BackendGen::makeMachine()
  1077. {
  1078. cgd->createMachine();
  1079. /* Action tables. */
  1080. reduceActionTables();
  1081. makeActionList();
  1082. makeActionTableList();
  1083. makeConditions();
  1084. /* Start State. */
  1085. cgd->setStartState( fsm->startState->alg.stateNum );
  1086. /* Error state. */
  1087. if ( fsm->errState != 0 )
  1088. cgd->setErrorState( fsm->errState->alg.stateNum );
  1089. makeEntryPoints();
  1090. makeStateList();
  1091. cgd->closeMachine();
  1092. }
  1093. void BackendGen::close_ragel_def()
  1094. {
  1095. /* Do this before distributing transitions out to singles and defaults
  1096. * makes life easier. */
  1097. cgd->redFsm->maxKey = cgd->findMaxKey();
  1098. cgd->redFsm->assignActionLocs();
  1099. /* Find the first final state (The final state with the lowest id). */
  1100. cgd->redFsm->findFirstFinState();
  1101. /* Call the user's callback. */
  1102. cgd->finishRagelDef();
  1103. }
  1104. void BackendGen::makeBackend()
  1105. {
  1106. /* Alphabet type. */
  1107. cgd->setAlphType( keyOps->alphType->internalName );
  1108. /* Getkey expression. */
  1109. if ( pd->getKeyExpr != 0 ) {
  1110. cgd->getKeyExpr = new GenInlineList;
  1111. makeGenInlineList( cgd->getKeyExpr, pd->getKeyExpr );
  1112. }
  1113. /* Access expression. */
  1114. if ( pd->accessExpr != 0 ) {
  1115. cgd->accessExpr = new GenInlineList;
  1116. makeGenInlineList( cgd->accessExpr, pd->accessExpr );
  1117. }
  1118. /* PrePush expression. */
  1119. if ( pd->prePushExpr != 0 ) {
  1120. cgd->prePushExpr = new GenInlineList;
  1121. makeGenInlineList( cgd->prePushExpr, pd->prePushExpr );
  1122. }
  1123. /* PostPop expression. */
  1124. if ( pd->postPopExpr != 0 ) {
  1125. cgd->postPopExpr = new GenInlineList;
  1126. makeGenInlineList( cgd->postPopExpr, pd->postPopExpr );
  1127. }
  1128. /*
  1129. * Variable expressions.
  1130. */
  1131. if ( pd->pExpr != 0 ) {
  1132. cgd->pExpr = new GenInlineList;
  1133. makeGenInlineList( cgd->pExpr, pd->pExpr );
  1134. }
  1135. if ( pd->peExpr != 0 ) {
  1136. cgd->peExpr = new GenInlineList;
  1137. makeGenInlineList( cgd->peExpr, pd->peExpr );
  1138. }
  1139. if ( pd->eofExpr != 0 ) {
  1140. cgd->eofExpr = new GenInlineList;
  1141. makeGenInlineList( cgd->eofExpr, pd->eofExpr );
  1142. }
  1143. if ( pd->csExpr != 0 ) {
  1144. cgd->csExpr = new GenInlineList;
  1145. makeGenInlineList( cgd->csExpr, pd->csExpr );
  1146. }
  1147. if ( pd->topExpr != 0 ) {
  1148. cgd->topExpr = new GenInlineList;
  1149. makeGenInlineList( cgd->topExpr, pd->topExpr );
  1150. }
  1151. if ( pd->stackExpr != 0 ) {
  1152. cgd->stackExpr = new GenInlineList;
  1153. makeGenInlineList( cgd->stackExpr, pd->stackExpr );
  1154. }
  1155. if ( pd->actExpr != 0 ) {
  1156. cgd->actExpr = new GenInlineList;
  1157. makeGenInlineList( cgd->actExpr, pd->actExpr );
  1158. }
  1159. if ( pd->tokstartExpr != 0 ) {
  1160. cgd->tokstartExpr = new GenInlineList;
  1161. makeGenInlineList( cgd->tokstartExpr, pd->tokstartExpr );
  1162. }
  1163. if ( pd->tokendExpr != 0 ) {
  1164. cgd->tokendExpr = new GenInlineList;
  1165. makeGenInlineList( cgd->tokendExpr, pd->tokendExpr );
  1166. }
  1167. if ( pd->dataExpr != 0 ) {
  1168. cgd->dataExpr = new GenInlineList;
  1169. makeGenInlineList( cgd->dataExpr, pd->dataExpr );
  1170. }
  1171. makeExports();
  1172. makeMachine();
  1173. close_ragel_def();
  1174. }
  1175. void InputData::writeLanguage( std::ostream &out )
  1176. {
  1177. out << " lang=\"";
  1178. switch ( hostLang->lang ) {
  1179. case HostLang::C: out << "C"; break;
  1180. case HostLang::D: out << "D"; break;
  1181. case HostLang::D2: out << "D2"; break;
  1182. case HostLang::Go: out << "Go"; break;
  1183. case HostLang::Java: out << "Java"; break;
  1184. case HostLang::Ruby: out << "Ruby"; break;
  1185. case HostLang::CSharp: out << "C#"; break;
  1186. case HostLang::OCaml: out << "OCaml"; break;
  1187. }
  1188. out << "\"";
  1189. }
  1190. void InputData::writeXML( std::ostream &out )
  1191. {
  1192. out << "<ragel version=\"" VERSION "\" filename=\"" << inputFileName << "\"";
  1193. writeLanguage( out );
  1194. out << ">\n";
  1195. for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) {
  1196. ParseData *pd = parser->value->pd;
  1197. if ( pd->instanceList.length() > 0 )
  1198. pd->generateXML( *outStream );
  1199. }
  1200. out << "</ragel>\n";
  1201. }