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

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

Update SBI to rev. 100.

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