source: mainline/uspace/app/sbi/src/parse.c@ b535aeb

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

Update SBI to rev. 128.

  • Property mode set to 100644
File size: 16.4 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 Parser
30 *
31 * Consumes a sequence of lexical elements and produces a syntax tree (stree).
32 * Parsing primitives, module members, statements.
33 */
34
35#include <assert.h>
36#include <stdlib.h>
37#include "debug.h"
38#include "lex.h"
39#include "list.h"
40#include "mytypes.h"
41#include "p_expr.h"
42#include "p_type.h"
43#include "stree.h"
44#include "strtab.h"
45
46#include "parse.h"
47
48/*
49 * Module members
50 */
51static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass);
52static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
53
54static stree_fun_t *parse_fun(parse_t *parse);
55static stree_var_t *parse_var(parse_t *parse);
56static stree_prop_t *parse_prop(parse_t *parse);
57
58static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
59static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
60
61/*
62 * Statements
63 */
64static stree_block_t *parse_block(parse_t *parse);
65static stree_stat_t *parse_stat(parse_t *parse);
66
67static stree_vdecl_t *parse_vdecl(parse_t *parse);
68static stree_if_t *parse_if(parse_t *parse);
69static stree_while_t *parse_while(parse_t *parse);
70static stree_for_t *parse_for(parse_t *parse);
71static stree_raise_t *parse_raise(parse_t *parse);
72static stree_return_t *parse_return(parse_t *parse);
73static stree_wef_t *parse_wef(parse_t *parse);
74static stree_exps_t *parse_exps(parse_t *parse);
75
76static stree_except_t *parse_except(parse_t *parse);
77
78void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
79{
80 parse->program = prog;
81 parse->cur_mod = parse->program->module;
82 parse->lex = lex;
83 lex_next(parse->lex);
84}
85
86/** Parse module. */
87void parse_module(parse_t *parse)
88{
89 stree_csi_t *csi;
90 stree_modm_t *modm;
91 stree_symbol_t *symbol;
92
93 while (lcur_lc(parse) != lc_eof) {
94 switch (lcur_lc(parse)) {
95 case lc_class:
96 case lc_struct:
97 case lc_interface:
98 csi = parse_csi(parse, lcur_lc(parse));
99 modm = stree_modm_new(mc_csi);
100 modm->u.csi = csi;
101
102 symbol = stree_symbol_new(sc_csi);
103 symbol->u.csi = csi;
104 symbol->outer_csi = NULL;
105 csi->symbol = symbol;
106
107 list_append(&parse->cur_mod->members, modm);
108 break;
109 default:
110 lunexpected_error(parse);
111 lex_next(parse->lex);
112 break;
113 }
114
115 }
116}
117
118/** Parse class, struct or interface declaration. */
119static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass)
120{
121 stree_csi_t *csi;
122 csi_class_t cc;
123 stree_csimbr_t *csimbr;
124
125 switch (dclass) {
126 case lc_class: cc = csi_class; break;
127 case lc_struct: cc = csi_struct; break;
128 case lc_interface: cc = csi_interface; break;
129 default: assert(b_false);
130 }
131
132 lskip(parse);
133
134 csi = stree_csi_new(cc);
135 csi->name = parse_ident(parse);
136
137#ifdef DEBUG_PARSE_TRACE
138 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
139 strtab_get_str(csi->name->sid));
140#endif
141 if (lcur_lc(parse) == lc_colon) {
142 /* Inheritance list */
143 lskip(parse);
144 csi->base_csi_ref = parse_texpr(parse);
145 } else {
146 csi->base_csi_ref = NULL;
147 }
148
149 lmatch(parse, lc_is);
150 list_init(&csi->members);
151
152 /* Parse class, struct or interface members. */
153 while (lcur_lc(parse) != lc_end) {
154 csimbr = parse_csimbr(parse, csi);
155 list_append(&csi->members, csimbr);
156 }
157
158 lmatch(parse, lc_end);
159
160 return csi;
161}
162
163/** Parse class, struct or interface member. */
164static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
165{
166 stree_csimbr_t *csimbr;
167
168 stree_csi_t *csi;
169 stree_fun_t *fun;
170 stree_var_t *var;
171 stree_prop_t *prop;
172
173 stree_symbol_t *symbol;
174
175 switch (lcur_lc(parse)) {
176 case lc_class:
177 case lc_struct:
178 case lc_interface:
179 csi = parse_csi(parse, lcur_lc(parse));
180 csimbr = stree_csimbr_new(csimbr_csi);
181 csimbr->u.csi = csi;
182
183 symbol = stree_symbol_new(sc_csi);
184 symbol->u.csi = csi;
185 symbol->outer_csi = outer_csi;
186 csi->symbol = symbol;
187 break;
188 case lc_fun:
189 fun = parse_fun(parse);
190 csimbr = stree_csimbr_new(csimbr_fun);
191 csimbr->u.fun = fun;
192
193 symbol = stree_symbol_new(sc_fun);
194 symbol->u.fun = fun;
195 symbol->outer_csi = outer_csi;
196 fun->symbol = symbol;
197 fun->proc->outer_symbol = symbol;
198 break;
199 case lc_var:
200 var = parse_var(parse);
201 csimbr = stree_csimbr_new(csimbr_var);
202 csimbr->u.var = var;
203
204 symbol = stree_symbol_new(sc_var);
205 symbol->u.var = var;
206 symbol->outer_csi = outer_csi;
207 var->symbol = symbol;
208 break;
209 case lc_prop:
210 prop = parse_prop(parse);
211 csimbr = stree_csimbr_new(csimbr_prop);
212 csimbr->u.prop = prop;
213
214 symbol = stree_symbol_new(sc_prop);
215 symbol->u.prop = prop;
216 symbol->outer_csi = outer_csi;
217 prop->symbol = symbol;
218 if (prop->getter)
219 prop->getter->outer_symbol = symbol;
220 if (prop->setter)
221 prop->setter->outer_symbol = symbol;
222 break;
223 default:
224 lunexpected_error(parse);
225 lex_next(parse->lex);
226 }
227
228 return csimbr;
229}
230
231
232/** Parse member function. */
233static stree_fun_t *parse_fun(parse_t *parse)
234{
235 stree_fun_t *fun;
236 stree_proc_arg_t *arg;
237
238 fun = stree_fun_new();
239
240 lmatch(parse, lc_fun);
241 fun->name = parse_ident(parse);
242 lmatch(parse, lc_lparen);
243
244#ifdef DEBUG_PARSE_TRACE
245 printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
246#endif
247
248 list_init(&fun->args);
249
250 if (lcur_lc(parse) != lc_rparen) {
251
252 /* Parse formal parameters. */
253 while (b_true) {
254 arg = parse_proc_arg(parse);
255
256 if (stree_arg_has_attr(arg, aac_packed)) {
257 fun->varg = arg;
258 break;
259 } else {
260 list_append(&fun->args, arg);
261 }
262
263 if (lcur_lc(parse) == lc_rparen)
264 break;
265
266 lmatch(parse, lc_scolon);
267 }
268 }
269
270 lmatch(parse, lc_rparen);
271
272 if (lcur_lc(parse) == lc_colon) {
273 lskip(parse);
274 fun->rtype = parse_texpr(parse);
275 } else {
276 fun->rtype = NULL;
277 }
278
279 lmatch(parse, lc_is);
280 fun->proc = stree_proc_new();
281 fun->proc->body = parse_block(parse);
282 lmatch(parse, lc_end);
283
284 return fun;
285}
286
287/** Parse member variable. */
288static stree_var_t *parse_var(parse_t *parse)
289{
290 stree_var_t *var;
291
292 var = stree_var_new();
293
294 lmatch(parse, lc_var);
295 var->name = parse_ident(parse);
296 lmatch(parse, lc_colon);
297 var->type = parse_texpr(parse);
298 lmatch(parse, lc_scolon);
299
300 return var;
301}
302
303/** Parse member property. */
304static stree_prop_t *parse_prop(parse_t *parse)
305{
306 stree_prop_t *prop;
307 stree_ident_t *ident;
308 stree_proc_arg_t *arg;
309
310 prop = stree_prop_new();
311 list_init(&prop->args);
312
313 lmatch(parse, lc_prop);
314
315 if (lcur_lc(parse) == lc_self) {
316 /* Indexed property set */
317
318 /* Use some name that is impossible as identifier. */
319 ident = stree_ident_new();
320 ident->sid = strtab_get_sid(INDEXER_IDENT);
321 prop->name = ident;
322
323 lskip(parse);
324 lmatch(parse, lc_lsbr);
325
326 /* Parse formal parameters. */
327 while (b_true) {
328 arg = parse_proc_arg(parse);
329 if (stree_arg_has_attr(arg, aac_packed)) {
330 prop->varg = arg;
331 break;
332 } else {
333 list_append(&prop->args, arg);
334 }
335
336 if (lcur_lc(parse) == lc_rsbr)
337 break;
338
339 lmatch(parse, lc_scolon);
340 }
341
342 lmatch(parse, lc_rsbr);
343 } else {
344 /* Named property */
345 prop->name = parse_ident(parse);
346 }
347
348 lmatch(parse, lc_colon);
349 prop->type = parse_texpr(parse);
350 lmatch(parse, lc_is);
351
352 while (lcur_lc(parse) != lc_end) {
353 switch (lcur_lc(parse)) {
354 case lc_get:
355 lskip(parse);
356 lmatch(parse, lc_is);
357 if (prop->getter != NULL) {
358 printf("Error: Duplicate getter.\n");
359 exit(1);
360 }
361
362 /* Create setter procedure */
363 prop->getter = stree_proc_new();
364 prop->getter->body = parse_block(parse);
365
366 lmatch(parse, lc_end);
367 break;
368 case lc_set:
369 lskip(parse);
370 prop->setter_arg = stree_proc_arg_new();
371 prop->setter_arg->name = parse_ident(parse);
372 prop->setter_arg->type = prop->type;
373 lmatch(parse, lc_is);
374 if (prop->setter != NULL) {
375 printf("Error: Duplicate setter.\n");
376 exit(1);
377 }
378
379 /* Create setter procedure */
380 prop->setter = stree_proc_new();
381 prop->setter->body = parse_block(parse);
382
383 lmatch(parse, lc_end);
384 break;
385 default:
386 lunexpected_error(parse);
387 }
388 }
389
390 lmatch(parse, lc_end);
391
392 return prop;
393}
394
395/** Parse formal function argument. */
396static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
397{
398 stree_proc_arg_t *arg;
399 stree_arg_attr_t *attr;
400
401 arg = stree_proc_arg_new();
402 arg->name = parse_ident(parse);
403 lmatch(parse, lc_colon);
404 arg->type = parse_texpr(parse);
405
406 list_init(&arg->attr);
407
408 /* Parse attributes. */
409 while (lcur_lc(parse) == lc_comma) {
410 lskip(parse);
411 attr = parse_arg_attr(parse);
412 list_append(&arg->attr, attr);
413 }
414
415#ifdef DEBUG_PARSE_TRACE
416 printf("Parsed arg attr, type=%p.\n", arg->type);
417#endif
418 return arg;
419}
420
421/** Parse argument attribute. */
422static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
423{
424 stree_arg_attr_t *attr;
425
426 if (lcur_lc(parse) != lc_packed) {
427 printf("Error: Unexpected attribute '");
428 lem_print(lcur(parse));
429 printf("'.\n");
430 exit(1);
431 }
432
433 lskip(parse);
434
435 attr = stree_arg_attr_new(aac_packed);
436 return attr;
437}
438
439/** Parse statement block. */
440static stree_block_t *parse_block(parse_t *parse)
441{
442 stree_block_t *block;
443 stree_stat_t *stat;
444
445 block = stree_block_new();
446 list_init(&block->stats);
447
448 while (terminates_block(lcur_lc(parse)) != b_true) {
449 stat = parse_stat(parse);
450 list_append(&block->stats, stat);
451 }
452
453 return block;
454}
455
456/** Parse statement. */
457static stree_stat_t *parse_stat(parse_t *parse)
458{
459 stree_stat_t *stat;
460
461 stree_vdecl_t *vdecl_s;
462 stree_if_t *if_s;
463 stree_while_t *while_s;
464 stree_for_t *for_s;
465 stree_raise_t *raise_s;
466 stree_return_t *return_s;
467 stree_wef_t *wef_s;
468 stree_exps_t *exp_s;
469
470 switch (lcur_lc(parse)) {
471 case lc_var:
472 vdecl_s = parse_vdecl(parse);
473 stat = stree_stat_new(st_vdecl);
474 stat->u.vdecl_s = vdecl_s;
475 break;
476 case lc_if:
477 if_s = parse_if(parse);
478 stat = stree_stat_new(st_if);
479 stat->u.if_s = if_s;
480 break;
481 case lc_while:
482 while_s = parse_while(parse);
483 stat = stree_stat_new(st_while);
484 stat->u.while_s = while_s;
485 break;
486 case lc_for:
487 for_s = parse_for(parse);
488 stat = stree_stat_new(st_for);
489 stat->u.for_s = for_s;
490 break;
491 case lc_raise:
492 raise_s = parse_raise(parse);
493 stat = stree_stat_new(st_raise);
494 stat->u.raise_s = raise_s;
495 break;
496 case lc_return:
497 return_s = parse_return(parse);
498 stat = stree_stat_new(st_return);
499 stat->u.return_s = return_s;
500 break;
501 case lc_do:
502 case lc_with:
503 wef_s = parse_wef(parse);
504 stat = stree_stat_new(st_wef);
505 stat->u.wef_s = wef_s;
506 break;
507 default:
508 exp_s = parse_exps(parse);
509 stat = stree_stat_new(st_exps);
510 stat->u.exp_s = exp_s;
511 break;
512 }
513
514#ifdef DEBUG_PARSE_TRACE
515 printf("Parsed statement %p\n", stat);
516#endif
517 return stat;
518}
519
520/** Parse variable declaration statement. */
521static stree_vdecl_t *parse_vdecl(parse_t *parse)
522{
523 stree_vdecl_t *vdecl;
524
525 vdecl = stree_vdecl_new();
526
527 lmatch(parse, lc_var);
528 vdecl->name = parse_ident(parse);
529 lmatch(parse, lc_colon);
530 vdecl->type = parse_texpr(parse);
531
532 if (lcur_lc(parse) == lc_assign) {
533 lskip(parse);
534 (void) parse_expr(parse);
535 }
536
537 lmatch(parse, lc_scolon);
538
539#ifdef DEBUG_PARSE_TRACE
540 printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
541 printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
542 vdecl, vdecl->name, vdecl->name->sid);
543#endif
544 return vdecl;
545}
546
547/** Parse @c if statement, */
548static stree_if_t *parse_if(parse_t *parse)
549{
550 stree_if_t *if_s;
551
552 if_s = stree_if_new();
553
554 lmatch(parse, lc_if);
555 if_s->cond = parse_expr(parse);
556 lmatch(parse, lc_then);
557 if_s->if_block = parse_block(parse);
558
559 if (lcur_lc(parse) == lc_else) {
560 lskip(parse);
561 if_s->else_block = parse_block(parse);
562 } else {
563 if_s->else_block = NULL;
564 }
565
566 lmatch(parse, lc_end);
567 return if_s;
568}
569
570/** Parse @c while statement. */
571static stree_while_t *parse_while(parse_t *parse)
572{
573 stree_while_t *while_s;
574
575 while_s = stree_while_new();
576
577 lmatch(parse, lc_while);
578 while_s->cond = parse_expr(parse);
579 lmatch(parse, lc_do);
580 while_s->body = parse_block(parse);
581 lmatch(parse, lc_end);
582
583 return while_s;
584}
585
586/** Parse @c for statement. */
587static stree_for_t *parse_for(parse_t *parse)
588{
589 stree_for_t *for_s;
590
591 for_s = stree_for_new();
592
593 lmatch(parse, lc_for);
594 lmatch(parse, lc_ident);
595 lmatch(parse, lc_colon);
596 (void) parse_texpr(parse);
597 lmatch(parse, lc_in);
598 (void) parse_expr(parse);
599 lmatch(parse, lc_do);
600 for_s->body = parse_block(parse);
601 lmatch(parse, lc_end);
602
603 return for_s;
604}
605
606/** Parse @c raise statement. */
607static stree_raise_t *parse_raise(parse_t *parse)
608{
609 stree_raise_t *raise_s;
610
611 raise_s = stree_raise_new();
612 lmatch(parse, lc_raise);
613 raise_s->expr = parse_expr(parse);
614 lmatch(parse, lc_scolon);
615
616 return raise_s;
617}
618
619/** Parse @c return statement. */
620static stree_return_t *parse_return(parse_t *parse)
621{
622 stree_return_t *return_s;
623
624 return_s = stree_return_new();
625
626 lmatch(parse, lc_return);
627 return_s->expr = parse_expr(parse);
628 lmatch(parse, lc_scolon);
629
630 return return_s;
631}
632
633/* Parse @c with-except-finally statement. */
634static stree_wef_t *parse_wef(parse_t *parse)
635{
636 stree_wef_t *wef_s;
637 stree_except_t *except_c;
638
639 wef_s = stree_wef_new();
640 list_init(&wef_s->except_clauses);
641
642 if (lcur_lc(parse) == lc_with) {
643 lmatch(parse, lc_with);
644 lmatch(parse, lc_ident);
645 lmatch(parse, lc_colon);
646 (void) parse_texpr(parse);
647 lmatch(parse, lc_assign);
648 (void) parse_expr(parse);
649 }
650
651 lmatch(parse, lc_do);
652 wef_s->with_block = parse_block(parse);
653
654 while (lcur_lc(parse) == lc_except) {
655 except_c = parse_except(parse);
656 list_append(&wef_s->except_clauses, except_c);
657 }
658
659 if (lcur_lc(parse) == lc_finally) {
660 lmatch(parse, lc_finally);
661 lmatch(parse, lc_do);
662 wef_s->finally_block = parse_block(parse);
663 } else {
664 wef_s->finally_block = NULL;
665 }
666
667 lmatch(parse, lc_end);
668
669 return wef_s;
670}
671
672/* Parse expression statement. */
673static stree_exps_t *parse_exps(parse_t *parse)
674{
675 stree_expr_t *expr;
676 stree_exps_t *exps;
677
678 expr = parse_expr(parse);
679 lmatch(parse, lc_scolon);
680
681 exps = stree_exps_new();
682 exps->expr = expr;
683
684 return exps;
685}
686
687/* Parse @c except clause. */
688static stree_except_t *parse_except(parse_t *parse)
689{
690 stree_except_t *except_c;
691
692 except_c = stree_except_new();
693
694 lmatch(parse, lc_except);
695 except_c->evar = parse_ident(parse);
696 lmatch(parse, lc_colon);
697 except_c->etype = parse_texpr(parse);
698 lmatch(parse, lc_do);
699
700 except_c->block = parse_block(parse);
701
702 return except_c;
703}
704
705/** Parse identifier. */
706stree_ident_t *parse_ident(parse_t *parse)
707{
708 stree_ident_t *ident;
709
710 lcheck(parse, lc_ident);
711 ident = stree_ident_new();
712 ident->sid = lcur(parse)->u.ident.sid;
713 lskip(parse);
714
715 return ident;
716}
717
718/** Return current lem. */
719lem_t *lcur(parse_t *parse)
720{
721 return &parse->lex->current;
722}
723
724/** Retturn current lem lclass. */
725lclass_t lcur_lc(parse_t *parse)
726{
727 return parse->lex->current.lclass;
728}
729
730/** Skip to next lem. */
731void lskip(parse_t *parse)
732{
733 lex_next(parse->lex);
734}
735
736/** Verify that lclass of current lem is @a lc. */
737void lcheck(parse_t *parse, lclass_t lc)
738{
739 if (lcur(parse)->lclass != lc) {
740 lem_print_coords(lcur(parse));
741 printf(" Error: expected '"); lclass_print(lc);
742 printf("', got '"); lem_print(lcur(parse));
743 printf("'.\n");
744 exit(1);
745 }
746}
747
748/** Verify that lclass of current lem is @a lc and go to next lem. */
749void lmatch(parse_t *parse, lclass_t lc)
750{
751 lcheck(parse, lc);
752 lskip(parse);
753}
754
755/** Display generic parsing error. */
756void lunexpected_error(parse_t *parse)
757{
758 lem_print_coords(lcur(parse));
759 printf(" Error: unexpected token '");
760 lem_print(lcur(parse));
761 printf("'.\n");
762 exit(1);
763}
764
765/** Basically tells us whether @a lclass is in next(block). */
766bool_t terminates_block(lclass_t lclass)
767{
768 switch (lclass) {
769 case lc_else:
770 case lc_end:
771 case lc_except:
772 case lc_finally:
773 return b_true;
774 default:
775 return b_false;
776 }
777}
Note: See TracBrowser for help on using the repository browser.