]>
Commit | Line | Data |
---|---|---|
6cfea11b TJ |
1 | %{ /* -*- c -*- emacs mode c */ |
2 | /* | |
3 | ||
4 | TREELANG Compiler parser. | |
5 | ||
6 | --------------------------------------------------------------------- | |
7 | ||
8 | Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. | |
9 | ||
10 | This program is free software; you can redistribute it and/or modify it | |
11 | under the terms of the GNU General Public License as published by the | |
12 | Free Software Foundation; either version 2, or (at your option) any | |
13 | later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with this program; if not, write to the Free Software | |
22 | Foundation, 59 Temple Place - Suite 330, | |
23 | Boston, MA 02111-1307, USA. | |
24 | ||
25 | In other words, you are welcome to use, share and improve this program. | |
26 | You are forbidden to forbid anyone else to use, share and improve | |
27 | what you give them. Help stamp out software-hoarding! | |
28 | ||
29 | --------------------------------------------------------------------- | |
30 | ||
31 | Written by Tim Josling 1999-2001, based in part on other parts of | |
32 | the GCC compiler. | |
33 | ||
34 | */ | |
35 | ||
36 | /* | |
37 | ||
38 | Grammar Conflicts | |
39 | ***************** | |
40 | ||
41 | There are no conflicts in this grammar. Please keep it that way. | |
42 | ||
43 | */ | |
44 | ||
6cfea11b TJ |
45 | #include "config.h" |
46 | #include "system.h" | |
4977bab6 ZW |
47 | #include "coretypes.h" |
48 | #include "tm.h" | |
6cfea11b TJ |
49 | #include "diagnostic.h" |
50 | ||
51 | #include "treelang.h" | |
52 | #include "treetree.h" | |
53 | ||
54 | #define YYDEBUG 1 | |
55 | #define YYPRINT(file, type, value) print_token (file, type, value) | |
56 | #define YYERROR_VERBOSE YES | |
57 | ||
58 | ||
59 | extern int option_parser_trace; | |
60 | ||
61 | /* Local prototypes. */ | |
62 | ||
63 | static void yyerror (const char *error_message); | |
64 | int yylex (void); | |
65 | int yyparse (void); | |
66 | void print_token (FILE * file, unsigned int type ATTRIBUTE_UNUSED, YYSTYPE value); | |
96e3ac4f TJ |
67 | static struct prod_token_parm_item *reverse_prod_list (struct prod_token_parm_item *old_first); |
68 | static void ensure_not_void (unsigned int type, struct prod_token_parm_item* name); | |
69 | static int check_type_match (int type_num, struct prod_token_parm_item *exp); | |
70 | static int get_common_type (struct prod_token_parm_item *type1, struct prod_token_parm_item *type2); | |
71 | static struct prod_token_parm_item *make_integer_constant (struct prod_token_parm_item* value); | |
72 | static void set_storage (struct prod_token_parm_item *prod); | |
6cfea11b TJ |
73 | |
74 | /* File global variables. */ | |
75 | ||
96e3ac4f | 76 | static struct prod_token_parm_item *current_function=NULL; |
6cfea11b TJ |
77 | |
78 | %} | |
79 | ||
80 | /* Not %raw - seems to have bugs. */ | |
81 | %token_table | |
82 | ||
83 | /* Punctuation. */ | |
84 | %token RIGHT_BRACE | |
85 | %token LEFT_BRACE | |
86 | %token RIGHT_SQUARE_BRACKET | |
87 | %token LEFT_SQUARE_BRACKET | |
88 | %token RIGHT_PARENTHESIS | |
89 | %token LEFT_PARENTHESIS | |
90 | %token SEMICOLON | |
91 | %token ASTERISK | |
92 | %token COMMA | |
93 | %right EQUALS | |
94 | %right ASSIGN | |
95 | %left PLUS | |
96 | %left MINUS | |
97 | ||
98 | /* Literals. */ | |
99 | %token INTEGER | |
100 | ||
101 | /* Keywords. */ | |
102 | %token IF | |
103 | %token ELSE | |
104 | %token RETURN | |
105 | %token CHAR | |
106 | %token INT | |
107 | %token UNSIGNED | |
108 | %token VOID | |
109 | %token TYPEDEF | |
110 | %token NAME | |
111 | %token STATIC | |
112 | %token AUTOMATIC | |
113 | %token EXTERNAL_DEFINITION | |
114 | %token EXTERNAL_REFERENCE | |
115 | ||
116 | /* Tokens not passed to parser. */ | |
117 | %token WHITESPACE | |
118 | %token COMMENT | |
119 | ||
120 | /* Pseudo tokens - productions. */ | |
121 | %token PROD_VARIABLE_NAME | |
122 | %token PROD_TYPE_NAME | |
123 | %token PROD_FUNCTION_NAME | |
124 | %token PROD_INTEGER_CONSTANT | |
125 | %token PROD_PLUS_EXPRESSION | |
126 | %token PROD_MINUS_EXPRESSION | |
127 | %token PROD_ASSIGN_EXPRESSION | |
128 | %token PROD_VARIABLE_REFERENCE_EXPRESSION | |
129 | %token PROD_PARAMETER | |
130 | %token PROD_FUNCTION_INVOCATION | |
131 | %expect 0 | |
132 | %% | |
133 | ||
134 | file: | |
135 | /* Nil. */ { | |
136 | /* Nothing to do. */ | |
137 | } | |
138 | |declarations { | |
139 | /* Nothing to do. */ | |
140 | } | |
141 | ; | |
142 | ||
143 | ||
144 | declarations: | |
145 | declaration { | |
146 | /* Nothing to do. */ | |
147 | } | |
148 | | declarations declaration { | |
149 | /* Nothing to do. */ | |
150 | } | |
151 | ; | |
152 | ||
153 | declaration: | |
154 | variable_def { | |
155 | /* Nothing to do. */ | |
156 | } | |
157 | |function_prototype { | |
158 | /* Nothing to do. */ | |
159 | } | |
160 | |function { | |
161 | /* Nothing to do. */ | |
162 | } | |
163 | ; | |
164 | ||
165 | variable_def: | |
166 | storage typename NAME init_opt SEMICOLON { | |
96e3ac4f TJ |
167 | struct prod_token_parm_item* tok; |
168 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
169 | tok = $3; |
170 | prod = make_production (PROD_VARIABLE_NAME, tok); | |
171 | SYMBOL_TABLE_NAME (prod) = tok; | |
172 | EXPRESSION_TYPE (prod) = $2; | |
173 | VAR_INIT (prod) = $4; | |
96e3ac4f | 174 | NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (prod))); |
6cfea11b TJ |
175 | ensure_not_void (NUMERIC_TYPE (prod), tok); |
176 | if (insert_tree_name (prod)) | |
177 | { | |
178 | YYERROR; | |
179 | } | |
180 | STORAGE_CLASS_TOKEN (prod) = $1; | |
181 | set_storage (prod); | |
182 | ||
183 | if (VAR_INIT (prod)) | |
184 | { | |
96e3ac4f | 185 | if (! ((struct prod_token_parm_item*)VAR_INIT (prod))->tp.pro.code) |
6cfea11b TJ |
186 | abort (); |
187 | if (STORAGE_CLASS (prod) == EXTERNAL_REFERENCE_STORAGE) | |
188 | { | |
189 | fprintf (stderr, "%s:%i:%i: External reference variables may not have initial value\n", in_fname, | |
96e3ac4f | 190 | tok->tp.tok.lineno, tok->tp.tok.charno); |
6cfea11b TJ |
191 | print_token (stderr, 0, tok); |
192 | errorcount++; | |
193 | YYERROR; | |
194 | } | |
195 | } | |
96e3ac4f | 196 | prod->tp.pro.code = tree_code_create_variable |
6cfea11b | 197 | (STORAGE_CLASS (prod), |
96e3ac4f TJ |
198 | ((struct prod_token_parm_item*)SYMBOL_TABLE_NAME (prod))->tp.tok.chars, |
199 | ((struct prod_token_parm_item*)SYMBOL_TABLE_NAME (prod))->tp.tok.length, | |
6cfea11b | 200 | NUMERIC_TYPE (prod), |
96e3ac4f | 201 | VAR_INIT (prod)? ((struct prod_token_parm_item*)VAR_INIT (prod))->tp.pro.code:NULL, |
6cfea11b | 202 | in_fname, |
96e3ac4f TJ |
203 | tok->tp.tok.lineno); |
204 | if (!prod->tp.pro.code) | |
6cfea11b TJ |
205 | abort (); |
206 | } | |
207 | ; | |
208 | ||
209 | storage: | |
210 | STATIC | |
211 | |AUTOMATIC | |
212 | |EXTERNAL_DEFINITION | |
213 | |EXTERNAL_REFERENCE | |
214 | ; | |
215 | ||
216 | parameter: | |
217 | typename NAME { | |
96e3ac4f TJ |
218 | struct prod_token_parm_item* tok; |
219 | struct prod_token_parm_item *prod; | |
220 | struct prod_token_parm_item *prod2; | |
6cfea11b TJ |
221 | tok = $2; |
222 | prod = make_production (PROD_VARIABLE_NAME, tok); | |
223 | SYMBOL_TABLE_NAME (prod) = $2; | |
224 | EXPRESSION_TYPE (prod) = $1; | |
96e3ac4f | 225 | NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (prod))); |
6cfea11b TJ |
226 | ensure_not_void (NUMERIC_TYPE (prod), tok); |
227 | if (insert_tree_name (prod)) | |
228 | { | |
229 | YYERROR; | |
230 | } | |
231 | prod2 = make_production (PROD_PARAMETER, tok); | |
232 | VARIABLE (prod2) = prod; | |
233 | $$ = prod2; | |
234 | } | |
235 | ; | |
236 | ||
237 | function_prototype: | |
238 | storage typename NAME LEFT_PARENTHESIS parameters RIGHT_PARENTHESIS SEMICOLON { | |
96e3ac4f TJ |
239 | struct prod_token_parm_item* tok; |
240 | struct prod_token_parm_item *prod; | |
241 | struct prod_token_parm_item *type; | |
242 | struct prod_token_parm_item* first_parms; | |
243 | struct prod_token_parm_item* last_parms; | |
244 | struct prod_token_parm_item* this_parms; | |
245 | struct prod_token_parm_item *this_parm; | |
246 | struct prod_token_parm_item *this_parm_var; | |
6cfea11b TJ |
247 | tok = $3; |
248 | prod = make_production (PROD_FUNCTION_NAME, $3); | |
249 | SYMBOL_TABLE_NAME (prod) = $3; | |
250 | EXPRESSION_TYPE (prod) = $2; | |
96e3ac4f | 251 | NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (prod))); |
6cfea11b TJ |
252 | PARAMETERS (prod) = reverse_prod_list ($5); |
253 | insert_tree_name (prod); | |
254 | STORAGE_CLASS_TOKEN (prod) = $1; | |
255 | set_storage (prod); | |
256 | switch (STORAGE_CLASS (prod)) | |
257 | { | |
258 | case STATIC_STORAGE: | |
259 | case EXTERNAL_DEFINITION_STORAGE: | |
260 | break; | |
261 | ||
262 | case AUTOMATIC_STORAGE: | |
263 | fprintf (stderr, "%s:%i:%i: A function cannot be automatic\n", in_fname, | |
96e3ac4f | 264 | tok->tp.tok.lineno, tok->tp.tok.charno); |
6cfea11b TJ |
265 | print_token (stderr, 0, tok); |
266 | errorcount++; | |
267 | YYERROR; | |
268 | break; | |
269 | ||
270 | default: | |
271 | abort (); | |
272 | } | |
273 | type = EXPRESSION_TYPE (prod); | |
274 | /* Create a parameter list in a non-front end specific format. */ | |
275 | for (first_parms = NULL, last_parms = NULL, this_parm = PARAMETERS (prod); | |
276 | this_parm; | |
96e3ac4f | 277 | this_parm = this_parm->tp.pro.next) |
6cfea11b TJ |
278 | { |
279 | if (this_parm->category != production_category) | |
280 | abort (); | |
281 | this_parm_var = VARIABLE (this_parm); | |
282 | if (!this_parm_var) | |
283 | abort (); | |
284 | if (this_parm_var->category != production_category) | |
285 | abort (); | |
96e3ac4f TJ |
286 | this_parms = my_malloc (sizeof (struct prod_token_parm_item)); |
287 | if (!this_parm_var->tp.pro.main_token) | |
6cfea11b | 288 | abort (); |
96e3ac4f TJ |
289 | this_parms->tp.par.variable_name = this_parm_var->tp.pro.main_token->tp.tok.chars; |
290 | this_parms->type = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (this_parm_var))); | |
6cfea11b TJ |
291 | if (last_parms) |
292 | { | |
96e3ac4f | 293 | last_parms->tp.par.next = this_parms; |
6cfea11b TJ |
294 | last_parms = this_parms; |
295 | } | |
296 | else | |
297 | { | |
298 | first_parms = this_parms; | |
299 | last_parms = this_parms; | |
300 | } | |
96e3ac4f TJ |
301 | this_parms->tp.par.where_to_put_var_tree = |
302 | & (( (struct prod_token_parm_item*)VARIABLE (this_parm))->tp.pro.code); | |
6cfea11b TJ |
303 | } |
304 | FIRST_PARMS (prod) = first_parms; | |
305 | ||
96e3ac4f TJ |
306 | prod->tp.pro.code = tree_code_create_function_prototype |
307 | (tok->tp.tok.chars, STORAGE_CLASS (prod), NUMERIC_TYPE (type), | |
308 | first_parms, in_fname, tok->tp.tok.lineno); | |
6cfea11b TJ |
309 | |
310 | } | |
311 | ; | |
312 | ||
313 | function: | |
314 | NAME LEFT_BRACE { | |
96e3ac4f TJ |
315 | struct prod_token_parm_item *proto; |
316 | struct prod_token_parm_item search_prod; | |
317 | struct prod_token_parm_item* tok; | |
318 | struct prod_token_parm_item *this_parm; | |
6cfea11b TJ |
319 | tok = $1; |
320 | SYMBOL_TABLE_NAME ((&search_prod)) = tok; | |
321 | current_function = proto = lookup_tree_name (&search_prod); | |
322 | if (!proto) | |
323 | { | |
324 | fprintf (stderr, "%s:%i:%i: Function prototype not found\n", in_fname, | |
96e3ac4f | 325 | tok->tp.tok.lineno, tok->tp.tok.charno); |
6cfea11b TJ |
326 | print_token (stderr, 0, tok); |
327 | errorcount++; | |
328 | YYERROR; | |
329 | } | |
96e3ac4f | 330 | if (!proto->tp.pro.code) |
6cfea11b TJ |
331 | abort (); |
332 | tree_code_create_function_initial | |
96e3ac4f | 333 | (proto->tp.pro.code, in_fname, tok->tp.tok.lineno, |
6cfea11b TJ |
334 | FIRST_PARMS (current_function)); |
335 | ||
336 | /* Check all the parameters have code. */ | |
337 | for (this_parm = PARAMETERS (proto); | |
338 | this_parm; | |
96e3ac4f | 339 | this_parm = this_parm->tp.pro.next) |
6cfea11b | 340 | { |
96e3ac4f | 341 | if (! (struct prod_token_parm_item*)VARIABLE (this_parm)) |
6cfea11b | 342 | abort (); |
96e3ac4f | 343 | if (! (( (struct prod_token_parm_item*)VARIABLE (this_parm))->tp.pro.code)) |
6cfea11b TJ |
344 | abort (); |
345 | } | |
346 | } | |
347 | variable_defs_opt statements_opt RIGHT_BRACE { | |
96e3ac4f | 348 | struct prod_token_parm_item* tok; |
6cfea11b | 349 | tok = $1; |
96e3ac4f | 350 | tree_code_create_function_wrapup (in_fname, tok->tp.tok.lineno); |
6cfea11b TJ |
351 | current_function = NULL; |
352 | } | |
353 | ; | |
354 | ||
355 | variable_defs_opt: | |
356 | /* Nil. */ { | |
357 | $$ = 0; | |
358 | } | |
359 | |variable_defs { | |
360 | $$ = $1; | |
361 | } | |
362 | ; | |
363 | ||
364 | statements_opt: | |
365 | /* Nil. */ { | |
366 | $$ = 0; | |
367 | } | |
368 | |statements { | |
369 | $$ = $1; | |
370 | } | |
371 | ; | |
372 | ||
373 | variable_defs: | |
374 | variable_def { | |
375 | /* Nothing to do. */ | |
376 | } | |
377 | |variable_defs variable_def { | |
378 | /* Nothing to do. */ | |
379 | } | |
380 | ; | |
381 | ||
382 | typename: | |
383 | INT { | |
96e3ac4f TJ |
384 | struct prod_token_parm_item* tok; |
385 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
386 | tok = $1; |
387 | prod = make_production (PROD_TYPE_NAME, tok); | |
388 | NUMERIC_TYPE (prod) = SIGNED_INT; | |
96e3ac4f | 389 | prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); |
6cfea11b TJ |
390 | $$ = prod; |
391 | } | |
392 | |UNSIGNED INT { | |
96e3ac4f TJ |
393 | struct prod_token_parm_item* tok; |
394 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
395 | tok = $1; |
396 | prod = make_production (PROD_TYPE_NAME, tok); | |
397 | NUMERIC_TYPE (prod) = UNSIGNED_INT; | |
96e3ac4f | 398 | prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); |
6cfea11b TJ |
399 | $$ = prod; |
400 | } | |
401 | |CHAR { | |
96e3ac4f TJ |
402 | struct prod_token_parm_item* tok; |
403 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
404 | tok = $1; |
405 | prod = make_production (PROD_TYPE_NAME, tok); | |
406 | NUMERIC_TYPE (prod) = SIGNED_CHAR; | |
96e3ac4f | 407 | prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); |
6cfea11b TJ |
408 | $$ = prod; |
409 | } | |
410 | |UNSIGNED CHAR { | |
96e3ac4f TJ |
411 | struct prod_token_parm_item* tok; |
412 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
413 | tok = $1; |
414 | prod = make_production (PROD_TYPE_NAME, tok); | |
415 | NUMERIC_TYPE (prod) = UNSIGNED_CHAR; | |
96e3ac4f | 416 | prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); |
6cfea11b TJ |
417 | $$ = prod; |
418 | } | |
419 | |VOID { | |
96e3ac4f TJ |
420 | struct prod_token_parm_item* tok; |
421 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
422 | tok = $1; |
423 | prod = make_production (PROD_TYPE_NAME, tok); | |
424 | NUMERIC_TYPE (prod) = VOID_TYPE; | |
96e3ac4f | 425 | prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); |
6cfea11b TJ |
426 | $$ = prod; |
427 | } | |
428 | ; | |
429 | ||
430 | parameters: | |
431 | parameter { | |
432 | /* Nothing to do. */ | |
433 | $$ = $1; | |
434 | } | |
435 | |parameters COMMA parameter { | |
96e3ac4f | 436 | struct prod_token_parm_item *prod1; |
6cfea11b | 437 | prod1 = $3; |
96e3ac4f | 438 | prod1->tp.pro.next = $1; /* Insert in reverse order. */ |
6cfea11b TJ |
439 | $$ = prod1; |
440 | } | |
441 | ; | |
442 | ||
443 | statements: | |
444 | statement { | |
445 | /* Nothing to do. */ | |
446 | } | |
447 | |statements statement { | |
448 | /* Nothing to do. */ | |
449 | } | |
450 | ; | |
451 | ||
452 | statement: | |
453 | expression SEMICOLON { | |
96e3ac4f | 454 | struct prod_token_parm_item *exp; |
6cfea11b | 455 | exp = $1; |
96e3ac4f | 456 | tree_code_output_expression_statement (exp->tp.pro.code, in_fname, exp->tp.pro.main_token->tp.tok.lineno); |
6cfea11b TJ |
457 | } |
458 | |return SEMICOLON { | |
459 | /* Nothing to do. */ | |
460 | } | |
461 | |if_statement { | |
462 | /* Nothing to do. */ | |
463 | } | |
464 | ; | |
465 | ||
466 | if_statement: | |
467 | IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS { | |
96e3ac4f TJ |
468 | struct prod_token_parm_item* tok; |
469 | struct prod_token_parm_item *exp; | |
6cfea11b TJ |
470 | tok = $1; |
471 | exp = $3; | |
96e3ac4f TJ |
472 | ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token); |
473 | tree_code_if_start (exp->tp.pro.code, in_fname, tok->tp.tok.lineno); | |
6cfea11b TJ |
474 | } |
475 | LEFT_BRACE statements_opt RIGHT_BRACE { | |
476 | /* Just let the statements flow. */ | |
477 | } | |
478 | ELSE { | |
96e3ac4f | 479 | struct prod_token_parm_item* tok; |
6cfea11b | 480 | tok = $1; |
96e3ac4f | 481 | tree_code_if_else (in_fname, tok->tp.tok.lineno); |
6cfea11b TJ |
482 | } |
483 | LEFT_BRACE statements_opt RIGHT_BRACE { | |
96e3ac4f | 484 | struct prod_token_parm_item* tok; |
6cfea11b | 485 | tok = $12; |
96e3ac4f | 486 | tree_code_if_end (in_fname, tok->tp.tok.lineno); |
6cfea11b TJ |
487 | } |
488 | ; | |
489 | ||
490 | ||
491 | return: | |
492 | RETURN expression_opt { | |
96e3ac4f TJ |
493 | struct prod_token_parm_item *type_prod; |
494 | struct prod_token_parm_item* ret_tok; | |
6cfea11b TJ |
495 | ret_tok = $1; |
496 | type_prod = EXPRESSION_TYPE (current_function); | |
497 | if (NUMERIC_TYPE (type_prod) == VOID) | |
498 | if ($2 == NULL) | |
96e3ac4f | 499 | tree_code_generate_return (type_prod->tp.pro.code, NULL); |
6cfea11b TJ |
500 | else |
501 | { | |
502 | fprintf (stderr, "%s:%i:%i: Redundant expression in return\n", in_fname, | |
96e3ac4f | 503 | ret_tok->tp.tok.lineno, ret_tok->tp.tok.charno); |
6cfea11b TJ |
504 | print_token (stderr, 0, ret_tok); |
505 | errorcount++; | |
96e3ac4f | 506 | tree_code_generate_return (type_prod->tp.pro.code, NULL); |
6cfea11b TJ |
507 | } |
508 | else | |
509 | if ($2 == NULL) | |
510 | { | |
511 | fprintf (stderr, "%s:%i:%i: Expression missing in return\n", in_fname, | |
96e3ac4f | 512 | ret_tok->tp.tok.lineno, ret_tok->tp.tok.charno); |
6cfea11b TJ |
513 | print_token (stderr, 0, ret_tok); |
514 | errorcount++; | |
515 | } | |
516 | else | |
517 | { | |
96e3ac4f | 518 | struct prod_token_parm_item *exp; |
6cfea11b TJ |
519 | exp = $2; |
520 | /* Check same type. */ | |
521 | if (check_type_match (NUMERIC_TYPE (type_prod), $2)) | |
522 | { | |
96e3ac4f | 523 | if (!type_prod->tp.pro.code) |
6cfea11b | 524 | abort (); |
96e3ac4f | 525 | if (!exp->tp.pro.code) |
6cfea11b TJ |
526 | abort (); |
527 | /* Generate the code. */ | |
96e3ac4f | 528 | tree_code_generate_return (type_prod->tp.pro.code, exp->tp.pro.code); |
6cfea11b TJ |
529 | } |
530 | } | |
531 | } | |
532 | ; | |
533 | ||
534 | expression_opt: | |
535 | /* Nil. */ { | |
536 | $$ = 0; | |
537 | } | |
538 | |expression { | |
96e3ac4f | 539 | struct prod_token_parm_item *exp; |
6cfea11b | 540 | exp = $1; |
96e3ac4f | 541 | if (!exp->tp.pro.code) |
6cfea11b TJ |
542 | abort (); |
543 | ||
544 | $$ = $1; | |
545 | } | |
546 | ; | |
547 | ||
548 | expression: | |
549 | INTEGER { | |
550 | $$ = make_integer_constant ($1); | |
551 | } | |
552 | |variable_ref { | |
553 | $$ = $1; | |
554 | } | |
555 | |expression PLUS expression { | |
96e3ac4f TJ |
556 | struct prod_token_parm_item* tok; |
557 | struct prod_token_parm_item *prod; | |
558 | struct prod_token_parm_item *op1; | |
559 | struct prod_token_parm_item *op2; | |
6cfea11b TJ |
560 | tree type; |
561 | ||
562 | op1 = $1; | |
563 | op2 = $3; | |
564 | tok = $2; | |
96e3ac4f TJ |
565 | ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token); |
566 | ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); | |
6cfea11b TJ |
567 | prod = make_production (PROD_PLUS_EXPRESSION, tok); |
568 | NUMERIC_TYPE (prod) = get_common_type (op1, op2); | |
569 | if (!NUMERIC_TYPE (prod)) | |
570 | YYERROR; | |
571 | else | |
572 | { | |
573 | type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); | |
574 | if (!type) | |
575 | abort (); | |
576 | OP1 (prod) = $1; | |
577 | OP2 (prod) = $3; | |
578 | ||
96e3ac4f TJ |
579 | prod->tp.pro.code = tree_code_get_expression |
580 | (EXP_PLUS, type, op1->tp.pro.code, op2->tp.pro.code, NULL); | |
6cfea11b TJ |
581 | } |
582 | $$ = prod; | |
583 | } | |
584 | |expression MINUS expression %prec PLUS { | |
96e3ac4f TJ |
585 | struct prod_token_parm_item* tok; |
586 | struct prod_token_parm_item *prod; | |
587 | struct prod_token_parm_item *op1; | |
588 | struct prod_token_parm_item *op2; | |
6cfea11b TJ |
589 | tree type; |
590 | ||
591 | op1 = $1; | |
592 | op2 = $3; | |
96e3ac4f TJ |
593 | ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token); |
594 | ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); | |
6cfea11b TJ |
595 | tok = $2; |
596 | prod = make_production (PROD_PLUS_EXPRESSION, tok); | |
597 | NUMERIC_TYPE (prod) = get_common_type (op1, op2); | |
598 | if (!NUMERIC_TYPE (prod)) | |
599 | YYERROR; | |
600 | else | |
601 | { | |
602 | type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); | |
603 | if (!type) | |
604 | abort (); | |
605 | OP1 (prod) = $1; | |
606 | OP2 (prod) = $3; | |
607 | ||
96e3ac4f TJ |
608 | prod->tp.pro.code = tree_code_get_expression (EXP_MINUS, |
609 | type, op1->tp.pro.code, op2->tp.pro.code, NULL); | |
6cfea11b TJ |
610 | } |
611 | $$ = prod; | |
612 | } | |
613 | |expression EQUALS expression { | |
96e3ac4f TJ |
614 | struct prod_token_parm_item* tok; |
615 | struct prod_token_parm_item *prod; | |
616 | struct prod_token_parm_item *op1; | |
617 | struct prod_token_parm_item *op2; | |
6cfea11b TJ |
618 | tree type; |
619 | ||
620 | op1 = $1; | |
621 | op2 = $3; | |
96e3ac4f TJ |
622 | ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token); |
623 | ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); | |
6cfea11b TJ |
624 | tok = $2; |
625 | prod = make_production (PROD_PLUS_EXPRESSION, tok); | |
626 | NUMERIC_TYPE (prod) = SIGNED_INT; | |
627 | if (!NUMERIC_TYPE (prod)) | |
628 | YYERROR; | |
629 | else | |
630 | { | |
631 | type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); | |
632 | if (!type) | |
633 | abort (); | |
634 | OP1 (prod) = $1; | |
635 | OP2 (prod) = $3; | |
636 | ||
96e3ac4f TJ |
637 | prod->tp.pro.code = tree_code_get_expression (EXP_EQUALS, |
638 | type, op1->tp.pro.code, op2->tp.pro.code, NULL); | |
6cfea11b TJ |
639 | } |
640 | $$ = prod; | |
641 | } | |
642 | |variable_ref ASSIGN expression { | |
96e3ac4f TJ |
643 | struct prod_token_parm_item* tok; |
644 | struct prod_token_parm_item *prod; | |
645 | struct prod_token_parm_item *op1; | |
646 | struct prod_token_parm_item *op2; | |
6cfea11b TJ |
647 | tree type; |
648 | ||
649 | op1 = $1; | |
650 | op2 = $3; | |
651 | tok = $2; | |
96e3ac4f | 652 | ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); |
6cfea11b TJ |
653 | prod = make_production (PROD_ASSIGN_EXPRESSION, tok); |
654 | NUMERIC_TYPE (prod) = NUMERIC_TYPE (op1); | |
655 | if (!NUMERIC_TYPE (prod)) | |
656 | YYERROR; | |
657 | else | |
658 | { | |
659 | type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); | |
660 | if (!type) | |
661 | abort (); | |
662 | OP1 (prod) = $1; | |
663 | OP2 (prod) = $3; | |
96e3ac4f TJ |
664 | prod->tp.pro.code = tree_code_get_expression (EXP_ASSIGN, |
665 | type, op1->tp.pro.code, op2->tp.pro.code, NULL); | |
6cfea11b TJ |
666 | } |
667 | $$ = prod; | |
668 | } | |
669 | |function_invocation { | |
670 | $$ = $1; | |
671 | } | |
672 | ; | |
673 | ||
674 | function_invocation: | |
675 | NAME LEFT_PARENTHESIS expressions_with_commas RIGHT_PARENTHESIS { | |
96e3ac4f TJ |
676 | struct prod_token_parm_item *prod; |
677 | struct prod_token_parm_item* tok; | |
678 | struct prod_token_parm_item search_prod; | |
679 | struct prod_token_parm_item *proto; | |
680 | struct prod_token_parm_item *exp; | |
681 | struct prod_token_parm_item *exp_proto; | |
682 | struct prod_token_parm_item *var; | |
6cfea11b TJ |
683 | int exp_proto_count; |
684 | int exp_count; | |
685 | tree parms; | |
686 | tree type; | |
687 | ||
688 | tok = $1; | |
689 | prod = make_production (PROD_FUNCTION_INVOCATION, tok); | |
690 | SYMBOL_TABLE_NAME (prod) = tok; | |
691 | PARAMETERS (prod) = reverse_prod_list ($3); | |
692 | SYMBOL_TABLE_NAME ((&search_prod)) = tok; | |
693 | proto = lookup_tree_name (&search_prod); | |
694 | if (!proto) | |
695 | { | |
696 | fprintf (stderr, "%s:%i:%i: Function prototype not found\n", in_fname, | |
96e3ac4f | 697 | tok->tp.tok.lineno, tok->tp.tok.charno); |
6cfea11b TJ |
698 | print_token (stderr, 0, tok); |
699 | errorcount++; | |
700 | YYERROR; | |
701 | } | |
702 | EXPRESSION_TYPE (prod) = EXPRESSION_TYPE (proto); | |
703 | NUMERIC_TYPE (prod) = NUMERIC_TYPE (proto); | |
704 | /* Count the expressions and ensure they match the prototype. */ | |
705 | for (exp_proto_count = 0, exp_proto = PARAMETERS (proto); | |
96e3ac4f | 706 | exp_proto; exp_proto = exp_proto->tp.pro.next) |
6cfea11b TJ |
707 | exp_proto_count++; |
708 | ||
96e3ac4f | 709 | for (exp_count = 0, exp = PARAMETERS (prod); exp; exp = exp->tp.pro.next) |
6cfea11b TJ |
710 | exp_count++; |
711 | ||
712 | if (exp_count != exp_proto_count) | |
713 | { | |
714 | fprintf (stderr, "%s:%i:%i: expression count mismatch with prototype\n", in_fname, | |
96e3ac4f | 715 | tok->tp.tok.lineno, tok->tp.tok.charno); |
6cfea11b TJ |
716 | print_token (stderr, 0, tok); |
717 | errorcount++; | |
718 | YYERROR; | |
719 | } | |
720 | parms = tree_code_init_parameters (); | |
721 | for (exp_proto = PARAMETERS (proto), exp = PARAMETERS (prod); | |
722 | exp_proto; | |
96e3ac4f | 723 | exp = exp->tp.pro.next, exp_proto = exp_proto->tp.pro.next) |
6cfea11b TJ |
724 | { |
725 | if (!exp) | |
726 | abort (); | |
727 | if (!exp_proto) | |
728 | abort (); | |
96e3ac4f | 729 | if (!exp->tp.pro.code) |
6cfea11b TJ |
730 | abort (); |
731 | var = VARIABLE (exp_proto); | |
732 | if (!var) | |
733 | abort (); | |
96e3ac4f | 734 | if (!var->tp.pro.code) |
6cfea11b | 735 | abort (); |
96e3ac4f | 736 | parms = tree_code_add_parameter (parms, var->tp.pro.code, exp->tp.pro.code); |
6cfea11b TJ |
737 | } |
738 | type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); | |
96e3ac4f TJ |
739 | prod->tp.pro.code = tree_code_get_expression |
740 | (EXP_FUNCTION_INVOCATION, type, proto->tp.pro.code, parms, NULL); | |
6cfea11b TJ |
741 | $$ = prod; |
742 | } | |
743 | ; | |
744 | ||
745 | expressions_with_commas: | |
746 | expression { | |
96e3ac4f | 747 | struct prod_token_parm_item *exp; |
6cfea11b | 748 | exp = $1; |
96e3ac4f | 749 | ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token); |
6cfea11b TJ |
750 | $$ = $1; |
751 | } | |
752 | |expressions_with_commas COMMA expression { | |
96e3ac4f | 753 | struct prod_token_parm_item *exp; |
6cfea11b | 754 | exp = $3; |
96e3ac4f TJ |
755 | ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token); |
756 | exp->tp.pro.next = $1; /* Reverse order. */ | |
6cfea11b TJ |
757 | $$ = exp; |
758 | } | |
759 | ; | |
760 | ||
761 | variable_ref: | |
762 | NAME { | |
96e3ac4f TJ |
763 | struct prod_token_parm_item search_prod; |
764 | struct prod_token_parm_item *prod; | |
765 | struct prod_token_parm_item *symbol_table_entry; | |
766 | struct prod_token_parm_item* tok; | |
6cfea11b TJ |
767 | tree type; |
768 | ||
769 | tok = $1; | |
770 | SYMBOL_TABLE_NAME ((&search_prod)) = tok; | |
771 | symbol_table_entry = lookup_tree_name (&search_prod); | |
772 | if (!symbol_table_entry) | |
773 | { | |
774 | fprintf (stderr, "%s:%i:%i: Variable referred to but not defined\n", in_fname, | |
96e3ac4f | 775 | tok->tp.tok.lineno, tok->tp.tok.charno); |
6cfea11b TJ |
776 | print_token (stderr, 0, tok); |
777 | errorcount++; | |
778 | YYERROR; | |
779 | } | |
780 | ||
781 | prod = make_production (PROD_VARIABLE_REFERENCE_EXPRESSION, tok); | |
782 | NUMERIC_TYPE (prod) = NUMERIC_TYPE (symbol_table_entry); | |
783 | type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); | |
784 | if (!NUMERIC_TYPE (prod)) | |
785 | YYERROR; | |
786 | OP1 (prod) = $1; | |
787 | ||
96e3ac4f TJ |
788 | prod->tp.pro.code = tree_code_get_expression (EXP_REFERENCE, type, |
789 | symbol_table_entry->tp.pro.code, NULL, NULL); | |
6cfea11b TJ |
790 | $$ = prod; |
791 | } | |
792 | ; | |
793 | ||
794 | init_opt: | |
795 | /* Nil. */ { | |
796 | $$ = 0; | |
797 | } | |
798 | |init { | |
799 | /* Nothing to do. */ | |
a3b5decf | 800 | }; |
6cfea11b TJ |
801 | |
802 | init: | |
803 | ASSIGN init_element { | |
804 | } | |
805 | ; | |
806 | ||
807 | init_element: | |
808 | INTEGER { | |
809 | $$ = make_integer_constant ($1); | |
810 | } | |
811 | ; | |
812 | ||
813 | %% | |
814 | ||
815 | /* Print a token VALUE to file FILE. Ignore TYPE which is the token | |
816 | type. */ | |
817 | ||
818 | void | |
819 | print_token (FILE * file, unsigned int type ATTRIBUTE_UNUSED, YYSTYPE value) | |
820 | { | |
96e3ac4f | 821 | struct prod_token_parm_item *tok; |
6cfea11b TJ |
822 | unsigned int ix; |
823 | ||
824 | tok = value; | |
96e3ac4f TJ |
825 | fprintf (file, "%d \"", tok->tp.tok.lineno); |
826 | for (ix = 0; ix < tok->tp.tok.length; ix++) | |
827 | fprintf (file, "%c", tok->tp.tok.chars[ix]); | |
6cfea11b TJ |
828 | fprintf (file, "\""); |
829 | } | |
830 | ||
831 | /* Output a message ERROR_MESSAGE from the parser. */ | |
832 | void | |
833 | yyerror (const char *error_message) | |
834 | { | |
96e3ac4f | 835 | struct prod_token_parm_item *tok; |
6cfea11b TJ |
836 | |
837 | tok = yylval; | |
838 | if (tok) | |
839 | { | |
96e3ac4f | 840 | fprintf (stderr, "%s:%i:%i: %s\n", in_fname, tok->tp.tok.lineno, tok->tp.tok.charno, error_message); |
6cfea11b TJ |
841 | print_token (stderr, 0, tok); |
842 | } | |
843 | else | |
844 | fprintf (stderr, "%s\n", error_message); | |
845 | ||
846 | errorcount++; | |
847 | ||
848 | } | |
849 | ||
850 | /* Reverse the order of a token list, linked by parse_next, old first | |
851 | token is OLD_FIRST. */ | |
852 | ||
96e3ac4f TJ |
853 | static struct prod_token_parm_item* |
854 | reverse_prod_list (struct prod_token_parm_item *old_first) | |
6cfea11b | 855 | { |
96e3ac4f TJ |
856 | struct prod_token_parm_item *current; |
857 | struct prod_token_parm_item *next; | |
858 | struct prod_token_parm_item *prev = NULL; | |
6cfea11b TJ |
859 | |
860 | current = old_first; | |
861 | prev = NULL; | |
862 | ||
863 | while (current) | |
864 | { | |
865 | if (current->category != production_category) | |
866 | abort (); | |
96e3ac4f TJ |
867 | next = current->tp.pro.next; |
868 | current->tp.pro.next = prev; | |
6cfea11b TJ |
869 | prev = current; |
870 | current = next; | |
871 | } | |
872 | return prev; | |
873 | } | |
874 | ||
875 | /* Ensure TYPE is not VOID. Use NAME as the token for the error location. */ | |
876 | ||
877 | static void | |
96e3ac4f | 878 | ensure_not_void (unsigned int type, struct prod_token_parm_item* name) |
6cfea11b TJ |
879 | { |
880 | if (type == VOID) | |
881 | { | |
882 | fprintf (stderr, "%s:%i:%i: Type must not be void in this context\n", in_fname, | |
96e3ac4f | 883 | name->tp.tok.lineno, name->tp.tok.charno); |
6cfea11b TJ |
884 | print_token (stderr, 0, name); |
885 | errorcount++; | |
886 | } | |
887 | } | |
888 | ||
889 | /* Check TYPE1 and TYPE2 which are integral types. Return the lowest | |
890 | common type (min is signed int). */ | |
891 | ||
892 | static int | |
96e3ac4f | 893 | get_common_type (struct prod_token_parm_item *type1, struct prod_token_parm_item *type2) |
6cfea11b TJ |
894 | { |
895 | if (NUMERIC_TYPE (type1) == UNSIGNED_INT) | |
896 | return UNSIGNED_INT; | |
897 | if (NUMERIC_TYPE (type2) == UNSIGNED_INT) | |
898 | return UNSIGNED_INT; | |
899 | ||
900 | return SIGNED_INT; | |
901 | } | |
902 | ||
903 | /* Check type (TYPE_NUM) and expression (EXP) match. Return the 1 if | |
904 | OK else 0. Must be exact match - same name unless it is an | |
905 | integral type. */ | |
906 | ||
907 | static int | |
96e3ac4f | 908 | check_type_match (int type_num, struct prod_token_parm_item *exp) |
6cfea11b TJ |
909 | { |
910 | switch (type_num) | |
911 | { | |
912 | case SIGNED_INT: | |
913 | case UNSIGNED_INT: | |
914 | case SIGNED_CHAR: | |
915 | case UNSIGNED_CHAR: | |
916 | switch (NUMERIC_TYPE (exp)) | |
917 | { | |
918 | case SIGNED_INT: | |
919 | case UNSIGNED_INT: | |
920 | case SIGNED_CHAR: | |
921 | case UNSIGNED_CHAR: | |
922 | return 1; | |
923 | ||
924 | case VOID: | |
925 | abort (); | |
926 | ||
927 | default: | |
928 | abort (); | |
929 | } | |
930 | break; | |
931 | ||
932 | case VOID: | |
933 | abort (); | |
934 | ||
935 | default: | |
936 | abort (); | |
937 | ||
938 | } | |
939 | } | |
940 | ||
941 | /* Make a production for an integer constant VALUE. */ | |
942 | ||
96e3ac4f TJ |
943 | static struct prod_token_parm_item * |
944 | make_integer_constant (struct prod_token_parm_item* value) | |
6cfea11b | 945 | { |
96e3ac4f TJ |
946 | struct prod_token_parm_item* tok; |
947 | struct prod_token_parm_item *prod; | |
6cfea11b TJ |
948 | tok = value; |
949 | prod = make_production (PROD_INTEGER_CONSTANT, tok); | |
96e3ac4f | 950 | if ((tok->tp.tok.chars[0] == (unsigned char)'-')|| (tok->tp.tok.chars[0] == (unsigned char)'+')) |
6cfea11b TJ |
951 | NUMERIC_TYPE (prod) = SIGNED_INT; |
952 | else | |
953 | NUMERIC_TYPE (prod) = UNSIGNED_INT; | |
96e3ac4f | 954 | prod->tp.pro.code = tree_code_get_integer_value (tok->tp.tok.chars, tok->tp.tok.length); |
6cfea11b TJ |
955 | return prod; |
956 | } | |
957 | ||
958 | /* Set STORAGE_CLASS in PROD according to CLASS_TOKEN. */ | |
959 | ||
960 | static void | |
96e3ac4f | 961 | set_storage (struct prod_token_parm_item *prod) |
6cfea11b | 962 | { |
96e3ac4f | 963 | struct prod_token_parm_item* stg_class; |
6cfea11b TJ |
964 | stg_class = STORAGE_CLASS_TOKEN (prod); |
965 | switch (stg_class->type) | |
966 | { | |
967 | case STATIC: | |
968 | STORAGE_CLASS (prod) = STATIC_STORAGE; | |
969 | break; | |
970 | ||
971 | case AUTOMATIC: | |
972 | STORAGE_CLASS (prod) = AUTOMATIC_STORAGE; | |
973 | break; | |
974 | ||
975 | case EXTERNAL_DEFINITION: | |
976 | STORAGE_CLASS (prod) = EXTERNAL_DEFINITION_STORAGE; | |
977 | break; | |
978 | ||
979 | case EXTERNAL_REFERENCE: | |
980 | STORAGE_CLASS (prod) = EXTERNAL_REFERENCE_STORAGE; | |
981 | break; | |
982 | ||
983 | default: | |
984 | abort (); | |
985 | } | |
986 | } | |
987 | ||
988 | /* Set parse trace. */ | |
989 | ||
990 | void | |
991 | treelang_debug (void) | |
992 | { | |
993 | if (option_parser_trace) | |
994 | yydebug = 1; | |
995 | } |