Minimal changes to get it to compile (a few taken from David Given ack-6.0pre5)
[Ack-5.5.git] / util / ceg / EM_parser / common / pars.g
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
32 #include <stdio.h>
33 #include <system.h>
34 #include "decl.h"
35 #include "em.h"
36
37 extern char yytext[];
38 extern int yylineno;
39 extern int first_action, last_action, token;
40
41 t_token tok, stok;
42 int no_conversions = FALSE, library, segment = UNKNOWN;
43 File *outfile;
44 char *to_change;
45
46 }
47
48 %token  C_INSTR, DEF_C_INSTR, CONDITION, ARROW,
49         CALL, ASSEM_INSTR, DEFAULT, ERROR;
50 %start  table, table;
51 %start  def_row, def_row;
52 %start  c_table, c_table;
53 %lexical        lex_analyzer ;
54
55
56 table   : row*
57         ;
58
59 row     : C_INSTR               { set_outfile( yytext); header( yytext);
60                                   set_segment(segment);
61                                 }
62           [ special | simple]   { out( "}\n\n");}
63
64         | DEF_C_INSTR           { init_defaults( yytext);}
65           [ Dspecial | Dsimple] { handle_defaults();}
66         ;
67
68 special : 
69                                 { out( "if( 0 ) ;\n"); }
70
71           [ CONDITION           { out( "else "); question( &yytext[0]);}
72             simple              { out( "}\n");}
73           ]*
74
75           DEFAULT               { out( "else {\n");}
76           simple                { out( "}\n");}
77         ;
78
79 simple  : ARROW                 { save_output();}
80           actionlist            { back_patch();}
81         ;
82
83
84 actionlist :                    { first_action = TRUE;}
85         [ action                { first_action = FALSE;}
86           [ ';' action]*
87         ]?
88         '.'
89         ;
90
91 action  : CALL                  { print_call( &yytext[0]);}
92
93         | as_block              { last_action = ( token == '.');
94                                   do_block_assemble();}
95
96         ;
97
98 as_block :                      { init_as_block();}
99         ASSEM_INSTR             { save_as( &yytext[0]);}
100         more_as
101         ;
102
103 more_as :
104           %if ( next_token() == ASSEM_INSTR)
105           ';' 
106           ASSEM_INSTR           { save_as( &yytext[0]);}
107           more_as
108         |
109         ;
110
111
112 /* Grammar rules for a default-instruction, just copy to a temporary file. */
113
114 Dspecial: CONDITION             { out( " %s ", yytext);}
115           Dsimple               
116
117           [ CONDITION           { out( " %s ", yytext);}
118             Dsimple             
119           ]*
120
121           DEFAULT               { out( " %s ", yytext);}
122           Dsimple               
123         ;
124
125 Dsimple : ARROW                 { out( "%s", yytext);}
126           Dactionlist
127
128         ;
129
130 Dactionlist : 
131           [ Daction
132             [ ';'               { out( ";\n");}
133               Daction
134             ]*
135           ]?
136           '.'                   { out( ".\n");}
137         ;
138
139 Daction : CALL                  { out( "%s", yytext);}
140
141         | ASSEM_INSTR           { out( "\"%s\"", yytext);}
142
143         ;
144
145 def_row :                       { set_segment(segment);}
146         [ special | simple]     { out( "}\n\n");}
147         ;
148
149
150
151 /* This is a grammar to handle the -c flag ( only one entry has changed).
152  * Skip all entries in the table until the one that has changed, then
153  * use the grammar rules for the normal case above.
154  */
155
156 c_table : c_row*
157         ;
158
159 c_row   : %if ( to_change && strcmp( yytext, to_change) == 0)
160           C_INSTR               { set_outfile( yytext); header( yytext);
161                                   set_segment(segment);
162                                 }
163           [ special | simple]   { out( "}\n\n"); to_change = 0; }
164
165         | C_INSTR
166           [ c_special | c_simple]
167
168         | %if ( to_change && strcmp( yytext, to_change) == 0)
169           DEF_C_INSTR           { init_defaults( yytext);}
170           [ Dspecial | Dsimple] { handle_defaults(); to_change = 0; }
171
172         | DEF_C_INSTR
173           [ c_special | c_simple]
174         ;
175
176 c_special : CONDITION
177           c_simple
178
179           [ CONDITION
180             c_simple
181           ]*
182
183           DEFAULT
184           c_simple
185         ;
186
187 c_simple: ARROW
188           c_actionlist
189
190         ;
191
192 c_actionlist : 
193           [ c_action [ ';' c_action]* ]? '.' 
194         ;
195
196 c_action: CALL
197         | ASSEM_INSTR
198         ;
199
200
201
202
203
204 {
205
206 int saved = 0, token;
207 int nerrors = 0;
208
209
210 LLmessage( inserted_token)
211 int inserted_token;
212 {
213         nerrors++;
214         if ( inserted_token == 0) {
215                 fprint( STDERR, "EM_table : syntax error in line %d, >>",
216                         yylineno);
217                 print_token( LLsymb);
218                 fprint( STDERR, "<<  will be deleted!!\n");
219         }
220         else if ( inserted_token < 0) {
221                 fprint(STDERR,"EM_table : syntax error in line %d, garbage at end of table\n",
222                          yylineno);
223         }
224         else {
225                 fprint( STDERR, "EM_table : syntax error in line %d, >>",
226                         yylineno);
227                 print_token( inserted_token);
228                 fprint( STDERR, "<<  will be inserted!!\n");
229                 token = LLsymb;
230                 saved = 1;
231         }
232 }
233
234 print_token( token)
235 int token;
236 {
237         switch ( token) {
238           case C_INSTR  : fprint( STDERR,  "C_INSTR  %s", yytext);
239                           break;
240           case ASSEM_INSTR : fprint( STDERR,  "STRING  %s", yytext);
241                           break;
242           case CALL     : fprint( STDERR,  "CALL  %s", yytext);
243                           break;
244           case ARROW    : fprint( STDERR,  "==> ");
245                           break;
246           case CONDITION: fprint( STDERR,  "CONDITION  %s", yytext);
247                           break;
248           case DEFAULT  : fprint( STDERR,  "default ");
249                           break;
250           case ERROR    : fprint( STDERR,  "unmatched  %s", yytext);
251                           break;
252           default       : fprint( STDERR, " %c", token);
253                           break;
254         }
255 }
256
257
258 /* The lexical analyzer.
259  *      It uses mylex() to get the tokens.
260  *      It supports the buffering of one token.
261  *      If the curent token is a C_INSTR it will set the global variable
262  *      'C_instr_info' to point to the correct information ( arguments, header,
263  *      etc.).
264  */
265
266 int lex_analyzer()
267 {
268         extern char *next;
269
270         if ( saved) {
271                 saved = 0;
272         }
273         else {
274                 token = mylex();
275                 *next = '\0';
276         }
277         if ( token == C_INSTR)
278                 set_C_instr_info( yytext);
279         return( token);
280 }
281
282 int next_token()
283 {
284         extern char *next;
285
286         if ( !saved) {
287                 token = mylex();
288                 *next = '\0';
289                 saved = 1;
290         }
291         return( token);
292 }
293
294
295 /******************************************************************************/
296
297 /* Handle arguments :
298  *      -l              : Library, generate one function per file.
299  *      -c <name>       : Change, only update the <name> file.
300  */
301
302 main( argc, argv)
303 int argc;
304 char **argv;
305 {
306         extern FILE *infile;
307         infile = stdin;
308
309         outfile = STDOUT;
310         if ( argc > 1) {
311                 if ( strcmp( argv[1], "-l") == 0)
312                         library = TRUE;
313                 else if( strcmp( argv[1], "-c") == 0) {
314                         library = TRUE;
315                         to_change = argv[2];
316                         c_table();
317                         if (to_change) {
318                                 fprint( STDERR, "No rule for %s\n", to_change);
319                                 exit( 1);
320                         }
321                         exit(nerrors);
322                 }
323         }
324         else {
325                 library = FALSE;
326                 file_header();
327         }
328         
329         table();
330         exit(nerrors);
331 }
332
333 }