gofgoto.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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 "gofgoto.h"
  24. #include "redfsm.h"
  25. #include "gendata.h"
  26. #include "bstmap.h"
  27. using std::endl;
  28. std::ostream &GoFGotoCodeGen::EXEC_ACTIONS()
  29. {
  30. /* Loop the actions. */
  31. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  32. if ( redAct->numTransRefs > 0 ) {
  33. /* We are at the start of a glob, write the case. */
  34. out << "f" << redAct->actListId << ":" << endl;
  35. /* Write each action in the list of action items. */
  36. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  37. ACTION( out, item->value, 0, false, false );
  38. out << TABS(1) << "goto _again" << endl;
  39. }
  40. }
  41. return out;
  42. }
  43. /* Write out the function switch. This switch is keyed on the values
  44. * of the func index. */
  45. std::ostream &GoFGotoCodeGen::TO_STATE_ACTION_SWITCH( int level )
  46. {
  47. /* Loop the actions. */
  48. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  49. if ( redAct->numToStateRefs > 0 ) {
  50. /* Write the entry label. */
  51. out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl;
  52. /* Write each action in the list of action items. */
  53. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  54. ACTION( out, item->value, 0, false, false );
  55. }
  56. }
  57. genLineDirective( out );
  58. return out;
  59. }
  60. /* Write out the function switch. This switch is keyed on the values
  61. * of the func index. */
  62. std::ostream &GoFGotoCodeGen::FROM_STATE_ACTION_SWITCH( int level )
  63. {
  64. /* Loop the actions. */
  65. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  66. if ( redAct->numFromStateRefs > 0 ) {
  67. /* Write the entry label. */
  68. out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl;
  69. /* Write each action in the list of action items. */
  70. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  71. ACTION( out, item->value, 0, false, false );
  72. }
  73. }
  74. genLineDirective( out );
  75. return out;
  76. }
  77. std::ostream &GoFGotoCodeGen::EOF_ACTION_SWITCH( int level )
  78. {
  79. /* Loop the actions. */
  80. for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  81. if ( redAct->numEofRefs > 0 ) {
  82. /* Write the entry label. */
  83. out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl;
  84. /* Write each action in the list of action items. */
  85. for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ )
  86. ACTION( out, item->value, 0, true, false );
  87. }
  88. }
  89. genLineDirective( out );
  90. return out;
  91. }
  92. std::ostream &GoFGotoCodeGen::FINISH_CASES()
  93. {
  94. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  95. /* States that are final and have an out action need a case. */
  96. if ( st->eofAction != 0 ) {
  97. /* Write the case label. */
  98. out << TABS(2) << "case " << st->id << ":" << endl;
  99. /* Jump to the func. */
  100. out << TABS(3) << "goto f" << st->eofAction->actListId << endl;
  101. }
  102. }
  103. return out;
  104. }
  105. unsigned int GoFGotoCodeGen::TO_STATE_ACTION( RedStateAp *state )
  106. {
  107. int act = 0;
  108. if ( state->toStateAction != 0 )
  109. act = state->toStateAction->actListId+1;
  110. return act;
  111. }
  112. unsigned int GoFGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  113. {
  114. int act = 0;
  115. if ( state->fromStateAction != 0 )
  116. act = state->fromStateAction->actListId+1;
  117. return act;
  118. }
  119. unsigned int GoFGotoCodeGen::EOF_ACTION( RedStateAp *state )
  120. {
  121. int act = 0;
  122. if ( state->eofAction != 0 )
  123. act = state->eofAction->actListId+1;
  124. return act;
  125. }
  126. void GoFGotoCodeGen::writeData()
  127. {
  128. if ( redFsm->anyToStateActions() ) {
  129. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  130. TO_STATE_ACTIONS();
  131. CLOSE_ARRAY() <<
  132. endl;
  133. }
  134. if ( redFsm->anyFromStateActions() ) {
  135. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  136. FROM_STATE_ACTIONS();
  137. CLOSE_ARRAY() <<
  138. endl;
  139. }
  140. if ( redFsm->anyEofActions() ) {
  141. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  142. EOF_ACTIONS();
  143. CLOSE_ARRAY() <<
  144. endl;
  145. }
  146. STATE_IDS();
  147. }
  148. void GoFGotoCodeGen::writeExec()
  149. {
  150. testEofUsed = false;
  151. outLabelUsed = false;
  152. out << " {" << endl;
  153. if ( redFsm->anyRegCurStateRef() )
  154. out << " var _ps " << INT() << " = 0" << endl;
  155. if ( redFsm->anyConditions() )
  156. out << " var _widec " << WIDE_ALPH_TYPE() << endl;
  157. if ( !noEnd ) {
  158. testEofUsed = true;
  159. out <<
  160. " if " << P() << " == " << PE() << " {" << endl <<
  161. " goto _test_eof" << endl <<
  162. " }" << endl;
  163. }
  164. if ( redFsm->errState != 0 ) {
  165. outLabelUsed = true;
  166. out <<
  167. " if " << vCS() << " == " << redFsm->errState->id << " {" << endl <<
  168. " goto _out" << endl <<
  169. " }" << endl;
  170. }
  171. out << "_resume:" << endl;
  172. if ( redFsm->anyFromStateActions() ) {
  173. out <<
  174. " switch " << FSA() << "[" << vCS() << "] {" << endl;
  175. FROM_STATE_ACTION_SWITCH(1);
  176. out <<
  177. " }" << endl <<
  178. endl;
  179. }
  180. out <<
  181. " switch " << vCS() << " {" << endl;
  182. STATE_GOTOS(1);
  183. out <<
  184. " }" << endl <<
  185. endl;
  186. TRANSITIONS() <<
  187. endl;
  188. if ( redFsm->anyRegActions() )
  189. EXEC_ACTIONS() << endl;
  190. out << "_again:" << endl;
  191. if ( redFsm->anyToStateActions() ) {
  192. out <<
  193. " switch " << TSA() << "[" << vCS() << "] {" << endl;
  194. TO_STATE_ACTION_SWITCH(1);
  195. out <<
  196. " }" << endl <<
  197. endl;
  198. }
  199. if ( redFsm->errState != 0 ) {
  200. outLabelUsed = true;
  201. out <<
  202. " if " << vCS() << " == " << redFsm->errState->id << " {" << endl <<
  203. " goto _out" << endl <<
  204. " }" << endl;
  205. }
  206. if ( !noEnd ) {
  207. out <<
  208. " if " << P() << "++; " << P() << " != " << PE() << " {" << endl <<
  209. " goto _resume" << endl <<
  210. " }" << endl;
  211. }
  212. else {
  213. out <<
  214. " " << P() << "++" << endl <<
  215. " goto _resume" << endl;
  216. }
  217. if ( testEofUsed )
  218. out << " _test_eof: {}" << endl;
  219. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  220. out <<
  221. " if " << P() << " == " << vEOF() << " {" << endl;
  222. if ( redFsm->anyEofTrans() ) {
  223. out <<
  224. " switch " << vCS() << " {" << endl;
  225. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  226. if ( st->eofTrans != 0 )
  227. out <<
  228. " case " << st->id << ":" << endl <<
  229. " goto tr" << st->eofTrans->id << endl;
  230. }
  231. out <<
  232. " }" << endl;
  233. }
  234. if ( redFsm->anyEofActions() ) {
  235. out <<
  236. " switch " << EA() << "[" << vCS() << "] {" << endl;
  237. EOF_ACTION_SWITCH(2);
  238. out <<
  239. " }" << endl;
  240. }
  241. out <<
  242. " }" << endl <<
  243. endl;
  244. }
  245. if ( outLabelUsed )
  246. out << " _out: {}" << endl;
  247. out << " }" << endl;
  248. }