Pristine Ack-5.5
[Ack-5.5.git] / lang / pc / comp / statement.g
1 /* S T A T E M E N T S */
2 {
3 #include        <alloc.h>
4 #include        <em.h>
5 #include        <stb.h>
6
7 #include        "LLlex.h"
8 #include        "chk_expr.h"
9 #include        "def.h"
10 #include        "desig.h"
11 #include        "f_info.h"
12 #include        "idf.h"
13 #include        "main.h"
14 #include        "misc.h"
15 #include        "node.h"
16 #include        "scope.h"
17 #include        "type.h"
18 #include        "dbsymtab.h"
19
20 int slevel = 0;         /* nesting level of statements */
21 }
22
23
24 /* ISO section 6.8.3.2, p. 128 */
25 CompoundStatement:
26         BEGIN StatementSequence END
27 ;
28
29 /* ISO section 6.8.3.1, p. 128 */
30 StatementSequence:
31         Statement
32         [ %persistent
33                 ';' Statement
34         ]*
35                                         { chk_labels(slevel + 1); }
36 ;
37
38 /* ISO section 6.8.1, p. 126 */
39 Statement
40 {
41         struct node *nd;
42 } :
43                                         {
44                                           slevel++;
45                                         }
46         [ Label(&nd) ':'
47                                         { if( nd ) DefLabel(nd, slevel); }
48         ]?
49                                         { if( !options['L'] )
50                                                 C_lin((arith) dot.tk_lineno);
51 #ifdef DBSYMTAB
52                                           if (options['g']) {
53                                             static int ms_lineno;
54
55                                             if (ms_lineno != dot.tk_lineno) {
56                                                 C_ms_std((char *) 0, N_SLINE, (int) dot.tk_lineno);
57                                                 ms_lineno = dot.tk_lineno;
58                                             }
59                                           }
60 #endif /* DBSYMTAB */
61                                         }
62         [
63                 SimpleStatement
64         |
65                 StructuredStatement
66         ]
67                                         { slevel--; }
68 ;
69
70 /* ISO section 6.8.2.1, p. 126 */
71 SimpleStatement
72 {
73         struct node *pnd, *expp;
74         unsigned short line;
75 } :
76         /* This is a changed rule, because the grammar as specified in the
77          * reference is not LL(1), and this gives conflicts.
78          * Note : the grammar states : AssignmentStatement |
79          *                              ProcedureStatement | ...
80          * In order to add assertions, there is an extra entry, which gives
81          * a conflict. This conflict is then resolved using an %if clause.
82          */
83         EmptyStatement
84 |
85         GotoStatement
86 |
87         /* Evidently this is the beginning of the changed part
88          */
89         %if( !options['s'] && !strcmp(dot.TOK_IDF->id_text, "assert") )
90         IDENT                   { line = LineNumber; }
91                 Expression(&expp)
92                                 { AssertStat(expp, line);
93                                   FreeNode(expp);
94                                 }
95 |
96         IDENT                   { pnd = MkLeaf(Name, &dot); }
97         [       %default
98
99                 /* At this point the IDENT can be a FunctionIdentifier in
100                  * which case the VariableAccessTail must be empty.
101                  */
102                 VariableAccessTail(&pnd)
103                 [
104                         %default
105                         BECOMES
106                 |
107                         '='     { error("':=' expected instead of '='"); }
108                 ]
109                 Expression(&expp)
110                                 { AssignStat(pnd, expp); }
111         |
112                                 { pnd = MkNode(Call, pnd, NULLNODE, &dot); }
113                 ActualParameterList(&(pnd->nd_right))?
114                                 { ProcStat(pnd);
115
116                                   if( !err_occurred )
117                                         CodeCall(pnd);
118
119                                   FreeNode(pnd);
120                                 }
121
122         ]
123 |
124         InputOutputStatement
125         /* end of changed part
126          */
127 ;
128
129 InputOutputStatement
130 {
131         struct node *nd = NULLNODE;
132 } :
133         /* This is a new rule because the grammar specified by the standard
134          * is not exactly LL(1) (see SimpleStatement).
135          */
136         [
137                 READ ReadParameterList(&nd)             { ChkRead(nd); }
138         |
139                 READLN ReadParameterList(&nd)?          { ChkReadln(nd); }
140         |
141                 WRITE WriteParameterList(&nd)           { ChkWrite(nd); }
142         |
143                 WRITELN WriteParameterList(&nd)?        { ChkWriteln(nd); }
144         ]
145                                                         { FreeNode(nd); }
146 ;
147
148 EmptyStatement:
149         /* empty */
150 ;
151
152 /* ISO section 6.8.3.1, p. 128 */
153 StructuredStatement:
154         CompoundStatement
155 |
156         ConditionalStatement
157 |
158         RepetitiveStatement
159 |
160         WithStatement
161 ;
162
163 /* ISO section 6.8.2.4, p. 127 */
164 GotoStatement
165 {
166         struct node *nd;
167 } :
168         GOTO Label(&nd)
169                                         { if( nd ) TstLabel(nd, slevel); }
170 ;
171
172 /* ISO section 6.8.3.3, p. 128 */
173 ConditionalStatement:
174         %default
175         CaseStatement
176 |
177         IfStatement
178 ;
179
180 /* ISO section 6.8.3.6, p. 129 */
181 RepetitiveStatement:
182         RepeatStatement
183 |
184         WhileStatement
185 |
186         ForStatement
187 ;
188
189 /* ISO section 6.8.3.10, p. 132 */
190 WithStatement
191 {
192         struct scopelist *Save = CurrVis;
193         struct node *nd;
194 } :
195         WITH
196         RecordVariableList(&nd)
197         DO
198         Statement       { EndWith(Save, nd);
199                           chk_labels(slevel + 1);
200                         }
201 ;
202
203 RecordVariableList(register struct node **pnd;)
204 {
205         struct node *nd;
206 } :
207         RecordVariable(&nd)
208                                 { *pnd = nd = MkNode(Link, nd, NULLNODE, &dot);
209                                   nd->nd_symb = ',';
210                                 }
211         [ %persistent
212                 ','             { nd->nd_right = MkLeaf(Link, &dot);
213                                   nd = nd->nd_right;
214                                 }
215                 RecordVariable(&(nd->nd_left))
216         ]*
217 ;
218
219 RecordVariable(register struct node **pnd;):
220         VariableAccess(pnd)
221                                 { WithStat(*pnd); }
222 ;
223
224 /* ISO section 6.8.3.4, p. 128 */
225 IfStatement
226 {
227         struct node *nd;
228         label l1 = ++text_label;
229         label l2 = ++text_label;
230 } :
231         IF
232         BooleanExpression(&nd)
233                                         { struct desig ds;
234                                         
235                                           ds = InitDesig;
236                                           if( !err_occurred )
237                                                 CodeExpr(nd, &ds, l1);
238                                           FreeNode(nd);
239                                         }
240         THEN
241         Statement                       { chk_labels(slevel + 1); }
242         [ %prefer       /* closest matching */
243                 ELSE
244                                         { C_bra(l2);
245                                           C_df_ilb(l1);
246                                         }
247                 Statement
248                                         { C_df_ilb(l2);
249                                           chk_labels(slevel + 1);
250                                         }
251         |
252                 /* empty */
253                                         { C_df_ilb(l1); }
254         ]
255 ;
256
257 /* ISO section 6.8.3.5, p. 128 */
258 CaseStatement
259 {
260         struct node *casend, *nd;
261         label exit_label;
262 } :
263         /* This is a changed rule, because the grammar as specified in the
264          * reference states that a semicolon is optional before END,
265          * and this is not LL(1).
266          */
267         CASE                            { casend = nd = MkLeaf(Link, &dot);
268                                           casend->nd_lab = ++text_label;
269                                           exit_label = ++text_label;
270                                         }
271         Expression(&(nd->nd_left))
272                                         { CaseExpr(casend); }
273         OF
274         CaseListElement(&(nd->nd_right), exit_label)
275                                         { nd = nd->nd_right; }
276         CaseListElementTail(&(nd->nd_right), exit_label)
277         END
278                                         { CaseEnd(casend, exit_label); }
279 ;
280
281 CaseListElementTail(register struct node **pnd; label exit_label;):
282         /* This is a new rule, all because of a silly semicolon
283          */
284         /* empty */
285 |
286 %default
287         ';'
288         [
289                 /* empty */
290         |
291                 CaseListElement(pnd, exit_label)
292                 CaseListElementTail(&((*pnd)->nd_right), exit_label)
293         ]
294 ;
295
296 CaseListElement(register struct node **pnd; label exit_label;):
297         CaseConstantList(pnd)
298         ':'
299                                 { *pnd = MkNode(Link, *pnd, NULLNODE, &dot);
300                                   (*pnd)->nd_lab = ++text_label;
301                                   C_df_ilb(text_label);
302                                 }
303         Statement               { C_bra(exit_label);
304                                   chk_labels(slevel + 1);
305                                 }
306 ;
307
308 /* ISO section 6.8.3.7, p. 129 */
309 RepeatStatement
310 {
311         struct node *nd;
312         label repeatlb = ++text_label;
313 } :
314         REPEAT
315                                         { C_df_ilb(repeatlb); }
316         StatementSequence
317         UNTIL
318         BooleanExpression(&nd)
319                                         { struct desig ds;
320
321                                           ds = InitDesig;
322                                           if( !err_occurred )
323                                                 CodeExpr(nd, &ds, repeatlb);
324                                           FreeNode(nd);
325                                         }
326 ;
327
328 /* ISO section 6.8.3.8, p. 129 */
329 WhileStatement
330 {
331         struct node *nd;
332         label whilelb = ++text_label;
333         label exitlb = ++text_label;
334
335 } :
336         WHILE
337                                         { C_df_ilb(whilelb); }
338         BooleanExpression(&nd)
339                                         { struct desig ds;
340
341                                           ds = InitDesig;
342                                           if( !err_occurred )
343                                                 CodeExpr(nd, &ds, exitlb);
344                                           FreeNode(nd);
345                                         }
346         DO
347         Statement
348                                         { C_bra(whilelb);
349                                           C_df_ilb(exitlb);
350                                           chk_labels(slevel + 1);
351                                         }
352 ;
353
354 /* ISO section 6.8.3.9, p. 130 */
355 ForStatement
356 {
357         register struct node *nd;
358         int stepsize;
359         label l1 = ++text_label;
360         label l2 = ++text_label;
361         arith tmp2 = (arith) 0;
362 } :
363         FOR
364         /* ControlVariable must be an EntireVariable */
365         IDENT                   { nd = MkLeaf(Name, &dot); }
366         BECOMES
367         Expression(&(nd->nd_left))
368         [
369                 TO              { stepsize = 1; }
370         |
371                 DOWNTO          { stepsize = -1; }
372         ]
373         Expression(&(nd->nd_right))
374                                 { ChkForStat(nd);
375                                   if( !err_occurred )   {
376                                         CodePExpr(nd->nd_left);
377                                         C_dup(int_size);
378                                         tmp2 = CodeInitFor(nd->nd_right, 2);
379                                         CodeFor(nd, stepsize, l1, l2);
380                                   }
381                                 }
382         DO
383         Statement
384                                 { if( !err_occurred )
385                                        CodeEndFor(nd, stepsize, l1, l2, tmp2);
386                                   EndForStat(nd);
387                                   chk_labels(slevel + 1);
388                                   FreeNode(nd);
389                                   if( tmp2 ) FreeInt(tmp2);
390                                 }
391 ;
392
393 /* SPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIALSPECIAL */
394 /* ISO section 6.9, p. 132-136 */
395 ReadParameterList(register struct node **pnd;)
396 {
397         register struct node *nd;
398 } :
399         /* This is a changed rule, because the grammar as specified in the
400          * reference is not LL(1), and this gives conflicts.
401          */
402         '('
403                 VariableAccess(pnd)     /* possibly a FileVariable */
404                                         { *pnd = nd =
405                                              MkNode(Link, *pnd, NULLNODE, &dot);
406                                           nd->nd_symb = ',';
407                                         }
408                 [ %persistent
409                         ','             { nd->nd_right = MkLeaf(Link, &dot);
410                                           nd = nd->nd_right;
411                                         }
412                         VariableAccess(&(nd->nd_left))
413                 ]*
414         ')'
415 ;
416
417 WriteParameterList(register struct node **pnd;)
418 {
419         register struct node *nd;
420 } :
421         /* This is a changed rule, because the grammar as specified in the
422          * reference is not LL(1), and this gives conflicts.
423          */
424         '('
425                 /* Only the first WriteParameter can be a FileVariable !!
426                  */
427                 WriteParameter(pnd)
428                                         { *pnd = nd =
429                                              MkNode(Link, *pnd, NULLNODE, &dot);
430                                           nd->nd_symb = ',';
431                                         }
432                 [ %persistent
433                         ','             { nd->nd_right = MkLeaf(Link, &dot);
434                                           nd = nd->nd_right;
435                                         }
436                         WriteParameter(&(nd->nd_left))
437                 ]*
438         ')'
439 ;
440
441 WriteParameter(register struct node **pnd;)
442 {
443         register struct node *nd;
444 } :
445         Expression(pnd)
446                                         { if( !ChkExpression(*pnd) )
447                                                 (*pnd)->nd_type = error_type;
448                                           MarkUsed(*pnd);
449                                           *pnd = nd =
450                                              MkNode(Link, *pnd, NULLNODE, &dot);
451                                           nd->nd_symb = ':';
452                                         }
453         [
454         /* Here the first Expression can't be a FileVariable
455          */
456                 ':'                     { nd->nd_right = MkLeaf(Link, &dot);
457                                           nd = nd->nd_right;
458                                         }
459                 Expression(&(nd->nd_left))
460                                         { if( !ChkExpression(nd->nd_left) )
461                                               nd->nd_left->nd_type = error_type;
462                                           MarkUsed(nd->nd_left);
463                                         }
464                 [
465                         ':'             { nd->nd_right = MkLeaf(Link, &dot);
466                                           nd = nd->nd_right;
467                                         }
468                         Expression(&(nd->nd_left))
469                                         { if( !ChkExpression(nd->nd_left) )
470                                               nd->nd_left->nd_type = error_type;
471                                           MarkUsed(nd->nd_left);
472                                         }
473                 ]?
474         ]?
475 ;