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

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

Update SBI to rev. 291.

  • Property mode set to 100644
File size: 35.9 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 "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"
47
48#include "parse.h"
49
50/*
51 * Module and CSI members
52 */
53static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
54 stree_csi_t *outer_csi);
55static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
56
57static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi);
58
59static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi);
60static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum);
61
62static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi);
63static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi);
64static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi);
65static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi);
66
67static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol);
68static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse);
69
70static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
71static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
72static stree_fun_sig_t *parse_fun_sig(parse_t *parse);
73
74static void parse_prop_get(parse_t *parse, stree_prop_t *prop);
75static void parse_prop_set(parse_t *parse, stree_prop_t *prop);
76
77/*
78 * Statements
79 */
80static stree_block_t *parse_block(parse_t *parse);
81
82static stree_vdecl_t *parse_vdecl(parse_t *parse);
83static stree_if_t *parse_if(parse_t *parse);
84static stree_while_t *parse_while(parse_t *parse);
85static stree_for_t *parse_for(parse_t *parse);
86static stree_raise_t *parse_raise(parse_t *parse);
87static stree_break_t *parse_break(parse_t *parse);
88static stree_return_t *parse_return(parse_t *parse);
89static stree_wef_t *parse_wef(parse_t *parse);
90static stree_exps_t *parse_exps(parse_t *parse);
91
92static stree_except_t *parse_except(parse_t *parse);
93
94/** Initialize parser object.
95 *
96 * Set up parser @a parse to use lexer @a lex for input and to store
97 * output (i.e. new declarations) to program @a prog. @a prog is not
98 * necessarily empty, the declarations being parsed are simply added
99 * to it.
100 *
101 * @param parse Parser object.
102 * @param prog Destination program stree.
103 * @param lex Input lexer.
104 */
105void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
106{
107 parse->program = prog;
108 parse->cur_mod = parse->program->module;
109 parse->lex = lex;
110
111 parse->error = b_false;
112 parse->error_bailout = b_false;
113
114 lex_next(parse->lex);
115}
116
117/** Parse module.
118 *
119 * Parse a program module.
120 *
121 * The input is read using the lexer associated with @a parse. The resulting
122 * declarations are added to existing declarations in the program associated
123 * with @a parse.
124 *
125 * If any parse error occurs, parse->error will @c b_true when this function
126 * returns. parse->error_bailout will be @c b_true if the error has not
127 * been recovered yet. Similar holds for other parsing functions in this
128 * module.
129 *
130 * @param parse Parser object.
131 */
132void parse_module(parse_t *parse)
133{
134 stree_csi_t *csi;
135 stree_enum_t *enum_d;
136 stree_modm_t *modm;
137
138 while (lcur_lc(parse) != lc_eof && !parse_is_error(parse)) {
139 switch (lcur_lc(parse)) {
140 case lc_class:
141 case lc_struct:
142 case lc_interface:
143 csi = parse_csi(parse, lcur_lc(parse), NULL);
144 modm = stree_modm_new(mc_csi);
145 modm->u.csi = csi;
146
147 list_append(&parse->cur_mod->members, modm);
148 break;
149 case lc_enum:
150 enum_d = parse_enum(parse, NULL);
151 modm = stree_modm_new(mc_enum);
152 modm->u.enum_d = enum_d;
153
154 list_append(&parse->cur_mod->members, modm);
155 break;
156 default:
157 lunexpected_error(parse);
158 lex_next(parse->lex);
159 break;
160 }
161
162 }
163}
164
165/** Parse class, struct or interface declaration.
166 *
167 * @param parse Parser object.
168 * @param dclass What to parse: @c lc_class, @c lc_struct or @c lc_csi.
169 * @param outer_csi CSI containing this declaration or @c NULL if global.
170 * @return New syntax tree node.
171 */
172static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
173 stree_csi_t *outer_csi)
174{
175 stree_csi_t *csi;
176 csi_class_t cc;
177 stree_csimbr_t *csimbr;
178 stree_symbol_t *symbol;
179 stree_ident_t *targ_name;
180 stree_targ_t *targ;
181 stree_texpr_t *pref;
182
183 switch (dclass) {
184 case lc_class: cc = csi_class; break;
185 case lc_struct: cc = csi_struct; break;
186 case lc_interface: cc = csi_interface; break;
187 default: assert(b_false);
188 }
189
190 lskip(parse);
191
192 csi = stree_csi_new(cc);
193 csi->name = parse_ident(parse);
194
195 list_init(&csi->targ);
196
197 while (lcur_lc(parse) == lc_slash) {
198 lskip(parse);
199 targ_name = parse_ident(parse);
200
201 targ = stree_targ_new();
202 targ->name = targ_name;
203
204 list_append(&csi->targ, targ);
205 }
206
207 symbol = stree_symbol_new(sc_csi);
208 symbol->u.csi = csi;
209 symbol->outer_csi = outer_csi;
210 csi->symbol = symbol;
211
212#ifdef DEBUG_PARSE_TRACE
213 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
214 strtab_get_str(csi->name->sid));
215#endif
216 if (lcur_lc(parse) == lc_colon) {
217 /* Inheritance list */
218 lskip(parse);
219
220 while (b_true) {
221 pref = parse_texpr(parse);
222 if (parse_is_error(parse))
223 break;
224
225 list_append(&csi->inherit, pref);
226 if (lcur_lc(parse) != lc_plus)
227 break;
228
229 lskip(parse);
230 }
231 }
232
233 lmatch(parse, lc_is);
234 list_init(&csi->members);
235
236 /* Parse class, struct or interface members. */
237 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
238 csimbr = parse_csimbr(parse, csi);
239 if (csimbr == NULL)
240 continue;
241
242 list_append(&csi->members, csimbr);
243 }
244
245 lmatch(parse, lc_end);
246
247 if (outer_csi != NULL) {
248 switch (outer_csi->cc) {
249 case csi_class:
250 case csi_struct:
251 break;
252 case csi_interface:
253 cspan_print(csi->name->cspan);
254 printf(" Error: CSI declared inside interface.\n");
255 parse_note_error(parse);
256 /* XXX Free csi */
257 return NULL;
258 }
259 }
260
261 return csi;
262}
263
264/** Parse class, struct or interface member.
265 *
266 * @param parse Parser object.
267 * @param outer_csi CSI containing this declaration.
268 * @return New syntax tree node. In case of parse error,
269 * @c NULL may (but need not) be returned.
270 */
271static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
272{
273 stree_csimbr_t *csimbr;
274
275 stree_csi_t *csi;
276 stree_ctor_t *ctor;
277 stree_deleg_t *deleg;
278 stree_enum_t *enum_d;
279 stree_fun_t *fun;
280 stree_var_t *var;
281 stree_prop_t *prop;
282
283 csimbr = NULL;
284
285 switch (lcur_lc(parse)) {
286 case lc_class:
287 case lc_struct:
288 case lc_interface:
289 csi = parse_csi(parse, lcur_lc(parse), outer_csi);
290 if (csi != NULL) {
291 csimbr = stree_csimbr_new(csimbr_csi);
292 csimbr->u.csi = csi;
293 }
294 break;
295 case lc_new:
296 ctor = parse_ctor(parse, outer_csi);
297 if (ctor != NULL) {
298 csimbr = stree_csimbr_new(csimbr_ctor);
299 csimbr->u.ctor = ctor;
300 }
301 break;
302 case lc_deleg:
303 deleg = parse_deleg(parse, outer_csi);
304 if (deleg != NULL) {
305 csimbr = stree_csimbr_new(csimbr_deleg);
306 csimbr->u.deleg = deleg;
307 }
308 break;
309 case lc_enum:
310 enum_d = parse_enum(parse, outer_csi);
311 if (enum_d != NULL) {
312 csimbr = stree_csimbr_new(csimbr_enum);
313 csimbr->u.enum_d = enum_d;
314 }
315 break;
316 case lc_fun:
317 fun = parse_fun(parse, outer_csi);
318 csimbr = stree_csimbr_new(csimbr_fun);
319 csimbr->u.fun = fun;
320 break;
321 case lc_var:
322 var = parse_var(parse, outer_csi);
323 if (var != NULL) {
324 csimbr = stree_csimbr_new(csimbr_var);
325 csimbr->u.var = var;
326 }
327 break;
328 case lc_prop:
329 prop = parse_prop(parse, outer_csi);
330 csimbr = stree_csimbr_new(csimbr_prop);
331 csimbr->u.prop = prop;
332 break;
333 default:
334 lunexpected_error(parse);
335 lex_next(parse->lex);
336 break;
337 }
338
339 return csimbr;
340}
341
342/** Parse constructor.
343 *
344 * @param parse Parser object.
345 * @param outer_csi CSI containing this declaration or @c NULL if global.
346 * @return New syntax tree node.
347 */
348static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi)
349{
350 stree_ctor_t *ctor;
351 stree_symbol_t *symbol;
352 cspan_t *cspan;
353
354 ctor = stree_ctor_new();
355 symbol = stree_symbol_new(sc_ctor);
356
357 symbol->u.ctor = ctor;
358 symbol->outer_csi = outer_csi;
359 ctor->symbol = symbol;
360
361 lmatch(parse, lc_new);
362 cspan = lprev_span(parse);
363
364 /* Fake identifier. */
365 ctor->name = stree_ident_new();
366 ctor->name->sid = strtab_get_sid(CTOR_IDENT);
367 ctor->name->cspan = lprev_span(parse);
368
369#ifdef DEBUG_PARSE_TRACE
370 printf("Parsing constructor of CSI '");
371 symbol_print_fqn(csi_to_symbol(outer_csi));
372 printf("'.\n");
373#endif
374 ctor->sig = parse_fun_sig(parse);
375 if (ctor->sig->rtype != NULL) {
376 cspan_print(cspan);
377 printf(" Error: Constructor of CSI '");
378 symbol_print_fqn(csi_to_symbol(outer_csi));
379 printf("' has a return type.\n");
380 parse_note_error(parse);
381 }
382
383 /* Parse attributes. */
384 parse_symbol_attrs(parse, symbol);
385
386 ctor->proc = stree_proc_new();
387 ctor->proc->outer_symbol = symbol;
388
389 if (lcur_lc(parse) == lc_scolon) {
390 lskip(parse);
391
392 /* This constructor has no body. */
393 cspan_print(cspan);
394 printf(" Error: Constructor of CSI '");
395 symbol_print_fqn(csi_to_symbol(outer_csi));
396 printf("' has no body.\n");
397 parse_note_error(parse);
398
399 ctor->proc->body = NULL;
400 } else {
401 lmatch(parse, lc_is);
402 ctor->proc->body = parse_block(parse);
403 lmatch(parse, lc_end);
404 }
405
406 switch (outer_csi->cc) {
407 case csi_class:
408 case csi_struct:
409 break;
410 case csi_interface:
411 cspan_print(ctor->name->cspan);
412 printf(" Error: Constructor declared inside interface.\n");
413 parse_note_error(parse);
414 /* XXX Free ctor */
415 return NULL;
416 }
417
418 return ctor;
419}
420
421/** Parse @c enum declaration.
422 *
423 * @param parse Parser object.
424 * @param outer_csi CSI containing this declaration or @c NULL if global.
425 * @return New syntax tree node.
426 */
427static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi)
428{
429 stree_enum_t *enum_d;
430 stree_symbol_t *symbol;
431 stree_embr_t *embr;
432
433 enum_d = stree_enum_new();
434 symbol = stree_symbol_new(sc_enum);
435
436 symbol->u.enum_d = enum_d;
437 symbol->outer_csi = outer_csi;
438 enum_d->symbol = symbol;
439
440 lmatch(parse, lc_enum);
441 enum_d->name = parse_ident(parse);
442 list_init(&enum_d->members);
443
444#ifdef DEBUG_PARSE_TRACE
445 printf("Parse enum '%s'.\n", strtab_get_str(enum_d->name->sid));
446#endif
447 lmatch(parse, lc_is);
448
449 /* Parse enum members. */
450 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
451 embr = parse_embr(parse, enum_d);
452 if (embr == NULL)
453 break;
454
455 list_append(&enum_d->members, embr);
456 }
457
458 if (list_is_empty(&enum_d->members)) {
459 cspan_print(enum_d->name->cspan);
460 printf("Error: Enum type '%s' has no members.\n",
461 strtab_get_str(enum_d->name->sid));
462 parse_note_error(parse);
463 }
464
465 lmatch(parse, lc_end);
466
467 if (outer_csi != NULL) {
468 switch (outer_csi->cc) {
469 case csi_class:
470 case csi_struct:
471 break;
472 case csi_interface:
473 cspan_print(enum_d->name->cspan);
474 printf(" Error: Enum declared inside interface.\n");
475 parse_note_error(parse);
476 /* XXX Free enum */
477 return NULL;
478 }
479 }
480
481 return enum_d;
482}
483
484/** Parse enum member.
485 *
486 * @param parse Parser object.
487 * @param outer_enum Enum containing this declaration.
488 * @return New syntax tree node. In case of parse error,
489 * @c NULL may (but need not) be returned.
490 */
491static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum)
492{
493 stree_embr_t *embr;
494
495 embr = stree_embr_new();
496 embr->outer_enum = outer_enum;
497 embr->name = parse_ident(parse);
498
499 lmatch(parse, lc_scolon);
500
501 return embr;
502}
503
504/** Parse delegate.
505 *
506 * @param parse Parser object.
507 * @param outer_csi CSI containing this declaration or @c NULL if global.
508 * @return New syntax tree node.
509 */
510static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi)
511{
512 stree_deleg_t *deleg;
513 stree_symbol_t *symbol;
514
515 deleg = stree_deleg_new();
516 symbol = stree_symbol_new(sc_deleg);
517
518 symbol->u.deleg = deleg;
519 symbol->outer_csi = outer_csi;
520 deleg->symbol = symbol;
521
522 lmatch(parse, lc_deleg);
523 deleg->name = parse_ident(parse);
524
525#ifdef DEBUG_PARSE_TRACE
526 printf("Parsing delegate '%s'.\n", strtab_get_str(deleg->name->sid));
527#endif
528
529 deleg->sig = parse_fun_sig(parse);
530
531 /* Parse attributes. */
532 parse_symbol_attrs(parse, symbol);
533
534 lmatch(parse, lc_scolon);
535
536 switch (outer_csi->cc) {
537 case csi_class:
538 case csi_struct:
539 break;
540 case csi_interface:
541 cspan_print(deleg->name->cspan);
542 printf(" Error: Delegate declared inside interface.\n");
543 parse_note_error(parse);
544 /* XXX Free deleg */
545 return NULL;
546 }
547
548 return deleg;
549}
550
551/** Parse member function.
552 *
553 * @param parse Parser object.
554 * @param outer_csi CSI containing this declaration or @c NULL if global.
555 * @return New syntax tree node.
556 */
557static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
558{
559 stree_fun_t *fun;
560 stree_symbol_t *symbol;
561 bool_t body_expected;
562
563 fun = stree_fun_new();
564 symbol = stree_symbol_new(sc_fun);
565
566 symbol->u.fun = fun;
567 symbol->outer_csi = outer_csi;
568 fun->symbol = symbol;
569
570 lmatch(parse, lc_fun);
571 fun->name = parse_ident(parse);
572
573#ifdef DEBUG_PARSE_TRACE
574 printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
575#endif
576 fun->sig = parse_fun_sig(parse);
577
578 /* Parse attributes. */
579 parse_symbol_attrs(parse, symbol);
580
581 body_expected = !stree_symbol_has_attr(symbol, sac_builtin) &&
582 (outer_csi->cc != csi_interface);
583
584 fun->proc = stree_proc_new();
585 fun->proc->outer_symbol = symbol;
586
587 if (lcur_lc(parse) == lc_scolon) {
588 lskip(parse);
589
590 /* Body not present */
591 if (body_expected) {
592 cspan_print(fun->name->cspan);
593 printf(" Error: Function '");
594 symbol_print_fqn(symbol);
595 printf("' should have a body.\n");
596 parse_note_error(parse);
597 }
598
599 fun->proc->body = NULL;
600 } else {
601 lmatch(parse, lc_is);
602 fun->proc->body = parse_block(parse);
603 lmatch(parse, lc_end);
604
605 /* Body present */
606 if (!body_expected) {
607 cspan_print(fun->name->cspan);
608 printf(" Error: Function declaration '");
609 symbol_print_fqn(symbol);
610 printf("' should not have a body.\n");
611 parse_note_error(parse);
612 }
613 }
614
615 return fun;
616}
617
618/** Parse member variable.
619 *
620 * @param parse Parser object.
621 * @param outer_csi CSI containing this declaration or @c NULL if global.
622 * @return New syntax tree node.
623 */
624static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi)
625{
626 stree_var_t *var;
627 stree_symbol_t *symbol;
628
629 var = stree_var_new();
630 symbol = stree_symbol_new(sc_var);
631 symbol->u.var = var;
632 symbol->outer_csi = outer_csi;
633 var->symbol = symbol;
634
635 lmatch(parse, lc_var);
636 var->name = parse_ident(parse);
637 lmatch(parse, lc_colon);
638 var->type = parse_texpr(parse);
639
640 parse_symbol_attrs(parse, symbol);
641
642 lmatch(parse, lc_scolon);
643
644 switch (outer_csi->cc) {
645 case csi_class:
646 case csi_struct:
647 break;
648 case csi_interface:
649 cspan_print(var->name->cspan);
650 printf(" Error: Variable declared inside interface.\n");
651 parse_note_error(parse);
652 /* XXX Free var */
653 return NULL;
654 }
655
656 return var;
657}
658
659/** Parse member property.
660 *
661 * @param parse Parser object.
662 * @param outer_csi CSI containing this declaration or @c NULL if global.
663 * @return New syntax tree node.
664 */
665static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
666{
667 stree_prop_t *prop;
668 stree_symbol_t *symbol;
669 bool_t body_expected;
670
671 stree_ident_t *ident;
672 stree_proc_arg_t *arg;
673
674 prop = stree_prop_new();
675 list_init(&prop->args);
676
677 symbol = stree_symbol_new(sc_prop);
678 symbol->u.prop = prop;
679 symbol->outer_csi = outer_csi;
680 prop->symbol = symbol;
681
682 lmatch(parse, lc_prop);
683
684 if (lcur_lc(parse) == lc_self) {
685 /* Indexed property set */
686
687 /* Use some name that is impossible as identifier. */
688 ident = stree_ident_new();
689 ident->sid = strtab_get_sid(INDEXER_IDENT);
690 prop->name = ident;
691
692 lskip(parse);
693 lmatch(parse, lc_lsbr);
694
695 /* Parse formal parameters. */
696 while (!parse_is_error(parse)) {
697 arg = parse_proc_arg(parse);
698 if (stree_arg_has_attr(arg, aac_packed)) {
699 prop->varg = arg;
700 break;
701 } else {
702 list_append(&prop->args, arg);
703 }
704
705 if (lcur_lc(parse) == lc_rsbr)
706 break;
707
708 lmatch(parse, lc_scolon);
709 }
710
711 lmatch(parse, lc_rsbr);
712 } else {
713 /* Named property */
714 prop->name = parse_ident(parse);
715 }
716
717 lmatch(parse, lc_colon);
718 prop->type = parse_texpr(parse);
719
720 /* Parse attributes. */
721 parse_symbol_attrs(parse, symbol);
722
723 body_expected = (outer_csi->cc != csi_interface);
724
725 lmatch(parse, lc_is);
726
727 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
728 switch (lcur_lc(parse)) {
729 case lc_get:
730 parse_prop_get(parse, prop);
731 break;
732 case lc_set:
733 parse_prop_set(parse, prop);
734 break;
735 default:
736 lunexpected_error(parse);
737 }
738 }
739
740 lmatch(parse, lc_end);
741
742 return prop;
743}
744
745/** Parse symbol attributes.
746 *
747 * Parse list of attributes and add them to @a symbol.
748 *
749 * @param parse Parser object
750 * @param symbol Symbol to add these attributes to
751 */
752static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol)
753{
754 stree_symbol_attr_t *attr;
755
756 /* Parse attributes. */
757 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
758 lskip(parse);
759 attr = parse_symbol_attr(parse);
760 list_append(&symbol->attr, attr);
761 }
762}
763
764/** Parse symbol attribute.
765 *
766 * @param parse Parser object
767 * @return New syntax tree node
768 */
769static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
770{
771 stree_symbol_attr_t *attr;
772 symbol_attr_class_t sac;
773
774 /* Make compiler happy. */
775 sac = 0;
776
777 switch (lcur_lc(parse)) {
778 case lc_builtin: sac = sac_builtin; break;
779 case lc_static: sac = sac_static; break;
780 default:
781 cspan_print(lcur_span(parse));
782 printf(" Error: Unexpected attribute '");
783 lem_print(lcur(parse));
784 printf("'.\n");
785 parse_note_error(parse);
786 break;
787 }
788
789 lskip(parse);
790
791 attr = stree_symbol_attr_new(sac);
792 return attr;
793}
794
795/** Parse formal function argument.
796 *
797 * @param parse Parser object.
798 * @return New syntax tree node.
799 */
800static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
801{
802 stree_proc_arg_t *arg;
803 stree_arg_attr_t *attr;
804
805 arg = stree_proc_arg_new();
806 arg->name = parse_ident(parse);
807 lmatch(parse, lc_colon);
808 arg->type = parse_texpr(parse);
809
810#ifdef DEBUG_PARSE_TRACE
811 printf("Parse procedure argument.\n");
812#endif
813 list_init(&arg->attr);
814
815 /* Parse attributes. */
816 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
817 lskip(parse);
818 attr = parse_arg_attr(parse);
819 list_append(&arg->attr, attr);
820 }
821
822 return arg;
823}
824
825/** Parse argument attribute.
826 *
827 * @param parse Parser object.
828 * @return New syntax tree node.
829 */
830static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
831{
832 stree_arg_attr_t *attr;
833
834 if (lcur_lc(parse) != lc_packed) {
835 cspan_print(lcur_span(parse));
836 printf(" Error: Unexpected attribute '");
837 lem_print(lcur(parse));
838 printf("'.\n");
839 parse_note_error(parse);
840 }
841
842 lskip(parse);
843
844 attr = stree_arg_attr_new(aac_packed);
845 return attr;
846}
847
848/** Parse function signature.
849 *
850 * @param parse Parser object.
851 * @return New syntax tree node.
852 */
853static stree_fun_sig_t *parse_fun_sig(parse_t *parse)
854{
855 stree_fun_sig_t *sig;
856 stree_proc_arg_t *arg;
857
858 sig = stree_fun_sig_new();
859
860 lmatch(parse, lc_lparen);
861
862#ifdef DEBUG_PARSE_TRACE
863 printf("Parsing function signature.\n");
864#endif
865
866 list_init(&sig->args);
867
868 if (lcur_lc(parse) != lc_rparen) {
869
870 /* Parse formal parameters. */
871 while (!parse_is_error(parse)) {
872 arg = parse_proc_arg(parse);
873
874 if (stree_arg_has_attr(arg, aac_packed)) {
875 sig->varg = arg;
876 break;
877 } else {
878 list_append(&sig->args, arg);
879 }
880
881 if (lcur_lc(parse) == lc_rparen)
882 break;
883
884 lmatch(parse, lc_scolon);
885 }
886 }
887
888 lmatch(parse, lc_rparen);
889
890 if (lcur_lc(parse) == lc_colon) {
891 lskip(parse);
892 sig->rtype = parse_texpr(parse);
893 } else {
894 sig->rtype = NULL;
895 }
896
897 return sig;
898}
899
900/** Parse member property getter.
901 *
902 * @param parse Parser object.
903 * @param prop Property containing this declaration.
904 */
905static void parse_prop_get(parse_t *parse, stree_prop_t *prop)
906{
907 cspan_t *cspan;
908 stree_block_t *block;
909 stree_proc_t *getter;
910 bool_t body_expected;
911
912 body_expected = (prop->symbol->outer_csi->cc != csi_interface);
913
914 lskip(parse);
915 cspan = lprev_span(parse);
916
917 if (prop->getter != NULL) {
918 cspan_print(cspan);
919 printf(" Error: Duplicate getter.\n");
920 parse_note_error(parse);
921 return;
922 }
923
924 if (lcur_lc(parse) == lc_scolon) {
925 /* Body not present */
926 lskip(parse);
927 block = NULL;
928
929 if (body_expected) {
930 cspan_print(prop->name->cspan);
931 printf(" Error: Property '");
932 symbol_print_fqn(prop->symbol);
933 printf("' getter should have "
934 "a body.\n");
935 parse_note_error(parse);
936 }
937 } else {
938 /* Body present */
939 lmatch(parse, lc_is);
940 block = parse_block(parse);
941 lmatch(parse, lc_end);
942
943 if (!body_expected) {
944 cspan_print(prop->name->cspan);
945 printf(" Error: Property '");
946 symbol_print_fqn(prop->symbol);
947 printf("' getter declaration should "
948 "not have a body.\n");
949 parse_note_error(parse);
950
951 /* XXX Free block */
952 block = NULL;
953 }
954 }
955
956 /* Create getter procedure */
957 getter = stree_proc_new();
958 getter->body = block;
959 getter->outer_symbol = prop->symbol;
960
961 /* Store getter in property. */
962 prop->getter = getter;
963}
964
965
966/** Parse member property setter.
967 *
968 * @param parse Parser object.
969 * @param prop Property containing this declaration.
970 */
971static void parse_prop_set(parse_t *parse, stree_prop_t *prop)
972{
973 cspan_t *cspan;
974 stree_block_t *block;
975 stree_proc_t *setter;
976 bool_t body_expected;
977
978 body_expected = (prop->symbol->outer_csi->cc != csi_interface);
979
980 lskip(parse);
981 cspan = lprev_span(parse);
982
983 if (prop->setter != NULL) {
984 cspan_print(cspan);
985 printf(" Error: Duplicate setter.\n");
986 parse_note_error(parse);
987 return;
988 }
989
990 prop->setter_arg = stree_proc_arg_new();
991 prop->setter_arg->name = parse_ident(parse);
992 prop->setter_arg->type = prop->type;
993
994 if (lcur_lc(parse) == lc_scolon) {
995 /* Body not present */
996 lskip(parse);
997
998 block = NULL;
999
1000 if (body_expected) {
1001 cspan_print(prop->name->cspan);
1002 printf(" Error: Property '");
1003 symbol_print_fqn(prop->symbol);
1004 printf("' setter should have "
1005 "a body.\n");
1006 parse_note_error(parse);
1007 }
1008 } else {
1009 /* Body present */
1010 lmatch(parse, lc_is);
1011 block = parse_block(parse);
1012 lmatch(parse, lc_end);
1013
1014 if (!body_expected) {
1015 cspan_print(prop->name->cspan);
1016 printf(" Error: Property '");
1017 symbol_print_fqn(prop->symbol);
1018 printf("' setter declaration should "
1019 "not have a body.\n");
1020 parse_note_error(parse);
1021 }
1022 }
1023
1024
1025 /* Create setter procedure */
1026 setter = stree_proc_new();
1027 setter->body = block;
1028 setter->outer_symbol = prop->symbol;
1029
1030 /* Store setter in property. */
1031 prop->setter = setter;
1032}
1033
1034/** Parse statement block.
1035 *
1036 * @param parse Parser object.
1037 * @return New syntax tree node.
1038 */
1039static stree_block_t *parse_block(parse_t *parse)
1040{
1041 stree_block_t *block;
1042 stree_stat_t *stat;
1043
1044 block = stree_block_new();
1045 list_init(&block->stats);
1046
1047 /* Avoid peeking if there is an error condition. */
1048 if (parse_is_error(parse))
1049 return block;
1050
1051 while (terminates_block(lcur_lc(parse)) != b_true &&
1052 !parse_is_error(parse)) {
1053
1054 stat = parse_stat(parse);
1055 list_append(&block->stats, stat);
1056 }
1057
1058 return block;
1059}
1060
1061/** Parse statement.
1062 *
1063 * @param parse Parser object.
1064 * @return New syntax tree node.
1065 */
1066stree_stat_t *parse_stat(parse_t *parse)
1067{
1068 stree_stat_t *stat;
1069
1070 stree_vdecl_t *vdecl_s;
1071 stree_if_t *if_s;
1072 stree_while_t *while_s;
1073 stree_for_t *for_s;
1074 stree_raise_t *raise_s;
1075 stree_break_t *break_s;
1076 stree_return_t *return_s;
1077 stree_wef_t *wef_s;
1078 stree_exps_t *exp_s;
1079
1080#ifdef DEBUG_PARSE_TRACE
1081 printf("Parse statement.\n");
1082#endif
1083 switch (lcur_lc(parse)) {
1084 case lc_var:
1085 vdecl_s = parse_vdecl(parse);
1086 stat = stree_stat_new(st_vdecl);
1087 stat->u.vdecl_s = vdecl_s;
1088 break;
1089 case lc_if:
1090 if_s = parse_if(parse);
1091 stat = stree_stat_new(st_if);
1092 stat->u.if_s = if_s;
1093 break;
1094 case lc_while:
1095 while_s = parse_while(parse);
1096 stat = stree_stat_new(st_while);
1097 stat->u.while_s = while_s;
1098 break;
1099 case lc_for:
1100 for_s = parse_for(parse);
1101 stat = stree_stat_new(st_for);
1102 stat->u.for_s = for_s;
1103 break;
1104 case lc_raise:
1105 raise_s = parse_raise(parse);
1106 stat = stree_stat_new(st_raise);
1107 stat->u.raise_s = raise_s;
1108 break;
1109 case lc_break:
1110 break_s = parse_break(parse);
1111 stat = stree_stat_new(st_break);
1112 stat->u.break_s = break_s;
1113 break;
1114 case lc_return:
1115 return_s = parse_return(parse);
1116 stat = stree_stat_new(st_return);
1117 stat->u.return_s = return_s;
1118 break;
1119 case lc_do:
1120 case lc_with:
1121 wef_s = parse_wef(parse);
1122 stat = stree_stat_new(st_wef);
1123 stat->u.wef_s = wef_s;
1124 break;
1125 default:
1126 exp_s = parse_exps(parse);
1127 stat = stree_stat_new(st_exps);
1128 stat->u.exp_s = exp_s;
1129 break;
1130 }
1131
1132#ifdef DEBUG_PARSE_TRACE
1133 printf("Parsed statement %p\n", stat);
1134#endif
1135 return stat;
1136}
1137
1138/** Parse variable declaration statement.
1139 *
1140 * @param parse Parser object.
1141 * @return New syntax tree node.
1142 */
1143static stree_vdecl_t *parse_vdecl(parse_t *parse)
1144{
1145 stree_vdecl_t *vdecl;
1146
1147 vdecl = stree_vdecl_new();
1148
1149 lmatch(parse, lc_var);
1150 vdecl->name = parse_ident(parse);
1151 lmatch(parse, lc_colon);
1152 vdecl->type = parse_texpr(parse);
1153
1154 if (lcur_lc(parse) == lc_assign) {
1155 lskip(parse);
1156 (void) parse_expr(parse);
1157 }
1158
1159 lmatch(parse, lc_scolon);
1160
1161#ifdef DEBUG_PARSE_TRACE
1162 printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
1163 printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
1164 vdecl, vdecl->name, vdecl->name->sid);
1165#endif
1166 return vdecl;
1167}
1168
1169/** Parse @c if statement.
1170 *
1171 * @param parse Parser object.
1172 * @return New syntax tree node.
1173 */
1174static stree_if_t *parse_if(parse_t *parse)
1175{
1176 stree_if_t *if_s;
1177 stree_if_clause_t *if_c;
1178
1179#ifdef DEBUG_PARSE_TRACE
1180 printf("Parse 'if' statement.\n");
1181#endif
1182 if_s = stree_if_new();
1183 list_init(&if_s->if_clauses);
1184
1185 /* Parse @c if clause. */
1186 lmatch(parse, lc_if);
1187
1188 if_c = stree_if_clause_new();
1189 if_c->cond = parse_expr(parse);
1190 lmatch(parse, lc_then);
1191 if_c->block = parse_block(parse);
1192
1193 list_append(&if_s->if_clauses, if_c);
1194
1195 /* Parse @c elif clauses. */
1196 while (lcur_lc(parse) == lc_elif) {
1197 lskip(parse);
1198 if_c = stree_if_clause_new();
1199 if_c->cond = parse_expr(parse);
1200 lmatch(parse, lc_then);
1201 if_c->block = parse_block(parse);
1202
1203 list_append(&if_s->if_clauses, if_c);
1204 }
1205
1206 /* Parse @c else clause. */
1207 if (lcur_lc(parse) == lc_else) {
1208 lskip(parse);
1209 if_s->else_block = parse_block(parse);
1210 } else {
1211 if_s->else_block = NULL;
1212 }
1213
1214 lmatch(parse, lc_end);
1215 return if_s;
1216}
1217
1218/** Parse @c while statement.
1219 *
1220 * @param parse Parser object.
1221 */
1222static stree_while_t *parse_while(parse_t *parse)
1223{
1224 stree_while_t *while_s;
1225
1226#ifdef DEBUG_PARSE_TRACE
1227 printf("Parse 'while' statement.\n");
1228#endif
1229 while_s = stree_while_new();
1230
1231 lmatch(parse, lc_while);
1232 while_s->cond = parse_expr(parse);
1233 lmatch(parse, lc_do);
1234 while_s->body = parse_block(parse);
1235 lmatch(parse, lc_end);
1236
1237 return while_s;
1238}
1239
1240/** Parse @c for statement.
1241 *
1242 * @param parse Parser object.
1243 * @return New syntax tree node.
1244 */
1245static stree_for_t *parse_for(parse_t *parse)
1246{
1247 stree_for_t *for_s;
1248
1249#ifdef DEBUG_PARSE_TRACE
1250 printf("Parse 'for' statement.\n");
1251#endif
1252 for_s = stree_for_new();
1253
1254 lmatch(parse, lc_for);
1255 lmatch(parse, lc_ident);
1256 lmatch(parse, lc_colon);
1257 (void) parse_texpr(parse);
1258 lmatch(parse, lc_in);
1259 (void) parse_expr(parse);
1260 lmatch(parse, lc_do);
1261 for_s->body = parse_block(parse);
1262 lmatch(parse, lc_end);
1263
1264 return for_s;
1265}
1266
1267/** Parse @c raise statement.
1268 *
1269 * @param parse Parser object.
1270 */
1271static stree_raise_t *parse_raise(parse_t *parse)
1272{
1273 stree_raise_t *raise_s;
1274
1275#ifdef DEBUG_PARSE_TRACE
1276 printf("Parse 'raise' statement.\n");
1277#endif
1278 raise_s = stree_raise_new();
1279 lmatch(parse, lc_raise);
1280 raise_s->expr = parse_expr(parse);
1281 lmatch(parse, lc_scolon);
1282
1283 return raise_s;
1284}
1285
1286/** Parse @c break statement.
1287 *
1288 * @param parse Parser object.
1289 * @return New syntax tree node.
1290 */
1291static stree_break_t *parse_break(parse_t *parse)
1292{
1293 stree_break_t *break_s;
1294
1295#ifdef DEBUG_PARSE_TRACE
1296 printf("Parse 'break' statement.\n");
1297#endif
1298 break_s = stree_break_new();
1299
1300 lmatch(parse, lc_break);
1301 lmatch(parse, lc_scolon);
1302
1303 return break_s;
1304}
1305
1306/** Parse @c return statement.
1307 *
1308 * @param parse Parser object.
1309 * @return New syntax tree node.
1310 */
1311static stree_return_t *parse_return(parse_t *parse)
1312{
1313 stree_return_t *return_s;
1314
1315#ifdef DEBUG_PARSE_TRACE
1316 printf("Parse 'return' statement.\n");
1317#endif
1318 return_s = stree_return_new();
1319
1320 lmatch(parse, lc_return);
1321
1322 if (lcur_lc(parse) != lc_scolon)
1323 return_s->expr = parse_expr(parse);
1324
1325 lmatch(parse, lc_scolon);
1326
1327 return return_s;
1328}
1329
1330/* Parse @c with-except-finally statement.
1331 *
1332 * @param parse Parser object.
1333 * @return New syntax tree node.
1334 */
1335static stree_wef_t *parse_wef(parse_t *parse)
1336{
1337 stree_wef_t *wef_s;
1338 stree_except_t *except_c;
1339
1340#ifdef DEBUG_PARSE_TRACE
1341 printf("Parse WEF statement.\n");
1342#endif
1343 wef_s = stree_wef_new();
1344 list_init(&wef_s->except_clauses);
1345
1346 if (lcur_lc(parse) == lc_with) {
1347 lmatch(parse, lc_with);
1348 lmatch(parse, lc_ident);
1349 lmatch(parse, lc_colon);
1350 (void) parse_texpr(parse);
1351 lmatch(parse, lc_assign);
1352 (void) parse_expr(parse);
1353 }
1354
1355 lmatch(parse, lc_do);
1356 wef_s->with_block = parse_block(parse);
1357
1358 while (lcur_lc(parse) == lc_except && !parse_is_error(parse)) {
1359 except_c = parse_except(parse);
1360 list_append(&wef_s->except_clauses, except_c);
1361 }
1362
1363 if (lcur_lc(parse) == lc_finally) {
1364 lmatch(parse, lc_finally);
1365 lmatch(parse, lc_do);
1366 wef_s->finally_block = parse_block(parse);
1367 } else {
1368 wef_s->finally_block = NULL;
1369 }
1370
1371 lmatch(parse, lc_end);
1372
1373 return wef_s;
1374}
1375
1376/* Parse expression statement.
1377 *
1378 * @param parse Parser object.
1379 * @return New syntax tree node.
1380 */
1381static stree_exps_t *parse_exps(parse_t *parse)
1382{
1383 stree_expr_t *expr;
1384 stree_exps_t *exps;
1385
1386#ifdef DEBUG_PARSE_TRACE
1387 printf("Parse expression statement.\n");
1388#endif
1389 expr = parse_expr(parse);
1390 lmatch(parse, lc_scolon);
1391
1392 exps = stree_exps_new();
1393 exps->expr = expr;
1394
1395 return exps;
1396}
1397
1398/* Parse @c except clause.
1399 *
1400 * @param parse Parser object.
1401 * @return New syntax tree node.
1402 */
1403static stree_except_t *parse_except(parse_t *parse)
1404{
1405 stree_except_t *except_c;
1406
1407#ifdef DEBUG_PARSE_TRACE
1408 printf("Parse 'except' statement.\n");
1409#endif
1410 except_c = stree_except_new();
1411
1412 lmatch(parse, lc_except);
1413 except_c->evar = parse_ident(parse);
1414 lmatch(parse, lc_colon);
1415 except_c->etype = parse_texpr(parse);
1416 lmatch(parse, lc_do);
1417
1418 except_c->block = parse_block(parse);
1419
1420 return except_c;
1421}
1422
1423/** Parse identifier.
1424 *
1425 * @param parse Parser object.
1426 * @return New syntax tree node.
1427 */
1428stree_ident_t *parse_ident(parse_t *parse)
1429{
1430 stree_ident_t *ident;
1431
1432#ifdef DEBUG_PARSE_TRACE
1433 printf("Parse identifier.\n");
1434#endif
1435 lcheck(parse, lc_ident);
1436 ident = stree_ident_new();
1437 ident->sid = lcur(parse)->u.ident.sid;
1438 ident->cspan = lcur_span(parse);
1439 lskip(parse);
1440
1441 return ident;
1442}
1443
1444/** Signal a parse error, start bailing out from parser.
1445 *
1446 * @param parse Parser object.
1447 */
1448void parse_raise_error(parse_t *parse)
1449{
1450 parse->error = b_true;
1451 parse->error_bailout = b_true;
1452}
1453
1454/** Note a parse error that has been immediately recovered.
1455 *
1456 * @param parse Parser object.
1457 */
1458void parse_note_error(parse_t *parse)
1459{
1460 parse->error = b_true;
1461}
1462
1463/** Check if we are currently bailing out of parser due to a parse error.
1464 *
1465 * @param parse Parser object.
1466 */
1467bool_t parse_is_error(parse_t *parse)
1468{
1469 return parse->error_bailout;
1470}
1471
1472/** Recover from parse error bailout.
1473 *
1474 * Still remember that there was an error, but stop bailing out.
1475 *
1476 * @param parse Parser object.
1477 */
1478void parse_recover_error(parse_t *parse)
1479{
1480 assert(parse->error == b_true);
1481 assert(parse->error_bailout == b_true);
1482
1483 parse->error_bailout = b_false;
1484}
1485
1486/** Return current lem.
1487 *
1488 * @param parse Parser object.
1489 * @return Pointer to current lem. Only valid until the lexing
1490 * position is advanced.
1491 */
1492lem_t *lcur(parse_t *parse)
1493{
1494#ifdef DEBUG_LPARSE_TRACE
1495 printf("lcur()\n");
1496#endif
1497 return lex_get_current(parse->lex);
1498}
1499
1500/** Return current lem lclass.
1501 *
1502 * @param parse Parser object
1503 * @return Lclass of the current lem
1504 */
1505lclass_t lcur_lc(parse_t *parse)
1506{
1507 lem_t *lem;
1508
1509 /*
1510 * This allows us to skip error checking in many places. If there is an
1511 * active error, lcur_lc() returns lc_invalid without reading input.
1512 *
1513 * Without this measure we would have to check for error all the time
1514 * or risk requiring extra input from the user (in interactive mode)
1515 * before actually bailing out from the parser.
1516 */
1517 if (parse_is_error(parse))
1518 return lc_invalid;
1519
1520 lem = lcur(parse);
1521 return lem->lclass;
1522}
1523
1524/** Return coordinate span of current lem.
1525 *
1526 * @param parse Parser object
1527 * @return Coordinate span of current lem or @c NULL if a
1528 * parse error is active
1529 */
1530cspan_t *lcur_span(parse_t *parse)
1531{
1532 lem_t *lem;
1533
1534 if (parse_is_error(parse))
1535 return NULL;
1536
1537 lem = lcur(parse);
1538 return lem->cspan;
1539}
1540
1541/** Return coordinate span of previous lem.
1542 *
1543 * @param parse Parser object
1544 * @return Coordinate span of previous lem or @c NULL if
1545 * parse error is active or previous lem is not
1546 * available.
1547 */
1548cspan_t *lprev_span(parse_t *parse)
1549{
1550 lem_t *lem;
1551
1552 if (parse_is_error(parse))
1553 return NULL;
1554
1555 lem = lex_peek_prev(parse->lex);
1556 if (lem == NULL)
1557 return NULL;
1558
1559 return lem->cspan;
1560}
1561
1562/** Skip to next lem.
1563 *
1564 * @param parse Parser object.
1565 */
1566void lskip(parse_t *parse)
1567{
1568#ifdef DEBUG_LPARSE_TRACE
1569 printf("lskip()\n");
1570#endif
1571 lex_next(parse->lex);
1572}
1573
1574/** Verify that lclass of current lem is @a lc.
1575 *
1576 * If a lem of different lclass is found, a parse error is raised and
1577 * a message is printed.
1578 *
1579 * @param parse Parser object.
1580 * @param lc Expected lclass.
1581 */
1582void lcheck(parse_t *parse, lclass_t lc)
1583{
1584#ifdef DEBUG_LPARSE_TRACE
1585 printf("lcheck(");
1586 lclass_print(lc);
1587 printf(")\n");
1588#endif
1589 if (lcur(parse)->lclass != lc) {
1590 lem_print_coords(lcur(parse));
1591 printf(" Error: expected '"); lclass_print(lc);
1592 printf("', got '"); lem_print(lcur(parse));
1593 printf("'.\n");
1594 parse_raise_error(parse);
1595 }
1596}
1597
1598/** Verify that lclass of current lem is @a lc and go to next lem.
1599 *
1600 * If a lem of different lclass is found, a parse error is raised and
1601 * a message is printed.
1602 *
1603 * @param parse Parser object.
1604 * @param lc Expected lclass.
1605 */
1606void lmatch(parse_t *parse, lclass_t lc)
1607{
1608#ifdef DEBUG_LPARSE_TRACE
1609 printf("lmatch(");
1610 lclass_print(lc);
1611 printf(")\n");
1612#endif
1613 /*
1614 * This allows us to skip error checking in many places. If there is an
1615 * active error, lmatch() does nothing (similar to parse_block(), etc.
1616 *
1617 * Without this measure we would have to check for error all the time
1618 * or risk requiring extra input from the user (in interactive mode)
1619 * before actually bailing out from the parser.
1620 */
1621 if (parse_is_error(parse))
1622 return;
1623
1624 lcheck(parse, lc);
1625 lskip(parse);
1626}
1627
1628/** Raise and display generic parsing error.
1629 *
1630 * @param parse Parser object.
1631 */
1632void lunexpected_error(parse_t *parse)
1633{
1634 lem_print_coords(lcur(parse));
1635 printf(" Error: unexpected token '");
1636 lem_print(lcur(parse));
1637 printf("'.\n");
1638 parse_raise_error(parse);
1639}
1640
1641/** Determine whether @a lclass is in follow(block).
1642 *
1643 * Tests whether @a lclass belongs to the follow(block) set, i.e. if it is
1644 * lclass of a lem that can follow a block in the program.
1645 *
1646 * @param lclass Lclass.
1647 */
1648bool_t terminates_block(lclass_t lclass)
1649{
1650 switch (lclass) {
1651 case lc_elif:
1652 case lc_else:
1653 case lc_end:
1654 case lc_except:
1655 case lc_finally:
1656 return b_true;
1657 default:
1658 return b_false;
1659 }
1660}
Note: See TracBrowser for help on using the repository browser.