gotable.cpp 25 KB

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