mlfflat.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Copyright 2004-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 "ragel.h"
  23. #include "mlfflat.h"
  24. #include "redfsm.h"
  25. #include "gendata.h"
  26. std::ostream &OCamlFFlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
  27. {
  28. int act = 0;
  29. if ( state->toStateAction != 0 )
  30. act = state->toStateAction->actListId+1;
  31. out << act;
  32. return out;
  33. }
  34. std::ostream &OCamlFFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  35. {
  36. int act = 0;
  37. if ( state->fromStateAction != 0 )
  38. act = state->fromStateAction->actListId+1;
  39. out << act;
  40. return out;
  41. }
  42. std::ostream &OCamlFFlatCodeGen::EOF_ACTION( RedStateAp *state )
  43. {
  44. int act = 0;
  45. if ( state->eofAction != 0 )
  46. act = state->eofAction->actListId+1;
  47. out << act;
  48. return out;
  49. }
  50. /* Write out the function for a transition. */
  51. std::ostream &OCamlFFlatCodeGen::TRANS_ACTION( RedTransAp *trans )
  52. {
  53. int action = 0;
  54. if ( trans->action != 0 )
  55. action = trans->action->actListId+1;
  56. out << action;
  57. return out;
  58. }
  59. /* Write out the function switch. This switch is keyed on the values
  60. * of the func index. */
  61. std::ostream &OCamlFFlatCodeGen::TO_STATE_ACTION_SWITCH()
  62. {
  63. /* Loop the actions. */
  64. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  65. if ( redAct->numToStateRefs > 0 ) {
  66. /* Write the entry label. */
  67. out << "\t| " << redAct->actListId+1 << " ->\n";
  68. /* Write each action in the list of action items. */
  69. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  70. ACTION( out, item->value, 0, false );
  71. out << "\t()\n";
  72. }
  73. }
  74. genLineDirective( out );
  75. return out;
  76. }
  77. /* Write out the function switch. This switch is keyed on the values
  78. * of the func index. */
  79. std::ostream &OCamlFFlatCodeGen::FROM_STATE_ACTION_SWITCH()
  80. {
  81. /* Loop the actions. */
  82. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  83. if ( redAct->numFromStateRefs > 0 ) {
  84. /* Write the entry label. */
  85. out << "\t| " << redAct->actListId+1 << " ->\n";
  86. /* Write each action in the list of action items. */
  87. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  88. ACTION( out, item->value, 0, false );
  89. out << "\t()\n";
  90. }
  91. }
  92. genLineDirective( out );
  93. return out;
  94. }
  95. std::ostream &OCamlFFlatCodeGen::EOF_ACTION_SWITCH()
  96. {
  97. /* Loop the actions. */
  98. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  99. if ( redAct->numEofRefs > 0 ) {
  100. /* Write the entry label. */
  101. out << "\t| " << redAct->actListId+1 << " ->\n";
  102. /* Write each action in the list of action items. */
  103. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  104. ACTION( out, item->value, 0, true );
  105. out << "\t()\n";
  106. }
  107. }
  108. genLineDirective( out );
  109. return out;
  110. }
  111. /* Write out the function switch. This switch is keyed on the values
  112. * of the func index. */
  113. std::ostream &OCamlFFlatCodeGen::ACTION_SWITCH()
  114. {
  115. /* Loop the actions. */
  116. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  117. if ( redAct->numTransRefs > 0 ) {
  118. /* Write the entry label. */
  119. out << "\t| " << redAct->actListId+1 << " ->\n";
  120. /* Write each action in the list of action items. */
  121. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  122. ACTION( out, item->value, 0, false );
  123. out << "\t()\n";
  124. }
  125. }
  126. genLineDirective( out );
  127. return out;
  128. }
  129. void OCamlFFlatCodeGen::writeData()
  130. {
  131. if ( redFsm->anyConditions() ) {
  132. OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
  133. COND_KEYS();
  134. CLOSE_ARRAY() <<
  135. "\n";
  136. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
  137. COND_KEY_SPANS();
  138. CLOSE_ARRAY() <<
  139. "\n";
  140. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
  141. CONDS();
  142. CLOSE_ARRAY() <<
  143. "\n";
  144. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
  145. COND_INDEX_OFFSET();
  146. CLOSE_ARRAY() <<
  147. "\n";
  148. }
  149. OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
  150. KEYS();
  151. CLOSE_ARRAY() <<
  152. "\n";
  153. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
  154. KEY_SPANS();
  155. CLOSE_ARRAY() <<
  156. "\n";
  157. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
  158. FLAT_INDEX_OFFSET();
  159. CLOSE_ARRAY() <<
  160. "\n";
  161. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
  162. INDICIES();
  163. CLOSE_ARRAY() <<
  164. "\n";
  165. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  166. TRANS_TARGS();
  167. CLOSE_ARRAY() <<
  168. "\n";
  169. if ( redFsm->anyActions() ) {
  170. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), TA() );
  171. TRANS_ACTIONS();
  172. CLOSE_ARRAY() <<
  173. "\n";
  174. }
  175. if ( redFsm->anyToStateActions() ) {
  176. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  177. TO_STATE_ACTIONS();
  178. CLOSE_ARRAY() <<
  179. "\n";
  180. }
  181. if ( redFsm->anyFromStateActions() ) {
  182. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  183. FROM_STATE_ACTIONS();
  184. CLOSE_ARRAY() <<
  185. "\n";
  186. }
  187. if ( redFsm->anyEofActions() ) {
  188. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActListId), EA() );
  189. EOF_ACTIONS();
  190. CLOSE_ARRAY() <<
  191. "\n";
  192. }
  193. if ( redFsm->anyEofTrans() ) {
  194. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
  195. EOF_TRANS();
  196. CLOSE_ARRAY() <<
  197. "\n";
  198. }
  199. STATE_IDS();
  200. out << "type " << TYPE_STATE() << " = { mutable keys : int; mutable trans : int; }"
  201. << TOP_SEP();
  202. out << "exception Goto_match" << TOP_SEP();
  203. out << "exception Goto_again" << TOP_SEP();
  204. out << "exception Goto_eof_trans" << TOP_SEP();
  205. }
  206. void OCamlFFlatCodeGen::writeExec()
  207. {
  208. testEofUsed = false;
  209. outLabelUsed = false;
  210. initVarTypes();
  211. out <<
  212. " begin\n";
  213. // " " << slenType << " _slen";
  214. // if ( redFsm->anyRegCurStateRef() )
  215. // out << ", _ps";
  216. // out << ";\n";
  217. // out << " " << transType << " _trans";
  218. // if ( redFsm->anyConditions() )
  219. // out << ", _cond";
  220. // out << ";\n";
  221. // out <<
  222. // " " << "int _keys;\n"
  223. // " " << indsType << " _inds;\n";
  224. /*
  225. " " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
  226. " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";*/
  227. out <<
  228. " let state = { keys = 0; trans = 0; } in\n"
  229. " let rec do_start () =\n";
  230. // if ( redFsm->anyConditions() ) {
  231. // out <<
  232. // " " << condsType << " _conds;\n"
  233. // " " << WIDE_ALPH_TYPE() << " _widec;\n";
  234. // }
  235. if ( !noEnd ) {
  236. testEofUsed = true;
  237. out <<
  238. " if " << P() << " = " << PE() << " then\n"
  239. " do_test_eof ()\n"
  240. "\telse\n";
  241. }
  242. if ( redFsm->errState != 0 ) {
  243. outLabelUsed = true;
  244. out <<
  245. " if " << vCS() << " = " << redFsm->errState->id << " then\n"
  246. " do_out ()\n"
  247. "\telse\n";
  248. }
  249. out << "\tdo_resume ()\n";
  250. out << "and do_resume () =\n";
  251. if ( redFsm->anyFromStateActions() ) {
  252. out <<
  253. " begin match " << AT( FSA(), vCS() ) << " with\n";
  254. FROM_STATE_ACTION_SWITCH();
  255. SWITCH_DEFAULT() <<
  256. " end;\n"
  257. "\n";
  258. }
  259. if ( redFsm->anyConditions() )
  260. COND_TRANSLATE();
  261. out << "\tbegin try\n";
  262. LOCATE_TRANS();
  263. out << "\twith Goto_match -> () end;\n";
  264. out << "\tdo_eof_trans ()\n";
  265. // if ( redFsm->anyEofTrans() )
  266. out << "and do_eof_trans () =\n";
  267. if ( redFsm->anyRegCurStateRef() )
  268. out << " let ps = " << vCS() << " in\n";
  269. out <<
  270. " " << vCS() << " <- " << AT( TT() ,"state.trans" ) << ";\n"
  271. "\n";
  272. if ( redFsm->anyRegActions() ) {
  273. out <<
  274. " begin try if " << AT( TA() , "state.trans" ) << " = 0 then\n"
  275. " raise Goto_again;\n"
  276. "\n"
  277. " match " << AT( TA(), "state.trans" ) << " with\n";
  278. ACTION_SWITCH();
  279. SWITCH_DEFAULT() <<
  280. " with Goto_again -> () end;\n"
  281. "\n";
  282. }
  283. out << "\tdo_again ()\n";
  284. // if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
  285. // redFsm->anyActionCalls() || redFsm->anyActionRets() )
  286. out << "\tand do_again () =\n";
  287. if ( redFsm->anyToStateActions() ) {
  288. out <<
  289. " begin match " << AT( TSA(), vCS() ) << " with\n";
  290. TO_STATE_ACTION_SWITCH();
  291. SWITCH_DEFAULT() <<
  292. " end;\n"
  293. "\n";
  294. }
  295. if ( redFsm->errState != 0 ) {
  296. outLabelUsed = true;
  297. out <<
  298. " match " << vCS() << " with\n"
  299. "\t| " << redFsm->errState->id << " -> do_out ()\n"
  300. "\t| _ ->\n";
  301. }
  302. out << "\t" << P() << " <- " << P() << " + 1;\n";
  303. if ( !noEnd ) {
  304. out <<
  305. " if " << P() << " <> " << PE() << " then\n"
  306. " do_resume ()\n"
  307. "\telse do_test_eof ()\n";
  308. }
  309. else {
  310. out <<
  311. " do_resume ()\n";
  312. }
  313. // if ( testEofUsed )
  314. out << "and do_test_eof () =\n";
  315. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  316. out <<
  317. " if " << P() << " = " << vEOF() << " then\n"
  318. " begin try\n";
  319. if ( redFsm->anyEofTrans() ) {
  320. out <<
  321. " if " << AT( ET(), vCS() ) << " > 0 then\n"
  322. " begin\n"
  323. " state.trans <- " << CAST(transType) << "(" << AT( ET(), vCS() ) << " - 1);\n"
  324. " raise Goto_eof_trans;\n"
  325. " end;\n";
  326. }
  327. if ( redFsm->anyEofActions() ) {
  328. out <<
  329. " begin match " << AT( EA(), vCS() ) << " with\n";
  330. EOF_ACTION_SWITCH();
  331. SWITCH_DEFAULT() <<
  332. " end\n";
  333. }
  334. out <<
  335. " with Goto_again -> do_again ()\n"
  336. " | Goto_eof_trans -> do_eof_trans () end\n"
  337. "\n";
  338. }
  339. else
  340. {
  341. out << "\t()\n";
  342. }
  343. if ( outLabelUsed )
  344. out << " and do_out () = ()\n";
  345. out << "\tin do_start ()\n";
  346. out << " end;\n";
  347. }