csgoto.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  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 "csgoto.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 &CSharpGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level )
  29. {
  30. out << TABS(level) << "goto tr" << trans->id << ";";
  31. return out;
  32. }
  33. std::ostream &CSharpGotoCodeGen::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 );
  42. out << "\tbreak;\n";
  43. }
  44. }
  45. genLineDirective( out );
  46. return out;
  47. }
  48. std::ostream &CSharpGotoCodeGen::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 );
  57. out << "\tbreak;\n";
  58. }
  59. }
  60. genLineDirective( out );
  61. return out;
  62. }
  63. std::ostream &CSharpGotoCodeGen::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 );
  72. out << "\tbreak;\n";
  73. }
  74. }
  75. genLineDirective( out );
  76. return out;
  77. }
  78. std::ostream &CSharpGotoCodeGen::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 );
  87. out << "\tbreak;\n";
  88. }
  89. }
  90. genLineDirective( out );
  91. return out;
  92. }
  93. void CSharpGotoCodeGen::GOTO_HEADER( RedStateAp *state )
  94. {
  95. /* Label the state. */
  96. out << "case " << state->id << ":\n";
  97. }
  98. void CSharpGotoCodeGen::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. KEY(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 " << ALPHA_KEY(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 CSharpGotoCodeGen::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. KEY(data[mid].lowKey) << " ) {\n";
  139. emitRangeBSearch( state, level+1, low, mid-1 );
  140. out << TABS(level) << "} else if ( " << GET_WIDE_KEY(state) << " > " <<
  141. KEY(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. KEY(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. KEY(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. KEY(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. KEY(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 ( " << KEY(data[mid].lowKey) << " <= " <<
  185. GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " <<
  186. KEY(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. KEY(data[mid].highKey) << " )\n";
  192. TRANS_GOTO(data[mid].value, level+1) << "\n";
  193. }
  194. else if ( !limitLow && limitHigh ) {
  195. out << TABS(level) << "if ( " << KEY(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 CSharpGotoCodeGen::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 CSharpGotoCodeGen::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 CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 = " << itoa( redAct->location+1 ) << ";"
  368. " goto execFuncs;\n";
  369. }
  370. }
  371. out <<
  372. "\n"
  373. "execFuncs:\n"
  374. " _nacts = " << A() << "[_acts++];\n"
  375. " while ( _nacts-- > 0 ) {\n"
  376. " switch ( " << A() << "[_acts++] ) {\n";
  377. ACTION_SWITCH();
  378. SWITCH_DEFAULT() <<
  379. " }\n"
  380. " }\n"
  381. " goto _again;\n";
  382. return out;
  383. }
  384. unsigned int CSharpGotoCodeGen::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 CSharpGotoCodeGen::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 CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 &CSharpGotoCodeGen::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 CSharpGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
  485. {
  486. ret << "{" << vCS() << " = " << gotoDest << "; " <<
  487. CTRL_FLOW() << "goto _again;}";
  488. }
  489. void CSharpGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  490. {
  491. ret << "{" << vCS() << " = (";
  492. INLINE_LIST( ret, ilItem->children, 0, inFinish );
  493. ret << "); " << CTRL_FLOW() << "goto _again;}";
  494. }
  495. void CSharpGotoCodeGen::CURS( ostream &ret, bool inFinish )
  496. {
  497. ret << "(_ps)";
  498. }
  499. void CSharpGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
  500. {
  501. ret << "(" << vCS() << ")";
  502. }
  503. void CSharpGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
  504. {
  505. ret << vCS() << " = " << nextDest << ";";
  506. }
  507. void CSharpGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  508. {
  509. ret << vCS() << " = (";
  510. INLINE_LIST( ret, ilItem->children, 0, inFinish );
  511. ret << ");";
  512. }
  513. void CSharpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
  514. {
  515. if ( prePushExpr != 0 ) {
  516. ret << "{";
  517. INLINE_LIST( ret, prePushExpr, 0, false );
  518. }
  519. ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " <<
  520. callDest << "; " << CTRL_FLOW() << "goto _again;}";
  521. if ( prePushExpr != 0 )
  522. ret << "}";
  523. }
  524. void CSharpGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
  525. {
  526. if ( prePushExpr != 0 ) {
  527. ret << "{";
  528. INLINE_LIST( ret, prePushExpr, 0, false );
  529. }
  530. ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
  531. INLINE_LIST( ret, ilItem->children, targState, inFinish );
  532. ret << "); " << CTRL_FLOW() << "goto _again;}";
  533. if ( prePushExpr != 0 )
  534. ret << "}";
  535. }
  536. void CSharpGotoCodeGen::RET( ostream &ret, bool inFinish )
  537. {
  538. ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];";
  539. if ( postPopExpr != 0 ) {
  540. ret << "{";
  541. INLINE_LIST( ret, postPopExpr, 0, false );
  542. ret << "}";
  543. }
  544. ret << CTRL_FLOW() << "goto _again;}";
  545. }
  546. void CSharpGotoCodeGen::BREAK( ostream &ret, int targState )
  547. {
  548. outLabelUsed = true;
  549. ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }";
  550. }
  551. void CSharpGotoCodeGen::writeData()
  552. {
  553. if ( redFsm->anyActions() ) {
  554. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  555. ACTIONS_ARRAY();
  556. CLOSE_ARRAY() <<
  557. "\n";
  558. }
  559. if ( redFsm->anyToStateActions() ) {
  560. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  561. TO_STATE_ACTIONS();
  562. CLOSE_ARRAY() <<
  563. "\n";
  564. }
  565. if ( redFsm->anyFromStateActions() ) {
  566. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  567. FROM_STATE_ACTIONS();
  568. CLOSE_ARRAY() <<
  569. "\n";
  570. }
  571. if ( redFsm->anyEofActions() ) {
  572. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  573. EOF_ACTIONS();
  574. CLOSE_ARRAY() <<
  575. "\n";
  576. }
  577. STATE_IDS();
  578. }
  579. void CSharpGotoCodeGen::writeExec()
  580. {
  581. testEofUsed = false;
  582. outLabelUsed = false;
  583. out << " {\n";
  584. if ( redFsm->anyRegCurStateRef() )
  585. out << " int _ps = 0;\n";
  586. if ( redFsm->anyToStateActions() || redFsm->anyRegActions()
  587. || redFsm->anyFromStateActions() )
  588. {
  589. out <<
  590. " " << ARRAY_TYPE(redFsm->maxActionLoc) << " _acts;\n"
  591. " " << ARRAY_TYPE(redFsm->maxActArrItem) << " _nacts;\n";
  592. }
  593. if ( redFsm->anyConditions() )
  594. out << " " << WIDE_ALPH_TYPE() << " _widec;\n";
  595. out << "\n";
  596. if ( !noEnd ) {
  597. testEofUsed = true;
  598. out <<
  599. " if ( " << P() << " == " << PE() << " )\n"
  600. " goto _test_eof;\n";
  601. }
  602. if ( redFsm->errState != 0 ) {
  603. outLabelUsed = true;
  604. out <<
  605. " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
  606. " goto _out;\n";
  607. }
  608. out << "_resume:\n";
  609. if ( redFsm->anyFromStateActions() ) {
  610. out <<
  611. " _acts = " << FSA() << "[" << vCS() << "];\n"
  612. " _nacts = " << A() << "[_acts++];\n"
  613. " while ( _nacts-- > 0 ) {\n"
  614. " switch ( " << A() << "[_acts++] ) {\n";
  615. FROM_STATE_ACTION_SWITCH();
  616. SWITCH_DEFAULT() <<
  617. " }\n"
  618. " }\n"
  619. "\n";
  620. }
  621. out <<
  622. " switch ( " << vCS() << " ) {\n";
  623. STATE_GOTOS();
  624. SWITCH_DEFAULT() <<
  625. " }\n"
  626. "\n";
  627. TRANSITIONS() <<
  628. "\n";
  629. if ( redFsm->anyRegActions() )
  630. EXEC_FUNCS() << "\n";
  631. out << "_again:\n";
  632. if ( redFsm->anyToStateActions() ) {
  633. out <<
  634. " _acts = " << TSA() << "[" << vCS() << "];\n"
  635. " _nacts = " << A() << "[_acts++];\n"
  636. " while ( _nacts-- > 0 ) {\n"
  637. " switch ( " << A() << "[_acts++] ) {\n";
  638. TO_STATE_ACTION_SWITCH();
  639. SWITCH_DEFAULT() <<
  640. " }\n"
  641. " }\n"
  642. "\n";
  643. }
  644. if ( redFsm->errState != 0 ) {
  645. outLabelUsed = true;
  646. out <<
  647. " if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
  648. " goto _out;\n";
  649. }
  650. if ( !noEnd ) {
  651. out <<
  652. " if ( ++" << P() << " != " << PE() << " )\n"
  653. " goto _resume;\n";
  654. }
  655. else {
  656. out <<
  657. " " << P() << " += 1;\n"
  658. " goto _resume;\n";
  659. }
  660. if ( testEofUsed )
  661. out << " _test_eof: {}\n";
  662. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  663. out <<
  664. " if ( " << P() << " == " << vEOF() << " )\n"
  665. " {\n";
  666. if ( redFsm->anyEofTrans() ) {
  667. out <<
  668. " switch ( " << vCS() << " ) {\n";
  669. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  670. if ( st->eofTrans != 0 )
  671. out << " case " << st->id << ": goto tr" << st->eofTrans->id << ";\n";
  672. }
  673. SWITCH_DEFAULT() <<
  674. " }\n";
  675. }
  676. if ( redFsm->anyEofActions() ) {
  677. out <<
  678. " " << ARRAY_TYPE(redFsm->maxActionLoc) << " __acts = " <<
  679. EA() << "[" << vCS() << "];\n"
  680. " " << ARRAY_TYPE(redFsm->maxActArrItem) << " __nacts = " <<
  681. A() << "[__acts++];\n"
  682. " while ( __nacts-- > 0 ) {\n"
  683. " switch ( " << A() << "[__acts++] ) {\n";
  684. EOF_ACTION_SWITCH();
  685. SWITCH_DEFAULT() <<
  686. " }\n"
  687. " }\n";
  688. }
  689. out <<
  690. " }\n"
  691. "\n";
  692. }
  693. if ( outLabelUsed )
  694. out << " _out: {}\n";
  695. out << " }\n";
  696. }