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