cdcodegen.cpp 21 KB

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