Update GCC and binutils to latest versions
[helenos.git] / uspace / app / sbi / src / parse.c
blob26f19e106e13155232a283a54ce5888d8785760c
1 /*
2 * Copyright (c) 2011 Jiri Svoboda
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
29 /** @file Parser
31 * Consumes a sequence of lexical elements and produces a syntax tree (stree).
32 * Parsing primitives, module members, statements.
35 #include <assert.h>
36 #include <stdlib.h>
37 #include "cspan.h"
38 #include "debug.h"
39 #include "lex.h"
40 #include "list.h"
41 #include "mytypes.h"
42 #include "p_expr.h"
43 #include "p_type.h"
44 #include "stree.h"
45 #include "strtab.h"
46 #include "symbol.h"
48 #include "parse.h"
51 * Module and CSI members
53 static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
54 stree_csi_t *outer_csi);
55 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
57 static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi);
59 static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi);
60 static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum);
62 static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi);
63 static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi);
64 static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi);
65 static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi);
67 static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol);
68 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse);
70 static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
71 static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
72 static stree_fun_sig_t *parse_fun_sig(parse_t *parse);
74 static void parse_prop_get(parse_t *parse, stree_prop_t *prop);
75 static void parse_prop_set(parse_t *parse, stree_prop_t *prop);
78 * Statements
80 static stree_block_t *parse_block(parse_t *parse);
82 static stree_vdecl_t *parse_vdecl(parse_t *parse);
83 static stree_if_t *parse_if(parse_t *parse);
84 static stree_switch_t *parse_switch(parse_t *parse);
85 static stree_while_t *parse_while(parse_t *parse);
86 static stree_for_t *parse_for(parse_t *parse);
87 static stree_raise_t *parse_raise(parse_t *parse);
88 static stree_break_t *parse_break(parse_t *parse);
89 static stree_return_t *parse_return(parse_t *parse);
90 static stree_wef_t *parse_wef(parse_t *parse);
91 static stree_exps_t *parse_exps(parse_t *parse);
93 static stree_except_t *parse_except(parse_t *parse);
95 /** Initialize parser object.
97 * Set up parser @a parse to use lexer @a lex for input and to store
98 * output (i.e. new declarations) to program @a prog. @a prog is not
99 * necessarily empty, the declarations being parsed are simply added
100 * to it.
102 * @param parse Parser object.
103 * @param prog Destination program stree.
104 * @param lex Input lexer.
106 void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
108 parse->program = prog;
109 parse->cur_mod = parse->program->module;
110 parse->lex = lex;
112 parse->error = b_false;
113 parse->error_bailout = b_false;
115 lex_next(parse->lex);
118 /** Parse module.
120 * Parse a program module.
122 * The input is read using the lexer associated with @a parse. The resulting
123 * declarations are added to existing declarations in the program associated
124 * with @a parse.
126 * If any parse error occurs, parse->error will @c b_true when this function
127 * returns. parse->error_bailout will be @c b_true if the error has not
128 * been recovered yet. Similar holds for other parsing functions in this
129 * module.
131 * @param parse Parser object.
133 void parse_module(parse_t *parse)
135 stree_csi_t *csi;
136 stree_enum_t *enum_d;
137 stree_modm_t *modm;
139 while (lcur_lc(parse) != lc_eof && !parse_is_error(parse)) {
140 switch (lcur_lc(parse)) {
141 case lc_class:
142 case lc_struct:
143 case lc_interface:
144 csi = parse_csi(parse, lcur_lc(parse), NULL);
145 modm = stree_modm_new(mc_csi);
146 modm->u.csi = csi;
148 list_append(&parse->cur_mod->members, modm);
149 break;
150 case lc_enum:
151 enum_d = parse_enum(parse, NULL);
152 modm = stree_modm_new(mc_enum);
153 modm->u.enum_d = enum_d;
155 list_append(&parse->cur_mod->members, modm);
156 break;
157 default:
158 lunexpected_error(parse);
159 lex_next(parse->lex);
160 break;
166 /** Parse class, struct or interface declaration.
168 * @param parse Parser object.
169 * @param dclass What to parse: @c lc_class, @c lc_struct or @c lc_csi.
170 * @param outer_csi CSI containing this declaration or @c NULL if global.
171 * @return New syntax tree node.
173 static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
174 stree_csi_t *outer_csi)
176 stree_csi_t *csi;
177 csi_class_t cc;
178 stree_csimbr_t *csimbr;
179 stree_symbol_t *symbol;
180 stree_ident_t *targ_name;
181 stree_targ_t *targ;
182 stree_texpr_t *pref;
184 switch (dclass) {
185 case lc_class:
186 cc = csi_class;
187 break;
188 case lc_struct:
189 cc = csi_struct;
190 break;
191 case lc_interface:
192 cc = csi_interface;
193 break;
194 default:
195 assert(b_false);
198 lskip(parse);
200 csi = stree_csi_new(cc);
201 csi->name = parse_ident(parse);
203 list_init(&csi->targ);
205 while (lcur_lc(parse) == lc_slash) {
206 lskip(parse);
207 targ_name = parse_ident(parse);
209 targ = stree_targ_new();
210 targ->name = targ_name;
212 list_append(&csi->targ, targ);
215 symbol = stree_symbol_new(sc_csi);
216 symbol->u.csi = csi;
217 symbol->outer_csi = outer_csi;
218 csi->symbol = symbol;
220 #ifdef DEBUG_PARSE_TRACE
221 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
222 strtab_get_str(csi->name->sid));
223 #endif
224 if (lcur_lc(parse) == lc_colon) {
225 /* Inheritance list */
226 lskip(parse);
228 while (b_true) {
229 pref = parse_texpr(parse);
230 if (parse_is_error(parse))
231 break;
233 list_append(&csi->inherit, pref);
234 if (lcur_lc(parse) != lc_plus)
235 break;
237 lskip(parse);
241 lmatch(parse, lc_is);
242 list_init(&csi->members);
244 /* Parse class, struct or interface members. */
245 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
246 csimbr = parse_csimbr(parse, csi);
247 if (csimbr == NULL)
248 continue;
250 list_append(&csi->members, csimbr);
253 lmatch(parse, lc_end);
255 if (outer_csi != NULL) {
256 switch (outer_csi->cc) {
257 case csi_class:
258 case csi_struct:
259 break;
260 case csi_interface:
261 cspan_print(csi->name->cspan);
262 printf(" Error: CSI declared inside interface.\n");
263 parse_note_error(parse);
264 /* XXX Free csi */
265 return NULL;
269 return csi;
272 /** Parse class, struct or interface member.
274 * @param parse Parser object.
275 * @param outer_csi CSI containing this declaration.
276 * @return New syntax tree node. In case of parse error,
277 * @c NULL may (but need not) be returned.
279 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
281 stree_csimbr_t *csimbr;
283 stree_csi_t *csi;
284 stree_ctor_t *ctor;
285 stree_deleg_t *deleg;
286 stree_enum_t *enum_d;
287 stree_fun_t *fun;
288 stree_var_t *var;
289 stree_prop_t *prop;
291 csimbr = NULL;
293 switch (lcur_lc(parse)) {
294 case lc_class:
295 case lc_struct:
296 case lc_interface:
297 csi = parse_csi(parse, lcur_lc(parse), outer_csi);
298 if (csi != NULL) {
299 csimbr = stree_csimbr_new(csimbr_csi);
300 csimbr->u.csi = csi;
302 break;
303 case lc_new:
304 ctor = parse_ctor(parse, outer_csi);
305 if (ctor != NULL) {
306 csimbr = stree_csimbr_new(csimbr_ctor);
307 csimbr->u.ctor = ctor;
309 break;
310 case lc_deleg:
311 deleg = parse_deleg(parse, outer_csi);
312 if (deleg != NULL) {
313 csimbr = stree_csimbr_new(csimbr_deleg);
314 csimbr->u.deleg = deleg;
316 break;
317 case lc_enum:
318 enum_d = parse_enum(parse, outer_csi);
319 if (enum_d != NULL) {
320 csimbr = stree_csimbr_new(csimbr_enum);
321 csimbr->u.enum_d = enum_d;
323 break;
324 case lc_fun:
325 fun = parse_fun(parse, outer_csi);
326 csimbr = stree_csimbr_new(csimbr_fun);
327 csimbr->u.fun = fun;
328 break;
329 case lc_var:
330 var = parse_var(parse, outer_csi);
331 if (var != NULL) {
332 csimbr = stree_csimbr_new(csimbr_var);
333 csimbr->u.var = var;
335 break;
336 case lc_prop:
337 prop = parse_prop(parse, outer_csi);
338 csimbr = stree_csimbr_new(csimbr_prop);
339 csimbr->u.prop = prop;
340 break;
341 default:
342 lunexpected_error(parse);
343 lex_next(parse->lex);
344 break;
347 return csimbr;
350 /** Parse constructor.
352 * @param parse Parser object.
353 * @param outer_csi CSI containing this declaration or @c NULL if global.
354 * @return New syntax tree node.
356 static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi)
358 stree_ctor_t *ctor;
359 stree_symbol_t *symbol;
360 cspan_t *cspan;
362 ctor = stree_ctor_new();
363 symbol = stree_symbol_new(sc_ctor);
365 symbol->u.ctor = ctor;
366 symbol->outer_csi = outer_csi;
367 ctor->symbol = symbol;
369 lmatch(parse, lc_new);
370 cspan = lprev_span(parse);
372 /* Fake identifier. */
373 ctor->name = stree_ident_new();
374 ctor->name->sid = strtab_get_sid(CTOR_IDENT);
375 ctor->name->cspan = lprev_span(parse);
377 #ifdef DEBUG_PARSE_TRACE
378 printf("Parsing constructor of CSI '");
379 symbol_print_fqn(csi_to_symbol(outer_csi));
380 printf("'.\n");
381 #endif
382 ctor->sig = parse_fun_sig(parse);
383 if (ctor->sig->rtype != NULL) {
384 cspan_print(cspan);
385 printf(" Error: Constructor of CSI '");
386 symbol_print_fqn(csi_to_symbol(outer_csi));
387 printf("' has a return type.\n");
388 parse_note_error(parse);
391 /* Parse attributes. */
392 parse_symbol_attrs(parse, symbol);
394 ctor->proc = stree_proc_new();
395 ctor->proc->outer_symbol = symbol;
397 if (lcur_lc(parse) == lc_scolon) {
398 lskip(parse);
400 /* This constructor has no body. */
401 cspan_print(cspan);
402 printf(" Error: Constructor of CSI '");
403 symbol_print_fqn(csi_to_symbol(outer_csi));
404 printf("' has no body.\n");
405 parse_note_error(parse);
407 ctor->proc->body = NULL;
408 } else {
409 lmatch(parse, lc_is);
410 ctor->proc->body = parse_block(parse);
411 lmatch(parse, lc_end);
414 switch (outer_csi->cc) {
415 case csi_class:
416 case csi_struct:
417 break;
418 case csi_interface:
419 cspan_print(ctor->name->cspan);
420 printf(" Error: Constructor declared inside interface.\n");
421 parse_note_error(parse);
422 /* XXX Free ctor */
423 return NULL;
426 return ctor;
429 /** Parse @c enum declaration.
431 * @param parse Parser object.
432 * @param outer_csi CSI containing this declaration or @c NULL if global.
433 * @return New syntax tree node.
435 static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi)
437 stree_enum_t *enum_d;
438 stree_symbol_t *symbol;
439 stree_embr_t *embr;
441 enum_d = stree_enum_new();
442 symbol = stree_symbol_new(sc_enum);
444 symbol->u.enum_d = enum_d;
445 symbol->outer_csi = outer_csi;
446 enum_d->symbol = symbol;
448 lmatch(parse, lc_enum);
449 enum_d->name = parse_ident(parse);
450 list_init(&enum_d->members);
452 #ifdef DEBUG_PARSE_TRACE
453 printf("Parse enum '%s'.\n", strtab_get_str(enum_d->name->sid));
454 #endif
455 lmatch(parse, lc_is);
457 /* Parse enum members. */
458 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
459 embr = parse_embr(parse, enum_d);
460 if (embr == NULL)
461 break;
463 list_append(&enum_d->members, embr);
466 if (list_is_empty(&enum_d->members)) {
467 cspan_print(enum_d->name->cspan);
468 printf("Error: Enum type '%s' has no members.\n",
469 strtab_get_str(enum_d->name->sid));
470 parse_note_error(parse);
473 lmatch(parse, lc_end);
475 if (outer_csi != NULL) {
476 switch (outer_csi->cc) {
477 case csi_class:
478 case csi_struct:
479 break;
480 case csi_interface:
481 cspan_print(enum_d->name->cspan);
482 printf(" Error: Enum declared inside interface.\n");
483 parse_note_error(parse);
484 /* XXX Free enum */
485 return NULL;
489 return enum_d;
492 /** Parse enum member.
494 * @param parse Parser object.
495 * @param outer_enum Enum containing this declaration.
496 * @return New syntax tree node. In case of parse error,
497 * @c NULL may (but need not) be returned.
499 static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum)
501 stree_embr_t *embr;
503 embr = stree_embr_new();
504 embr->outer_enum = outer_enum;
505 embr->name = parse_ident(parse);
507 lmatch(parse, lc_scolon);
509 return embr;
512 /** Parse delegate.
514 * @param parse Parser object.
515 * @param outer_csi CSI containing this declaration or @c NULL if global.
516 * @return New syntax tree node.
518 static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi)
520 stree_deleg_t *deleg;
521 stree_symbol_t *symbol;
523 deleg = stree_deleg_new();
524 symbol = stree_symbol_new(sc_deleg);
526 symbol->u.deleg = deleg;
527 symbol->outer_csi = outer_csi;
528 deleg->symbol = symbol;
530 lmatch(parse, lc_deleg);
531 deleg->name = parse_ident(parse);
533 #ifdef DEBUG_PARSE_TRACE
534 printf("Parsing delegate '%s'.\n", strtab_get_str(deleg->name->sid));
535 #endif
537 deleg->sig = parse_fun_sig(parse);
539 /* Parse attributes. */
540 parse_symbol_attrs(parse, symbol);
542 lmatch(parse, lc_scolon);
544 switch (outer_csi->cc) {
545 case csi_class:
546 case csi_struct:
547 break;
548 case csi_interface:
549 cspan_print(deleg->name->cspan);
550 printf(" Error: Delegate declared inside interface.\n");
551 parse_note_error(parse);
552 /* XXX Free deleg */
553 return NULL;
556 return deleg;
559 /** Parse member function.
561 * @param parse Parser object.
562 * @param outer_csi CSI containing this declaration or @c NULL if global.
563 * @return New syntax tree node.
565 static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
567 stree_fun_t *fun;
568 stree_symbol_t *symbol;
569 bool_t body_expected;
571 fun = stree_fun_new();
572 symbol = stree_symbol_new(sc_fun);
574 symbol->u.fun = fun;
575 symbol->outer_csi = outer_csi;
576 fun->symbol = symbol;
578 lmatch(parse, lc_fun);
579 fun->name = parse_ident(parse);
581 #ifdef DEBUG_PARSE_TRACE
582 printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
583 #endif
584 fun->sig = parse_fun_sig(parse);
586 /* Parse attributes. */
587 parse_symbol_attrs(parse, symbol);
589 body_expected = !stree_symbol_has_attr(symbol, sac_builtin) &&
590 (outer_csi->cc != csi_interface);
592 fun->proc = stree_proc_new();
593 fun->proc->outer_symbol = symbol;
595 if (lcur_lc(parse) == lc_scolon) {
596 lskip(parse);
598 /* Body not present */
599 if (body_expected) {
600 cspan_print(fun->name->cspan);
601 printf(" Error: Function '");
602 symbol_print_fqn(symbol);
603 printf("' should have a body.\n");
604 parse_note_error(parse);
607 fun->proc->body = NULL;
608 } else {
609 lmatch(parse, lc_is);
610 fun->proc->body = parse_block(parse);
611 lmatch(parse, lc_end);
613 /* Body present */
614 if (!body_expected) {
615 cspan_print(fun->name->cspan);
616 printf(" Error: Function declaration '");
617 symbol_print_fqn(symbol);
618 printf("' should not have a body.\n");
619 parse_note_error(parse);
623 return fun;
626 /** Parse member variable.
628 * @param parse Parser object.
629 * @param outer_csi CSI containing this declaration or @c NULL if global.
630 * @return New syntax tree node.
632 static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi)
634 stree_var_t *var;
635 stree_symbol_t *symbol;
637 var = stree_var_new();
638 symbol = stree_symbol_new(sc_var);
639 symbol->u.var = var;
640 symbol->outer_csi = outer_csi;
641 var->symbol = symbol;
643 lmatch(parse, lc_var);
644 var->name = parse_ident(parse);
645 lmatch(parse, lc_colon);
646 var->type = parse_texpr(parse);
648 parse_symbol_attrs(parse, symbol);
650 lmatch(parse, lc_scolon);
652 switch (outer_csi->cc) {
653 case csi_class:
654 case csi_struct:
655 break;
656 case csi_interface:
657 cspan_print(var->name->cspan);
658 printf(" Error: Variable declared inside interface.\n");
659 parse_note_error(parse);
660 /* XXX Free var */
661 return NULL;
664 return var;
667 /** Parse member property.
669 * @param parse Parser object.
670 * @param outer_csi CSI containing this declaration or @c NULL if global.
671 * @return New syntax tree node.
673 static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
675 stree_prop_t *prop;
676 stree_symbol_t *symbol;
678 stree_ident_t *ident;
679 stree_proc_arg_t *arg;
681 prop = stree_prop_new();
682 list_init(&prop->args);
684 symbol = stree_symbol_new(sc_prop);
685 symbol->u.prop = prop;
686 symbol->outer_csi = outer_csi;
687 prop->symbol = symbol;
689 lmatch(parse, lc_prop);
691 if (lcur_lc(parse) == lc_self) {
692 /* Indexed property set */
694 /* Use some name that is impossible as identifier. */
695 ident = stree_ident_new();
696 ident->sid = strtab_get_sid(INDEXER_IDENT);
697 prop->name = ident;
699 lskip(parse);
700 lmatch(parse, lc_lsbr);
702 /* Parse formal parameters. */
703 while (!parse_is_error(parse)) {
704 arg = parse_proc_arg(parse);
705 if (stree_arg_has_attr(arg, aac_packed)) {
706 prop->varg = arg;
707 break;
708 } else {
709 list_append(&prop->args, arg);
712 if (lcur_lc(parse) == lc_rsbr)
713 break;
715 lmatch(parse, lc_scolon);
718 lmatch(parse, lc_rsbr);
719 } else {
720 /* Named property */
721 prop->name = parse_ident(parse);
724 lmatch(parse, lc_colon);
725 prop->type = parse_texpr(parse);
727 /* Parse attributes. */
728 parse_symbol_attrs(parse, symbol);
730 lmatch(parse, lc_is);
732 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
733 switch (lcur_lc(parse)) {
734 case lc_get:
735 parse_prop_get(parse, prop);
736 break;
737 case lc_set:
738 parse_prop_set(parse, prop);
739 break;
740 default:
741 lunexpected_error(parse);
745 lmatch(parse, lc_end);
747 return prop;
750 /** Parse symbol attributes.
752 * Parse list of attributes and add them to @a symbol.
754 * @param parse Parser object
755 * @param symbol Symbol to add these attributes to
757 static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol)
759 stree_symbol_attr_t *attr;
761 /* Parse attributes. */
762 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
763 lskip(parse);
764 attr = parse_symbol_attr(parse);
765 list_append(&symbol->attr, attr);
769 /** Parse symbol attribute.
771 * @param parse Parser object
772 * @return New syntax tree node
774 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
776 stree_symbol_attr_t *attr;
777 symbol_attr_class_t sac;
779 /* Make compiler happy. */
780 sac = 0;
782 switch (lcur_lc(parse)) {
783 case lc_builtin:
784 sac = sac_builtin;
785 break;
786 case lc_static:
787 sac = sac_static;
788 break;
789 default:
790 cspan_print(lcur_span(parse));
791 printf(" Error: Unexpected attribute '");
792 lem_print(lcur(parse));
793 printf("'.\n");
794 parse_note_error(parse);
795 break;
798 lskip(parse);
800 attr = stree_symbol_attr_new(sac);
801 return attr;
804 /** Parse formal function argument.
806 * @param parse Parser object.
807 * @return New syntax tree node.
809 static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
811 stree_proc_arg_t *arg;
812 stree_arg_attr_t *attr;
814 arg = stree_proc_arg_new();
815 arg->name = parse_ident(parse);
816 lmatch(parse, lc_colon);
817 arg->type = parse_texpr(parse);
819 #ifdef DEBUG_PARSE_TRACE
820 printf("Parse procedure argument.\n");
821 #endif
822 list_init(&arg->attr);
824 /* Parse attributes. */
825 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
826 lskip(parse);
827 attr = parse_arg_attr(parse);
828 list_append(&arg->attr, attr);
831 return arg;
834 /** Parse argument attribute.
836 * @param parse Parser object.
837 * @return New syntax tree node.
839 static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
841 stree_arg_attr_t *attr;
843 if (lcur_lc(parse) != lc_packed) {
844 cspan_print(lcur_span(parse));
845 printf(" Error: Unexpected attribute '");
846 lem_print(lcur(parse));
847 printf("'.\n");
848 parse_note_error(parse);
851 lskip(parse);
853 attr = stree_arg_attr_new(aac_packed);
854 return attr;
857 /** Parse function signature.
859 * @param parse Parser object.
860 * @return New syntax tree node.
862 static stree_fun_sig_t *parse_fun_sig(parse_t *parse)
864 stree_fun_sig_t *sig;
865 stree_proc_arg_t *arg;
867 sig = stree_fun_sig_new();
869 lmatch(parse, lc_lparen);
871 #ifdef DEBUG_PARSE_TRACE
872 printf("Parsing function signature.\n");
873 #endif
875 list_init(&sig->args);
877 if (lcur_lc(parse) != lc_rparen) {
879 /* Parse formal parameters. */
880 while (!parse_is_error(parse)) {
881 arg = parse_proc_arg(parse);
883 if (stree_arg_has_attr(arg, aac_packed)) {
884 sig->varg = arg;
885 break;
886 } else {
887 list_append(&sig->args, arg);
890 if (lcur_lc(parse) == lc_rparen)
891 break;
893 lmatch(parse, lc_scolon);
897 lmatch(parse, lc_rparen);
899 if (lcur_lc(parse) == lc_colon) {
900 lskip(parse);
901 sig->rtype = parse_texpr(parse);
902 } else {
903 sig->rtype = NULL;
906 return sig;
909 /** Parse member property getter.
911 * @param parse Parser object.
912 * @param prop Property containing this declaration.
914 static void parse_prop_get(parse_t *parse, stree_prop_t *prop)
916 cspan_t *cspan;
917 stree_block_t *block;
918 stree_proc_t *getter;
919 bool_t body_expected;
921 body_expected = (prop->symbol->outer_csi->cc != csi_interface);
923 lskip(parse);
924 cspan = lprev_span(parse);
926 if (prop->getter != NULL) {
927 cspan_print(cspan);
928 printf(" Error: Duplicate getter.\n");
929 parse_note_error(parse);
930 return;
933 if (lcur_lc(parse) == lc_scolon) {
934 /* Body not present */
935 lskip(parse);
936 block = NULL;
938 if (body_expected) {
939 cspan_print(prop->name->cspan);
940 printf(" Error: Property '");
941 symbol_print_fqn(prop->symbol);
942 printf("' getter should have "
943 "a body.\n");
944 parse_note_error(parse);
946 } else {
947 /* Body present */
948 lmatch(parse, lc_is);
949 block = parse_block(parse);
950 lmatch(parse, lc_end);
952 if (!body_expected) {
953 cspan_print(prop->name->cspan);
954 printf(" Error: Property '");
955 symbol_print_fqn(prop->symbol);
956 printf("' getter declaration should "
957 "not have a body.\n");
958 parse_note_error(parse);
960 /* XXX Free block */
961 block = NULL;
965 /* Create getter procedure */
966 getter = stree_proc_new();
967 getter->body = block;
968 getter->outer_symbol = prop->symbol;
970 /* Store getter in property. */
971 prop->getter = getter;
974 /** Parse member property setter.
976 * @param parse Parser object.
977 * @param prop Property containing this declaration.
979 static void parse_prop_set(parse_t *parse, stree_prop_t *prop)
981 cspan_t *cspan;
982 stree_block_t *block;
983 stree_proc_t *setter;
984 bool_t body_expected;
986 body_expected = (prop->symbol->outer_csi->cc != csi_interface);
988 lskip(parse);
989 cspan = lprev_span(parse);
991 if (prop->setter != NULL) {
992 cspan_print(cspan);
993 printf(" Error: Duplicate setter.\n");
994 parse_note_error(parse);
995 return;
998 prop->setter_arg = stree_proc_arg_new();
999 prop->setter_arg->name = parse_ident(parse);
1000 prop->setter_arg->type = prop->type;
1002 if (lcur_lc(parse) == lc_scolon) {
1003 /* Body not present */
1004 lskip(parse);
1006 block = NULL;
1008 if (body_expected) {
1009 cspan_print(prop->name->cspan);
1010 printf(" Error: Property '");
1011 symbol_print_fqn(prop->symbol);
1012 printf("' setter should have "
1013 "a body.\n");
1014 parse_note_error(parse);
1016 } else {
1017 /* Body present */
1018 lmatch(parse, lc_is);
1019 block = parse_block(parse);
1020 lmatch(parse, lc_end);
1022 if (!body_expected) {
1023 cspan_print(prop->name->cspan);
1024 printf(" Error: Property '");
1025 symbol_print_fqn(prop->symbol);
1026 printf("' setter declaration should "
1027 "not have a body.\n");
1028 parse_note_error(parse);
1032 /* Create setter procedure */
1033 setter = stree_proc_new();
1034 setter->body = block;
1035 setter->outer_symbol = prop->symbol;
1037 /* Store setter in property. */
1038 prop->setter = setter;
1041 /** Parse statement block.
1043 * @param parse Parser object.
1044 * @return New syntax tree node.
1046 static stree_block_t *parse_block(parse_t *parse)
1048 stree_block_t *block;
1049 stree_stat_t *stat;
1051 block = stree_block_new();
1052 list_init(&block->stats);
1054 /* Avoid peeking if there is an error condition. */
1055 if (parse_is_error(parse))
1056 return block;
1058 while (terminates_block(lcur_lc(parse)) != b_true &&
1059 !parse_is_error(parse)) {
1061 stat = parse_stat(parse);
1062 list_append(&block->stats, stat);
1065 return block;
1068 /** Parse statement.
1070 * @param parse Parser object.
1071 * @return New syntax tree node.
1073 stree_stat_t *parse_stat(parse_t *parse)
1075 stree_stat_t *stat;
1077 stree_vdecl_t *vdecl_s;
1078 stree_if_t *if_s;
1079 stree_switch_t *switch_s;
1080 stree_while_t *while_s;
1081 stree_for_t *for_s;
1082 stree_raise_t *raise_s;
1083 stree_break_t *break_s;
1084 stree_return_t *return_s;
1085 stree_wef_t *wef_s;
1086 stree_exps_t *exp_s;
1088 #ifdef DEBUG_PARSE_TRACE
1089 printf("Parse statement.\n");
1090 #endif
1091 switch (lcur_lc(parse)) {
1092 case lc_var:
1093 vdecl_s = parse_vdecl(parse);
1094 stat = stree_stat_new(st_vdecl);
1095 stat->u.vdecl_s = vdecl_s;
1096 break;
1097 case lc_if:
1098 if_s = parse_if(parse);
1099 stat = stree_stat_new(st_if);
1100 stat->u.if_s = if_s;
1101 break;
1102 case lc_switch:
1103 switch_s = parse_switch(parse);
1104 stat = stree_stat_new(st_switch);
1105 stat->u.switch_s = switch_s;
1106 break;
1107 case lc_while:
1108 while_s = parse_while(parse);
1109 stat = stree_stat_new(st_while);
1110 stat->u.while_s = while_s;
1111 break;
1112 case lc_for:
1113 for_s = parse_for(parse);
1114 stat = stree_stat_new(st_for);
1115 stat->u.for_s = for_s;
1116 break;
1117 case lc_raise:
1118 raise_s = parse_raise(parse);
1119 stat = stree_stat_new(st_raise);
1120 stat->u.raise_s = raise_s;
1121 break;
1122 case lc_break:
1123 break_s = parse_break(parse);
1124 stat = stree_stat_new(st_break);
1125 stat->u.break_s = break_s;
1126 break;
1127 case lc_return:
1128 return_s = parse_return(parse);
1129 stat = stree_stat_new(st_return);
1130 stat->u.return_s = return_s;
1131 break;
1132 case lc_do:
1133 case lc_with:
1134 wef_s = parse_wef(parse);
1135 stat = stree_stat_new(st_wef);
1136 stat->u.wef_s = wef_s;
1137 break;
1138 default:
1139 exp_s = parse_exps(parse);
1140 stat = stree_stat_new(st_exps);
1141 stat->u.exp_s = exp_s;
1142 break;
1145 #ifdef DEBUG_PARSE_TRACE
1146 printf("Parsed statement %p\n", stat);
1147 #endif
1148 return stat;
1151 /** Parse variable declaration statement.
1153 * @param parse Parser object.
1154 * @return New syntax tree node.
1156 static stree_vdecl_t *parse_vdecl(parse_t *parse)
1158 stree_vdecl_t *vdecl;
1160 vdecl = stree_vdecl_new();
1162 lmatch(parse, lc_var);
1163 vdecl->name = parse_ident(parse);
1164 lmatch(parse, lc_colon);
1165 vdecl->type = parse_texpr(parse);
1167 if (lcur_lc(parse) == lc_assign) {
1168 lskip(parse);
1169 (void) parse_expr(parse);
1172 lmatch(parse, lc_scolon);
1174 #ifdef DEBUG_PARSE_TRACE
1175 printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
1176 printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
1177 vdecl, vdecl->name, vdecl->name->sid);
1178 #endif
1179 return vdecl;
1182 /** Parse @c if statement.
1184 * @param parse Parser object.
1185 * @return New syntax tree node.
1187 static stree_if_t *parse_if(parse_t *parse)
1189 stree_if_t *if_s;
1190 stree_if_clause_t *if_c;
1192 #ifdef DEBUG_PARSE_TRACE
1193 printf("Parse 'if' statement.\n");
1194 #endif
1195 if_s = stree_if_new();
1196 list_init(&if_s->if_clauses);
1198 /* Parse @c if clause. */
1199 lmatch(parse, lc_if);
1201 if_c = stree_if_clause_new();
1202 if_c->cond = parse_expr(parse);
1203 lmatch(parse, lc_then);
1204 if_c->block = parse_block(parse);
1206 list_append(&if_s->if_clauses, if_c);
1208 /* Parse @c elif clauses. */
1209 while (lcur_lc(parse) == lc_elif) {
1210 lskip(parse);
1211 if_c = stree_if_clause_new();
1212 if_c->cond = parse_expr(parse);
1213 lmatch(parse, lc_then);
1214 if_c->block = parse_block(parse);
1216 list_append(&if_s->if_clauses, if_c);
1219 /* Parse @c else clause. */
1220 if (lcur_lc(parse) == lc_else) {
1221 lskip(parse);
1222 if_s->else_block = parse_block(parse);
1223 } else {
1224 if_s->else_block = NULL;
1227 lmatch(parse, lc_end);
1228 return if_s;
1231 /** Parse @c switch statement.
1233 * @param parse Parser object.
1234 * @return New syntax tree node.
1236 static stree_switch_t *parse_switch(parse_t *parse)
1238 stree_switch_t *switch_s;
1239 stree_when_t *when_c;
1240 stree_expr_t *expr;
1242 #ifdef DEBUG_PARSE_TRACE
1243 printf("Parse 'switch' statement.\n");
1244 #endif
1245 lmatch(parse, lc_switch);
1247 switch_s = stree_switch_new();
1248 list_init(&switch_s->when_clauses);
1250 switch_s->expr = parse_expr(parse);
1251 lmatch(parse, lc_is);
1253 /* Parse @c when clauses. */
1254 while (lcur_lc(parse) == lc_when) {
1255 lskip(parse);
1256 when_c = stree_when_new();
1257 list_init(&when_c->exprs);
1258 while (b_true) {
1259 expr = parse_expr(parse);
1260 list_append(&when_c->exprs, expr);
1261 if (lcur_lc(parse) != lc_comma)
1262 break;
1263 lskip(parse);
1266 lmatch(parse, lc_do);
1267 when_c->block = parse_block(parse);
1269 list_append(&switch_s->when_clauses, when_c);
1272 /* Parse @c else clause. */
1273 if (lcur_lc(parse) == lc_else) {
1274 lskip(parse);
1275 lmatch(parse, lc_do);
1276 switch_s->else_block = parse_block(parse);
1277 } else {
1278 switch_s->else_block = NULL;
1281 lmatch(parse, lc_end);
1282 return switch_s;
1285 /** Parse @c while statement.
1287 * @param parse Parser object.
1289 static stree_while_t *parse_while(parse_t *parse)
1291 stree_while_t *while_s;
1293 #ifdef DEBUG_PARSE_TRACE
1294 printf("Parse 'while' statement.\n");
1295 #endif
1296 while_s = stree_while_new();
1298 lmatch(parse, lc_while);
1299 while_s->cond = parse_expr(parse);
1300 lmatch(parse, lc_do);
1301 while_s->body = parse_block(parse);
1302 lmatch(parse, lc_end);
1304 return while_s;
1307 /** Parse @c for statement.
1309 * @param parse Parser object.
1310 * @return New syntax tree node.
1312 static stree_for_t *parse_for(parse_t *parse)
1314 stree_for_t *for_s;
1316 #ifdef DEBUG_PARSE_TRACE
1317 printf("Parse 'for' statement.\n");
1318 #endif
1319 for_s = stree_for_new();
1321 lmatch(parse, lc_for);
1322 lmatch(parse, lc_ident);
1323 lmatch(parse, lc_colon);
1324 (void) parse_texpr(parse);
1325 lmatch(parse, lc_in);
1326 (void) parse_expr(parse);
1327 lmatch(parse, lc_do);
1328 for_s->body = parse_block(parse);
1329 lmatch(parse, lc_end);
1331 return for_s;
1334 /** Parse @c raise statement.
1336 * @param parse Parser object.
1338 static stree_raise_t *parse_raise(parse_t *parse)
1340 stree_raise_t *raise_s;
1342 #ifdef DEBUG_PARSE_TRACE
1343 printf("Parse 'raise' statement.\n");
1344 #endif
1345 raise_s = stree_raise_new();
1346 lmatch(parse, lc_raise);
1347 raise_s->expr = parse_expr(parse);
1348 lmatch(parse, lc_scolon);
1350 return raise_s;
1353 /** Parse @c break statement.
1355 * @param parse Parser object.
1356 * @return New syntax tree node.
1358 static stree_break_t *parse_break(parse_t *parse)
1360 stree_break_t *break_s;
1362 #ifdef DEBUG_PARSE_TRACE
1363 printf("Parse 'break' statement.\n");
1364 #endif
1365 break_s = stree_break_new();
1367 lmatch(parse, lc_break);
1368 lmatch(parse, lc_scolon);
1370 return break_s;
1373 /** Parse @c return statement.
1375 * @param parse Parser object.
1376 * @return New syntax tree node.
1378 static stree_return_t *parse_return(parse_t *parse)
1380 stree_return_t *return_s;
1382 #ifdef DEBUG_PARSE_TRACE
1383 printf("Parse 'return' statement.\n");
1384 #endif
1385 return_s = stree_return_new();
1387 lmatch(parse, lc_return);
1389 if (lcur_lc(parse) != lc_scolon)
1390 return_s->expr = parse_expr(parse);
1392 lmatch(parse, lc_scolon);
1394 return return_s;
1397 /** Parse @c with-except-finally statement.
1399 * @param parse Parser object.
1400 * @return New syntax tree node.
1402 static stree_wef_t *parse_wef(parse_t *parse)
1404 stree_wef_t *wef_s;
1405 stree_except_t *except_c;
1407 #ifdef DEBUG_PARSE_TRACE
1408 printf("Parse WEF statement.\n");
1409 #endif
1410 wef_s = stree_wef_new();
1411 list_init(&wef_s->except_clauses);
1413 if (lcur_lc(parse) == lc_with) {
1414 lmatch(parse, lc_with);
1415 lmatch(parse, lc_ident);
1416 lmatch(parse, lc_colon);
1417 (void) parse_texpr(parse);
1418 lmatch(parse, lc_assign);
1419 (void) parse_expr(parse);
1422 lmatch(parse, lc_do);
1423 wef_s->with_block = parse_block(parse);
1425 while (lcur_lc(parse) == lc_except && !parse_is_error(parse)) {
1426 except_c = parse_except(parse);
1427 list_append(&wef_s->except_clauses, except_c);
1430 if (lcur_lc(parse) == lc_finally) {
1431 lmatch(parse, lc_finally);
1432 lmatch(parse, lc_do);
1433 wef_s->finally_block = parse_block(parse);
1434 } else {
1435 wef_s->finally_block = NULL;
1438 lmatch(parse, lc_end);
1440 return wef_s;
1443 /** Parse expression statement.
1445 * @param parse Parser object.
1446 * @return New syntax tree node.
1448 static stree_exps_t *parse_exps(parse_t *parse)
1450 stree_expr_t *expr;
1451 stree_exps_t *exps;
1453 #ifdef DEBUG_PARSE_TRACE
1454 printf("Parse expression statement.\n");
1455 #endif
1456 expr = parse_expr(parse);
1457 lmatch(parse, lc_scolon);
1459 exps = stree_exps_new();
1460 exps->expr = expr;
1462 return exps;
1465 /** Parse @c except clause.
1467 * @param parse Parser object.
1468 * @return New syntax tree node.
1470 static stree_except_t *parse_except(parse_t *parse)
1472 stree_except_t *except_c;
1474 #ifdef DEBUG_PARSE_TRACE
1475 printf("Parse 'except' statement.\n");
1476 #endif
1477 except_c = stree_except_new();
1479 lmatch(parse, lc_except);
1480 except_c->evar = parse_ident(parse);
1481 lmatch(parse, lc_colon);
1482 except_c->etype = parse_texpr(parse);
1483 lmatch(parse, lc_do);
1485 except_c->block = parse_block(parse);
1487 return except_c;
1490 /** Parse identifier.
1492 * @param parse Parser object.
1493 * @return New syntax tree node.
1495 stree_ident_t *parse_ident(parse_t *parse)
1497 stree_ident_t *ident;
1499 #ifdef DEBUG_PARSE_TRACE
1500 printf("Parse identifier.\n");
1501 #endif
1502 lcheck(parse, lc_ident);
1503 ident = stree_ident_new();
1504 ident->sid = lcur(parse)->u.ident.sid;
1505 ident->cspan = lcur_span(parse);
1506 lskip(parse);
1508 return ident;
1511 /** Signal a parse error, start bailing out from parser.
1513 * @param parse Parser object.
1515 void parse_raise_error(parse_t *parse)
1517 parse->error = b_true;
1518 parse->error_bailout = b_true;
1521 /** Note a parse error that has been immediately recovered.
1523 * @param parse Parser object.
1525 void parse_note_error(parse_t *parse)
1527 parse->error = b_true;
1530 /** Check if we are currently bailing out of parser due to a parse error.
1532 * @param parse Parser object.
1534 bool_t parse_is_error(parse_t *parse)
1536 return parse->error_bailout;
1539 /** Recover from parse error bailout.
1541 * Still remember that there was an error, but stop bailing out.
1543 * @param parse Parser object.
1545 void parse_recover_error(parse_t *parse)
1547 assert(parse->error == b_true);
1548 assert(parse->error_bailout == b_true);
1550 parse->error_bailout = b_false;
1553 /** Return current lem.
1555 * @param parse Parser object.
1556 * @return Pointer to current lem. Only valid until the lexing
1557 * position is advanced.
1559 lem_t *lcur(parse_t *parse)
1561 #ifdef DEBUG_LPARSE_TRACE
1562 printf("lcur()\n");
1563 #endif
1564 return lex_get_current(parse->lex);
1567 /** Return current lem lclass.
1569 * @param parse Parser object
1570 * @return Lclass of the current lem
1572 lclass_t lcur_lc(parse_t *parse)
1574 lem_t *lem;
1577 * This allows us to skip error checking in many places. If there is an
1578 * active error, lcur_lc() returns lc_invalid without reading input.
1580 * Without this measure we would have to check for error all the time
1581 * or risk requiring extra input from the user (in interactive mode)
1582 * before actually bailing out from the parser.
1584 if (parse_is_error(parse))
1585 return lc_invalid;
1587 lem = lcur(parse);
1588 return lem->lclass;
1591 /** Return coordinate span of current lem.
1593 * @param parse Parser object
1594 * @return Coordinate span of current lem or @c NULL if a
1595 * parse error is active
1597 cspan_t *lcur_span(parse_t *parse)
1599 lem_t *lem;
1601 if (parse_is_error(parse))
1602 return NULL;
1604 lem = lcur(parse);
1605 return lem->cspan;
1608 /** Return coordinate span of previous lem.
1610 * @param parse Parser object
1611 * @return Coordinate span of previous lem or @c NULL if
1612 * parse error is active or previous lem is not
1613 * available.
1615 cspan_t *lprev_span(parse_t *parse)
1617 lem_t *lem;
1619 if (parse_is_error(parse))
1620 return NULL;
1622 lem = lex_peek_prev(parse->lex);
1623 if (lem == NULL)
1624 return NULL;
1626 return lem->cspan;
1629 /** Skip to next lem.
1631 * @param parse Parser object.
1633 void lskip(parse_t *parse)
1635 #ifdef DEBUG_LPARSE_TRACE
1636 printf("lskip()\n");
1637 #endif
1638 lex_next(parse->lex);
1641 /** Verify that lclass of current lem is @a lc.
1643 * If a lem of different lclass is found, a parse error is raised and
1644 * a message is printed.
1646 * @param parse Parser object.
1647 * @param lc Expected lclass.
1649 void lcheck(parse_t *parse, lclass_t lc)
1651 #ifdef DEBUG_LPARSE_TRACE
1652 printf("lcheck(");
1653 lclass_print(lc);
1654 printf(")\n");
1655 #endif
1656 if (lcur(parse)->lclass != lc) {
1657 lem_print_coords(lcur(parse));
1658 printf(" Error: expected '");
1659 lclass_print(lc);
1660 printf("', got '");
1661 lem_print(lcur(parse));
1662 printf("'.\n");
1663 parse_raise_error(parse);
1667 /** Verify that lclass of current lem is @a lc and go to next lem.
1669 * If a lem of different lclass is found, a parse error is raised and
1670 * a message is printed.
1672 * @param parse Parser object.
1673 * @param lc Expected lclass.
1675 void lmatch(parse_t *parse, lclass_t lc)
1677 #ifdef DEBUG_LPARSE_TRACE
1678 printf("lmatch(");
1679 lclass_print(lc);
1680 printf(")\n");
1681 #endif
1683 * This allows us to skip error checking in many places. If there is an
1684 * active error, lmatch() does nothing (similar to parse_block(), etc.
1686 * Without this measure we would have to check for error all the time
1687 * or risk requiring extra input from the user (in interactive mode)
1688 * before actually bailing out from the parser.
1690 if (parse_is_error(parse))
1691 return;
1693 lcheck(parse, lc);
1694 lskip(parse);
1697 /** Raise and display generic parsing error.
1699 * @param parse Parser object.
1701 void lunexpected_error(parse_t *parse)
1703 lem_print_coords(lcur(parse));
1704 printf(" Error: unexpected token '");
1705 lem_print(lcur(parse));
1706 printf("'.\n");
1707 parse_raise_error(parse);
1710 /** Determine whether @a lclass is in follow(block).
1712 * Tests whether @a lclass belongs to the follow(block) set, i.e. if it is
1713 * lclass of a lem that can follow a block in the program.
1715 * @param lclass Lclass.
1717 bool_t terminates_block(lclass_t lclass)
1719 switch (lclass) {
1720 case lc_elif:
1721 case lc_else:
1722 case lc_end:
1723 case lc_except:
1724 case lc_finally:
1725 case lc_when:
1726 return b_true;
1727 default:
1728 return b_false;