rubytable.cpp 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * Copyright 2007 Victor Hugo Borja <vic@rubyforge.org>
  3. * 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 <iomanip>
  22. #include <sstream>
  23. #include "redfsm.h"
  24. #include "gendata.h"
  25. #include "ragel.h"
  26. #include "rubytable.h"
  27. using std::ostream;
  28. using std::ostringstream;
  29. using std::string;
  30. using std::cerr;
  31. using std::endl;
  32. void RubyTabCodeGen::GOTO( ostream &out, int gotoDest, bool inFinish )
  33. {
  34. out <<
  35. " begin\n"
  36. " " << vCS() << " = " << gotoDest << "\n"
  37. " _trigger_goto = true\n"
  38. " _goto_level = _again\n"
  39. " break\n"
  40. " end\n";
  41. }
  42. void RubyTabCodeGen::GOTO_EXPR( ostream &out, GenInlineItem *ilItem, bool inFinish )
  43. {
  44. out <<
  45. " begin\n"
  46. " " << vCS() << " = (";
  47. INLINE_LIST( out, ilItem->children, 0, inFinish );
  48. out << ")\n";
  49. out <<
  50. " _trigger_goto = true\n"
  51. " _goto_level = _again\n"
  52. " break\n"
  53. " end\n";
  54. }
  55. void RubyTabCodeGen::CALL( ostream &out, int callDest, int targState, bool inFinish )
  56. {
  57. if ( prePushExpr != 0 ) {
  58. out << "begin\n";
  59. INLINE_LIST( out, prePushExpr, 0, false );
  60. }
  61. out <<
  62. " begin\n"
  63. " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
  64. " " << TOP() << "+= 1\n"
  65. " " << vCS() << " = " << callDest << "\n"
  66. " _trigger_goto = true\n"
  67. " _goto_level = _again\n"
  68. " break\n"
  69. " end\n";
  70. if ( prePushExpr != 0 )
  71. out << "end\n";
  72. }
  73. void RubyTabCodeGen::CALL_EXPR(ostream &out, GenInlineItem *ilItem, int targState, bool inFinish )
  74. {
  75. if ( prePushExpr != 0 ) {
  76. out << "begin\n";
  77. INLINE_LIST( out, prePushExpr, 0, false );
  78. }
  79. out <<
  80. " begin\n"
  81. " " << STACK() << "[" << TOP() << "] = " << vCS() << "\n"
  82. " " << TOP() << " += 1\n"
  83. " " << vCS() << " = (";
  84. INLINE_LIST( out, ilItem->children, targState, inFinish );
  85. out << ")\n";
  86. out <<
  87. " _trigger_goto = true\n"
  88. " _goto_level = _again\n"
  89. " break\n"
  90. " end\n";
  91. if ( prePushExpr != 0 )
  92. out << "end\n";
  93. }
  94. void RubyTabCodeGen::RET( ostream &out, bool inFinish )
  95. {
  96. out <<
  97. " begin\n"
  98. " " << TOP() << " -= 1\n"
  99. " " << vCS() << " = " << STACK() << "[" << TOP() << "]\n";
  100. if ( postPopExpr != 0 ) {
  101. out << "begin\n";
  102. INLINE_LIST( out, postPopExpr, 0, false );
  103. out << "end\n";
  104. }
  105. out <<
  106. " _trigger_goto = true\n"
  107. " _goto_level = _again\n"
  108. " break\n"
  109. " end\n";
  110. }
  111. void RubyTabCodeGen::BREAK( ostream &out, int targState )
  112. {
  113. out <<
  114. " begin\n"
  115. " " << P() << " += 1\n"
  116. " _trigger_goto = true\n"
  117. " _goto_level = _out\n"
  118. " break\n"
  119. " end\n";
  120. }
  121. void RubyTabCodeGen::COND_TRANSLATE()
  122. {
  123. out <<
  124. " _widec = " << GET_KEY() << "\n"
  125. " _keys = " << CO() << "[" << vCS() << "]*2\n"
  126. " _klen = " << CL() << "[" << vCS() << "]\n"
  127. " if _klen > 0\n"
  128. " _lower = _keys\n"
  129. " _upper = _keys + (_klen<<1) - 2\n"
  130. " loop do\n"
  131. " break if _upper < _lower\n"
  132. " _mid = _lower + (((_upper-_lower) >> 1) & ~1)\n"
  133. " if " << GET_WIDE_KEY() << " < " << CK() << "[_mid]\n"
  134. " _upper = _mid - 2\n"
  135. " elsif " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1]\n"
  136. " _lower = _mid + 2\n"
  137. " else\n"
  138. " case " << C() << "[" << CO() << "[" << vCS() << "]"
  139. " + ((_mid - _keys)>>1)]\n";
  140. for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
  141. GenCondSpace *condSpace = csi;
  142. out << " when " << condSpace->condSpaceId << " then" ;
  143. out << " _widec = " << KEY(condSpace->baseKey) <<
  144. "+ (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ")\n";
  145. for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
  146. Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
  147. out << " _widec += " << condValOffset << " if ( ";
  148. CONDITION( out, *csi );
  149. out << " )\n";
  150. }
  151. }
  152. out <<
  153. " end # case\n"
  154. " end\n"
  155. " end # loop\n"
  156. " end\n";
  157. }
  158. void RubyTabCodeGen::LOCATE_TRANS()
  159. {
  160. out <<
  161. " _keys = " << KO() << "[" << vCS() << "]\n"
  162. " _trans = " << IO() << "[" << vCS() << "]\n"
  163. " _klen = " << SL() << "[" << vCS() << "]\n"
  164. " _break_match = false\n"
  165. " \n"
  166. " begin\n"
  167. " if _klen > 0\n"
  168. " _lower = _keys\n"
  169. " _upper = _keys + _klen - 1\n"
  170. "\n"
  171. " loop do\n"
  172. " break if _upper < _lower\n"
  173. " _mid = _lower + ( (_upper - _lower) >> 1 )\n"
  174. "\n"
  175. " if " << GET_WIDE_KEY() << " < " << K() << "[_mid]\n"
  176. " _upper = _mid - 1\n"
  177. " elsif " << GET_WIDE_KEY() << " > " << K() << "[_mid]\n"
  178. " _lower = _mid + 1\n"
  179. " else\n"
  180. " _trans += (_mid - _keys)\n"
  181. " _break_match = true\n"
  182. " break\n"
  183. " end\n"
  184. " end # loop\n"
  185. " break if _break_match\n"
  186. " _keys += _klen\n"
  187. " _trans += _klen\n"
  188. " end"
  189. "\n"
  190. " _klen = " << RL() << "[" << vCS() << "]\n"
  191. " if _klen > 0\n"
  192. " _lower = _keys\n"
  193. " _upper = _keys + (_klen << 1) - 2\n"
  194. " loop do\n"
  195. " break if _upper < _lower\n"
  196. " _mid = _lower + (((_upper-_lower) >> 1) & ~1)\n"
  197. " if " << GET_WIDE_KEY() << " < " << K() << "[_mid]\n"
  198. " _upper = _mid - 2\n"
  199. " elsif " << GET_WIDE_KEY() << " > " << K() << "[_mid+1]\n"
  200. " _lower = _mid + 2\n"
  201. " else\n"
  202. " _trans += ((_mid - _keys) >> 1)\n"
  203. " _break_match = true\n"
  204. " break\n"
  205. " end\n"
  206. " end # loop\n"
  207. " break if _break_match\n"
  208. " _trans += _klen\n"
  209. " end\n"
  210. " end while false\n";
  211. }
  212. void RubyTabCodeGen::writeExec()
  213. {
  214. out <<
  215. "begin\n"
  216. " _klen, _trans, _keys";
  217. if ( redFsm->anyRegCurStateRef() )
  218. out << ", _ps";
  219. if ( redFsm->anyConditions() )
  220. out << ", _widec";
  221. if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
  222. || redFsm->anyFromStateActions() )
  223. out << ", _acts, _nacts";
  224. out << " = nil\n";
  225. out <<
  226. " _goto_level = 0\n"
  227. " _resume = 10\n"
  228. " _eof_trans = 15\n"
  229. " _again = 20\n"
  230. " _test_eof = 30\n"
  231. " _out = 40\n";
  232. out <<
  233. " while true\n"
  234. " _trigger_goto = false\n"
  235. " if _goto_level <= 0\n";
  236. if ( !noEnd ) {
  237. out <<
  238. " if " << P() << " == " << PE() << "\n"
  239. " _goto_level = _test_eof\n"
  240. " next\n"
  241. " end\n";
  242. }
  243. if ( redFsm->errState != 0 ) {
  244. out <<
  245. " if " << vCS() << " == " << redFsm->errState->id << "\n"
  246. " _goto_level = _out\n"
  247. " next\n"
  248. " end\n";
  249. }
  250. /* The resume label. */
  251. out <<
  252. " end\n"
  253. " if _goto_level <= _resume\n";
  254. if ( redFsm->anyFromStateActions() ) {
  255. out <<
  256. " _acts = " << FSA() << "[" << vCS() << "]\n"
  257. " _nacts = " << A() << "[_acts]\n"
  258. " _acts += 1\n"
  259. " while _nacts > 0\n"
  260. " _nacts -= 1\n"
  261. " _acts += 1\n"
  262. " case " << A() << "[_acts - 1]\n";
  263. FROM_STATE_ACTION_SWITCH();
  264. out <<
  265. " end # from state action switch\n"
  266. " end\n"
  267. " if _trigger_goto\n"
  268. " next\n"
  269. " end\n";
  270. }
  271. if ( redFsm->anyConditions() )
  272. COND_TRANSLATE();
  273. LOCATE_TRANS();
  274. if ( useIndicies )
  275. out << " _trans = " << I() << "[_trans]\n";
  276. if ( redFsm->anyEofTrans() ) {
  277. out <<
  278. " end\n"
  279. " if _goto_level <= _eof_trans\n";
  280. }
  281. if ( redFsm->anyRegCurStateRef() )
  282. out << " _ps = " << vCS() << "\n";
  283. out << " " << vCS() << " = " << TT() << "[_trans]\n";
  284. if ( redFsm->anyRegActions() ) {
  285. out <<
  286. " if " << TA() << "[_trans] != 0\n"
  287. " _acts = " << TA() << "[_trans]\n"
  288. " _nacts = " << A() << "[_acts]\n"
  289. " _acts += 1\n"
  290. " while _nacts > 0\n"
  291. " _nacts -= 1\n"
  292. " _acts += 1\n"
  293. " case " << A() << "[_acts - 1]\n";
  294. ACTION_SWITCH();
  295. out <<
  296. " end # action switch\n"
  297. " end\n"
  298. " end\n"
  299. " if _trigger_goto\n"
  300. " next\n"
  301. " end\n";
  302. }
  303. /* The again label. */
  304. out <<
  305. " end\n"
  306. " if _goto_level <= _again\n";
  307. if ( redFsm->anyToStateActions() ) {
  308. out <<
  309. " _acts = " << TSA() << "[" << vCS() << "]\n"
  310. " _nacts = " << A() << "[_acts]\n"
  311. " _acts += 1\n"
  312. " while _nacts > 0\n"
  313. " _nacts -= 1\n"
  314. " _acts += 1\n"
  315. " case " << A() << "[_acts - 1]\n";
  316. TO_STATE_ACTION_SWITCH();
  317. out <<
  318. " end # to state action switch\n"
  319. " end\n"
  320. " if _trigger_goto\n"
  321. " next\n"
  322. " end\n";
  323. }
  324. if ( redFsm->errState != 0 ) {
  325. out <<
  326. " if " << vCS() << " == " << redFsm->errState->id << "\n"
  327. " _goto_level = _out\n"
  328. " next\n"
  329. " end\n";
  330. }
  331. out << " " << P() << " += 1\n";
  332. if ( !noEnd ) {
  333. out <<
  334. " if " << P() << " != " << PE() << "\n"
  335. " _goto_level = _resume\n"
  336. " next\n"
  337. " end\n";
  338. }
  339. else {
  340. out <<
  341. " _goto_level = _resume\n"
  342. " next\n";
  343. }
  344. /* The test_eof label. */
  345. out <<
  346. " end\n"
  347. " if _goto_level <= _test_eof\n";
  348. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  349. out <<
  350. " if " << P() << " == " << vEOF() << "\n";
  351. if ( redFsm->anyEofTrans() ) {
  352. out <<
  353. " if " << ET() << "[" << vCS() << "] > 0\n"
  354. " _trans = " << ET() << "[" << vCS() << "] - 1;\n"
  355. " _goto_level = _eof_trans\n"
  356. " next;\n"
  357. " end\n";
  358. }
  359. if ( redFsm->anyEofActions() ) {
  360. out <<
  361. " __acts = " << EA() << "[" << vCS() << "]\n"
  362. " __nacts = " << " " << A() << "[__acts]\n"
  363. " __acts += 1\n"
  364. " while __nacts > 0\n"
  365. " __nacts -= 1\n"
  366. " __acts += 1\n"
  367. " case " << A() << "[__acts - 1]\n";
  368. EOF_ACTION_SWITCH() <<
  369. " end # eof action switch\n"
  370. " end\n"
  371. " if _trigger_goto\n"
  372. " next\n"
  373. " end\n";
  374. }
  375. out <<
  376. "end\n";
  377. }
  378. out <<
  379. " end\n"
  380. " if _goto_level <= _out\n"
  381. " break\n"
  382. " end\n";
  383. /* The loop for next. */
  384. out <<
  385. " end\n";
  386. /* Wrapping the execute block. */
  387. out <<
  388. " end\n";
  389. }
  390. std::ostream &RubyTabCodeGen::FROM_STATE_ACTION_SWITCH()
  391. {
  392. /* Walk the list of functions, printing the cases. */
  393. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  394. /* Write out referenced actions. */
  395. if ( act->numFromStateRefs > 0 ) {
  396. /* Write the case label, the action */
  397. out << " when " << act->actionId << " then\n";
  398. ACTION( out, act, 0, false );
  399. }
  400. }
  401. genLineDirective( out );
  402. return out;
  403. }
  404. std::ostream &RubyTabCodeGen::TO_STATE_ACTION_SWITCH()
  405. {
  406. /* Walk the list of functions, printing the cases. */
  407. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  408. /* Write out referenced actions. */
  409. if ( act->numToStateRefs > 0 ) {
  410. /* Write the case label, the action and the case break. */
  411. out << "when " << act->actionId << " then\n";
  412. ACTION( out, act, 0, false );
  413. }
  414. }
  415. genLineDirective( out );
  416. return out;
  417. }
  418. std::ostream &RubyTabCodeGen::EOF_ACTION_SWITCH()
  419. {
  420. /* Walk the list of functions, printing the cases. */
  421. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  422. /* Write out referenced actions. */
  423. if ( act->numEofRefs > 0 ) {
  424. /* Write the case label, the action and the case break. */
  425. out << "when " << act->actionId << " then\n";
  426. ACTION( out, act, 0, true );
  427. }
  428. }
  429. genLineDirective( out );
  430. return out;
  431. }
  432. std::ostream &RubyTabCodeGen::ACTION_SWITCH()
  433. {
  434. /* Walk the list of functions, printing the cases. */
  435. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  436. /* Write out referenced actions. */
  437. if ( act->numTransRefs > 0 ) {
  438. /* Write the case label, the action and the case break. */
  439. out << "when " << act->actionId << " then\n";
  440. ACTION( out, act, 0, false );
  441. }
  442. }
  443. genLineDirective( out );
  444. return out;
  445. }
  446. void RubyTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
  447. {
  448. ret << vCS() << " = " << nextDest << ";";
  449. }
  450. void RubyTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  451. {
  452. ret << vCS() << " = (";
  453. INLINE_LIST( ret, ilItem->children, 0, inFinish );
  454. ret << ");";
  455. }
  456. int RubyTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
  457. {
  458. int act = 0;
  459. if ( state->toStateAction != 0 )
  460. act = state->toStateAction->location+1;
  461. return act;
  462. }
  463. int RubyTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  464. {
  465. int act = 0;
  466. if ( state->fromStateAction != 0 )
  467. act = state->fromStateAction->location+1;
  468. return act;
  469. }
  470. int RubyTabCodeGen::EOF_ACTION( RedStateAp *state )
  471. {
  472. int act = 0;
  473. if ( state->eofAction != 0 )
  474. act = state->eofAction->location+1;
  475. return act;
  476. }
  477. std::ostream &RubyTabCodeGen::COND_OFFSETS()
  478. {
  479. START_ARRAY_LINE();
  480. int totalStateNum = 0, curKeyOffset = 0;
  481. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  482. /* Write the key offset. */
  483. ARRAY_ITEM( INT(curKeyOffset), ++totalStateNum, st.last() );
  484. /* Move the key offset ahead. */
  485. curKeyOffset += st->stateCondList.length();
  486. }
  487. END_ARRAY_LINE();
  488. return out;
  489. }
  490. std::ostream &RubyTabCodeGen::KEY_OFFSETS()
  491. {
  492. START_ARRAY_LINE();
  493. int totalStateNum = 0, curKeyOffset = 0;
  494. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  495. /* Write the key offset. */
  496. ARRAY_ITEM( INT(curKeyOffset), ++totalStateNum, st.last() );
  497. /* Move the key offset ahead. */
  498. curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
  499. }
  500. END_ARRAY_LINE();
  501. return out;
  502. }
  503. std::ostream &RubyTabCodeGen::INDEX_OFFSETS()
  504. {
  505. START_ARRAY_LINE();
  506. int totalStateNum = 0, curIndOffset = 0;
  507. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  508. /* Write the index offset. */
  509. ARRAY_ITEM( INT(curIndOffset), ++totalStateNum, st.last() );
  510. /* Move the index offset ahead. */
  511. curIndOffset += st->outSingle.length() + st->outRange.length();
  512. if ( st->defTrans != 0 )
  513. curIndOffset += 1;
  514. }
  515. END_ARRAY_LINE();
  516. return out;
  517. }
  518. std::ostream &RubyTabCodeGen::COND_LENS()
  519. {
  520. START_ARRAY_LINE();
  521. int totalStateNum = 0;
  522. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  523. /* Write singles length. */
  524. ARRAY_ITEM( INT(st->stateCondList.length()), ++totalStateNum, st.last() );
  525. }
  526. END_ARRAY_LINE();
  527. return out;
  528. }
  529. std::ostream &RubyTabCodeGen::SINGLE_LENS()
  530. {
  531. START_ARRAY_LINE();
  532. int totalStateNum = 0;
  533. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  534. /* Write singles length. */
  535. ARRAY_ITEM( INT(st->outSingle.length()), ++totalStateNum, st.last() );
  536. }
  537. END_ARRAY_LINE();
  538. return out;
  539. }
  540. std::ostream &RubyTabCodeGen::RANGE_LENS()
  541. {
  542. START_ARRAY_LINE();
  543. int totalStateNum = 0;
  544. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  545. /* Emit length of range index. */
  546. ARRAY_ITEM( INT(st->outRange.length()), ++totalStateNum, st.last() );
  547. }
  548. END_ARRAY_LINE();
  549. return out;
  550. }
  551. std::ostream &RubyTabCodeGen::TO_STATE_ACTIONS()
  552. {
  553. START_ARRAY_LINE();
  554. int totalStateNum = 0;
  555. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  556. /* Write any eof action. */
  557. ARRAY_ITEM( INT(TO_STATE_ACTION(st)), ++totalStateNum, st.last() );
  558. }
  559. END_ARRAY_LINE();
  560. return out;
  561. }
  562. std::ostream &RubyTabCodeGen::FROM_STATE_ACTIONS()
  563. {
  564. START_ARRAY_LINE();
  565. int totalStateNum = 0;
  566. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  567. /* Write any eof action. */
  568. ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), ++totalStateNum, st.last() );
  569. }
  570. END_ARRAY_LINE();
  571. return out;
  572. }
  573. std::ostream &RubyTabCodeGen::EOF_ACTIONS()
  574. {
  575. START_ARRAY_LINE();
  576. int totalStateNum = 0;
  577. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  578. /* Write any eof action. */
  579. ARRAY_ITEM( INT(EOF_ACTION(st)), ++totalStateNum, st.last() );
  580. }
  581. END_ARRAY_LINE();
  582. return out;
  583. }
  584. std::ostream &RubyTabCodeGen::EOF_TRANS()
  585. {
  586. START_ARRAY_LINE();
  587. int totalStateNum = 0;
  588. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  589. /* Write any eof action. */
  590. long trans = 0;
  591. if ( st->eofTrans != 0 ) {
  592. assert( st->eofTrans->pos >= 0 );
  593. trans = st->eofTrans->pos+1;
  594. }
  595. /* Write any eof action. */
  596. ARRAY_ITEM( INT(trans), ++totalStateNum, st.last() );
  597. }
  598. END_ARRAY_LINE();
  599. return out;
  600. }
  601. std::ostream &RubyTabCodeGen::COND_KEYS()
  602. {
  603. START_ARRAY_LINE();
  604. int totalTrans = 0;
  605. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  606. /* Loop the state's transitions. */
  607. for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
  608. /* Lower key. */
  609. ARRAY_ITEM( KEY( sc->lowKey ), ++totalTrans, false );
  610. ARRAY_ITEM( KEY( sc->highKey ), ++totalTrans, false );
  611. }
  612. }
  613. /* Output one last number so we don't have to figure out when the last
  614. * entry is and avoid writing a comma. */
  615. ARRAY_ITEM( INT(0), ++totalTrans, true );
  616. END_ARRAY_LINE();
  617. return out;
  618. }
  619. std::ostream &RubyTabCodeGen::COND_SPACES()
  620. {
  621. START_ARRAY_LINE();
  622. int totalTrans = 0;
  623. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  624. /* Loop the state's transitions. */
  625. for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
  626. /* Cond Space id. */
  627. ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), ++totalTrans, false );
  628. }
  629. }
  630. /* Output one last number so we don't have to figure out when the last
  631. * entry is and avoid writing a comma. */
  632. ARRAY_ITEM( INT(0), ++totalTrans, true );
  633. END_ARRAY_LINE();
  634. return out;
  635. }
  636. std::ostream &RubyTabCodeGen::KEYS()
  637. {
  638. START_ARRAY_LINE();
  639. int totalTrans = 0;
  640. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  641. /* Loop the singles. */
  642. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  643. ARRAY_ITEM( KEY( stel->lowKey ), ++totalTrans, false );
  644. }
  645. /* Loop the state's transitions. */
  646. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  647. /* Lower key. */
  648. ARRAY_ITEM( KEY( rtel->lowKey ), ++totalTrans, false );
  649. /* Upper key. */
  650. ARRAY_ITEM( KEY( rtel->highKey ), ++totalTrans, false );
  651. }
  652. }
  653. /* Output one last number so we don't have to figure out when the last
  654. * entry is and avoid writing a comma. */
  655. ARRAY_ITEM( INT(0), ++totalTrans, true );
  656. END_ARRAY_LINE();
  657. return out;
  658. }
  659. std::ostream &RubyTabCodeGen::INDICIES()
  660. {
  661. int totalTrans = 0;
  662. START_ARRAY_LINE();
  663. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  664. /* Walk the singles. */
  665. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  666. ARRAY_ITEM( KEY( stel->value->id ), ++totalTrans, false );
  667. }
  668. /* Walk the ranges. */
  669. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  670. ARRAY_ITEM( KEY( rtel->value->id ), ++totalTrans, false );
  671. }
  672. /* The state's default index goes next. */
  673. if ( st->defTrans != 0 ) {
  674. ARRAY_ITEM( KEY( st->defTrans->id ), ++totalTrans, false );
  675. }
  676. }
  677. /* Output one last number so we don't have to figure out when the last
  678. * entry is and avoid writing a comma. */
  679. ARRAY_ITEM( INT(0), ++totalTrans, true );
  680. END_ARRAY_LINE();
  681. return out;
  682. }
  683. std::ostream &RubyTabCodeGen::TRANS_TARGS()
  684. {
  685. int totalTrans = 0;
  686. START_ARRAY_LINE();
  687. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  688. /* Walk the singles. */
  689. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  690. RedTransAp *trans = stel->value;
  691. ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
  692. }
  693. /* Walk the ranges. */
  694. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  695. RedTransAp *trans = rtel->value;
  696. ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
  697. }
  698. /* The state's default target state. */
  699. if ( st->defTrans != 0 ) {
  700. RedTransAp *trans = st->defTrans;
  701. ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
  702. }
  703. }
  704. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  705. if ( st->eofTrans != 0 ) {
  706. RedTransAp *trans = st->eofTrans;
  707. trans->pos = totalTrans;
  708. ARRAY_ITEM( KEY( trans->targ->id ), ++totalTrans, false );
  709. }
  710. }
  711. /* Output one last number so we don't have to figure out when the last
  712. * entry is and avoid writing a comma. */
  713. ARRAY_ITEM( INT(0), ++totalTrans, true );
  714. END_ARRAY_LINE();
  715. return out;
  716. }
  717. std::ostream &RubyTabCodeGen::TRANS_ACTIONS()
  718. {
  719. int totalTrans = 0;
  720. START_ARRAY_LINE();
  721. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  722. /* Walk the singles. */
  723. for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  724. RedTransAp *trans = stel->value;
  725. ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
  726. }
  727. /* Walk the ranges. */
  728. for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  729. RedTransAp *trans = rtel->value;
  730. ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
  731. }
  732. /* The state's default index goes next. */
  733. if ( st->defTrans != 0 ) {
  734. RedTransAp *trans = st->defTrans;
  735. ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
  736. }
  737. }
  738. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  739. if ( st->eofTrans != 0 ) {
  740. RedTransAp *trans = st->eofTrans;
  741. ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalTrans, false );
  742. }
  743. }
  744. /* Output one last number so we don't have to figure out when the last
  745. * entry is and avoid writing a comma. */
  746. ARRAY_ITEM( INT(0), ++totalTrans, true );
  747. END_ARRAY_LINE();
  748. return out;
  749. }
  750. std::ostream &RubyTabCodeGen::TRANS_TARGS_WI()
  751. {
  752. /* Transitions must be written ordered by their id. */
  753. RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  754. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  755. transPtrs[trans->id] = trans;
  756. /* Keep a count of the num of items in the array written. */
  757. START_ARRAY_LINE();
  758. int totalStates = 0;
  759. for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  760. /* Save the position. Needed for eofTargs. */
  761. RedTransAp *trans = transPtrs[t];
  762. trans->pos = t;
  763. /* Write out the target state. */
  764. ARRAY_ITEM( INT(trans->targ->id), ++totalStates, ( t >= redFsm->transSet.length()-1 ) );
  765. }
  766. END_ARRAY_LINE();
  767. delete[] transPtrs;
  768. return out;
  769. }
  770. std::ostream &RubyTabCodeGen::TRANS_ACTIONS_WI()
  771. {
  772. /* Transitions must be written ordered by their id. */
  773. RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  774. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  775. transPtrs[trans->id] = trans;
  776. /* Keep a count of the num of items in the array written. */
  777. START_ARRAY_LINE();
  778. int totalAct = 0;
  779. for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  780. /* Write the function for the transition. */
  781. RedTransAp *trans = transPtrs[t];
  782. ARRAY_ITEM( INT(TRANS_ACTION( trans )), ++totalAct,
  783. ( t >= redFsm->transSet.length()-1 ) );
  784. }
  785. END_ARRAY_LINE();
  786. delete[] transPtrs;
  787. return out;
  788. }
  789. void RubyTabCodeGen::writeData()
  790. {
  791. /* If there are any transtion functions then output the array. If there
  792. * are none, don't bother emitting an empty array that won't be used. */
  793. if ( redFsm->anyActions() ) {
  794. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  795. ACTIONS_ARRAY();
  796. CLOSE_ARRAY() <<
  797. "\n";
  798. }
  799. if ( redFsm->anyConditions() ) {
  800. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
  801. COND_OFFSETS();
  802. CLOSE_ARRAY() <<
  803. "\n";
  804. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
  805. COND_LENS();
  806. CLOSE_ARRAY() <<
  807. "\n";
  808. OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
  809. COND_KEYS();
  810. CLOSE_ARRAY() <<
  811. "\n";
  812. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
  813. COND_SPACES();
  814. CLOSE_ARRAY() <<
  815. "\n";
  816. }
  817. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
  818. KEY_OFFSETS();
  819. CLOSE_ARRAY() <<
  820. "\n";
  821. OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
  822. KEYS();
  823. CLOSE_ARRAY() <<
  824. "\n";
  825. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
  826. SINGLE_LENS();
  827. CLOSE_ARRAY() <<
  828. "\n";
  829. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
  830. RANGE_LENS();
  831. CLOSE_ARRAY() <<
  832. "\n";
  833. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
  834. INDEX_OFFSETS();
  835. CLOSE_ARRAY() <<
  836. "\n";
  837. if ( useIndicies ) {
  838. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
  839. INDICIES();
  840. CLOSE_ARRAY() <<
  841. "\n";
  842. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  843. TRANS_TARGS_WI();
  844. CLOSE_ARRAY() <<
  845. "\n";
  846. if ( redFsm->anyActions() ) {
  847. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  848. TRANS_ACTIONS_WI();
  849. CLOSE_ARRAY() <<
  850. "\n";
  851. }
  852. }
  853. else {
  854. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  855. TRANS_TARGS();
  856. CLOSE_ARRAY() <<
  857. "\n";
  858. if ( redFsm->anyActions() ) {
  859. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  860. TRANS_ACTIONS();
  861. CLOSE_ARRAY() <<
  862. "\n";
  863. }
  864. }
  865. if ( redFsm->anyToStateActions() ) {
  866. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  867. TO_STATE_ACTIONS();
  868. CLOSE_ARRAY() <<
  869. "\n";
  870. }
  871. if ( redFsm->anyFromStateActions() ) {
  872. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  873. FROM_STATE_ACTIONS();
  874. CLOSE_ARRAY() <<
  875. "\n";
  876. }
  877. if ( redFsm->anyEofActions() ) {
  878. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  879. EOF_ACTIONS();
  880. CLOSE_ARRAY() <<
  881. "\n";
  882. }
  883. if ( redFsm->anyEofTrans() ) {
  884. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
  885. EOF_TRANS();
  886. CLOSE_ARRAY() <<
  887. "\n";
  888. }
  889. STATE_IDS();
  890. }
  891. /*
  892. Local Variables:
  893. mode: c++
  894. indent-tabs-mode: 1
  895. c-file-style: "bsd"
  896. End:
  897. */