comparison lwcc/cc-parse.c @ 502:14a40f8bb4eb

Add various operators to lwcc Add various binary and ternary operators to lwcc, but only those which can work with constant operands. Seems like variables are probably required next.
author William Astle <lost@l-w.ca>
date Wed, 25 Sep 2019 20:23:49 -0600
parents f3e9732973f1
children 7e8298f7bc0a
comparison
equal deleted inserted replaced
501:f3e9732973f1 502:14a40f8bb4eb
167 token_print(ps -> curtok, stderr); 167 token_print(ps -> curtok, stderr);
168 fprintf(stderr, "\n"); 168 fprintf(stderr, "\n");
169 169
170 } 170 }
171 171
172 node_t *parse_expr_real(struct parser_state *ps, int prec);
173
172 node_t *parse_term_real(struct parser_state *ps) 174 node_t *parse_term_real(struct parser_state *ps)
173 { 175 {
174 node_t *rv; 176 node_t *rv;
175 177
176 switch (ps -> curtok -> ttype) 178 switch (ps -> curtok -> ttype)
183 185
184 parse_generr(ps, "term"); 186 parse_generr(ps, "term");
185 return NULL; 187 return NULL;
186 } 188 }
187 189
190 node_t *parse_expr_fncall(struct parser_state *ps, node_t *term1)
191 {
192 if (ps -> curtok -> ttype != TOK_CPAREN)
193 {
194 node_destroy(term1);
195 parse_generr(ps, "missing )");
196 return NULL;
197 }
198 parse_next(ps);
199 return node_create(NODE_OPER_FNCALL, term1, NULL);
200 }
201
202 node_t *parse_expr_postinc(struct parser_state *ps, node_t *term1)
203 {
204 return node_create(NODE_OPER_POSTINC, term1);
205 }
206
207 node_t *parse_expr_postdec(struct parser_state *ps, node_t *term1)
208 {
209 return node_create(NODE_OPER_POSTDEC, term1);
210 }
211
212 node_t *parse_expr_subscript(struct parser_state *ps, node_t *term1)
213 {
214 node_t *term2;
215 term2 = parse_expr_real(ps, 0);
216 if (!term2)
217 {
218 node_destroy(term1);
219 return NULL;
220 }
221 if (ps -> curtok -> ttype != TOK_CSQUARE)
222 {
223 node_destroy(term2);
224 node_destroy(term1);
225 parse_generr(ps, "missing ]");
226 return NULL;
227 }
228 parse_next(ps);
229 return node_create(NODE_OPER_SUBSCRIPT, term1, term2);
230 }
231
232 node_t *parse_expr_cond(struct parser_state *ps, node_t *term1)
233 {
234 node_t *term2, *term3;
235 // conditional operator
236 // NOTE: the middle operand is evaluated as though it is its own
237 // independent expression because the : must appear. The third
238 // operand is evaluated at the ternary operator precedence so that
239 // subsequent operand binding behaves correctly (if surprisingly). This
240 // would be less confusing if the ternary operator was fully bracketed
241 // (that is, had a terminator)
242 term2 = parse_expr_real(ps, 0);
243 if (!term2)
244 {
245 node_destroy(term1);
246 return NULL;
247 }
248 if (ps -> curtok -> ttype == TOK_COLON)
249 {
250 parse_next(ps);
251 term3 = parse_expr_real(ps, 25);
252 if (!term3)
253 {
254 node_destroy(term1);
255 node_destroy(term2);
256 return NULL;
257 }
258 return node_create(NODE_OPER_COND, term1, term2, term3);
259 }
260 else
261 {
262 node_destroy(term1);
263 node_destroy(term2);
264 parse_generr(ps, "missing :");
265 return NULL;
266 }
267 }
268
188 node_t *parse_expr_real(struct parser_state *ps, int prec) 269 node_t *parse_expr_real(struct parser_state *ps, int prec)
189 { 270 {
190 static struct { int tok; int nodetype; int prec; } operlist[] = { 271 static struct { int tok; int nodetype; int prec; int ra; node_t *(*spec)(struct parser_state *, node_t *); } operlist[] = {
272 // { TOK_OPAREN, NODE_OPER_FNCALL, 200, 0, parse_expr_fncall },
273 // { TOK_OSQUARE, NODE_OPER_SUBSCRIPT, 200, 0, parse_expr_subscript },
274 // { TOK_ARROW, NODE_OPER_PTRMEM, 200, 0 },
275 // { TOK_DOT, NODE_OPER_OBJMEM, 200, 0 },
276 // { TOK_DBLADD, NODE_OPER_POSTINC, 200, 0, parse_expr_postinc },
277 // { TOK_DBLSUB, NODE_OPER_POSTDEC, 200, 0, parse_expr_postdec },
191 { TOK_STAR, NODE_OPER_TIMES, 150 }, 278 { TOK_STAR, NODE_OPER_TIMES, 150 },
192 { TOK_DIV, NODE_OPER_DIVIDE, 150 }, 279 { TOK_DIV, NODE_OPER_DIVIDE, 150 },
280 { TOK_MOD, NODE_OPER_MOD, 150 },
193 { TOK_ADD, NODE_OPER_PLUS, 100 }, 281 { TOK_ADD, NODE_OPER_PLUS, 100 },
194 { TOK_SUB, NODE_OPER_MINUS, 100 }, 282 { TOK_SUB, NODE_OPER_MINUS, 100 },
283 { TOK_LSH, NODE_OPER_LSH, 90 },
284 { TOK_RSH, NODE_OPER_RSH, 90 },
285 { TOK_LT, NODE_OPER_LT, 80 },
286 { TOK_LE, NODE_OPER_LE, 80 },
287 { TOK_GT, NODE_OPER_GT, 80 },
288 { TOK_GE, NODE_OPER_GE, 80 },
289 { TOK_EQ, NODE_OPER_EQ, 70 },
290 { TOK_NE, NODE_OPER_NE, 70 },
291 { TOK_BWAND, NODE_OPER_BWAND, 60},
292 { TOK_XOR, NODE_OPER_BWXOR, 55 },
293 { TOK_BWOR, NODE_OPER_BWOR, 50 },
294 { TOK_BAND, NODE_OPER_BAND, 40 },
295 { TOK_BOR, NODE_OPER_BOR, 35 },
296 { TOK_QMARK, NODE_OPER_COND, 25, 1, parse_expr_cond },
297 // { TOK_ASS, NODE_OPER_ASS, 20, 1 },
298 // { TOK_ADDASS, NODE_OPER_ADDASS, 20, 1 },
299 // { TOK_SUBASS, NODE_OPER_SUBASS, 20, 1 },
300 // { TOK_MULASS, NODE_OPER_MULASS, 20, 1 },
301 // { TOK_DIVASS, NODE_OPER_DIVASS, 20, 1 },
302 // { TOK_MODASS, NODE_OPER_MODASS, 20, 1 },
303 // { TOK_LSHASS, NODE_OPER_LSHASS, 20, 1 },
304 // { TOK_RSHASS, NODE_OPER_RSHASS, 20, 1 },
305 // { TOK_BWANDASS, NODE_OPER_BWANDASS, 20, 1},
306 // { TOK_BWORASS, NODE_OPER_BWORASS, 20, 1 },
307 // { TOK_XORASS, NODE_OPER_BWXORASS, 20, 1 },
308 { TOK_COMMA, NODE_OPER_COMMA, 1 },
195 { 0, 0, 0 } 309 { 0, 0, 0 }
196 }; 310 };
197 node_t *term1, *term2; 311 node_t *term1, *term2;
198 int i; 312 int i;
199 313
208 fprintf(stderr, "Matched operator: %d, %d\n", operlist[i].tok, operlist[i].prec); 322 fprintf(stderr, "Matched operator: %d, %d\n", operlist[i].tok, operlist[i].prec);
209 // if we hit the end of the expression, return 323 // if we hit the end of the expression, return
210 if (operlist[i].tok == 0) 324 if (operlist[i].tok == 0)
211 return term1; 325 return term1;
212 326
213 // is the next operator less or same precedence? 327 // is previous operation higher precedence? If so, just return the first term
214 if (operlist[i].prec <= prec) 328 if (operlist[i].prec < prec)
215 return term1; 329 return term1;
216 330
331 // is this operator left associative and previous operation is same precedence?
332 // if so, just return the first term
333 if (operlist[i].ra == 0 && operlist[i].prec == prec)
334 return term1;
335
336 // consume the operator
217 parse_next(ps); 337 parse_next(ps);
338
339 // special handling
340 if (operlist[i].spec)
341 {
342 term2 = (operlist[i].spec)(ps, term1);
343 if (!term2)
344 {
345 node_destroy(term1);
346 return NULL;
347 }
348 term1 = term2;
349 goto nextoper;
350 }
218 term2 = parse_expr_real(ps, operlist[i].prec); 351 term2 = parse_expr_real(ps, operlist[i].prec);
219 if (!term2) 352 if (!term2)
220 { 353 {
221 parse_generr(ps, "expr"); 354 parse_generr(ps, "expr");
222 node_destroy(term2); 355 node_destroy(term1);
223 } 356 }
224 357
225 term1 = node_create(operlist[i].nodetype, term1, term2); 358 term1 = node_create(operlist[i].nodetype, term1, term2);
226 term2 = NULL; 359 term2 = NULL;
227 goto nextoper; 360 goto nextoper;