rubyfflat.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /*
  2. * 2007 Victor Hugo Borja <vic@rubyforge.org>
  3. * Copyright 2001-2007 Adrian Thurston <thurston@complang.org>
  4. */
  5. /* This file is part of Ragel.
  6. *
  7. * Ragel is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * Ragel is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with Ragel; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include "rubyfflat.h"
  22. void RubyFFlatCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish )
  23. {
  24. out <<
  25. " begin\n"
  26. " " << vCS() << " = " << gotoDest << "\n"
  27. " _goto_level = _again\n"
  28. " next\n"
  29. " end\n";
  30. }
  31. void RubyFFlatCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish )
  32. {
  33. out <<
  34. " begin\n"
  35. " " << vCS() << " = (";
  36. INLINE_LIST( out, ilItem->children, 0, inFinish );
  37. out << ")\n";
  38. out <<
  39. " _goto_level = _again\n"
  40. " next\n"
  41. " end\n";
  42. }
  43. void RubyFFlatCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish )
  44. {
  45. if ( prePushExpr != 0 ) {
  46. out << "begin\n";
  47. INLINE_LIST( out, prePushExpr, 0, false );
  48. }
  49. out <<
  50. " begin\n"
  51. " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
  52. " " << TOP() << "+= 1\n"
  53. " " << vCS() << " = " << callDest << "\n"
  54. " _goto_level = _again\n"
  55. " next\n"
  56. " end\n";
  57. if ( prePushExpr != 0 )
  58. out << "end\n";
  59. }
  60. void RubyFFlatCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem,
  61. int targState, bool inFinish )
  62. {
  63. if ( prePushExpr != 0 ) {
  64. out << "begin\n";
  65. INLINE_LIST( out, prePushExpr, 0, false );
  66. }
  67. out <<
  68. " begin\n"
  69. " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
  70. " " << TOP() << " += 1\n"
  71. " " << vCS() << " = (";
  72. INLINE_LIST( out, ilItem->children, targState, inFinish );
  73. out << ")\n";
  74. out <<
  75. " _goto_level = _again\n"
  76. " next\n"
  77. " end\n";
  78. if ( prePushExpr != 0 )
  79. out << "end\n";
  80. }
  81. void RubyFFlatCodeGen::RET( ostream &out, bool inFinish )
  82. {
  83. out <<
  84. " begin\n"
  85. " " << TOP() << " -= 1\n"
  86. " " << vCS() << " = " << STACK() << "[" << TOP() << "]\n";
  87. if ( postPopExpr != 0 ) {
  88. out << "begin\n";
  89. INLINE_LIST( out, postPopExpr, 0, false );
  90. out << "end\n";
  91. }
  92. out <<
  93. " _goto_level = _again\n"
  94. " next\n"
  95. " end\n";
  96. }
  97. void RubyFFlatCodeGen::BREAK( ostream &out, int targState )
  98. {
  99. out <<
  100. " begin\n"
  101. " " << P() << " += 1\n"
  102. " _goto_level = _out\n"
  103. " next\n"
  104. " end\n";
  105. }
  106. int RubyFFlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
  107. {
  108. int act = 0;
  109. if ( state->toStateAction != 0 )
  110. act = state->toStateAction->actListId+1;
  111. return act;
  112. }
  113. int RubyFFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  114. {
  115. int act = 0;
  116. if ( state->fromStateAction != 0 )
  117. act = state->fromStateAction->actListId+1;
  118. return act;
  119. }
  120. int RubyFFlatCodeGen::EOF_ACTION( RedStateAp *state )
  121. {
  122. int act = 0;
  123. if ( state->eofAction != 0 )
  124. act = state->eofAction->actListId+1;
  125. return act;
  126. }
  127. /* Write out the function for a transition. */
  128. int RubyFFlatCodeGen::TRANS_ACTION( RedTransAp *trans )
  129. {
  130. int action = 0;
  131. if ( trans->action != 0 )
  132. action = trans->action->actListId+1;
  133. return action;
  134. }
  135. /* Write out the function switch. This switch is keyed on the values
  136. * of the func index. */
  137. std::ostream &RubyFFlatCodeGen::TO_STATE_ACTION_SWITCH()
  138. {
  139. /* Loop the actions. */
  140. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  141. if ( redAct->numToStateRefs > 0 ) {
  142. /* Write the entry label. */
  143. out << "\twhen " << redAct->actListId+1 << " then\n";
  144. /* Write each action in the list of action items. */
  145. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  146. ACTION( out, item->value, 0, false );
  147. }
  148. }
  149. genLineDirective( out );
  150. return out;
  151. }
  152. /* Write out the function switch. This switch is keyed on the values
  153. * of the func index. */
  154. std::ostream &RubyFFlatCodeGen::FROM_STATE_ACTION_SWITCH()
  155. {
  156. /* Loop the actions. */
  157. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  158. if ( redAct->numFromStateRefs > 0 ) {
  159. /* Write the entry label. */
  160. out << "\twhen " << redAct->actListId+1 << " then\n";
  161. /* Write each action in the list of action items. */
  162. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  163. ACTION( out, item->value, 0, false );
  164. }
  165. }
  166. genLineDirective( out );
  167. return out;
  168. }
  169. std::ostream &RubyFFlatCodeGen::EOF_ACTION_SWITCH()
  170. {
  171. /* Loop the actions. */
  172. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  173. if ( redAct->numEofRefs > 0 ) {
  174. /* Write the entry label. */
  175. out << "\twhen " << redAct->actListId+1 << " then\n";
  176. /* Write each action in the list of action items. */
  177. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  178. ACTION( out, item->value, 0, true );
  179. }
  180. }
  181. genLineDirective( out );
  182. return out;
  183. }
  184. /* Write out the function switch. This switch is keyed on the values
  185. * of the func index. */
  186. std::ostream &RubyFFlatCodeGen::ACTION_SWITCH()
  187. {
  188. /* Loop the actions. */
  189. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  190. if ( redAct->numTransRefs > 0 ) {
  191. /* Write the entry label. */
  192. out << "\twhen " << redAct->actListId+1 << " then\n";
  193. /* Write each action in the list of action items. */
  194. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  195. ACTION( out, item->value, 0, false );
  196. }
  197. }
  198. genLineDirective( out );
  199. return out;
  200. }
  201. void RubyFFlatCodeGen::writeData()
  202. {
  203. if ( redFsm->anyConditions() ) {
  204. OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
  205. COND_KEYS();
  206. CLOSE_ARRAY() <<
  207. "\n";
  208. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
  209. COND_KEY_SPANS();
  210. CLOSE_ARRAY() <<
  211. "\n";
  212. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
  213. CONDS();
  214. CLOSE_ARRAY() <<
  215. "\n";
  216. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
  217. COND_INDEX_OFFSET();
  218. CLOSE_ARRAY() <<
  219. "\n";
  220. }
  221. OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
  222. KEYS();
  223. CLOSE_ARRAY() <<
  224. "\n";
  225. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
  226. KEY_SPANS();
  227. CLOSE_ARRAY() <<
  228. "\n";
  229. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
  230. FLAT_INDEX_OFFSET();
  231. CLOSE_ARRAY() <<
  232. "\n";
  233. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
  234. INDICIES();
  235. CLOSE_ARRAY() <<
  236. "\n";
  237. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  238. TRANS_TARGS();
  239. CLOSE_ARRAY() <<
  240. "\n";
  241. if ( redFsm->anyActions() ) {
  242. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() );
  243. TRANS_ACTIONS();
  244. CLOSE_ARRAY() <<
  245. "\n";
  246. }
  247. if ( redFsm->anyToStateActions() ) {
  248. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  249. TO_STATE_ACTIONS();
  250. CLOSE_ARRAY() <<
  251. "\n";
  252. }
  253. if ( redFsm->anyFromStateActions() ) {
  254. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  255. FROM_STATE_ACTIONS();
  256. CLOSE_ARRAY() <<
  257. "\n";
  258. }
  259. if ( redFsm->anyEofActions() ) {
  260. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() );
  261. EOF_ACTIONS();
  262. CLOSE_ARRAY() <<
  263. "\n";
  264. }
  265. if ( redFsm->anyEofTrans() ) {
  266. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
  267. EOF_TRANS();
  268. CLOSE_ARRAY() <<
  269. "\n";
  270. }
  271. STATE_IDS();
  272. }
  273. void RubyFFlatCodeGen::writeExec()
  274. {
  275. out <<
  276. "begin\n"
  277. " testEof = false\n"
  278. " _slen, _trans, _keys, _inds";
  279. if ( redFsm->anyRegCurStateRef() )
  280. out << ", _ps";
  281. if ( redFsm->anyConditions() )
  282. out << ", _cond, _conds, _widec";
  283. if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
  284. || redFsm->anyFromStateActions() )
  285. out << ", _acts, _nacts";
  286. out << " = nil\n";
  287. out <<
  288. " _goto_level = 0\n"
  289. " _resume = 10\n"
  290. " _eof_trans = 15\n"
  291. " _again = 20\n"
  292. " _test_eof = 30\n"
  293. " _out = 40\n";
  294. out <<
  295. " while true\n"
  296. " if _goto_level <= 0\n";
  297. if ( !noEnd ) {
  298. out <<
  299. " if " << P() << " == " << PE() << "\n"
  300. " _goto_level = _test_eof\n"
  301. " next\n"
  302. " end\n";
  303. }
  304. if ( redFsm->errState != 0 ) {
  305. out <<
  306. " if " << vCS() << " == " << redFsm->errState->id << "\n"
  307. " _goto_level = _out\n"
  308. " next\n"
  309. " end\n";
  310. }
  311. /* The resume label. */
  312. out <<
  313. " end\n"
  314. " if _goto_level <= _resume\n";
  315. if ( redFsm->anyFromStateActions() ) {
  316. out <<
  317. " case " << FSA() << "[" << vCS() << "] \n";
  318. FROM_STATE_ACTION_SWITCH() <<
  319. " end\n";
  320. }
  321. if ( redFsm->anyConditions() )
  322. COND_TRANSLATE();
  323. LOCATE_TRANS();
  324. if ( redFsm->anyEofTrans() ) {
  325. out <<
  326. " end\n"
  327. " if _goto_level <= _eof_trans\n";
  328. }
  329. if ( redFsm->anyRegCurStateRef() )
  330. out << " _ps = " << vCS() << "\n";
  331. out << " " << vCS() << " = " << TT() << "[_trans]\n";
  332. if ( redFsm->anyRegActions() ) {
  333. /* break _again */
  334. out <<
  335. " if " << TA() << "[_trans] != 0\n"
  336. " case " << TA() << "[_trans]" << "\n";
  337. ACTION_SWITCH() <<
  338. " end\n"
  339. " end\n";
  340. }
  341. /* The again label. */
  342. out <<
  343. " end\n"
  344. " if _goto_level <= _again\n";
  345. if ( redFsm->anyToStateActions() ) {
  346. out <<
  347. " case " << TSA() << "[" << vCS() << "] \n";
  348. TO_STATE_ACTION_SWITCH() <<
  349. " end\n"
  350. "\n";
  351. }
  352. if ( redFsm->errState != 0 ) {
  353. out <<
  354. " if " << vCS() << " == " << redFsm->errState->id << "\n"
  355. " _goto_level = _out\n"
  356. " next\n"
  357. " end\n";
  358. }
  359. out << " " << P() << " += 1\n";
  360. if ( !noEnd ) {
  361. out <<
  362. " if " << P() << " != " << PE() << "\n"
  363. " _goto_level = _resume\n"
  364. " next\n"
  365. " end\n";
  366. }
  367. else {
  368. out <<
  369. " _goto_level = _resume\n"
  370. " next\n";
  371. }
  372. /* The test eof label. */
  373. out <<
  374. " end\n"
  375. " if _goto_level <= _test_eof\n";
  376. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  377. out <<
  378. " if " << P() << " == " << vEOF() << "\n";
  379. if ( redFsm->anyEofTrans() ) {
  380. out <<
  381. " if " << ET() << "[" << vCS() << "] > 0\n"
  382. " _trans = " << ET() << "[" << vCS() << "] - 1;\n"
  383. " _goto_level = _eof_trans\n"
  384. " next;\n"
  385. " end\n";
  386. }
  387. if ( redFsm->anyEofActions() ) {
  388. out <<
  389. " case " << EA() << "[" << vCS() << "]\n";
  390. EOF_ACTION_SWITCH() <<
  391. " end\n";
  392. }
  393. out <<
  394. " end\n"
  395. "\n";
  396. }
  397. out <<
  398. " end\n"
  399. " if _goto_level <= _out\n"
  400. " break\n"
  401. " end\n"
  402. "end\n";
  403. /* Wrapping the execute block. */
  404. out << " end\n";
  405. }
  406. /*
  407. * Local Variables:
  408. * mode: c++
  409. * indent-tabs-mode: 1
  410. * c-file-style: "bsd"
  411. * End:
  412. */