Mercurial > hg > index.cgi
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; |