Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / statement.g
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: statement.g,v 1.8 1994/06/27 08:02:37 ceriel Exp $ */
6 /*      STATEMENT SYNTAX PARSER */
7
8 {
9 #include        "lint.h"
10 #ifndef LINT
11 #include        <em.h>
12 #else
13 #include        "l_em.h"
14 #include        "l_lint.h"
15 #endif  /* LINT */
16
17 #include        "debug.h"
18 #include        "botch_free.h"
19 #include        "dbsymtab.h"
20
21 #include        <flt_arith.h>
22 #include        "arith.h"
23 #include        "LLlex.h"
24 #include        "type.h"
25 #include        "idf.h"
26 #include        "label.h"
27 #include        "expr.h"
28 #include        "code.h"
29 #include        "stack.h"
30 #include        "def.h"
31 #ifdef DBSYMTAB
32 #include        <stb.h>
33 #endif /* DBSYMTAB */
34
35 extern int level;
36 extern char options[];
37 }
38
39 /* Each statement construction is stacked in order to trace a
40  * statement to such a construction. Example: a case statement should
41  * be recognized as a piece of the most enclosing switch statement.
42  */
43
44 /* 3.6 */
45 statement
46         {
47 #ifdef  LINT
48                 lint_statement();
49 #endif  /* LINT */
50         }
51 :
52 %if (AHEAD != ':')
53         expression_statement
54 |
55         label ':' statement
56 |
57         compound_statement
58 |
59         if_statement
60 |
61         while_statement
62 |
63         do_statement
64 |
65         for_statement
66 |
67         switch_statement
68 |
69         case_statement
70 |
71         default_statement
72 |
73         BREAK
74         {
75                 code_break();
76 #ifdef  LINT
77                 lint_break_stmt();
78 #endif  /* LINT */
79         }
80         ';'
81 |
82         CONTINUE
83         {
84                 code_continue();
85 #ifdef  LINT
86                 lint_continue_stmt();
87 #endif  /* LINT */
88         }
89         ';'
90 |
91         return_statement
92 |
93         jump
94 |
95         ';'
96 ;
97
98
99 expression_statement
100         {       struct expr *expr;
101         }
102 :
103         expression(&expr)
104         ';'
105                 {
106 #ifdef  DEBUG
107                         print_expr("expression_statement", expr);
108 #endif  /* DEBUG */
109                         code_expr(expr, RVAL, FALSE, NO_LABEL, NO_LABEL);
110                         free_expression(expr);
111                 }
112 ;
113
114 /* 3.6.1 (partially) */
115 label
116         { struct idf *idf; }
117 :
118         identifier(&idf)
119         {
120                 /*      This allows the following absurd case:
121
122                                 typedef int grz;
123                                 main()  {
124                                         grz: printf("A labelled statement\n");
125                                 }
126                 */
127 #ifdef  LINT
128                 lint_label();
129 #endif  /* LINT */
130                 define_label(idf);
131                 C_df_ilb((label)idf->id_label->df_address);
132         }
133 ;
134
135 /* 3.6.4.1 */
136 if_statement
137         {
138                 struct expr *expr;
139                 label l_true = text_label();
140                 label l_false = text_label();
141                 label l_end = text_label();
142         }
143 :
144         IF
145         '('
146         expression(&expr)
147                 {
148                         opnd2test(&expr, IF);
149                         if (is_cp_cst(expr))    {
150                                 /*      The comparison has been optimized
151                                         to a 0 or 1.
152                                 */
153                                 if (expr->VL_VALUE == (arith)0) {
154                                         C_bra(l_false);
155                                 }
156                                 /* else fall through */
157 #ifdef  LINT
158                                 start_if_part(1);
159 #endif  /* LINT */
160                         }
161                         else    {
162                                 code_expr(expr, RVAL, TRUE, l_true, l_false);
163                                 C_df_ilb(l_true);
164 #ifdef  LINT
165                                 start_if_part(0);
166 #endif  /* LINT */
167                         }
168                         free_expression(expr);
169                 }
170         ')'
171         statement
172         [%prefer
173                 ELSE
174                         {
175 #ifdef  LINT
176                                 start_else_part();
177 #endif  /* LINT */
178                                 C_bra(l_end);
179                                 C_df_ilb(l_false);
180                         }
181                 statement
182                         {       C_df_ilb(l_end);
183 #ifdef  LINT
184                                 end_if_else_stmt();
185 #endif  /* LINT */
186                         }
187         |
188                 empty
189                         {       C_df_ilb(l_false);
190 #ifdef  LINT
191                                 end_if_stmt();
192 #endif  /* LINT */
193                         }
194         ]
195 ;
196
197 /* 3.6.5.3 */
198 while_statement
199         {
200                 struct expr *expr;
201                 label l_break = text_label();
202                 label l_continue = text_label();
203                 label l_body = text_label();
204         }
205 :
206         WHILE
207                 {
208                         stack_stmt(l_break, l_continue);
209                         C_df_ilb(l_continue);
210                 }
211         '('
212         expression(&expr)
213                 {
214                         opnd2test(&expr, WHILE);
215                         if (is_cp_cst(expr))    {
216                                 if (expr->VL_VALUE == (arith)0) {
217                                         C_bra(l_break);
218                                 }
219                         }
220                         else    {
221                                 code_expr(expr, RVAL, TRUE, l_body, l_break);
222                                 C_df_ilb(l_body);
223                         }
224 #ifdef  LINT
225                         start_while_stmt(expr);
226 #endif  /* LINT */
227                 }
228         ')'
229         statement
230                 {
231                         C_bra(l_continue);
232                         C_df_ilb(l_break);
233                         unstack_stmt();
234                         free_expression(expr);
235 #ifdef  LINT
236                         end_loop_body();
237                         end_loop_stmt();
238 #endif  /* LINT */
239                 }
240 ;
241
242 /* 3.6.5.2 */
243 do_statement
244         {       struct expr *expr;
245                 label l_break = text_label();
246                 label l_continue = text_label();
247                 label l_body = text_label();
248         }
249 :
250         DO
251                 {       C_df_ilb(l_body);
252                         stack_stmt(l_break, l_continue);
253 #ifdef  LINT
254                         start_do_stmt();
255 #endif  /* LINT */
256                 }
257         statement
258         WHILE
259         '('
260                 {
261 #ifdef  LINT
262                         end_loop_body();
263 #endif  /* LINT */
264                         C_df_ilb(l_continue);
265                 }
266         expression(&expr)
267                 {
268                         opnd2test(&expr, WHILE);
269                         if (is_cp_cst(expr))    {
270                                 if (expr->VL_VALUE == (arith)1) {
271                                         C_bra(l_body);
272                                 }
273 #ifdef  LINT
274                                 end_do_stmt(1, expr->VL_VALUE != (arith)0);
275 #endif  /* LINT */
276                         }
277                         else    {
278                                 code_expr(expr, RVAL, TRUE, l_body, l_break);
279 #ifdef  LINT
280                                 end_do_stmt(0, 0);
281 #endif  /* LINT */
282                         }
283                         C_df_ilb(l_break);
284                 }
285         ')'
286         ';'
287                 {
288                         unstack_stmt();
289                         free_expression(expr);
290                 }
291 ;
292
293 /* 3.6.5.3 */
294 for_statement
295         {       struct expr *e_init = 0, *e_test = 0, *e_incr = 0;
296                 label l_break = text_label();
297                 label l_continue = text_label();
298                 label l_body = text_label();
299                 label l_test = text_label();
300         }
301 :
302         FOR
303                 {       stack_stmt(l_break, l_continue);
304                 }
305         '('
306         [
307                 expression(&e_init)
308                 {       code_expr(e_init, RVAL, FALSE, NO_LABEL, NO_LABEL);
309                 }
310         ]?
311         ';'
312                 {       C_df_ilb(l_test);
313                 }
314         [
315                 expression(&e_test)
316                 {
317                         opnd2test(&e_test, FOR);
318                         if (is_cp_cst(e_test))  {
319                                 if (e_test->VL_VALUE == (arith)0)       {
320                                         C_bra(l_break);
321                                 }
322                         }
323                         else    {
324                                 code_expr(e_test, RVAL, TRUE, l_body, l_break);
325                                 C_df_ilb(l_body);
326                         }
327                 }
328         ]?
329         ';'
330         expression(&e_incr)?
331         ')'
332                 {
333 #ifdef  LINT
334                         start_for_stmt(e_test);
335 #endif  /* LINT */
336                 }
337         statement
338                 {
339 #ifdef  LINT
340                         end_loop_body();
341 #endif  /* LINT */
342                         C_df_ilb(l_continue);
343                         if (e_incr)
344                                 code_expr(e_incr, RVAL, FALSE,
345                                                         NO_LABEL, NO_LABEL);
346                         C_bra(l_test);
347                         C_df_ilb(l_break);
348                         unstack_stmt();
349                         free_expression(e_init);
350                         free_expression(e_test);
351                         free_expression(e_incr);
352 #ifdef  LINT
353                         end_loop_stmt();
354 #endif  /* LINT */
355                 }
356 ;
357
358 /* 3.6.4.2 */
359 switch_statement
360         {
361                 struct expr *expr;
362         }
363 :
364         SWITCH
365         '('
366         expression(&expr)
367                 {
368                         code_startswitch(&expr);
369 #ifdef  LINT
370                         start_switch_part(is_cp_cst(expr));
371 #endif  /* LINT */
372                 }
373         ')'
374         statement
375                 {
376 #ifdef  LINT
377                         end_switch_stmt();
378 #endif  /* LINT */
379                         code_endswitch();
380                         free_expression(expr);
381                 }
382 ;
383
384 /* 3.6.1 (partially) */
385 case_statement
386         {
387                 struct expr *expr;
388         }
389 :
390         CASE
391         constant_expression(&expr)
392                 {
393 #ifdef  LINT
394                         lint_case_stmt(0);
395 #endif  /* LINT */
396                         code_case(expr);
397                         free_expression(expr);
398                 }
399         ':'
400         statement
401 ;
402
403 /* 3.6.1 (partially) */
404 default_statement
405 :
406         DEFAULT
407                 {
408 #ifdef  LINT
409                         lint_case_stmt(1);
410 #endif  /* LINT */
411                         code_default();
412                 }
413         ':'
414         statement
415 ;
416
417 /* 3.6.6.4 */
418 return_statement
419         {       struct expr *expr = 0;
420         }
421 :
422         RETURN
423         [
424                 expression(&expr)
425                 {
426 #ifdef  LINT
427                         lint_ret_conv(expr);
428 #endif  /* LINT */
429
430                         do_return_expr(expr);
431                         free_expression(expr);
432 #ifdef  LINT
433                         lint_return_stmt(VALRETURNED);
434 #endif  /* LINT */
435                 }
436         |
437                 empty
438                 {
439                         do_return();
440 #ifdef  LINT
441                         lint_return_stmt(NOVALRETURNED);
442 #endif  /* LINT */
443                 }
444         ]
445         ';'
446 ;
447
448 /* 3.6.6.1 (partially) */
449 jump
450         {       struct idf *idf;
451         }
452 :
453         GOTO
454         identifier(&idf)
455         ';'
456                 {
457                         apply_label(idf);
458                         C_bra((label)idf->id_label->df_address);
459 #ifdef  LINT
460                         lint_jump_stmt(idf);
461 #endif  /* LINT */
462                 }
463 ;
464
465 /* 3.6.2 */
466 compound_statement
467         {
468 #ifdef DBSYMTAB
469         static int      brc_level = 1;
470         int             decl_seen = brc_level == 1;
471 #endif /* DBSYMTAB */
472         }
473 :
474         '{'
475                 {
476                         stack_level();
477                 }
478         [%while ((DOT != IDENTIFIER && AHEAD != ':') ||
479                  (DOT == IDENTIFIER && AHEAD == IDENTIFIER))
480                         /* >>> conflict on TYPE_IDENTIFIER, IDENTIFIER */
481                 declaration
482                 {
483 #ifdef DBSYMTAB
484                         decl_seen++;
485 #endif /* DBSYMTAB */
486                 }
487         ]*
488                 {
489 #ifdef DBSYMTAB
490                         ++brc_level;
491                         if (options['g'] && decl_seen) {
492                                 C_ms_std((char *) 0, N_LBRAC, brc_level);
493                         }
494 #endif /* DBSYMTAB */
495                 }
496         [%persistent
497                 statement
498         ]*
499         '}'
500                 {
501                         unstack_level();
502 #ifdef DBSYMTAB
503                         if (options['g'] && decl_seen) {
504                                 C_ms_std((char *) 0, N_RBRAC, brc_level);
505                         }
506                         brc_level--;
507 #endif /* DBSYMTAB */
508                 }
509 ;