source: mainline/uspace/app/sbi/src/p_expr.c@ 38aaacc2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 38aaacc2 was 074444f, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 184.

  • Property mode set to 100644
File size: 14.0 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Parse arithmetic expressions. */
30
31#include <assert.h>
32#include <stdlib.h>
33#include "bigint.h"
34#include "debug.h"
35#include "lex.h"
36#include "list.h"
37#include "mytypes.h"
38#include "p_type.h"
39#include "parse.h"
40#include "stree.h"
41
42#include "p_expr.h"
43
44static stree_expr_t *parse_assign(parse_t *parse);
45static stree_expr_t *parse_comparative(parse_t *parse);
46static stree_expr_t *parse_additive(parse_t *parse);
47static stree_expr_t *parse_multip(parse_t *parse);
48static stree_expr_t *parse_prefix(parse_t *parse);
49static stree_expr_t *parse_prefix_new(parse_t *parse);
50static stree_expr_t *parse_postfix(parse_t *parse);
51static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a);
52static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a);
53static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a);
54static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a);
55static stree_expr_t *parse_paren(parse_t *parse);
56static stree_expr_t *parse_primitive(parse_t *parse);
57static stree_expr_t *parse_nameref(parse_t *parse);
58static stree_expr_t *parse_lit_bool(parse_t *parse);
59static stree_expr_t *parse_lit_char(parse_t *parse);
60static stree_expr_t *parse_lit_int(parse_t *parse);
61static stree_expr_t *parse_lit_ref(parse_t *parse);
62static stree_expr_t *parse_lit_string(parse_t *parse);
63static stree_expr_t *parse_self_ref(parse_t *parse);
64
65static stree_expr_t *parse_recovery_expr(parse_t *parse);
66
67/** Parse expression.
68 *
69 * Input is read from the input object associated with @a parse. If any
70 * error occurs, parse->error will @c b_true when this function
71 * returns. parse->error_bailout will be @c b_true if the error has not
72 * been recovered yet. Similar holds for other parsing functions in this
73 * module.
74 *
75 * @param parse Parser object.
76 */
77stree_expr_t *parse_expr(parse_t *parse)
78{
79#ifdef DEBUG_PARSE_TRACE
80 printf("Parse expression.\n");
81#endif
82 if (parse_is_error(parse))
83 return parse_recovery_expr(parse);
84
85 return parse_assign(parse);
86}
87
88/** Parse assignment expression.
89 *
90 * @param parse Parser object.
91 */
92static stree_expr_t *parse_assign(parse_t *parse)
93{
94 stree_expr_t *a, *b, *tmp;
95 stree_assign_t *assign;
96
97 a = parse_comparative(parse);
98
99 switch (lcur_lc(parse)) {
100 case lc_assign:
101 assign = stree_assign_new(ac_set);
102 break;
103 case lc_increase:
104 assign = stree_assign_new(ac_increase);
105 break;
106 default:
107 return a;
108 }
109
110 lskip(parse);
111 b = parse_comparative(parse);
112
113 assign->dest = a;
114 assign->src = b;
115
116 tmp = stree_expr_new(ec_assign);
117 tmp->u.assign = assign;
118 return tmp;
119}
120
121/** Parse comparative expression.
122 *
123 * @param parse Parser object.
124 */
125static stree_expr_t *parse_comparative(parse_t *parse)
126{
127 stree_expr_t *a, *b, *tmp;
128 stree_binop_t *binop;
129 binop_class_t bc;
130
131 a = parse_additive(parse);
132
133 while (lcur_lc(parse) == lc_equal || lcur_lc(parse) == lc_notequal ||
134 lcur_lc(parse) == lc_lt || lcur_lc(parse) == lc_gt ||
135 lcur_lc(parse) == lc_lt_equal || lcur_lc(parse) == lc_gt_equal) {
136
137 if (parse_is_error(parse))
138 break;
139
140 switch (lcur_lc(parse)) {
141 case lc_equal: bc = bo_equal; break;
142 case lc_notequal: bc = bo_notequal; break;
143 case lc_lt: bc = bo_lt; break;
144 case lc_gt: bc = bo_gt; break;
145 case lc_lt_equal: bc = bo_lt_equal; break;
146 case lc_gt_equal: bc = bo_gt_equal; break;
147 default: assert(b_false);
148 }
149
150 lskip(parse);
151 b = parse_additive(parse);
152
153 binop = stree_binop_new(bc);
154 binop->arg1 = a;
155 binop->arg2 = b;
156
157 tmp = stree_expr_new(ec_binop);
158 tmp->u.binop = binop;
159 a = tmp;
160 }
161
162 return a;
163}
164
165/** Parse additive expression.
166 *
167 * @param parse Parser object.
168 */
169static stree_expr_t *parse_additive(parse_t *parse)
170{
171 stree_expr_t *a, *b, *tmp;
172 stree_binop_t *binop;
173 binop_class_t bc;
174
175 a = parse_multip(parse);
176 while (lcur_lc(parse) == lc_plus || lcur_lc(parse) == lc_minus) {
177 if (parse_is_error(parse))
178 break;
179
180 switch (lcur_lc(parse)) {
181 case lc_plus: bc = bo_plus; break;
182 case lc_minus: bc = bo_minus; break;
183 default: assert(b_false);
184 }
185
186 lskip(parse);
187 b = parse_multip(parse);
188
189 binop = stree_binop_new(bc);
190 binop->arg1 = a;
191 binop->arg2 = b;
192
193 tmp = stree_expr_new(ec_binop);
194 tmp->u.binop = binop;
195 a = tmp;
196 }
197
198 return a;
199}
200
201/** Parse multiplicative expression.
202 *
203 * @param parse Parser object.
204 */
205static stree_expr_t *parse_multip(parse_t *parse)
206{
207 stree_expr_t *a, *b, *tmp;
208 stree_binop_t *binop;
209 binop_class_t bc;
210
211 a = parse_prefix(parse);
212 while (lcur_lc(parse) == lc_mult) {
213 if (parse_is_error(parse))
214 break;
215
216 switch (lcur_lc(parse)) {
217 case lc_mult: bc = bo_mult; break;
218 default: assert(b_false);
219 }
220
221 lskip(parse);
222 b = parse_prefix(parse);
223
224 binop = stree_binop_new(bc);
225 binop->arg1 = a;
226 binop->arg2 = b;
227
228 tmp = stree_expr_new(ec_binop);
229 tmp->u.binop = binop;
230 a = tmp;
231 }
232
233 return a;
234}
235
236/** Parse prefix expression.
237 *
238 * @param parse Parser object.
239 */
240static stree_expr_t *parse_prefix(parse_t *parse)
241{
242 stree_expr_t *a;
243 stree_expr_t *tmp;
244 stree_unop_t *unop;
245 unop_class_t uc;
246
247 switch (lcur_lc(parse)) {
248 case lc_plus:
249 case lc_minus:
250 if (parse_is_error(parse))
251 return parse_recovery_expr(parse);
252
253 switch (lcur_lc(parse)) {
254 case lc_plus: uc = uo_plus; break;
255 case lc_minus: uc = uo_minus; break;
256 default: assert(b_false);
257 }
258
259 lskip(parse);
260 a = parse_postfix(parse);
261
262 unop = stree_unop_new(uc);
263 unop->arg = a;
264
265 tmp = stree_expr_new(ec_unop);
266 tmp->u.unop = unop;
267 a = tmp;
268 break;
269 case lc_new:
270 a = parse_prefix_new(parse);
271 break;
272 default:
273 a = parse_postfix(parse);
274 break;
275 }
276
277 return a;
278}
279
280/** Parse @c new operator.
281 *
282 * @param parse Parser object.
283 */
284static stree_expr_t *parse_prefix_new(parse_t *parse)
285{
286 stree_texpr_t *texpr;
287 stree_new_t *new_op;
288 stree_expr_t *expr;
289
290 lmatch(parse, lc_new);
291 texpr = parse_texpr(parse);
292
293 /* Parenthesis should be present except for arrays. */
294 if (texpr->tc != tc_tindex) {
295 lmatch(parse, lc_lparen);
296 lmatch(parse, lc_rparen);
297 }
298
299 new_op = stree_new_new();
300 new_op->texpr = texpr;
301 expr = stree_expr_new(ec_new);
302 expr->u.new_op = new_op;
303
304 return expr;
305}
306
307/** Parse postfix expression.
308 *
309 * @param parse Parser object.
310 */
311static stree_expr_t *parse_postfix(parse_t *parse)
312{
313 stree_expr_t *a;
314 stree_expr_t *tmp;
315
316 a = parse_paren(parse);
317
318 while (lcur_lc(parse) == lc_period || lcur_lc(parse) == lc_lparen ||
319 lcur_lc(parse) == lc_lsbr || lcur_lc(parse) == lc_as) {
320
321 if (parse_is_error(parse))
322 break;
323
324 switch (lcur_lc(parse)) {
325 case lc_period:
326 tmp = parse_pf_access(parse, a);
327 break;
328 case lc_lparen:
329 tmp = parse_pf_call(parse, a);
330 break;
331 case lc_lsbr:
332 tmp = parse_pf_index(parse, a);
333 break;
334 case lc_as:
335 tmp = parse_pf_as(parse, a);
336 break;
337 default:
338 assert(b_false);
339 }
340
341 a = tmp;
342 }
343
344 return a;
345}
346
347/** Parse member access expression
348 *
349 * @param parse Parser object.
350 */
351static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a)
352{
353 stree_ident_t *ident;
354 stree_expr_t *expr;
355 stree_access_t *access;
356
357 lmatch(parse, lc_period);
358 ident = parse_ident(parse);
359
360 access = stree_access_new();
361 access->arg = a;
362 access->member_name = ident;
363
364 expr = stree_expr_new(ec_access);
365 expr->u.access = access;
366
367 return expr;
368}
369
370/** Parse function call expression.
371 *
372 * @param parse Parser object.
373 */
374static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a)
375{
376 stree_expr_t *expr;
377 stree_call_t *call;
378 stree_expr_t *arg;
379
380 lmatch(parse, lc_lparen);
381
382 call = stree_call_new();
383 call->fun = a;
384 list_init(&call->args);
385
386 /* Parse function arguments */
387
388 if (lcur_lc(parse) != lc_rparen) {
389 while (!parse_is_error(parse)) {
390 arg = parse_expr(parse);
391 list_append(&call->args, arg);
392
393 if (lcur_lc(parse) == lc_rparen)
394 break;
395 lmatch(parse, lc_comma);
396 }
397 }
398
399 lmatch(parse, lc_rparen);
400
401 expr = stree_expr_new(ec_call);
402 expr->u.call = call;
403
404 return expr;
405}
406
407/** Parse index expression.
408 *
409 * @param parse Parser object.
410 */
411static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a)
412{
413 stree_expr_t *expr;
414 stree_index_t *index;
415 stree_expr_t *arg;
416
417 lmatch(parse, lc_lsbr);
418
419 index = stree_index_new();
420 index->base = a;
421 list_init(&index->args);
422
423 /* Parse indices */
424
425 if (lcur_lc(parse) != lc_rsbr) {
426 while (!parse_is_error(parse)) {
427 arg = parse_expr(parse);
428 list_append(&index->args, arg);
429
430 if (lcur_lc(parse) == lc_rsbr)
431 break;
432 lmatch(parse, lc_comma);
433 }
434 }
435
436 lmatch(parse, lc_rsbr);
437
438 expr = stree_expr_new(ec_index);
439 expr->u.index = index;
440
441 return expr;
442}
443
444/** Parse @c as operator.
445 *
446 * @param parse Parser object.
447 */
448static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a)
449{
450 stree_expr_t *expr;
451 stree_texpr_t *texpr;
452 stree_as_t *as_op;
453
454 lmatch(parse, lc_as);
455 texpr = parse_texpr(parse);
456
457 as_op = stree_as_new();
458 as_op->arg = a;
459 as_op->dtype = texpr;
460 expr = stree_expr_new(ec_as);
461 expr->u.as_op = as_op;
462
463 return expr;
464}
465
466/** Parse possibly partenthesized expression.
467 *
468 * @param parse Parser object.
469 */
470static stree_expr_t *parse_paren(parse_t *parse)
471{
472 stree_expr_t *expr;
473
474 if (lcur_lc(parse) == lc_lparen) {
475 lskip(parse);
476 expr = parse_expr(parse);
477 lmatch(parse, lc_rparen);
478 } else {
479 expr = parse_primitive(parse);
480 }
481
482 return expr;
483}
484
485
486/** Parse primitive expression.
487 *
488 * @param parse Parser object.
489 */
490static stree_expr_t *parse_primitive(parse_t *parse)
491{
492 stree_expr_t *expr;
493
494 switch (lcur_lc(parse)) {
495 case lc_ident:
496 expr = parse_nameref(parse);
497 break;
498 case lc_false:
499 case lc_true:
500 expr = parse_lit_bool(parse);
501 break;
502 case lc_lit_char:
503 expr = parse_lit_char(parse);
504 break;
505 case lc_lit_int:
506 expr = parse_lit_int(parse);
507 break;
508 case lc_nil:
509 expr = parse_lit_ref(parse);
510 break;
511 case lc_lit_string:
512 expr = parse_lit_string(parse);
513 break;
514 case lc_self:
515 expr = parse_self_ref(parse);
516 break;
517 default:
518 lunexpected_error(parse);
519 expr = parse_recovery_expr(parse);
520 }
521
522 return expr;
523}
524
525/** Parse name reference.
526 *
527 * @param parse Parser object.
528 */
529static stree_expr_t *parse_nameref(parse_t *parse)
530{
531 stree_nameref_t *nameref;
532 stree_expr_t *expr;
533
534 nameref = stree_nameref_new();
535 nameref->name = parse_ident(parse);
536 expr = stree_expr_new(ec_nameref);
537 expr->u.nameref = nameref;
538
539 return expr;
540}
541
542/** Parse boolean literal.
543 *
544 * @param parse Parser object.
545 */
546static stree_expr_t *parse_lit_bool(parse_t *parse)
547{
548 stree_literal_t *literal;
549 stree_expr_t *expr;
550 bool_t value;
551
552 switch (lcur_lc(parse)) {
553 case lc_false: value = b_false; break;
554 case lc_true: value = b_true; break;
555 default: assert(b_false);
556 }
557
558 lskip(parse);
559
560 literal = stree_literal_new(ltc_bool);
561 literal->u.lit_bool.value = value;
562
563 expr = stree_expr_new(ec_literal);
564 expr->u.literal = literal;
565
566 return expr;
567}
568
569/** Parse character literal.
570 *
571 * @param parse Parser object.
572 */
573static stree_expr_t *parse_lit_char(parse_t *parse)
574{
575 stree_literal_t *literal;
576 stree_expr_t *expr;
577
578 lcheck(parse, lc_lit_char);
579
580 literal = stree_literal_new(ltc_char);
581 bigint_clone(&lcur(parse)->u.lit_char.value,
582 &literal->u.lit_char.value);
583
584 lskip(parse);
585
586 expr = stree_expr_new(ec_literal);
587 expr->u.literal = literal;
588
589 return expr;
590}
591
592/** Parse integer literal.
593 *
594 * @param parse Parser object.
595 */
596static stree_expr_t *parse_lit_int(parse_t *parse)
597{
598 stree_literal_t *literal;
599 stree_expr_t *expr;
600
601 lcheck(parse, lc_lit_int);
602
603 literal = stree_literal_new(ltc_int);
604 bigint_clone(&lcur(parse)->u.lit_int.value,
605 &literal->u.lit_int.value);
606
607 lskip(parse);
608
609 expr = stree_expr_new(ec_literal);
610 expr->u.literal = literal;
611
612 return expr;
613}
614
615/** Parse reference literal (@c nil).
616 *
617 * @param parse Parser object.
618 */
619static stree_expr_t *parse_lit_ref(parse_t *parse)
620{
621 stree_literal_t *literal;
622 stree_expr_t *expr;
623
624 lmatch(parse, lc_nil);
625
626 literal = stree_literal_new(ltc_ref);
627
628 expr = stree_expr_new(ec_literal);
629 expr->u.literal = literal;
630
631 return expr;
632}
633
634/** Parse string literal.
635 *
636 * @param parse Parser object.
637 */
638static stree_expr_t *parse_lit_string(parse_t *parse)
639{
640 stree_literal_t *literal;
641 stree_expr_t *expr;
642
643 lcheck(parse, lc_lit_string);
644
645 literal = stree_literal_new(ltc_string);
646 literal->u.lit_string.value = lcur(parse)->u.lit_string.value;
647
648 lskip(parse);
649
650 expr = stree_expr_new(ec_literal);
651 expr->u.literal = literal;
652
653 return expr;
654}
655
656/** Parse @c self keyword.
657 *
658 * @param parse Parser object.
659 */
660static stree_expr_t *parse_self_ref(parse_t *parse)
661{
662 stree_self_ref_t *self_ref;
663 stree_expr_t *expr;
664
665 lmatch(parse, lc_self);
666
667 self_ref = stree_self_ref_new();
668
669 expr = stree_expr_new(ec_self_ref);
670 expr->u.self_ref = self_ref;
671
672 return expr;
673}
674
675/** Construct a special recovery expression.
676 *
677 * @param parse Parser object.
678 */
679static stree_expr_t *parse_recovery_expr(parse_t *parse)
680{
681 stree_literal_t *literal;
682 stree_expr_t *expr;
683
684 (void) parse;
685
686 literal = stree_literal_new(ltc_ref);
687
688 expr = stree_expr_new(ec_literal);
689 expr->u.literal = literal;
690
691 return expr;
692}
Note: See TracBrowser for help on using the repository browser.