gogoto.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  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 "ragel.h"
  23. #include "gogoto.h"
  24. #include "redfsm.h"
  25. #include "bstmap.h"
  26. #include "gendata.h"
  27. using std::endl;
  28. /* Emit the goto to take for a given transition. */
  29. std::ostream &GoGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level )
  30. {
  31. out << TABS(level) << "goto tr" << trans->id << ";";
  32. return out;
  33. }
  34. int GoGotoCodeGen::TRANS_NR( RedTransAp *trans )
  35. {
  36. return trans->id;
  37. }
  38. std::ostream &GoGotoCodeGen::TO_STATE_ACTION_SWITCH( int level )
  39. {
  40. /* Walk the list of functions, printing the cases. */
  41. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  42. /* Write out referenced actions. */
  43. if ( act->numToStateRefs > 0 ) {
  44. /* Write the case label, the action and the case break. */
  45. out << TABS(level) << "case " << act->actionId << ":" << endl;
  46. ACTION( out, act, 0, false, false );
  47. }
  48. }
  49. genLineDirective( out );
  50. return out;
  51. }
  52. std::ostream &GoGotoCodeGen::FROM_STATE_ACTION_SWITCH( int level )
  53. {
  54. /* Walk the list of functions, printing the cases. */
  55. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  56. /* Write out referenced actions. */
  57. if ( act->numFromStateRefs > 0 ) {
  58. /* Write the case label, the action and the case break. */
  59. out << TABS(level) << "case " << act->actionId << ":" << endl;
  60. ACTION( out, act, 0, false, false );
  61. }
  62. }
  63. genLineDirective( out );
  64. return out;
  65. }
  66. std::ostream &GoGotoCodeGen::EOF_ACTION_SWITCH( int level )
  67. {
  68. /* Walk the list of functions, printing the cases. */
  69. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  70. /* Write out referenced actions. */
  71. if ( act->numEofRefs > 0 ) {
  72. /* Write the case label, the action and the case break. */
  73. out << TABS(level) << "case " << act->actionId << ":" << endl;
  74. ACTION( out, act, 0, true, false );
  75. }
  76. }
  77. genLineDirective( out );
  78. return out;
  79. }
  80. std::ostream &GoGotoCodeGen::ACTION_SWITCH( int level )
  81. {
  82. /* Walk the list of functions, printing the cases. */
  83. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  84. /* Write out referenced actions. */
  85. if ( act->numTransRefs > 0 ) {
  86. /* Write the case label, the action and the case break. */
  87. out << TABS(level) << "case " << act->actionId << ":" << endl;
  88. ACTION( out, act, 0, false, false );
  89. }
  90. }
  91. genLineDirective( out );
  92. return out;
  93. }
  94. void GoGotoCodeGen::GOTO_HEADER( RedStateAp *state, int level )
  95. {
  96. /* Label the state. */
  97. out << TABS(level) << "case " << state->id << ":" << endl;
  98. }
  99. void GoGotoCodeGen::emitSingleSwitch( RedStateAp *state, int level )
  100. {
  101. /* Load up the singles. */
  102. int numSingles = state->outSingle.length();
  103. RedTransEl *data = state->outSingle.data;
  104. if ( numSingles == 1 ) {
  105. /* If there is a single single key then write it out as an if. */
  106. out << TABS(level) << "if " << GET_WIDE_KEY(state) << " == " <<
  107. WIDE_KEY(state, data[0].lowKey) << " {" << endl;
  108. /* Virtual function for writing the target of the transition. */
  109. TRANS_GOTO(data[0].value, level + 1) << endl;
  110. out << TABS(level) << "}" << endl;
  111. }
  112. else if ( numSingles > 1 ) {
  113. /* Write out single keys in a switch if there is more than one. */
  114. out << TABS(level) << "switch " << GET_WIDE_KEY(state) << " {" << endl;
  115. /* Write out the single indicies. */
  116. for ( int j = 0; j < numSingles; j++ ) {
  117. out << TABS(level) << "case " << WIDE_KEY(state, data[j].lowKey) << ":" << endl;
  118. TRANS_GOTO(data[j].value, level + 1) << endl;
  119. }
  120. /* Close off the transition switch. */
  121. out << TABS(level) << "}" << endl;
  122. }
  123. }
  124. void GoGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high )
  125. {
  126. /* Get the mid position, staying on the lower end of the range. */
  127. int mid = (low + high) >> 1;
  128. RedTransEl *data = state->outRange.data;
  129. /* Determine if we need to look higher or lower. */
  130. bool anyLower = mid > low;
  131. bool anyHigher = mid < high;
  132. /* Determine if the keys at mid are the limits of the alphabet. */
  133. bool limitLow = data[mid].lowKey == keyOps->minKey;
  134. bool limitHigh = data[mid].highKey == keyOps->maxKey;
  135. if ( anyLower && anyHigher ) {
  136. /* Can go lower and higher than mid. */
  137. out << TABS(level) << "switch {" << endl;
  138. out << TABS(level) << "case " << GET_WIDE_KEY(state) << " < " <<
  139. WIDE_KEY(state, data[mid].lowKey) << ":" << endl;
  140. emitRangeBSearch( state, level+1, low, mid-1 );
  141. out << TABS(level) << "case " << GET_WIDE_KEY(state) << " > " <<
  142. WIDE_KEY(state, data[mid].highKey) << ":" << endl;
  143. emitRangeBSearch( state, level+1, mid+1, high );
  144. out << TABS(level) << "default:" << endl;
  145. TRANS_GOTO(data[mid].value, level+1) << endl;
  146. out << TABS(level) << "}" << endl;
  147. }
  148. else if ( anyLower && !anyHigher ) {
  149. /* Can go lower than mid but not higher. */
  150. out << TABS(level) << "switch {" << endl;
  151. out << TABS(level) << "case " << GET_WIDE_KEY(state) << " < " <<
  152. WIDE_KEY(state, data[mid].lowKey) << ":" << endl;
  153. emitRangeBSearch( state, level+1, low, mid-1 );
  154. /* if the higher is the highest in the alphabet then there is no
  155. * sense testing it. */
  156. if ( limitHigh ) {
  157. out << TABS(level) << "default:" << endl;
  158. TRANS_GOTO(data[mid].value, level+1) << endl;
  159. }
  160. else {
  161. out << TABS(level) << "case " << GET_WIDE_KEY(state) << " <= " <<
  162. WIDE_KEY(state, data[mid].highKey) << ":" << endl;
  163. TRANS_GOTO(data[mid].value, level+1) << endl;
  164. }
  165. out << TABS(level) << "}" << endl;
  166. }
  167. else if ( !anyLower && anyHigher ) {
  168. /* Can go higher than mid but not lower. */
  169. out << TABS(level) << "switch {" << endl;
  170. out << TABS(level) << "case " << GET_WIDE_KEY(state) << " > " <<
  171. WIDE_KEY(state, data[mid].highKey) << ":" << endl;
  172. emitRangeBSearch( state, level+1, mid+1, high );
  173. /* If the lower end is the lowest in the alphabet then there is no
  174. * sense testing it. */
  175. if ( limitLow ) {
  176. out << TABS(level) << "default:" << endl;
  177. TRANS_GOTO(data[mid].value, level+1) << endl;
  178. }
  179. else {
  180. out << TABS(level) << "case " << GET_WIDE_KEY(state) << " >= " <<
  181. WIDE_KEY(state, data[mid].lowKey) << ":" << endl;
  182. TRANS_GOTO(data[mid].value, level+1) << endl;
  183. }
  184. out << TABS(level) << "}" << endl;
  185. }
  186. else {
  187. /* Cannot go higher or lower than mid. It's mid or bust. What
  188. * tests to do depends on limits of alphabet. */
  189. if ( !limitLow && !limitHigh ) {
  190. out << TABS(level) << "if " << WIDE_KEY(state, data[mid].lowKey) << " <= " <<
  191. GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " <<
  192. WIDE_KEY(state, data[mid].highKey) << " {" << endl;
  193. TRANS_GOTO(data[mid].value, level+1) << endl;
  194. out << TABS(level) << "}" << endl;
  195. }
  196. else if ( limitLow && !limitHigh ) {
  197. out << TABS(level) << "if " << GET_WIDE_KEY(state) << " <= " <<
  198. WIDE_KEY(state, data[mid].highKey) << " {" << endl;
  199. TRANS_GOTO(data[mid].value, level+1) << endl;
  200. out << TABS(level) << "}" << endl;
  201. }
  202. else if ( !limitLow && limitHigh ) {
  203. out << TABS(level) << "if " << WIDE_KEY(state, data[mid].lowKey) << " <= " <<
  204. GET_WIDE_KEY(state) << " {" << endl;
  205. TRANS_GOTO(data[mid].value, level+1) << endl;
  206. out << TABS(level) << "}" << endl;
  207. }
  208. else {
  209. /* Both high and low are at the limit. No tests to do. */
  210. TRANS_GOTO(data[mid].value, level) << endl;
  211. }
  212. }
  213. }
  214. void GoGotoCodeGen::STATE_GOTO_ERROR( int level )
  215. {
  216. /* Label the state and bail immediately. */
  217. outLabelUsed = true;
  218. RedStateAp *state = redFsm->errState;
  219. out << TABS(level) << "case " << state->id << ":" << endl;
  220. out << TABS(level + 1) << "goto _out" << endl;
  221. }
  222. void GoGotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level )
  223. {
  224. GenCondSpace *condSpace = stateCond->condSpace;
  225. out << TABS(level) << "_widec = " <<
  226. KEY(condSpace->baseKey) << " + (" << CAST(WIDE_ALPH_TYPE(), GET_KEY()) <<
  227. " - " << KEY(keyOps->minKey) << ")" << endl;
  228. for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
  229. out << TABS(level) << "if ";
  230. CONDITION( out, *csi );
  231. Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
  232. out << " {" << endl;
  233. out << TABS(level + 1) << "_widec += " << condValOffset << endl;
  234. out << TABS(level) << "}" << endl;
  235. }
  236. }
  237. void GoGotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high )
  238. {
  239. /* Get the mid position, staying on the lower end of the range. */
  240. int mid = (low + high) >> 1;
  241. GenStateCond **data = state->stateCondVect.data;
  242. /* Determine if we need to look higher or lower. */
  243. bool anyLower = mid > low;
  244. bool anyHigher = mid < high;
  245. /* Determine if the keys at mid are the limits of the alphabet. */
  246. bool limitLow = data[mid]->lowKey == keyOps->minKey;
  247. bool limitHigh = data[mid]->highKey == keyOps->maxKey;
  248. if ( anyLower && anyHigher ) {
  249. /* Can go lower and higher than mid. */
  250. out << TABS(level) << "switch {" << endl;
  251. out << TABS(level) << "case " << GET_KEY() << " < " <<
  252. KEY(data[mid]->lowKey) << ":" << endl;
  253. emitCondBSearch( state, level+1, low, mid-1 );
  254. out << TABS(level) << "case " << GET_KEY() << " > " <<
  255. KEY(data[mid]->highKey) << ":" << endl;
  256. emitCondBSearch( state, level+1, mid+1, high );
  257. out << TABS(level) << "default:" << endl;
  258. COND_TRANSLATE(data[mid], level+1);
  259. out << TABS(level) << "}" << endl;
  260. }
  261. else if ( anyLower && !anyHigher ) {
  262. /* Can go lower than mid but not higher. */
  263. out << TABS(level) << "switch {" << endl;
  264. out << TABS(level) << "case " << GET_KEY() << " < " <<
  265. KEY(data[mid]->lowKey) << ":" << endl;
  266. emitCondBSearch( state, level+1, low, mid-1 );
  267. /* if the higher is the highest in the alphabet then there is no
  268. * sense testing it. */
  269. if ( limitHigh ) {
  270. out << TABS(level) << "default:" << endl;
  271. COND_TRANSLATE(data[mid], level+1);
  272. }
  273. else {
  274. out << TABS(level) << "case " << GET_KEY() << " <= " <<
  275. KEY(data[mid]->highKey) << ":" << endl;
  276. COND_TRANSLATE(data[mid], level+1);
  277. }
  278. out << TABS(level) << "}" << endl;
  279. }
  280. else if ( !anyLower && anyHigher ) {
  281. /* Can go higher than mid but not lower. */
  282. out << TABS(level) << "switch {" << endl;
  283. out << TABS(level) << "case " << GET_KEY() << " > " <<
  284. KEY(data[mid]->highKey) << ":" << endl;
  285. emitCondBSearch( state, level+1, mid+1, high );
  286. /* If the lower end is the lowest in the alphabet then there is no
  287. * sense testing it. */
  288. if ( limitLow ) {
  289. out << TABS(level) << "default:" << endl;
  290. COND_TRANSLATE(data[mid], level+1);
  291. }
  292. else {
  293. out << TABS(level) << "case " << GET_KEY() << " >= " <<
  294. KEY(data[mid]->lowKey) << ":" << endl;
  295. COND_TRANSLATE(data[mid], level+1);
  296. }
  297. out << TABS(level) << "}" << endl;
  298. }
  299. else {
  300. /* Cannot go higher or lower than mid. It's mid or bust. What
  301. * tests to do depends on limits of alphabet. */
  302. if ( !limitLow && !limitHigh ) {
  303. out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " <<
  304. GET_KEY() << " && " << GET_KEY() << " <= " <<
  305. KEY(data[mid]->highKey) << " {" << endl;
  306. COND_TRANSLATE(data[mid], level+1);
  307. out << TABS(level) << "}" << endl;
  308. }
  309. else if ( limitLow && !limitHigh ) {
  310. out << TABS(level) << "if " << GET_KEY() << " <= " <<
  311. KEY(data[mid]->highKey) << " {" << endl;
  312. COND_TRANSLATE(data[mid], level+1);
  313. out << TABS(level) << "}" << endl;
  314. }
  315. else if ( !limitLow && limitHigh ) {
  316. out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " <<
  317. GET_KEY() << " {" << endl;
  318. COND_TRANSLATE(data[mid], level+1);
  319. out << TABS(level) << "}" << endl;
  320. }
  321. else {
  322. /* Both high and low are at the limit. No tests to do. */
  323. COND_TRANSLATE(data[mid], level);
  324. }
  325. }
  326. }
  327. std::ostream &GoGotoCodeGen::STATE_GOTOS( int level )
  328. {
  329. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  330. if ( st == redFsm->errState )
  331. STATE_GOTO_ERROR(level);
  332. else {
  333. /* Writing code above state gotos. */
  334. GOTO_HEADER( st, level );
  335. if ( st->stateCondVect.length() > 0 ) {
  336. out << TABS(level + 1) << "_widec = " << CAST(WIDE_ALPH_TYPE(), GET_KEY()) << endl;
  337. emitCondBSearch( st, level + 1, 0, st->stateCondVect.length() - 1 );
  338. }
  339. /* Try singles. */
  340. if ( st->outSingle.length() > 0 )
  341. emitSingleSwitch( st, level + 1 );
  342. /* Default case is to binary search for the ranges, if that fails then */
  343. if ( st->outRange.length() > 0 )
  344. emitRangeBSearch( st, level + 1, 0, st->outRange.length() - 1 );
  345. /* Write the default transition. */
  346. TRANS_GOTO( st->defTrans, level + 1 ) << endl;
  347. }
  348. }
  349. return out;
  350. }
  351. std::ostream &GoGotoCodeGen::TRANSITIONS()
  352. {
  353. /* Emit any transitions that have functions and that go to
  354. * this state. */
  355. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
  356. /* Write the label for the transition so it can be jumped to. */
  357. out << " tr" << trans->id << ": ";
  358. /* Destination state. */
  359. if ( trans->action != 0 && trans->action->anyCurStateRef() )
  360. out << "_ps = " << vCS() << ";";
  361. out << vCS() << " = " << trans->targ->id << "; ";
  362. if ( trans->action != 0 ) {
  363. /* Write out the transition func. */
  364. out << "goto f" << trans->action->actListId << endl;
  365. }
  366. else {
  367. /* No code to execute, just loop around. */
  368. out << "goto _again" << endl;
  369. }
  370. }
  371. return out;
  372. }
  373. std::ostream &GoGotoCodeGen::EXEC_FUNCS()
  374. {
  375. /* Make labels that set acts and jump to execFuncs. Loop func indicies. */
  376. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  377. if ( redAct->numTransRefs > 0 ) {
  378. out << " f" << redAct->actListId << ": " <<
  379. "_acts = " << (redAct->location + 1) << ";"
  380. " goto execFuncs" << endl;
  381. }
  382. }
  383. out <<
  384. endl <<
  385. "execFuncs:" << endl <<
  386. " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl <<
  387. " for ; _nacts > 0; _nacts-- {" << endl <<
  388. " _acts++" << endl <<
  389. " switch " << A() << "[_acts - 1]" << " {" << endl;
  390. ACTION_SWITCH(2);
  391. out <<
  392. " }" << endl <<
  393. " }" << endl <<
  394. " goto _again" << endl;
  395. return out;
  396. }
  397. unsigned int GoGotoCodeGen::TO_STATE_ACTION( RedStateAp *state )
  398. {
  399. int act = 0;
  400. if ( state->toStateAction != 0 )
  401. act = state->toStateAction->location+1;
  402. return act;
  403. }
  404. unsigned int GoGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  405. {
  406. int act = 0;
  407. if ( state->fromStateAction != 0 )
  408. act = state->fromStateAction->location+1;
  409. return act;
  410. }
  411. unsigned int GoGotoCodeGen::EOF_ACTION( RedStateAp *state )
  412. {
  413. int act = 0;
  414. if ( state->eofAction != 0 )
  415. act = state->eofAction->location+1;
  416. return act;
  417. }
  418. std::ostream &GoGotoCodeGen::TO_STATE_ACTIONS()
  419. {
  420. /* Take one off for the psuedo start state. */
  421. int numStates = redFsm->stateList.length();
  422. unsigned int *vals = new unsigned int[numStates];
  423. memset( vals, 0, sizeof(unsigned int)*numStates );
  424. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
  425. vals[st->id] = TO_STATE_ACTION(st);
  426. out << " ";
  427. for ( int st = 0; st < redFsm->nextStateId; st++ ) {
  428. /* Write any eof action. */
  429. out << vals[st] << ", ";
  430. if ( st < numStates-1 ) {
  431. if ( (st+1) % IALL == 0 )
  432. out << endl << " ";
  433. }
  434. }
  435. out << endl;
  436. delete[] vals;
  437. return out;
  438. }
  439. std::ostream &GoGotoCodeGen::FROM_STATE_ACTIONS()
  440. {
  441. /* Take one off for the psuedo start state. */
  442. int numStates = redFsm->stateList.length();
  443. unsigned int *vals = new unsigned int[numStates];
  444. memset( vals, 0, sizeof(unsigned int)*numStates );
  445. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
  446. vals[st->id] = FROM_STATE_ACTION(st);
  447. out << " ";
  448. for ( int st = 0; st < redFsm->nextStateId; st++ ) {
  449. /* Write any eof action. */
  450. out << vals[st] << ", ";
  451. if ( st < numStates-1 ) {
  452. if ( (st+1) % IALL == 0 )
  453. out << endl << " ";
  454. }
  455. }
  456. out << endl;
  457. delete[] vals;
  458. return out;
  459. }
  460. std::ostream &GoGotoCodeGen::EOF_ACTIONS()
  461. {
  462. /* Take one off for the psuedo start state. */
  463. int numStates = redFsm->stateList.length();
  464. unsigned int *vals = new unsigned int[numStates];
  465. memset( vals, 0, sizeof(unsigned int)*numStates );
  466. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
  467. vals[st->id] = EOF_ACTION(st);
  468. out << " ";
  469. for ( int st = 0; st < redFsm->nextStateId; st++ ) {
  470. /* Write any eof action. */
  471. out << vals[st] << ", ";
  472. if ( st < numStates-1 ) {
  473. if ( (st+1) % IALL == 0 )
  474. out << endl << " ";
  475. }
  476. }
  477. out << endl;
  478. delete[] vals;
  479. return out;
  480. }
  481. std::ostream &GoGotoCodeGen::FINISH_CASES()
  482. {
  483. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  484. /* States that are final and have an out action need a case. */
  485. if ( st->eofAction != 0 ) {
  486. /* Write the case label. */
  487. out << TABS(2) << "case " << st->id << ":" << endl;
  488. /* Write the goto func. */
  489. out << TABS(3) << "goto f" << st->eofAction->actListId << endl;
  490. }
  491. }
  492. return out;
  493. }
  494. void GoGotoCodeGen::writeData()
  495. {
  496. if ( redFsm->anyActions() ) {
  497. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  498. ACTIONS_ARRAY();
  499. CLOSE_ARRAY() <<
  500. endl;
  501. }
  502. if ( redFsm->anyToStateActions() ) {
  503. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  504. TO_STATE_ACTIONS();
  505. CLOSE_ARRAY() <<
  506. endl;
  507. }
  508. if ( redFsm->anyFromStateActions() ) {
  509. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  510. FROM_STATE_ACTIONS();
  511. CLOSE_ARRAY() <<
  512. endl;
  513. }
  514. if ( redFsm->anyEofActions() ) {
  515. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  516. EOF_ACTIONS();
  517. CLOSE_ARRAY() <<
  518. endl;
  519. }
  520. STATE_IDS();
  521. }
  522. void GoGotoCodeGen::writeExec()
  523. {
  524. testEofUsed = false;
  525. outLabelUsed = false;
  526. out << " {" << endl;
  527. if ( redFsm->anyRegCurStateRef() )
  528. out << " var _ps " << INT() << " = 0" << endl;
  529. if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
  530. || redFsm->anyFromStateActions() )
  531. {
  532. out <<
  533. " var _acts " << INT() << endl <<
  534. " var _nacts " << UINT() << endl;
  535. }
  536. if ( redFsm->anyConditions() )
  537. out << " var _widec " << WIDE_ALPH_TYPE() << endl;
  538. out << endl;
  539. if ( !noEnd ) {
  540. testEofUsed = true;
  541. out <<
  542. " if " << P() << " == " << PE() << " {" << endl <<
  543. " goto _test_eof" << endl <<
  544. " }" << endl;
  545. }
  546. if ( redFsm->errState != 0 ) {
  547. outLabelUsed = true;
  548. out <<
  549. " if " << vCS() << " == " << redFsm->errState->id << " {" << endl <<
  550. " goto _out" << endl <<
  551. " }" << endl;
  552. }
  553. out << "_resume:" << endl;
  554. if ( redFsm->anyFromStateActions() ) {
  555. out <<
  556. " _acts = " << CAST(INT(), FSA() + "[" + vCS() + "]") << endl <<
  557. " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl <<
  558. " for ; _nacts > 0; _nacts-- {" << endl <<
  559. " _acts++" << endl <<
  560. " switch " << A() << "[_acts - 1]" << " {" << endl;
  561. FROM_STATE_ACTION_SWITCH(2);
  562. out <<
  563. " }" << endl <<
  564. " }" << endl <<
  565. endl;
  566. }
  567. out <<
  568. " switch " << vCS() << " {" << endl;
  569. STATE_GOTOS(1);
  570. out <<
  571. " }" << endl <<
  572. endl;
  573. TRANSITIONS() <<
  574. endl;
  575. if ( redFsm->anyRegActions() )
  576. EXEC_FUNCS() << endl;
  577. out << "_again:" << endl;
  578. if ( redFsm->anyToStateActions() ) {
  579. out <<
  580. " _acts = " << CAST(INT(), TSA() + "[" + vCS() + "]") << endl <<
  581. " _nacts = " << CAST(UINT(), A() + "[_acts]") << "; _acts++" << endl <<
  582. " for ; _nacts > 0; _nacts-- {" << endl <<
  583. " _acts++" << endl <<
  584. " switch " << A() << "[_acts - 1]" << " {" << endl;
  585. TO_STATE_ACTION_SWITCH(2);
  586. out <<
  587. " }" << endl <<
  588. " }" << endl <<
  589. endl;
  590. }
  591. if ( redFsm->errState != 0 ) {
  592. outLabelUsed = true;
  593. out <<
  594. " if " << vCS() << " == " << redFsm->errState->id << " {" << endl <<
  595. " goto _out" << endl <<
  596. " }" << endl;
  597. }
  598. if ( !noEnd ) {
  599. out <<
  600. " if " << P() << "++; " << P() << " != " << PE() << " {" << endl <<
  601. " goto _resume" << endl <<
  602. " }" << endl;
  603. }
  604. else {
  605. out <<
  606. " " << P() << "++" << endl <<
  607. " goto _resume" << endl;
  608. }
  609. if ( testEofUsed )
  610. out << " _test_eof: {}" << endl;
  611. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  612. out <<
  613. " if " << P() << " == " << vEOF() << " {" << endl;
  614. if ( redFsm->anyEofTrans() ) {
  615. out <<
  616. " switch " << vCS() << " {" << endl;
  617. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  618. if ( st->eofTrans != 0 )
  619. out <<
  620. " case " << st->id << ":" << endl <<
  621. " goto tr" << st->eofTrans->id << endl;
  622. }
  623. out <<
  624. " }" << endl;
  625. }
  626. if ( redFsm->anyEofActions() ) {
  627. out <<
  628. " __acts := " << CAST(INT(), EA() + "[" + vCS() + "]") << endl <<
  629. " __nacts := " << CAST(UINT(), A() + "[__acts]") << "; __acts++" << endl <<
  630. " for ; __nacts > 0; __nacts-- {" << endl <<
  631. " __acts++" << endl <<
  632. " switch " << A() << "[__acts - 1]" << " {" << endl;
  633. EOF_ACTION_SWITCH(3);
  634. out <<
  635. " }" << endl <<
  636. " }" << endl;
  637. }
  638. out <<
  639. " }" << endl <<
  640. endl;
  641. }
  642. if ( outLabelUsed )
  643. out << " _out: {}" << endl;
  644. out << " }" << endl;
  645. }