2 * Copyright (c) 2011 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
31 * Consumes a sequence of lexical elements and produces a syntax tree (stree).
32 * Parsing primitives, module members, statements.
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
);
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
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
;
112 parse
->error
= b_false
;
113 parse
->error_bailout
= b_false
;
115 lex_next(parse
->lex
);
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
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
131 * @param parse Parser object.
133 void parse_module(parse_t
*parse
)
136 stree_enum_t
*enum_d
;
139 while (lcur_lc(parse
) != lc_eof
&& !parse_is_error(parse
)) {
140 switch (lcur_lc(parse
)) {
144 csi
= parse_csi(parse
, lcur_lc(parse
), NULL
);
145 modm
= stree_modm_new(mc_csi
);
148 list_append(&parse
->cur_mod
->members
, modm
);
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
);
158 lunexpected_error(parse
);
159 lex_next(parse
->lex
);
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
)
178 stree_csimbr_t
*csimbr
;
179 stree_symbol_t
*symbol
;
180 stree_ident_t
*targ_name
;
200 csi
= stree_csi_new(cc
);
201 csi
->name
= parse_ident(parse
);
203 list_init(&csi
->targ
);
205 while (lcur_lc(parse
) == lc_slash
) {
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
);
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
));
224 if (lcur_lc(parse
) == lc_colon
) {
225 /* Inheritance list */
229 pref
= parse_texpr(parse
);
230 if (parse_is_error(parse
))
233 list_append(&csi
->inherit
, pref
);
234 if (lcur_lc(parse
) != lc_plus
)
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
);
250 list_append(&csi
->members
, csimbr
);
253 lmatch(parse
, lc_end
);
255 if (outer_csi
!= NULL
) {
256 switch (outer_csi
->cc
) {
261 cspan_print(csi
->name
->cspan
);
262 printf(" Error: CSI declared inside interface.\n");
263 parse_note_error(parse
);
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
;
285 stree_deleg_t
*deleg
;
286 stree_enum_t
*enum_d
;
293 switch (lcur_lc(parse
)) {
297 csi
= parse_csi(parse
, lcur_lc(parse
), outer_csi
);
299 csimbr
= stree_csimbr_new(csimbr_csi
);
304 ctor
= parse_ctor(parse
, outer_csi
);
306 csimbr
= stree_csimbr_new(csimbr_ctor
);
307 csimbr
->u
.ctor
= ctor
;
311 deleg
= parse_deleg(parse
, outer_csi
);
313 csimbr
= stree_csimbr_new(csimbr_deleg
);
314 csimbr
->u
.deleg
= deleg
;
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
;
325 fun
= parse_fun(parse
, outer_csi
);
326 csimbr
= stree_csimbr_new(csimbr_fun
);
330 var
= parse_var(parse
, outer_csi
);
332 csimbr
= stree_csimbr_new(csimbr_var
);
337 prop
= parse_prop(parse
, outer_csi
);
338 csimbr
= stree_csimbr_new(csimbr_prop
);
339 csimbr
->u
.prop
= prop
;
342 lunexpected_error(parse
);
343 lex_next(parse
->lex
);
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
)
359 stree_symbol_t
*symbol
;
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
));
382 ctor
->sig
= parse_fun_sig(parse
);
383 if (ctor
->sig
->rtype
!= NULL
) {
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
) {
400 /* This constructor has no body. */
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
;
409 lmatch(parse
, lc_is
);
410 ctor
->proc
->body
= parse_block(parse
);
411 lmatch(parse
, lc_end
);
414 switch (outer_csi
->cc
) {
419 cspan_print(ctor
->name
->cspan
);
420 printf(" Error: Constructor declared inside interface.\n");
421 parse_note_error(parse
);
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
;
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
));
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
);
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
) {
481 cspan_print(enum_d
->name
->cspan
);
482 printf(" Error: Enum declared inside interface.\n");
483 parse_note_error(parse
);
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
)
503 embr
= stree_embr_new();
504 embr
->outer_enum
= outer_enum
;
505 embr
->name
= parse_ident(parse
);
507 lmatch(parse
, lc_scolon
);
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
));
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
) {
549 cspan_print(deleg
->name
->cspan
);
550 printf(" Error: Delegate declared inside interface.\n");
551 parse_note_error(parse
);
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
)
568 stree_symbol_t
*symbol
;
569 bool_t body_expected
;
571 fun
= stree_fun_new();
572 symbol
= stree_symbol_new(sc_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
));
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
) {
598 /* Body not present */
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
;
609 lmatch(parse
, lc_is
);
610 fun
->proc
->body
= parse_block(parse
);
611 lmatch(parse
, lc_end
);
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
);
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
)
635 stree_symbol_t
*symbol
;
637 var
= stree_var_new();
638 symbol
= stree_symbol_new(sc_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
) {
657 cspan_print(var
->name
->cspan
);
658 printf(" Error: Variable declared inside interface.\n");
659 parse_note_error(parse
);
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
)
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
);
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
)) {
709 list_append(&prop
->args
, arg
);
712 if (lcur_lc(parse
) == lc_rsbr
)
715 lmatch(parse
, lc_scolon
);
718 lmatch(parse
, lc_rsbr
);
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
)) {
735 parse_prop_get(parse
, prop
);
738 parse_prop_set(parse
, prop
);
741 lunexpected_error(parse
);
745 lmatch(parse
, lc_end
);
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
)) {
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. */
782 switch (lcur_lc(parse
)) {
790 cspan_print(lcur_span(parse
));
791 printf(" Error: Unexpected attribute '");
792 lem_print(lcur(parse
));
794 parse_note_error(parse
);
800 attr
= stree_symbol_attr_new(sac
);
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");
822 list_init(&arg
->attr
);
824 /* Parse attributes. */
825 while (lcur_lc(parse
) == lc_comma
&& !parse_is_error(parse
)) {
827 attr
= parse_arg_attr(parse
);
828 list_append(&arg
->attr
, attr
);
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
));
848 parse_note_error(parse
);
853 attr
= stree_arg_attr_new(aac_packed
);
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");
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
)) {
887 list_append(&sig
->args
, arg
);
890 if (lcur_lc(parse
) == lc_rparen
)
893 lmatch(parse
, lc_scolon
);
897 lmatch(parse
, lc_rparen
);
899 if (lcur_lc(parse
) == lc_colon
) {
901 sig
->rtype
= parse_texpr(parse
);
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
)
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
);
924 cspan
= lprev_span(parse
);
926 if (prop
->getter
!= NULL
) {
928 printf(" Error: Duplicate getter.\n");
929 parse_note_error(parse
);
933 if (lcur_lc(parse
) == lc_scolon
) {
934 /* Body not present */
939 cspan_print(prop
->name
->cspan
);
940 printf(" Error: Property '");
941 symbol_print_fqn(prop
->symbol
);
942 printf("' getter should have "
944 parse_note_error(parse
);
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
);
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
)
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
);
989 cspan
= lprev_span(parse
);
991 if (prop
->setter
!= NULL
) {
993 printf(" Error: Duplicate setter.\n");
994 parse_note_error(parse
);
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 */
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 "
1014 parse_note_error(parse
);
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
;
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
))
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
);
1068 /** Parse statement.
1070 * @param parse Parser object.
1071 * @return New syntax tree node.
1073 stree_stat_t
*parse_stat(parse_t
*parse
)
1077 stree_vdecl_t
*vdecl_s
;
1079 stree_switch_t
*switch_s
;
1080 stree_while_t
*while_s
;
1082 stree_raise_t
*raise_s
;
1083 stree_break_t
*break_s
;
1084 stree_return_t
*return_s
;
1086 stree_exps_t
*exp_s
;
1088 #ifdef DEBUG_PARSE_TRACE
1089 printf("Parse statement.\n");
1091 switch (lcur_lc(parse
)) {
1093 vdecl_s
= parse_vdecl(parse
);
1094 stat
= stree_stat_new(st_vdecl
);
1095 stat
->u
.vdecl_s
= vdecl_s
;
1098 if_s
= parse_if(parse
);
1099 stat
= stree_stat_new(st_if
);
1100 stat
->u
.if_s
= if_s
;
1103 switch_s
= parse_switch(parse
);
1104 stat
= stree_stat_new(st_switch
);
1105 stat
->u
.switch_s
= switch_s
;
1108 while_s
= parse_while(parse
);
1109 stat
= stree_stat_new(st_while
);
1110 stat
->u
.while_s
= while_s
;
1113 for_s
= parse_for(parse
);
1114 stat
= stree_stat_new(st_for
);
1115 stat
->u
.for_s
= for_s
;
1118 raise_s
= parse_raise(parse
);
1119 stat
= stree_stat_new(st_raise
);
1120 stat
->u
.raise_s
= raise_s
;
1123 break_s
= parse_break(parse
);
1124 stat
= stree_stat_new(st_break
);
1125 stat
->u
.break_s
= break_s
;
1128 return_s
= parse_return(parse
);
1129 stat
= stree_stat_new(st_return
);
1130 stat
->u
.return_s
= return_s
;
1134 wef_s
= parse_wef(parse
);
1135 stat
= stree_stat_new(st_wef
);
1136 stat
->u
.wef_s
= wef_s
;
1139 exp_s
= parse_exps(parse
);
1140 stat
= stree_stat_new(st_exps
);
1141 stat
->u
.exp_s
= exp_s
;
1145 #ifdef DEBUG_PARSE_TRACE
1146 printf("Parsed statement %p\n", 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
) {
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
);
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
)
1190 stree_if_clause_t
*if_c
;
1192 #ifdef DEBUG_PARSE_TRACE
1193 printf("Parse 'if' statement.\n");
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
) {
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
) {
1222 if_s
->else_block
= parse_block(parse
);
1224 if_s
->else_block
= NULL
;
1227 lmatch(parse
, lc_end
);
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
;
1242 #ifdef DEBUG_PARSE_TRACE
1243 printf("Parse 'switch' statement.\n");
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
) {
1256 when_c
= stree_when_new();
1257 list_init(&when_c
->exprs
);
1259 expr
= parse_expr(parse
);
1260 list_append(&when_c
->exprs
, expr
);
1261 if (lcur_lc(parse
) != lc_comma
)
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
) {
1275 lmatch(parse
, lc_do
);
1276 switch_s
->else_block
= parse_block(parse
);
1278 switch_s
->else_block
= NULL
;
1281 lmatch(parse
, lc_end
);
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");
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
);
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
)
1316 #ifdef DEBUG_PARSE_TRACE
1317 printf("Parse 'for' statement.\n");
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
);
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");
1345 raise_s
= stree_raise_new();
1346 lmatch(parse
, lc_raise
);
1347 raise_s
->expr
= parse_expr(parse
);
1348 lmatch(parse
, lc_scolon
);
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");
1365 break_s
= stree_break_new();
1367 lmatch(parse
, lc_break
);
1368 lmatch(parse
, lc_scolon
);
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");
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
);
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
)
1405 stree_except_t
*except_c
;
1407 #ifdef DEBUG_PARSE_TRACE
1408 printf("Parse WEF statement.\n");
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
);
1435 wef_s
->finally_block
= NULL
;
1438 lmatch(parse
, lc_end
);
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
)
1453 #ifdef DEBUG_PARSE_TRACE
1454 printf("Parse expression statement.\n");
1456 expr
= parse_expr(parse
);
1457 lmatch(parse
, lc_scolon
);
1459 exps
= stree_exps_new();
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");
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
);
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");
1502 lcheck(parse
, lc_ident
);
1503 ident
= stree_ident_new();
1504 ident
->sid
= lcur(parse
)->u
.ident
.sid
;
1505 ident
->cspan
= lcur_span(parse
);
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
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
)
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
))
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
)
1601 if (parse_is_error(parse
))
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
1615 cspan_t
*lprev_span(parse_t
*parse
)
1619 if (parse_is_error(parse
))
1622 lem
= lex_peek_prev(parse
->lex
);
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");
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
1656 if (lcur(parse
)->lclass
!= lc
) {
1657 lem_print_coords(lcur(parse
));
1658 printf(" Error: expected '");
1661 lem_print(lcur(parse
));
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
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
))
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
));
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
)