Pristine Ack-5.5
[Ack-5.5.git] / lang / m2 / comp / 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  * Author: Ceriel J.H. Jacobs
6  */
7
8 /* S T A T E M E N T S */
9
10 /* $Id: statement.g,v 1.34 1997/02/21 17:10:16 ceriel Exp $ */
11
12 {
13 #include        <assert.h>
14 #include        <em_arith.h>
15 #include        <em_label.h>
16
17 #include        "idf.h"
18 #include        "LLlex.h"
19 #include        "scope.h"
20 #include        "def.h"
21 #include        "type.h"
22 #include        "node.h"
23
24 static int      loopcount = 0;  /* Count nested loops */
25 extern t_node *EmptyStatement;
26 }
27
28 statement(register t_node **pnd;)
29 {
30         register t_node *nd;
31         extern int return_occurred;
32 } :
33         /*
34          * This part is not in the reference grammar. The reference grammar
35          * states : assignment | ProcedureCall | ...
36          * but this gives LL(1) conflicts
37          */
38         designator(pnd)
39         [                       { nd = dot2node(Stat, *pnd, NULLNODE);
40                                   nd->nd_symb = '(';
41                                   nd->nd_lineno = (*pnd)->nd_lineno;
42                                 }
43                 ActualParameters(&(nd->nd_RIGHT))?
44         |
45                 [ BECOMES       
46                 | %erroneous '='
47                                 { error("':=' expected instead of '='");
48                                   DOT = BECOMES;
49                                 }
50                 ]
51                                 { nd = dot2node(Stat, *pnd, NULLNODE); }
52                 expression(&(nd->nd_RIGHT))
53         ]
54                                 { *pnd = nd; }
55         /*
56          * end of changed part
57          */
58 |
59         IfStatement(pnd)
60 |
61         CaseStatement(pnd)
62 |
63         WHILE           { *pnd = nd = dot2leaf(Stat); }
64         expression(&(nd->nd_LEFT))
65         DO
66         StatementSequence(&(nd->nd_RIGHT))
67         END
68 |
69         REPEAT          { *pnd = nd = dot2leaf(Stat); }
70         StatementSequence(&(nd->nd_LEFT))
71         UNTIL
72         expression(&(nd->nd_RIGHT))
73 |
74                         { loopcount++; }
75         LOOP            { *pnd = nd = dot2leaf(Stat); }
76         StatementSequence(&((*pnd)->nd_RIGHT))
77         END
78                         { loopcount--; }
79 |
80         ForStatement(pnd)
81 |
82         WITH            { *pnd = nd = dot2leaf(Stat); }
83         designator(&(nd->nd_LEFT))
84         DO
85         StatementSequence(&(nd->nd_RIGHT))
86         END
87 |
88         EXIT
89                         { if (!loopcount) error("EXIT not in a LOOP");
90                           *pnd = dot2leaf(Stat);
91                         }
92 |
93         ReturnStatement(pnd)
94                         { return_occurred = 1; }
95 |
96         /* empty */     { *pnd = EmptyStatement; }
97 ;
98
99 /*
100  * The next two rules in-line in "Statement", because of an LL(1) conflict
101
102 assignment:
103         designator BECOMES expression
104 ;
105
106 ProcedureCall:
107         designator ActualParameters?
108 ;
109 */
110
111 StatementSequence(register t_node **pnd;)
112 {
113         t_node *nd;
114         register t_node *nd1;
115 } :
116         statement(pnd)
117         [ %persistent
118                 ';'
119                 statement(&nd)
120                         { if (nd != EmptyStatement) {
121                                 nd1 = dot2node(Link, *pnd, nd);
122                                 *pnd = nd1;
123                                 nd1->nd_symb = ';';
124                                 pnd = &(nd1->nd_RIGHT);
125                           }
126                         }
127         ]*
128 ;
129
130 IfStatement(t_node **pnd;)
131 {
132         register t_node *nd;
133 } :
134         IF              { nd = dot2leaf(Stat);
135                           *pnd = nd;
136                         }
137         expression(&(nd->nd_LEFT))
138         THEN            { nd->nd_RIGHT = dot2leaf(Link);
139                           nd = nd->nd_RIGHT;
140                         }
141         StatementSequence(&(nd->nd_LEFT))
142         [
143                 ELSIF   { nd->nd_RIGHT = dot2leaf(Stat);
144                           nd = nd->nd_RIGHT;
145                           nd->nd_symb = IF;
146                         }
147                 expression(&(nd->nd_LEFT))
148                 THEN    { nd->nd_RIGHT = dot2leaf(Link);
149                           nd = nd->nd_RIGHT;
150                         }
151                 StatementSequence(&(nd->nd_LEFT))
152         ]*
153         [
154                 ELSE
155                 StatementSequence(&(nd->nd_RIGHT))
156         |
157         ]
158         END
159 ;
160
161 CaseStatement(t_node **pnd;)
162 {
163         register t_node *nd;
164         t_type *tp = 0;
165 } :
166         CASE            { *pnd = nd = dot2leaf(Stat); }
167         expression(&(nd->nd_LEFT))
168         OF
169         case(&(nd->nd_RIGHT), &tp)
170                         { nd = nd->nd_RIGHT; }
171         [
172                 '|'
173                 case(&(nd->nd_RIGHT), &tp)
174                         { nd = nd->nd_RIGHT; }
175         ]*
176         [ ELSE StatementSequence(&(nd->nd_RIGHT))
177         |
178         ]
179         END
180 ;
181
182 case(t_node **pnd; t_type **ptp;) :
183         [ CaseLabelList(ptp, pnd)
184           ':'           { *pnd = dot2node(Link, *pnd, NULLNODE); }
185           StatementSequence(&((*pnd)->nd_RIGHT))
186         |
187         ]
188                         { *pnd = dot2node(Link, *pnd, NULLNODE);
189                           (*pnd)->nd_symb = '|';
190                         }
191 ;
192
193 /* inline in statement; lack of space 
194 WhileStatement(t_node **pnd;)
195 {
196         register t_node *nd;
197 }:
198         WHILE           { *pnd = nd = dot2leaf(Stat); }
199         expression(&(nd->nd_LEFT))
200         DO
201         StatementSequence(&(nd->nd_RIGHT))
202         END
203 ;
204
205 RepeatStatement(t_node **pnd;)
206 {
207         register t_node *nd;
208 }:
209         REPEAT          { *pnd = nd = dot2leaf(Stat); }
210         StatementSequence(&(nd->nd_LEFT))
211         UNTIL
212         expression(&(nd->nd_RIGHT))
213 ;
214 */
215
216 ForStatement(t_node **pnd;)
217 {
218         register t_node *nd, *nd1;
219 }:
220         FOR             { *pnd = nd = dot2leaf(Stat); }
221         IDENT           { nd1 = dot2leaf(Name); }
222         BECOMES         { nd->nd_LEFT = dot2node(Stat, nd1, dot2leaf(Link));
223                           nd1 = nd->nd_LEFT->nd_RIGHT;
224                           nd1->nd_symb = TO;
225                         }
226         expression(&(nd1->nd_LEFT))
227         TO
228         expression(&(nd1->nd_RIGHT))
229                         { nd->nd_RIGHT = nd1 = dot2leaf(Link); 
230                           nd1->nd_symb = BY;
231                         }
232         [
233                 BY
234                 ConstExpression(&(nd1->nd_LEFT))
235                         { if (!(nd1->nd_LEFT->nd_type->tp_fund & T_INTORCARD)) {
236                                 error("illegal type in BY clause");
237                           }
238                         }
239         |
240                         { nd1->nd_LEFT = dot2leaf(Value);
241                           nd1->nd_LEFT->nd_INT = 1;
242                         }
243         ]
244         DO
245         StatementSequence(&(nd1->nd_RIGHT))
246         END
247 ;
248
249 /* inline in Statement; lack of space
250 LoopStatement(t_node **pnd;):
251         LOOP            { *pnd = dot2leaf(Stat); }
252         StatementSequence(&((*pnd)->nd_RIGHT))
253         END
254 ;
255
256 WithStatement(t_node **pnd;)
257 {
258         register t_node *nd;
259 }:
260         WITH            { *pnd = nd = dot2leaf(Stat); }
261         designator(&(nd->nd_LEFT))
262         DO
263         StatementSequence(&(nd->nd_RIGHT))
264         END
265 ;
266 */
267
268 ReturnStatement(t_node **pnd;)
269 {
270         register t_def *df = CurrentScope->sc_definedby;
271         register t_type *tp = df->df_type ? ResultType(df->df_type) : 0;
272         register t_node *nd;
273 } :
274
275         RETURN          { *pnd = nd = dot2leaf(Stat); }
276         [
277                 expression(&(nd->nd_RIGHT))
278                         { if (scopeclosed(CurrentScope)) {
279 error("a module body cannot return a value");
280                           }
281                           else if (! tp) {
282 error("procedure \"%s\" is not a function, so cannot return a value", df->df_idf->id_text);
283                           }
284                         }
285         |
286                         { if (tp) {
287 error("function procedure \"%s\" must return a value", df->df_idf->id_text);
288                           }
289                         }
290         ]
291 ;