cdgoto.cpp 22 KB

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