Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / 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 3.26 1994/06/24 12:06:12 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        "arith.h"
22 #include        "LLlex.h"
23 #include        "type.h"
24 #include        "idf.h"
25 #include        "label.h"
26 #include        "expr.h"
27 #include        "code.h"
28 #include        "stack.h"
29 #include        "def.h"
30 #ifdef DBSYMTAB
31 #include        <stb.h>
32 #endif /* DBSYMTAB */
33
34 extern int level;
35 extern char options[];
36 }
37
38 /*      Each statement construction is stacked in order to trace a ???
39         statement to such a construction. Example: a case statement should
40         be recognized as a piece of the most enclosing switch statement.
41 */
42
43 /* 9 */
44 statement
45         {
46 #ifdef  LINT
47                 lint_statement();
48 #endif  /* LINT */
49         }
50 :
51 %if (AHEAD != ':')
52         expression_statement
53 |
54         label ':' statement
55 |
56         compound_statement
57 |
58         if_statement
59 |
60         while_statement
61 |
62         do_statement
63 |
64         for_statement
65 |
66         switch_statement
67 |
68         case_statement
69 |
70         default_statement
71 |
72         BREAK
73         {
74                 code_break();
75 #ifdef  LINT
76                 lint_break_stmt();
77 #endif  /* LINT */
78         }
79         ';'
80 |
81         CONTINUE
82         {
83                 code_continue();
84 #ifdef  LINT
85                 lint_continue_stmt();
86 #endif  /* LINT */
87         }
88         ';'
89 |
90         return_statement
91 |
92         jump
93 |
94         ';'
95 |
96         asm_statement
97 ;
98
99
100 expression_statement
101         {       struct expr *expr;
102         }
103 :
104         expression(&expr)
105         ';'
106                 {
107 #ifdef  DEBUG
108                         print_expr("expression_statement", expr);
109 #endif  /* DEBUG */
110                         code_expr(expr, RVAL, FALSE, NO_LABEL, NO_LABEL);
111                         free_expression(expr);
112                 }
113 ;
114
115 label
116         {       struct idf *idf;
117         }
118 :
119         identifier(&idf)
120         {
121                 /*      This allows the following absurd case:
122
123                                 typedef int grz;
124                                 main()  {
125                                         grz: printf("A labelled statement\n");
126                                 }
127                 */
128 #ifdef  LINT
129                 lint_label();
130 #endif  /* LINT */
131                 define_label(idf);
132                 C_df_ilb((label)idf->id_def->df_address);
133         }
134 ;
135
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 while_statement
198         {
199                 struct expr *expr;
200                 label l_break = text_label();
201                 label l_continue = text_label();
202                 label l_body = text_label();
203         }
204 :
205         WHILE
206                 {
207                         stack_stmt(l_break, l_continue);
208                         C_df_ilb(l_continue);
209                 }
210         '('
211         expression(&expr)
212                 {
213                         opnd2test(&expr, WHILE);
214                         if (is_cp_cst(expr))    {
215                                 if (expr->VL_VALUE == (arith)0) {
216                                         C_bra(l_break);
217                                 }
218                         }
219                         else    {
220                                 code_expr(expr, RVAL, TRUE, l_body, l_break);
221                                 C_df_ilb(l_body);
222                         }
223
224 #ifdef  LINT
225                         start_while_stmt(expr);
226 #endif  /* LINT */
227
228                 }
229         ')'
230         statement
231                 {
232                         C_bra(l_continue);
233                         C_df_ilb(l_break);
234                         unstack_stmt();
235                         free_expression(expr);
236 #ifdef  LINT
237                         end_loop_body();
238                         end_loop_stmt();
239 #endif  /* LINT */
240                 }
241 ;
242
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 for_statement
294         {       struct expr *e_init = 0, *e_test = 0, *e_incr = 0;
295                 label l_break = text_label();
296                 label l_continue = text_label();
297                 label l_body = text_label();
298                 label l_test = text_label();
299         }
300 :
301         FOR
302                 {       stack_stmt(l_break, l_continue);
303                 }
304         '('
305         [
306                 expression(&e_init)
307                 {       code_expr(e_init, RVAL, FALSE, NO_LABEL, NO_LABEL);
308                 }
309         ]?
310         ';'
311                 {       C_df_ilb(l_test);
312                 }
313         [
314                 expression(&e_test)
315                 {
316                         opnd2test(&e_test, FOR);
317                         if (is_cp_cst(e_test))  {
318                                 if (e_test->VL_VALUE == (arith)0)       {
319                                         C_bra(l_break);
320                                 }
321                         }
322                         else    {
323                                 code_expr(e_test, RVAL, TRUE, l_body, l_break);
324                                 C_df_ilb(l_body);
325                         }
326                 }
327         ]?
328         ';'
329         expression(&e_incr)?
330         ')'
331                 {
332 #ifdef  LINT
333                         start_for_stmt(e_test);
334 #endif  /* LINT */
335                 }
336         statement
337                 {
338 #ifdef  LINT
339                         end_loop_body();
340 #endif  /* LINT */
341                         C_df_ilb(l_continue);
342                         if (e_incr)
343                                 code_expr(e_incr, RVAL, FALSE,
344                                                         NO_LABEL, NO_LABEL);
345                         C_bra(l_test);
346                         C_df_ilb(l_break);
347                         unstack_stmt();
348                         free_expression(e_init);
349                         free_expression(e_test);
350                         free_expression(e_incr);
351 #ifdef  LINT
352                         end_loop_stmt();
353 #endif  /* LINT */
354                 }
355 ;
356
357 switch_statement
358         {
359                 struct expr *expr;
360         }
361 :
362         SWITCH
363         '('
364         expression(&expr)
365                 {
366                         code_startswitch(&expr);
367 #ifdef  LINT
368                         start_switch_part(is_cp_cst(expr));
369 #endif  /* LINT */
370                 }
371         ')'
372         statement
373                 {
374 #ifdef  LINT
375                         end_switch_stmt();
376 #endif  /* LINT */
377                         code_endswitch();
378                         free_expression(expr);
379                 }
380 ;
381
382 case_statement
383         {
384                 struct expr *expr;
385         }
386 :
387         CASE
388         constant_expression(&expr)
389                 {
390 #ifdef  LINT
391                         lint_case_stmt(0);
392 #endif  /* LINT */
393                         code_case(expr);
394                         free_expression(expr);
395                 }
396         ':'
397         statement
398 ;
399
400 default_statement
401 :
402         DEFAULT
403                 {
404 #ifdef  LINT
405                         lint_case_stmt(1);
406 #endif  /* LINT */
407                         code_default();
408                 }
409         ':'
410         statement
411 ;
412
413 return_statement
414         {       struct expr *expr = 0;
415         }
416 :
417         RETURN
418         [
419                 expression(&expr)
420                 {
421 #ifdef  LINT
422                         lint_ret_conv(expr);
423 #endif  /* LINT */
424
425                         do_return_expr(expr);
426                         free_expression(expr);
427 #ifdef  LINT
428                         lint_return_stmt(VALRETURNED);
429 #endif  /* LINT */
430                 }
431         |
432                 empty
433                 {
434                         do_return();
435 #ifdef  LINT
436                         lint_return_stmt(NOVALRETURNED);
437 #endif  /* LINT */
438                 }
439         ]
440         ';'
441 ;
442
443 jump
444         {       struct idf *idf;
445         }
446 :
447         GOTO
448         identifier(&idf)
449         ';'
450                 {
451                         apply_label(idf);
452                         C_bra((label)idf->id_def->df_address);
453 #ifdef  LINT
454                         lint_jump_stmt(idf);
455 #endif  /* LINT */
456                 }
457 ;
458
459 compound_statement
460         {
461 #ifdef DBSYMTAB
462         static int      brc_level = 1;
463         int             decl_seen = brc_level == 1;
464 #endif /* DBSYMTAB */
465         }
466 :
467         '{'
468                 {
469                         stack_level();
470                 }
471         [%while ((DOT != IDENTIFIER && AHEAD != ':') ||
472                  (DOT == IDENTIFIER && AHEAD == IDENTIFIER))
473                         /* >>> conflict on TYPE_IDENTIFIER, IDENTIFIER */
474                 declaration
475                 {
476 #ifdef DBSYMTAB
477                         decl_seen++;
478 #endif /* DBSYMTAB */
479                 }
480         ]*
481                 {
482 #ifdef DBSYMTAB
483                         ++brc_level;
484                         if (options['g'] && decl_seen) {
485                                 C_ms_std((char *) 0, N_LBRAC, brc_level);
486                         }
487 #endif /* DBSYMTAB */
488                 }
489         [%persistent
490                 statement
491         ]*
492         '}'
493                 {
494                         unstack_level();
495 #ifdef DBSYMTAB
496                         if (options['g'] && decl_seen) {
497                                 C_ms_std((char *) 0, N_RBRAC, brc_level);
498                         }
499                         brc_level--;
500 #endif /* DBSYMTAB */
501                 }
502 ;
503
504 asm_statement
505         {       char *asm_bts;
506                 int asm_len;
507         }
508 :
509         ASM
510         '('
511         STRING
512                 {       asm_bts = dot.tk_bts;
513                         asm_len = dot.tk_len;
514                 }
515         ')'
516         ';'
517                 {       code_asm(asm_bts, asm_len);
518                 }
519 ;
520