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

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

Update SBI to rev. 157.

  • Property mode set to 100644
File size: 20.4 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Parser
30 *
31 * Consumes a sequence of lexical elements and produces a syntax tree (stree).
32 * Parsing primitives, module members, statements.
33 */
34
35#include <assert.h>
36#include <stdlib.h>
37#include "debug.h"
38#include "lex.h"
39#include "list.h"
40#include "mytypes.h"
41#include "p_expr.h"
42#include "p_type.h"
43#include "stree.h"
44#include "strtab.h"
45#include "symbol.h"
46
47#include "parse.h"
48
49/*
50 * Module members
51 */
52static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
53 stree_csi_t *outer_csi);
54static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
55
56static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi);
57static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi);
58static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi);
59
60static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse);
61
62static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
63static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
64
65/*
66 * Statements
67 */
68static stree_block_t *parse_block(parse_t *parse);
69
70static stree_vdecl_t *parse_vdecl(parse_t *parse);
71static stree_if_t *parse_if(parse_t *parse);
72static stree_while_t *parse_while(parse_t *parse);
73static stree_for_t *parse_for(parse_t *parse);
74static stree_raise_t *parse_raise(parse_t *parse);
75static stree_return_t *parse_return(parse_t *parse);
76static stree_wef_t *parse_wef(parse_t *parse);
77static stree_exps_t *parse_exps(parse_t *parse);
78
79static stree_except_t *parse_except(parse_t *parse);
80
81void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
82{
83 parse->program = prog;
84 parse->cur_mod = parse->program->module;
85 parse->lex = lex;
86
87 parse->error = b_false;
88 parse->error_bailout = b_false;
89
90 lex_next(parse->lex);
91}
92
93/** Parse module. */
94void parse_module(parse_t *parse)
95{
96 stree_csi_t *csi;
97 stree_modm_t *modm;
98
99 while (lcur_lc(parse) != lc_eof && !parse_is_error(parse)) {
100 switch (lcur_lc(parse)) {
101 case lc_class:
102 case lc_struct:
103 case lc_interface:
104 csi = parse_csi(parse, lcur_lc(parse), NULL);
105 modm = stree_modm_new(mc_csi);
106 modm->u.csi = csi;
107
108 list_append(&parse->cur_mod->members, modm);
109 break;
110 default:
111 lunexpected_error(parse);
112 lex_next(parse->lex);
113 break;
114 }
115
116 }
117}
118
119/** Parse class, struct or interface declaration. */
120static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
121 stree_csi_t *outer_csi)
122{
123 stree_csi_t *csi;
124 csi_class_t cc;
125 stree_csimbr_t *csimbr;
126 stree_symbol_t *symbol;
127
128 switch (dclass) {
129 case lc_class: cc = csi_class; break;
130 case lc_struct: cc = csi_struct; break;
131 case lc_interface: cc = csi_interface; break;
132 default: assert(b_false);
133 }
134
135 lskip(parse);
136
137 csi = stree_csi_new(cc);
138 csi->name = parse_ident(parse);
139
140 symbol = stree_symbol_new(sc_csi);
141 symbol->u.csi = csi;
142 symbol->outer_csi = outer_csi;
143 csi->symbol = symbol;
144
145#ifdef DEBUG_PARSE_TRACE
146 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
147 strtab_get_str(csi->name->sid));
148#endif
149 if (lcur_lc(parse) == lc_colon) {
150 /* Inheritance list */
151 lskip(parse);
152 csi->base_csi_ref = parse_texpr(parse);
153 } else {
154 csi->base_csi_ref = NULL;
155 }
156
157 lmatch(parse, lc_is);
158 list_init(&csi->members);
159
160 /* Parse class, struct or interface members. */
161 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
162 csimbr = parse_csimbr(parse, csi);
163 list_append(&csi->members, csimbr);
164 }
165
166 lmatch(parse, lc_end);
167
168 return csi;
169}
170
171/** Parse class, struct or interface member. */
172static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
173{
174 stree_csimbr_t *csimbr;
175
176 stree_csi_t *csi;
177 stree_fun_t *fun;
178 stree_var_t *var;
179 stree_prop_t *prop;
180
181 switch (lcur_lc(parse)) {
182 case lc_class:
183 case lc_struct:
184 case lc_interface:
185 csi = parse_csi(parse, lcur_lc(parse), outer_csi);
186 csimbr = stree_csimbr_new(csimbr_csi);
187 csimbr->u.csi = csi;
188 break;
189 case lc_fun:
190 fun = parse_fun(parse, outer_csi);
191 csimbr = stree_csimbr_new(csimbr_fun);
192 csimbr->u.fun = fun;
193 break;
194 case lc_var:
195 var = parse_var(parse, outer_csi);
196 csimbr = stree_csimbr_new(csimbr_var);
197 csimbr->u.var = var;
198 break;
199 case lc_prop:
200 prop = parse_prop(parse, outer_csi);
201 csimbr = stree_csimbr_new(csimbr_prop);
202 csimbr->u.prop = prop;
203 break;
204 default:
205 lunexpected_error(parse);
206 lex_next(parse->lex);
207 }
208
209 return csimbr;
210}
211
212
213/** Parse member function. */
214static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
215{
216 stree_fun_t *fun;
217 stree_proc_arg_t *arg;
218 stree_symbol_t *symbol;
219 stree_symbol_attr_t *attr;
220
221 fun = stree_fun_new();
222 symbol = stree_symbol_new(sc_fun);
223
224 symbol->u.fun = fun;
225 symbol->outer_csi = outer_csi;
226 fun->symbol = symbol;
227
228 lmatch(parse, lc_fun);
229 fun->name = parse_ident(parse);
230 lmatch(parse, lc_lparen);
231
232#ifdef DEBUG_PARSE_TRACE
233 printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
234#endif
235
236 list_init(&fun->args);
237
238 if (lcur_lc(parse) != lc_rparen) {
239
240 /* Parse formal parameters. */
241 while (!parse_is_error(parse)) {
242 arg = parse_proc_arg(parse);
243
244 if (stree_arg_has_attr(arg, aac_packed)) {
245 fun->varg = arg;
246 break;
247 } else {
248 list_append(&fun->args, arg);
249 }
250
251 if (lcur_lc(parse) == lc_rparen)
252 break;
253
254 lmatch(parse, lc_scolon);
255 }
256 }
257
258 lmatch(parse, lc_rparen);
259
260 if (lcur_lc(parse) == lc_colon) {
261 lskip(parse);
262 fun->rtype = parse_texpr(parse);
263 } else {
264 fun->rtype = NULL;
265 }
266
267 list_init(&symbol->attr);
268
269 /* Parse attributes. */
270 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
271 lskip(parse);
272 attr = parse_symbol_attr(parse);
273 list_append(&symbol->attr, attr);
274 }
275
276 fun->proc = stree_proc_new();
277 fun->proc->outer_symbol = symbol;
278
279 if (lcur_lc(parse) == lc_scolon) {
280 lskip(parse);
281
282 /* This function has no body. */
283 if (!stree_symbol_has_attr(symbol, sac_builtin)) {
284 printf("Error: Function '");
285 symbol_print_fqn(symbol);
286 printf("' has no body.\n");
287 parse_note_error(parse);
288 }
289 fun->proc->body = NULL;
290 } else {
291 lmatch(parse, lc_is);
292 fun->proc->body = parse_block(parse);
293 lmatch(parse, lc_end);
294 }
295
296 return fun;
297}
298
299/** Parse member variable. */
300static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi)
301{
302 stree_var_t *var;
303 stree_symbol_t *symbol;
304
305 var = stree_var_new();
306 symbol = stree_symbol_new(sc_var);
307 symbol->u.var = var;
308 symbol->outer_csi = outer_csi;
309 var->symbol = symbol;
310
311 lmatch(parse, lc_var);
312 var->name = parse_ident(parse);
313 lmatch(parse, lc_colon);
314 var->type = parse_texpr(parse);
315 lmatch(parse, lc_scolon);
316
317 return var;
318}
319
320/** Parse member property. */
321static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
322{
323 stree_prop_t *prop;
324 stree_symbol_t *symbol;
325
326 stree_ident_t *ident;
327 stree_proc_arg_t *arg;
328
329 prop = stree_prop_new();
330 list_init(&prop->args);
331
332 symbol = stree_symbol_new(sc_prop);
333 symbol->u.prop = prop;
334 symbol->outer_csi = outer_csi;
335 prop->symbol = symbol;
336
337 lmatch(parse, lc_prop);
338
339 if (lcur_lc(parse) == lc_self) {
340 /* Indexed property set */
341
342 /* Use some name that is impossible as identifier. */
343 ident = stree_ident_new();
344 ident->sid = strtab_get_sid(INDEXER_IDENT);
345 prop->name = ident;
346
347 lskip(parse);
348 lmatch(parse, lc_lsbr);
349
350 /* Parse formal parameters. */
351 while (!parse_is_error(parse)) {
352 arg = parse_proc_arg(parse);
353 if (stree_arg_has_attr(arg, aac_packed)) {
354 prop->varg = arg;
355 break;
356 } else {
357 list_append(&prop->args, arg);
358 }
359
360 if (lcur_lc(parse) == lc_rsbr)
361 break;
362
363 lmatch(parse, lc_scolon);
364 }
365
366 lmatch(parse, lc_rsbr);
367 } else {
368 /* Named property */
369 prop->name = parse_ident(parse);
370 }
371
372 lmatch(parse, lc_colon);
373 prop->type = parse_texpr(parse);
374 lmatch(parse, lc_is);
375
376 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
377 switch (lcur_lc(parse)) {
378 case lc_get:
379 lskip(parse);
380 lmatch(parse, lc_is);
381 if (prop->getter != NULL) {
382 printf("Error: Duplicate getter.\n");
383 (void) parse_block(parse); /* XXX Free */
384 lmatch(parse, lc_end);
385 parse_note_error(parse);
386 break;
387 }
388
389 /* Create setter procedure */
390 prop->getter = stree_proc_new();
391 prop->getter->body = parse_block(parse);
392 prop->getter->outer_symbol = symbol;
393
394 lmatch(parse, lc_end);
395 break;
396 case lc_set:
397 lskip(parse);
398 prop->setter_arg = stree_proc_arg_new();
399 prop->setter_arg->name = parse_ident(parse);
400 prop->setter_arg->type = prop->type;
401 lmatch(parse, lc_is);
402 if (prop->setter != NULL) {
403 printf("Error: Duplicate setter.\n");
404 (void) parse_block(parse); /* XXX Free */
405 lmatch(parse, lc_end);
406 parse_note_error(parse);
407 }
408
409 /* Create setter procedure */
410 prop->setter = stree_proc_new();
411 prop->setter->body = parse_block(parse);
412 prop->setter->outer_symbol = symbol;
413
414 lmatch(parse, lc_end);
415 break;
416 default:
417 lunexpected_error(parse);
418 }
419 }
420
421 lmatch(parse, lc_end);
422
423 return prop;
424}
425
426/** Parse symbol attribute. */
427static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
428{
429 stree_symbol_attr_t *attr;
430
431 if (lcur_lc(parse) != lc_builtin) {
432 printf("Error: Unexpected attribute '");
433 lem_print(lcur(parse));
434 printf("'.\n");
435 parse_note_error(parse);
436 }
437
438 lskip(parse);
439
440 attr = stree_symbol_attr_new(sac_builtin);
441 return attr;
442}
443
444/** Parse formal function argument. */
445static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
446{
447 stree_proc_arg_t *arg;
448 stree_arg_attr_t *attr;
449
450 arg = stree_proc_arg_new();
451 arg->name = parse_ident(parse);
452 lmatch(parse, lc_colon);
453 arg->type = parse_texpr(parse);
454
455 list_init(&arg->attr);
456
457 /* Parse attributes. */
458 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
459 lskip(parse);
460 attr = parse_arg_attr(parse);
461 list_append(&arg->attr, attr);
462 }
463
464#ifdef DEBUG_PARSE_TRACE
465 printf("Parsed arg attr, type=%p.\n", arg->type);
466#endif
467 return arg;
468}
469
470/** Parse argument attribute. */
471static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
472{
473 stree_arg_attr_t *attr;
474
475 if (lcur_lc(parse) != lc_packed) {
476 printf("Error: Unexpected attribute '");
477 lem_print(lcur(parse));
478 printf("'.\n");
479 parse_note_error(parse);
480 }
481
482 lskip(parse);
483
484 attr = stree_arg_attr_new(aac_packed);
485 return attr;
486}
487
488/** Parse statement block. */
489static stree_block_t *parse_block(parse_t *parse)
490{
491 stree_block_t *block;
492 stree_stat_t *stat;
493
494 block = stree_block_new();
495 list_init(&block->stats);
496
497 /* Avoid peeking if there is an error condition. */
498 if (parse_is_error(parse))
499 return block;
500
501 while (terminates_block(lcur_lc(parse)) != b_true &&
502 !parse_is_error(parse)) {
503
504 stat = parse_stat(parse);
505 list_append(&block->stats, stat);
506 }
507
508 return block;
509}
510
511/** Parse statement. */
512stree_stat_t *parse_stat(parse_t *parse)
513{
514 stree_stat_t *stat;
515
516 stree_vdecl_t *vdecl_s;
517 stree_if_t *if_s;
518 stree_while_t *while_s;
519 stree_for_t *for_s;
520 stree_raise_t *raise_s;
521 stree_return_t *return_s;
522 stree_wef_t *wef_s;
523 stree_exps_t *exp_s;
524
525#ifdef DEBUG_PARSE_TRACE
526 printf("Parse statement.\n");
527#endif
528 switch (lcur_lc(parse)) {
529 case lc_var:
530 vdecl_s = parse_vdecl(parse);
531 stat = stree_stat_new(st_vdecl);
532 stat->u.vdecl_s = vdecl_s;
533 break;
534 case lc_if:
535 if_s = parse_if(parse);
536 stat = stree_stat_new(st_if);
537 stat->u.if_s = if_s;
538 break;
539 case lc_while:
540 while_s = parse_while(parse);
541 stat = stree_stat_new(st_while);
542 stat->u.while_s = while_s;
543 break;
544 case lc_for:
545 for_s = parse_for(parse);
546 stat = stree_stat_new(st_for);
547 stat->u.for_s = for_s;
548 break;
549 case lc_raise:
550 raise_s = parse_raise(parse);
551 stat = stree_stat_new(st_raise);
552 stat->u.raise_s = raise_s;
553 break;
554 case lc_return:
555 return_s = parse_return(parse);
556 stat = stree_stat_new(st_return);
557 stat->u.return_s = return_s;
558 break;
559 case lc_do:
560 case lc_with:
561 wef_s = parse_wef(parse);
562 stat = stree_stat_new(st_wef);
563 stat->u.wef_s = wef_s;
564 break;
565 default:
566 exp_s = parse_exps(parse);
567 stat = stree_stat_new(st_exps);
568 stat->u.exp_s = exp_s;
569 break;
570 }
571
572#ifdef DEBUG_PARSE_TRACE
573 printf("Parsed statement %p\n", stat);
574#endif
575 return stat;
576}
577
578/** Parse variable declaration statement. */
579static stree_vdecl_t *parse_vdecl(parse_t *parse)
580{
581 stree_vdecl_t *vdecl;
582
583 vdecl = stree_vdecl_new();
584
585 lmatch(parse, lc_var);
586 vdecl->name = parse_ident(parse);
587 lmatch(parse, lc_colon);
588 vdecl->type = parse_texpr(parse);
589
590 if (lcur_lc(parse) == lc_assign) {
591 lskip(parse);
592 (void) parse_expr(parse);
593 }
594
595 lmatch(parse, lc_scolon);
596
597#ifdef DEBUG_PARSE_TRACE
598 printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
599 printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
600 vdecl, vdecl->name, vdecl->name->sid);
601#endif
602 return vdecl;
603}
604
605/** Parse @c if statement, */
606static stree_if_t *parse_if(parse_t *parse)
607{
608 stree_if_t *if_s;
609
610#ifdef DEBUG_PARSE_TRACE
611 printf("Parse 'if' statement.\n");
612#endif
613 if_s = stree_if_new();
614
615 lmatch(parse, lc_if);
616 if_s->cond = parse_expr(parse);
617 lmatch(parse, lc_then);
618 if_s->if_block = parse_block(parse);
619
620 if (lcur_lc(parse) == lc_else) {
621 lskip(parse);
622 if_s->else_block = parse_block(parse);
623 } else {
624 if_s->else_block = NULL;
625 }
626
627 lmatch(parse, lc_end);
628 return if_s;
629}
630
631/** Parse @c while statement. */
632static stree_while_t *parse_while(parse_t *parse)
633{
634 stree_while_t *while_s;
635
636#ifdef DEBUG_PARSE_TRACE
637 printf("Parse 'while' statement.\n");
638#endif
639 while_s = stree_while_new();
640
641 lmatch(parse, lc_while);
642 while_s->cond = parse_expr(parse);
643 lmatch(parse, lc_do);
644 while_s->body = parse_block(parse);
645 lmatch(parse, lc_end);
646
647 return while_s;
648}
649
650/** Parse @c for statement. */
651static stree_for_t *parse_for(parse_t *parse)
652{
653 stree_for_t *for_s;
654
655#ifdef DEBUG_PARSE_TRACE
656 printf("Parse 'for' statement.\n");
657#endif
658 for_s = stree_for_new();
659
660 lmatch(parse, lc_for);
661 lmatch(parse, lc_ident);
662 lmatch(parse, lc_colon);
663 (void) parse_texpr(parse);
664 lmatch(parse, lc_in);
665 (void) parse_expr(parse);
666 lmatch(parse, lc_do);
667 for_s->body = parse_block(parse);
668 lmatch(parse, lc_end);
669
670 return for_s;
671}
672
673/** Parse @c raise statement. */
674static stree_raise_t *parse_raise(parse_t *parse)
675{
676 stree_raise_t *raise_s;
677
678#ifdef DEBUG_PARSE_TRACE
679 printf("Parse 'raise' statement.\n");
680#endif
681 raise_s = stree_raise_new();
682 lmatch(parse, lc_raise);
683 raise_s->expr = parse_expr(parse);
684 lmatch(parse, lc_scolon);
685
686 return raise_s;
687}
688
689/** Parse @c return statement. */
690static stree_return_t *parse_return(parse_t *parse)
691{
692 stree_return_t *return_s;
693
694#ifdef DEBUG_PARSE_TRACE
695 printf("Parse 'return' statement.\n");
696#endif
697 return_s = stree_return_new();
698
699 lmatch(parse, lc_return);
700 return_s->expr = parse_expr(parse);
701 lmatch(parse, lc_scolon);
702
703 return return_s;
704}
705
706/* Parse @c with-except-finally statement. */
707static stree_wef_t *parse_wef(parse_t *parse)
708{
709 stree_wef_t *wef_s;
710 stree_except_t *except_c;
711
712#ifdef DEBUG_PARSE_TRACE
713 printf("Parse WEF statement.\n");
714#endif
715 wef_s = stree_wef_new();
716 list_init(&wef_s->except_clauses);
717
718 if (lcur_lc(parse) == lc_with) {
719 lmatch(parse, lc_with);
720 lmatch(parse, lc_ident);
721 lmatch(parse, lc_colon);
722 (void) parse_texpr(parse);
723 lmatch(parse, lc_assign);
724 (void) parse_expr(parse);
725 }
726
727 lmatch(parse, lc_do);
728 wef_s->with_block = parse_block(parse);
729
730 while (lcur_lc(parse) == lc_except && !parse_is_error(parse)) {
731 except_c = parse_except(parse);
732 list_append(&wef_s->except_clauses, except_c);
733 }
734
735 if (lcur_lc(parse) == lc_finally) {
736 lmatch(parse, lc_finally);
737 lmatch(parse, lc_do);
738 wef_s->finally_block = parse_block(parse);
739 } else {
740 wef_s->finally_block = NULL;
741 }
742
743 lmatch(parse, lc_end);
744
745 return wef_s;
746}
747
748/* Parse expression statement. */
749static stree_exps_t *parse_exps(parse_t *parse)
750{
751 stree_expr_t *expr;
752 stree_exps_t *exps;
753
754#ifdef DEBUG_PARSE_TRACE
755 printf("Parse expression statement.\n");
756#endif
757 expr = parse_expr(parse);
758 lmatch(parse, lc_scolon);
759
760 exps = stree_exps_new();
761 exps->expr = expr;
762
763 return exps;
764}
765
766/* Parse @c except clause. */
767static stree_except_t *parse_except(parse_t *parse)
768{
769 stree_except_t *except_c;
770
771#ifdef DEBUG_PARSE_TRACE
772 printf("Parse 'except' statement.\n");
773#endif
774 except_c = stree_except_new();
775
776 lmatch(parse, lc_except);
777 except_c->evar = parse_ident(parse);
778 lmatch(parse, lc_colon);
779 except_c->etype = parse_texpr(parse);
780 lmatch(parse, lc_do);
781
782 except_c->block = parse_block(parse);
783
784 return except_c;
785}
786
787/** Parse identifier. */
788stree_ident_t *parse_ident(parse_t *parse)
789{
790 stree_ident_t *ident;
791
792#ifdef DEBUG_PARSE_TRACE
793 printf("Parse identifier.\n");
794#endif
795 lcheck(parse, lc_ident);
796 ident = stree_ident_new();
797 ident->sid = lcur(parse)->u.ident.sid;
798 lskip(parse);
799
800 return ident;
801}
802
803/** Signal a parse error, start bailing out from parser. */
804void parse_raise_error(parse_t *parse)
805{
806 parse->error = b_true;
807 parse->error_bailout = b_true;
808}
809
810/** Note a parse error that has been immediately recovered. */
811void parse_note_error(parse_t *parse)
812{
813 parse->error = b_true;
814}
815
816/** Check if we are currently bailing out of parser due to a parse error. */
817bool_t parse_is_error(parse_t *parse)
818{
819 return parse->error_bailout;
820}
821
822/** Recover from parse error bailout.
823 *
824 * Still remember that there was an error, but stop bailing out.
825 */
826void parse_recover_error(parse_t *parse)
827{
828 assert(parse->error == b_true);
829 assert(parse->error_bailout == b_true);
830
831 parse->error_bailout = b_false;
832}
833
834/** Return current lem. */
835lem_t *lcur(parse_t *parse)
836{
837#ifdef DEBUG_LPARSE_TRACE
838 printf("lcur()\n");
839#endif
840 return lex_get_current(parse->lex);
841}
842
843/** Retturn current lem lclass. */
844lclass_t lcur_lc(parse_t *parse)
845{
846 lem_t *lem;
847
848 /*
849 * This allows us to skip error checking in many places. If there is an
850 * active error, lcur_lc() returns lc_invalid without reading input.
851 *
852 * Without this measure we would have to check for error all the time
853 * or risk requiring extra input from the user (in interactive mode)
854 * before actually bailing out from the parser.
855 */
856 if (parse_is_error(parse))
857 return lc_invalid;
858
859 lem = lcur(parse);
860 return lem->lclass;
861}
862
863/** Skip to next lem. */
864void lskip(parse_t *parse)
865{
866#ifdef DEBUG_LPARSE_TRACE
867 printf("lskip()\n");
868#endif
869 lex_next(parse->lex);
870}
871
872/** Verify that lclass of current lem is @a lc. */
873void lcheck(parse_t *parse, lclass_t lc)
874{
875#ifdef DEBUG_LPARSE_TRACE
876 printf("lcheck(");
877 lclass_print(lc);
878 printf(")\n");
879#endif
880 if (lcur(parse)->lclass != lc) {
881 lem_print_coords(lcur(parse));
882 printf(" Error: expected '"); lclass_print(lc);
883 printf("', got '"); lem_print(lcur(parse));
884 printf("'.\n");
885 parse_raise_error(parse);
886 }
887}
888
889/** Verify that lclass of current lem is @a lc and go to next lem. */
890void lmatch(parse_t *parse, lclass_t lc)
891{
892#ifdef DEBUG_LPARSE_TRACE
893 printf("lmatch(");
894 lclass_print(lc);
895 printf(")\n");
896#endif
897 /*
898 * This allows us to skip error checking in many places. If there is an
899 * active error, lmatch() does nothing (similar to parse_block(), etc.
900 *
901 * Without this measure we would have to check for error all the time
902 * or risk requiring extra input from the user (in interactive mode)
903 * before actually bailing out from the parser.
904 */
905 if (parse_is_error(parse))
906 return;
907
908 lcheck(parse, lc);
909 lskip(parse);
910}
911
912/** Display generic parsing error. */
913void lunexpected_error(parse_t *parse)
914{
915 lem_print_coords(lcur(parse));
916 printf(" Error: unexpected token '");
917 lem_print(lcur(parse));
918 printf("'.\n");
919 parse_raise_error(parse);
920}
921
922/** Basically tells us whether @a lclass is in next(block). */
923bool_t terminates_block(lclass_t lclass)
924{
925 switch (lclass) {
926 case lc_else:
927 case lc_end:
928 case lc_except:
929 case lc_finally:
930 return b_true;
931 default:
932 return b_false;
933 }
934}
Note: See TracBrowser for help on using the repository browser.