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

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

Fix block comment formatting (ccheck).

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