pars.g 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* This file contains the parser for the 'EM_table'.
  2. * Every row in the table is converted to a C-function.
  3. * The parser is a fairly simple program, for each row it prints a function-
  4. * header and the following actions are printed as C-statements. A CALL is just
  5. * copied, and an ASSEM_INSTR will be handed to the routine assemble().
  6. * Assemble() will turn the assembly-string into a sequence of C-function calls.
  7. * How this should be done is expressed in the 'as_table'.
  8. *
  9. * There are however some complicating factors:
  10. * - A row in the 'EM_table' may contain CONDITION's.
  11. * The parser supports this by outptutting some "if" and "else"'s.
  12. *
  13. * - The user is allowed to use some abbreviation in the 'EM_table', (s)he
  14. * can use the DEF_C_INSTR's ( e.g. C_loe..).
  15. * One such DEF_C_INSTR must be expanded in 3 or more C-functions.
  16. * The solution is to copy the DEF_C_INSTR to a temporary file. Then
  17. * this file will be processed as many times as needed to generate all
  18. * the C-functions.
  19. *
  20. * - The assembler-instructions must be processed in blocks not one at a
  21. * time, so buffering is needed.
  22. *
  23. * - When generating object-code, the user can make use of the dist()
  24. * function. This function should return the number of bytes between
  25. * the current instruction and a labelled one, both forward and backward
  26. * references must be handled.
  27. * This requires the saving of the generated function, and
  28. * backpatching in a second phase.
  29. */
  30. {
  31. #include <system.h>
  32. #include "decl.h"
  33. #include "em.h"
  34. extern char yytext[];
  35. extern int yylineno;
  36. extern int first_action, last_action, token;
  37. t_token tok, stok;
  38. int no_conversions = FALSE, library, segment = UNKNOWN;
  39. File *outfile;
  40. char *to_change;
  41. }
  42. %token C_INSTR, DEF_C_INSTR, CONDITION, ARROW,
  43. CALL, ASSEM_INSTR, DEFAULT, ERROR;
  44. %start table, table;
  45. %start def_row, def_row;
  46. %start c_table, c_table;
  47. %lexical lex_analyzer ;
  48. table : row*
  49. ;
  50. row : C_INSTR { set_outfile( yytext); header( yytext);
  51. set_segment(segment);
  52. }
  53. [ special | simple] { out( "}\n\n");}
  54. | DEF_C_INSTR { init_defaults( yytext);}
  55. [ Dspecial | Dsimple] { handle_defaults();}
  56. ;
  57. special :
  58. { out( "if( 0 ) ;\n"); }
  59. [ CONDITION { out( "else "); question( &yytext[0]);}
  60. simple { out( "}\n");}
  61. ]*
  62. DEFAULT { out( "else {\n");}
  63. simple { out( "}\n");}
  64. ;
  65. simple : ARROW { save_output();}
  66. actionlist { back_patch();}
  67. ;
  68. actionlist : { first_action = TRUE;}
  69. [ action { first_action = FALSE;}
  70. [ ';' action]*
  71. ]?
  72. '.'
  73. ;
  74. action : CALL { print_call( &yytext[0]);}
  75. | as_block { last_action = ( token == '.');
  76. do_block_assemble();}
  77. ;
  78. as_block : { init_as_block();}
  79. ASSEM_INSTR { save_as( &yytext[0]);}
  80. more_as
  81. ;
  82. more_as :
  83. %if ( next_token() == ASSEM_INSTR)
  84. ';'
  85. ASSEM_INSTR { save_as( &yytext[0]);}
  86. more_as
  87. |
  88. ;
  89. /* Grammar rules for a default-instruction, just copy to a temporary file. */
  90. Dspecial: CONDITION { out( " %s ", yytext);}
  91. Dsimple
  92. [ CONDITION { out( " %s ", yytext);}
  93. Dsimple
  94. ]*
  95. DEFAULT { out( " %s ", yytext);}
  96. Dsimple
  97. ;
  98. Dsimple : ARROW { out( "%s", yytext);}
  99. Dactionlist
  100. ;
  101. Dactionlist :
  102. [ Daction
  103. [ ';' { out( ";\n");}
  104. Daction
  105. ]*
  106. ]?
  107. '.' { out( ".\n");}
  108. ;
  109. Daction : CALL { out( "%s", yytext);}
  110. | ASSEM_INSTR { out( "\"%s\"", yytext);}
  111. ;
  112. def_row : { set_segment(segment);}
  113. [ special | simple] { out( "}\n\n");}
  114. ;
  115. /* This is a grammar to handle the -c flag ( only one entry has changed).
  116. * Skip all entries in the table until the one that has changed, then
  117. * use the grammar rules for the normal case above.
  118. */
  119. c_table : c_row*
  120. ;
  121. c_row : %if ( to_change && strcmp( yytext, to_change) == 0)
  122. C_INSTR { set_outfile( yytext); header( yytext);
  123. set_segment(segment);
  124. }
  125. [ special | simple] { out( "}\n\n"); to_change = 0; }
  126. | C_INSTR
  127. [ c_special | c_simple]
  128. | %if ( to_change && strcmp( yytext, to_change) == 0)
  129. DEF_C_INSTR { init_defaults( yytext);}
  130. [ Dspecial | Dsimple] { handle_defaults(); to_change = 0; }
  131. | DEF_C_INSTR
  132. [ c_special | c_simple]
  133. ;
  134. c_special : CONDITION
  135. c_simple
  136. [ CONDITION
  137. c_simple
  138. ]*
  139. DEFAULT
  140. c_simple
  141. ;
  142. c_simple: ARROW
  143. c_actionlist
  144. ;
  145. c_actionlist :
  146. [ c_action [ ';' c_action]* ]? '.'
  147. ;
  148. c_action: CALL
  149. | ASSEM_INSTR
  150. ;
  151. {
  152. int saved = 0, token;
  153. int nerrors = 0;
  154. LLmessage( inserted_token)
  155. int inserted_token;
  156. {
  157. nerrors++;
  158. if ( inserted_token == 0) {
  159. fprint( STDERR, "EM_table : syntax error in line %d, >>",
  160. yylineno);
  161. print_token( LLsymb);
  162. fprint( STDERR, "<< will be deleted!!\n");
  163. }
  164. else if ( inserted_token < 0) {
  165. fprint(STDERR,"EM_table : syntax error in line %d, garbage at end of table\n",
  166. yylineno);
  167. }
  168. else {
  169. fprint( STDERR, "EM_table : syntax error in line %d, >>",
  170. yylineno);
  171. print_token( inserted_token);
  172. fprint( STDERR, "<< will be inserted!!\n");
  173. token = LLsymb;
  174. saved = 1;
  175. }
  176. }
  177. print_token( token)
  178. int token;
  179. {
  180. switch ( token) {
  181. case C_INSTR : fprint( STDERR, "C_INSTR %s", yytext);
  182. break;
  183. case ASSEM_INSTR : fprint( STDERR, "STRING %s", yytext);
  184. break;
  185. case CALL : fprint( STDERR, "CALL %s", yytext);
  186. break;
  187. case ARROW : fprint( STDERR, "==> ");
  188. break;
  189. case CONDITION: fprint( STDERR, "CONDITION %s", yytext);
  190. break;
  191. case DEFAULT : fprint( STDERR, "default ");
  192. break;
  193. case ERROR : fprint( STDERR, "unmatched %s", yytext);
  194. break;
  195. default : fprint( STDERR, " %c", token);
  196. break;
  197. }
  198. }
  199. /* The lexical analyzer.
  200. * It uses mylex() to get the tokens.
  201. * It supports the buffering of one token.
  202. * If the curent token is a C_INSTR it will set the global variable
  203. * 'C_instr_info' to point to the correct information ( arguments, header,
  204. * etc.).
  205. */
  206. int lex_analyzer()
  207. {
  208. extern char *next;
  209. if ( saved) {
  210. saved = 0;
  211. }
  212. else {
  213. token = mylex();
  214. *next = '\0';
  215. }
  216. if ( token == C_INSTR)
  217. set_C_instr_info( yytext);
  218. return( token);
  219. }
  220. int next_token()
  221. {
  222. extern char *next;
  223. if ( !saved) {
  224. token = mylex();
  225. *next = '\0';
  226. saved = 1;
  227. }
  228. return( token);
  229. }
  230. /******************************************************************************/
  231. /* Handle arguments :
  232. * -l : Library, generate one function per file.
  233. * -c <name> : Change, only update the <name> file.
  234. */
  235. main( argc, argv)
  236. int argc;
  237. char **argv;
  238. {
  239. outfile = STDOUT;
  240. if ( argc > 1) {
  241. if ( strcmp( argv[1], "-l") == 0)
  242. library = TRUE;
  243. else if( strcmp( argv[1], "-c") == 0) {
  244. library = TRUE;
  245. to_change = argv[2];
  246. c_table();
  247. if (to_change) {
  248. fprint( STDERR, "No rule for %s\n", to_change);
  249. exit( 1);
  250. }
  251. exit(nerrors);
  252. }
  253. }
  254. else {
  255. library = FALSE;
  256. file_header();
  257. }
  258. table();
  259. exit(nerrors);
  260. }
  261. }