Pristine Ack-5.5
[Ack-5.5.git] / lang / pc / comp / expression.g
1 /* EXPRESSIONS */
2
3 {
4 #include        "debug.h"
5
6 #include        <assert.h>
7 #include        <em_arith.h>
8 #include        <em_label.h>
9
10 #include        "LLlex.h"
11 #include        "chk_expr.h"
12 #include        "def.h"
13 #include        "main.h"
14 #include        "misc.h"
15 #include        "idf.h"
16 #include        "node.h"
17 #include        "scope.h"
18 #include        "type.h"
19 }
20
21 Constant(register struct node **pnd;)
22 {
23         register struct node **nd = pnd;
24 } :
25 %default
26         [
27                 Sign(nd)        { nd = &((*nd)->nd_right); }
28         ]?
29         [ %default
30                 UnsignedNumber(nd)
31         |
32                 ConstantIdentifier(nd)
33         ]
34                                 { (void) ChkConstant(*pnd); }
35 |
36         STRING                  { *pnd = MkLeaf(Value, &dot);
37                                   if( ((*pnd)->nd_type = toktype) != char_type )
38                                         RomString(*pnd);
39                                 }
40 ;
41
42 Sign(register struct node **pnd;):
43         ['+' | '-']             { *pnd = MkLeaf(Uoper, &dot); }
44 ;
45
46 UnsignedNumber(register struct node **pnd;):
47         [INTEGER | REAL]        { *pnd = MkLeaf(Value, &dot);
48                                   (*pnd)->nd_type = toktype;
49                                 }
50 ;
51
52 ConstantIdentifier(register struct node **pnd;):
53         IDENT                   { *pnd = MkLeaf(Name, &dot);
54                                 }
55 ;
56
57 /* ISO section 6.7.1, p. 121 */
58 Expression(register struct node **pnd;):
59         SimpleExpression(pnd)
60         [
61                 /* RelationalOperator substituted inline */
62                 [ '=' | NOTEQUAL | '<' | '>' | LESSEQUAL | GREATEREQUAL | IN ]
63                                 { *pnd = MkNode(Boper, *pnd, NULLNODE, &dot); }
64                 SimpleExpression(&((*pnd)->nd_right))
65         ]?
66 ;
67
68 SimpleExpression(register struct node **pnd;):
69         /* ISO 6.7.1: The signs and the adding-operators have equal precedence,
70                       and are left-associative.
71         */
72         [
73                 Sign(pnd)
74                 Term(&((*pnd)->nd_right))
75         |
76                 Term(pnd)
77         ]
78         [
79                 /* AddingOperator substituted inline */
80                 [ '+' | '-' | OR ]
81                                 { *pnd = MkNode(Boper, *pnd, NULLNODE, &dot); }
82                 Term(&((*pnd)->nd_right))
83         ]*
84 ;
85
86 Term(register struct node **pnd;):
87         Factor(pnd)
88         [
89                 /* MultiplyingOperator substituted inline */
90                 [ '*' | '/' | DIV | MOD | AND ]
91                                 { *pnd = MkNode(Boper, *pnd, NULLNODE, &dot); }
92                 Factor(&((*pnd)->nd_right))
93         ]*
94 ;
95
96 Factor(register struct node **pnd;)
97 {
98         register struct def *df;
99 } :
100         /* This is a changed rule, because the grammar as specified in the
101          * reference is not LL(1), and this gives conflicts.
102          */
103         %default
104         %prefer         /* solve conflicts on IDENT and UnsignedConstant */
105         IDENT                   { *pnd = MkLeaf(Name, &dot); }
106         [
107                 /* ISO section 6.7.3, p. 126
108                  * IDENT is a FunctionIdentifier
109                  */
110                                 {
111                                   *pnd = MkNode(Call, *pnd, NULLNODE, &dot);
112                                 }
113                 ActualParameterList(&((*pnd)->nd_right))
114         |
115                 /* IDENT can be a BoundIdentifier or a ConstantIdentifier or
116                  * a FunctionIdentifier (no parameterlist), in which case
117                  * VariableAccessTail is empty.
118                  * It could also be the beginning of a normal VariableAccess
119                  * (most likely).
120                  */
121                         { int class;
122
123                           df = lookfor(*pnd, CurrVis, 1);
124                           /* df->df_flags |= D_USED; */
125                           if( df->df_type->tp_fund & T_ROUTINE )        {
126                                 /* This part is context-sensitive:
127                                    is the occurence of the proc/func name
128                                    a call or not ?
129                                 */
130                                 if( df->df_type == std_type )
131                                         class = Call;
132                                 else
133                                         class = NameOrCall;
134                                 *pnd = MkNode(class, *pnd, NULLNODE, &dot);
135                                 (*pnd)->nd_symb = '(';
136                           }
137                         }
138
139                 VariableAccessTail(pnd)
140         ]
141 |
142         UnsignedConstant(pnd)
143 |
144         SetConstructor(pnd)
145 |
146         '('                     { /* dummy node to force ChkVariable */
147                                   *pnd = MkLeaf(Uoper, &dot);
148                                 }
149         Expression(&((*pnd)->nd_right))
150         ')'
151 |
152         NOT                     { *pnd = MkLeaf(Uoper, &dot); }
153         Factor(&((*pnd)->nd_right))
154 ;
155
156 UnsignedConstant(register struct node **pnd;):
157         UnsignedNumber(pnd)
158 |
159         STRING                  { *pnd = MkLeaf(Value, &dot);
160                                   if( ((*pnd)->nd_type = toktype) != char_type )
161                                         RomString(*pnd);
162                                 }
163 |
164         ConstantIdentifier(pnd)
165 |
166         NIL                     { *pnd = MkLeaf(Value, &dot);
167                                   (*pnd)->nd_type = nil_type;
168                                   /* to evaluate NIL = NIL */
169                                   (*pnd)->nd_INT = 0;
170                                 }
171 ;
172
173 SetConstructor(register struct node **pnd;)
174 {
175         register struct node *nd;
176 } :
177         '['             { dot.tk_symb = SET;
178                           *pnd = nd = MkLeaf(Xset, &dot);
179                         }
180                 [
181                         MemberDesignator(nd)
182                         [ %persistent
183                                 { nd = nd->nd_right; }
184                                 ',' MemberDesignator(nd)
185                         ]*
186                 ]?
187         ']'
188 ;
189
190 MemberDesignator(register struct node *nd;)
191 {
192         struct node *nd1;
193 } :
194         Expression(&nd1)
195         [ UPTO                  { nd1 = MkNode(Link, nd1, NULLNODE, &dot); }
196           Expression(&(nd1->nd_right))
197         ]?
198                         { nd->nd_right = MkNode(Link, nd1, NULLNODE, &dot);
199                           nd->nd_right->nd_symb = ',';
200                         }
201 ;
202
203 /* ISO section 6.7.2.1, p. 123 */
204 BooleanExpression(register struct node **pnd;):
205         Expression(pnd)
206                         { if( ChkExpression(*pnd) &&
207                                                 (*pnd)->nd_type != bool_type )
208                                 node_error(*pnd, "boolean expression expected");
209                           MarkUsed(*pnd);
210                         }
211 ;
212
213 ActualParameterList(register struct node **pnd;)
214 {
215         register struct node *nd;
216 } :
217         '('
218                 /* ActualParameter substituted inline */
219                 Expression(pnd)         { *pnd = nd =
220                                              MkNode(Link, *pnd, NULLNODE, &dot);
221                                           nd->nd_symb = ',';
222                                         }
223                 [ %persistent
224                         ','             { nd->nd_right = MkLeaf(Link, &dot);
225                                           nd = nd->nd_right;
226                                         }
227                         Expression(&(nd->nd_left))
228                 ]*
229         ')'
230 ;
231
232 /* ISO section 6.5.1, p. 105 */
233 VariableAccess(register struct node **pnd;):
234         /* This is a changed rule, because the grammar as specified in the
235          * reference is not LL(1), and this gives conflicts.
236          *
237          * IDENT is an EntireVariable or
238          * a FieldDesignatorIdentifier (see also 6.8.3.10, p. 132).
239          */
240         IDENT                           { *pnd = MkLeaf(Name, &dot); }
241         VariableAccessTail(pnd)         { (void) ChkVariable(*pnd); }
242 ;
243
244 VariableAccessTail(register struct node **pnd;):
245         /* This is a new rule because the grammar specified by the standard
246          * is not exactly LL(1).
247          */
248
249          /* empty */
250 |
251         /* PointerVariable or FileVariable
252          */
253
254         '^'                     { *pnd = MkNode(Arrow, NULLNODE, *pnd, &dot); }
255
256         /* At this point the VariableAccess is an IdentifiedVariable
257          * ISO section 6.5.4, p. 107 (IdentifiedVariable: PointerVariable '^'),
258          * or
259          * it is a BufferVariable
260          * ISO section 6.5.5, p. 107 (BufferVariable: FileVariable '^').
261          */
262
263         VariableAccessTail(pnd)
264 |
265         /* ArrayVariable
266          */
267
268         '['                     { *pnd = MkNode(Arrsel, *pnd, NULLNODE, &dot); }
269                 /* IndexExpression substituted inline */
270                 Expression(&((*pnd)->nd_right))
271                 [ %persistent
272                         ','     { *pnd = MkNode(Arrsel, *pnd, NULLNODE, &dot);
273                                   (*pnd)->nd_symb = '[';
274                                 }
275                         Expression(&((*pnd)->nd_right))
276                 ]*
277         ']'
278
279         /* At this point the VariableAccess is an IndexedVariable
280          * ISO section 6.5.3.2, p. 106
281          */
282
283         VariableAccessTail(pnd)
284 |
285         /* RecordVariable
286          */
287
288         '.'                     { *pnd = MkNode(Link, *pnd, NULLNODE, &dot); }
289         /* FieldSpecifier & FieldIdentifier substituted inline */
290         IDENT                   { (*pnd)->nd_IDF = dot.TOK_IDF; }
291
292         /* At this point the VariableAccess is a FieldDesignator
293          * ISO section 6.5.3.3, p. 107
294          */
295
296         VariableAccessTail(pnd)
297 ;