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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c5ad226 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
RevLine 
[09ababb7]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>
[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);
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);
[051bc69a]87static stree_break_t *parse_break(parse_t *parse);
[fa36f29]88static stree_return_t *parse_return(parse_t *parse);
[09ababb7]89static stree_wef_t *parse_wef(parse_t *parse);
90static stree_exps_t *parse_exps(parse_t *parse);
91
[94d484a]92static stree_except_t *parse_except(parse_t *parse);
93
[23de644]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 */
[09ababb7]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;
[1ebc1a62]110
111 parse->error = b_false;
112 parse->error_bailout = b_false;
113
[09ababb7]114 lex_next(parse->lex);
115}
116
[23de644]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 */
[09ababb7]132void parse_module(parse_t *parse)
133{
134 stree_csi_t *csi;
[051bc69a]135 stree_enum_t *enum_d;
[09ababb7]136 stree_modm_t *modm;
137
[1ebc1a62]138 while (lcur_lc(parse) != lc_eof && !parse_is_error(parse)) {
[09ababb7]139 switch (lcur_lc(parse)) {
140 case lc_class:
141 case lc_struct:
142 case lc_interface:
[37f527b]143 csi = parse_csi(parse, lcur_lc(parse), NULL);
[09ababb7]144 modm = stree_modm_new(mc_csi);
145 modm->u.csi = csi;
146
[051bc69a]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
[09ababb7]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
[23de644]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 */
[37f527b]172static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
173 stree_csi_t *outer_csi)
[09ababb7]174{
175 stree_csi_t *csi;
176 csi_class_t cc;
177 stree_csimbr_t *csimbr;
[37f527b]178 stree_symbol_t *symbol;
[074444f]179 stree_ident_t *targ_name;
[38aaacc2]180 stree_targ_t *targ;
[c5cb943d]181 stree_texpr_t *pref;
[09ababb7]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);
[39e8406]194
[38aaacc2]195 list_init(&csi->targ);
[074444f]196
197 while (lcur_lc(parse) == lc_slash) {
198 lskip(parse);
199 targ_name = parse_ident(parse);
[38aaacc2]200
201 targ = stree_targ_new();
202 targ->name = targ_name;
203
204 list_append(&csi->targ, targ);
[074444f]205 }
206
[37f527b]207 symbol = stree_symbol_new(sc_csi);
208 symbol->u.csi = csi;
209 symbol->outer_csi = outer_csi;
210 csi->symbol = symbol;
211
[39e8406]212#ifdef DEBUG_PARSE_TRACE
[09ababb7]213 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
214 strtab_get_str(csi->name->sid));
[39e8406]215#endif
[09ababb7]216 if (lcur_lc(parse) == lc_colon) {
217 /* Inheritance list */
218 lskip(parse);
[c5cb943d]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 }
[09ababb7]231 }
232
233 lmatch(parse, lc_is);
234 list_init(&csi->members);
235
236 /* Parse class, struct or interface members. */
[1ebc1a62]237 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
[09ababb7]238 csimbr = parse_csimbr(parse, csi);
[38aaacc2]239 if (csimbr == NULL)
[c5cb943d]240 continue;
[38aaacc2]241
[09ababb7]242 list_append(&csi->members, csimbr);
243 }
244
245 lmatch(parse, lc_end);
246
[c5cb943d]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
[09ababb7]261 return csi;
262}
263
[23de644]264/** Parse class, struct or interface member.
265 *
266 * @param parse Parser object.
[051bc69a]267 * @param outer_csi CSI containing this declaration.
[38aaacc2]268 * @return New syntax tree node. In case of parse error,
269 * @c NULL may (but need not) be returned.
[23de644]270 */
[09ababb7]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;
[051bc69a]276 stree_ctor_t *ctor;
[38aaacc2]277 stree_deleg_t *deleg;
[051bc69a]278 stree_enum_t *enum_d;
[09ababb7]279 stree_fun_t *fun;
280 stree_var_t *var;
281 stree_prop_t *prop;
282
[c5cb943d]283 csimbr = NULL;
284
[09ababb7]285 switch (lcur_lc(parse)) {
286 case lc_class:
287 case lc_struct:
288 case lc_interface:
[37f527b]289 csi = parse_csi(parse, lcur_lc(parse), outer_csi);
[c5cb943d]290 if (csi != NULL) {
291 csimbr = stree_csimbr_new(csimbr_csi);
292 csimbr->u.csi = csi;
293 }
[09ababb7]294 break;
[051bc69a]295 case lc_new:
296 ctor = parse_ctor(parse, outer_csi);
[c5cb943d]297 if (ctor != NULL) {
298 csimbr = stree_csimbr_new(csimbr_ctor);
299 csimbr->u.ctor = ctor;
300 }
[051bc69a]301 break;
[38aaacc2]302 case lc_deleg:
303 deleg = parse_deleg(parse, outer_csi);
[c5cb943d]304 if (deleg != NULL) {
305 csimbr = stree_csimbr_new(csimbr_deleg);
306 csimbr->u.deleg = deleg;
307 }
[38aaacc2]308 break;
[051bc69a]309 case lc_enum:
310 enum_d = parse_enum(parse, outer_csi);
[c5cb943d]311 if (enum_d != NULL) {
312 csimbr = stree_csimbr_new(csimbr_enum);
313 csimbr->u.enum_d = enum_d;
314 }
[051bc69a]315 break;
[09ababb7]316 case lc_fun:
[37f527b]317 fun = parse_fun(parse, outer_csi);
[09ababb7]318 csimbr = stree_csimbr_new(csimbr_fun);
319 csimbr->u.fun = fun;
320 break;
321 case lc_var:
[37f527b]322 var = parse_var(parse, outer_csi);
[c5cb943d]323 if (var != NULL) {
324 csimbr = stree_csimbr_new(csimbr_var);
325 csimbr->u.var = var;
326 }
[09ababb7]327 break;
328 case lc_prop:
[37f527b]329 prop = parse_prop(parse, outer_csi);
[09ababb7]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);
[38aaacc2]336 break;
[09ababb7]337 }
338
339 return csimbr;
340}
341
[051bc69a]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;
[c5cb943d]352 cspan_t *cspan;
[051bc69a]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);
[c5cb943d]362 cspan = lprev_span(parse);
[051bc69a]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) {
[c5cb943d]376 cspan_print(cspan);
377 printf(" Error: Constructor of CSI '");
[051bc69a]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. */
[c5cb943d]384 parse_symbol_attrs(parse, symbol);
[051bc69a]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. */
[c5cb943d]393 cspan_print(cspan);
394 printf(" Error: Constructor of CSI '");
[051bc69a]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
[c5cb943d]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
[051bc69a]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)) {
[c5cb943d]459 cspan_print(enum_d->name->cspan);
[051bc69a]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
[c5cb943d]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
[051bc69a]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
[38aaacc2]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. */
[c5cb943d]532 parse_symbol_attrs(parse, symbol);
[38aaacc2]533
534 lmatch(parse, lc_scolon);
535
[c5cb943d]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
[38aaacc2]548 return deleg;
549}
[09ababb7]550
[23de644]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 */
[37f527b]557static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
[09ababb7]558{
559 stree_fun_t *fun;
[37f527b]560 stree_symbol_t *symbol;
[c5cb943d]561 bool_t body_expected;
[09ababb7]562
563 fun = stree_fun_new();
[37f527b]564 symbol = stree_symbol_new(sc_fun);
565
566 symbol->u.fun = fun;
567 symbol->outer_csi = outer_csi;
568 fun->symbol = symbol;
[09ababb7]569
570 lmatch(parse, lc_fun);
571 fun->name = parse_ident(parse);
572
[39e8406]573#ifdef DEBUG_PARSE_TRACE
574 printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
575#endif
[38aaacc2]576 fun->sig = parse_fun_sig(parse);
[09ababb7]577
[37f527b]578 /* Parse attributes. */
[c5cb943d]579 parse_symbol_attrs(parse, symbol);
580
581 body_expected = !stree_symbol_has_attr(symbol, sac_builtin) &&
582 (outer_csi->cc != csi_interface);
[37f527b]583
[39e8406]584 fun->proc = stree_proc_new();
[37f527b]585 fun->proc->outer_symbol = symbol;
586
587 if (lcur_lc(parse) == lc_scolon) {
588 lskip(parse);
589
[c5cb943d]590 /* Body not present */
591 if (body_expected) {
592 cspan_print(fun->name->cspan);
593 printf(" Error: Function '");
[37f527b]594 symbol_print_fqn(symbol);
[c5cb943d]595 printf("' should have a body.\n");
[1ebc1a62]596 parse_note_error(parse);
[37f527b]597 }
[c5cb943d]598
[37f527b]599 fun->proc->body = NULL;
600 } else {
601 lmatch(parse, lc_is);
602 fun->proc->body = parse_block(parse);
603 lmatch(parse, lc_end);
[c5cb943d]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 }
[37f527b]613 }
[09ababb7]614
615 return fun;
616}
617
[23de644]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 */
[37f527b]624static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi)
[09ababb7]625{
626 stree_var_t *var;
[37f527b]627 stree_symbol_t *symbol;
[09ababb7]628
629 var = stree_var_new();
[37f527b]630 symbol = stree_symbol_new(sc_var);
631 symbol->u.var = var;
632 symbol->outer_csi = outer_csi;
633 var->symbol = symbol;
[09ababb7]634
635 lmatch(parse, lc_var);
636 var->name = parse_ident(parse);
637 lmatch(parse, lc_colon);
638 var->type = parse_texpr(parse);
[c5cb943d]639
640 parse_symbol_attrs(parse, symbol);
641
[09ababb7]642 lmatch(parse, lc_scolon);
643
[c5cb943d]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
[09ababb7]656 return var;
657}
658
[23de644]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 */
[37f527b]665static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
[09ababb7]666{
667 stree_prop_t *prop;
[37f527b]668 stree_symbol_t *symbol;
[c5cb943d]669 bool_t body_expected;
[37f527b]670
[d0febca]671 stree_ident_t *ident;
672 stree_proc_arg_t *arg;
[09ababb7]673
674 prop = stree_prop_new();
[d0febca]675 list_init(&prop->args);
[09ababb7]676
[37f527b]677 symbol = stree_symbol_new(sc_prop);
678 symbol->u.prop = prop;
679 symbol->outer_csi = outer_csi;
680 prop->symbol = symbol;
681
[09ababb7]682 lmatch(parse, lc_prop);
[d0febca]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. */
[1ebc1a62]696 while (!parse_is_error(parse)) {
[d0febca]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
[09ababb7]717 lmatch(parse, lc_colon);
718 prop->type = parse_texpr(parse);
[c5cb943d]719
720 /* Parse attributes. */
721 parse_symbol_attrs(parse, symbol);
722
723 body_expected = (outer_csi->cc != csi_interface);
724
[09ababb7]725 lmatch(parse, lc_is);
[d0febca]726
[1ebc1a62]727 while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
[d0febca]728 switch (lcur_lc(parse)) {
729 case lc_get:
[c5cb943d]730 parse_prop_get(parse, prop);
[d0febca]731 break;
732 case lc_set:
[c5cb943d]733 parse_prop_set(parse, prop);
[d0febca]734 break;
735 default:
736 lunexpected_error(parse);
737 }
738 }
739
[09ababb7]740 lmatch(parse, lc_end);
741
742 return prop;
743}
744
[c5cb943d]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
[23de644]764/** Parse symbol attribute.
765 *
[c5cb943d]766 * @param parse Parser object
767 * @return New syntax tree node
[23de644]768 */
[37f527b]769static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
770{
771 stree_symbol_attr_t *attr;
[c5cb943d]772 symbol_attr_class_t sac;
773
774 /* Make compiler happy. */
775 sac = 0;
[37f527b]776
[c5cb943d]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 '");
[37f527b]783 lem_print(lcur(parse));
784 printf("'.\n");
[1ebc1a62]785 parse_note_error(parse);
[c5cb943d]786 break;
[37f527b]787 }
788
789 lskip(parse);
790
[c5cb943d]791 attr = stree_symbol_attr_new(sac);
[37f527b]792 return attr;
793}
794
[23de644]795/** Parse formal function argument.
796 *
797 * @param parse Parser object.
798 * @return New syntax tree node.
799 */
[d0febca]800static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
[09ababb7]801{
[d0febca]802 stree_proc_arg_t *arg;
[94d484a]803 stree_arg_attr_t *attr;
[09ababb7]804
[d0febca]805 arg = stree_proc_arg_new();
[09ababb7]806 arg->name = parse_ident(parse);
807 lmatch(parse, lc_colon);
808 arg->type = parse_texpr(parse);
809
[38aaacc2]810#ifdef DEBUG_PARSE_TRACE
811 printf("Parse procedure argument.\n");
812#endif
[c5cb943d]813 list_init(&arg->attr);
[94d484a]814
815 /* Parse attributes. */
[1ebc1a62]816 while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
[94d484a]817 lskip(parse);
818 attr = parse_arg_attr(parse);
819 list_append(&arg->attr, attr);
820 }
821
[09ababb7]822 return arg;
823}
824
[23de644]825/** Parse argument attribute.
826 *
827 * @param parse Parser object.
828 * @return New syntax tree node.
829 */
[94d484a]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) {
[c5cb943d]835 cspan_print(lcur_span(parse));
836 printf(" Error: Unexpected attribute '");
[94d484a]837 lem_print(lcur(parse));
838 printf("'.\n");
[1ebc1a62]839 parse_note_error(parse);
[94d484a]840 }
841
842 lskip(parse);
843
844 attr = stree_arg_attr_new(aac_packed);
845 return attr;
846}
847
[38aaacc2]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
[c5cb943d]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
[23de644]1034/** Parse statement block.
1035 *
1036 * @param parse Parser object.
1037 * @return New syntax tree node.
1038 */
[09ababb7]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
[1ebc1a62]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
[09ababb7]1054 stat = parse_stat(parse);
1055 list_append(&block->stats, stat);
1056 }
1057
1058 return block;
1059}
1060
[23de644]1061/** Parse statement.
1062 *
1063 * @param parse Parser object.
1064 * @return New syntax tree node.
1065 */
[37f527b]1066stree_stat_t *parse_stat(parse_t *parse)
[09ababb7]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;
[051bc69a]1075 stree_break_t *break_s;
[fa36f29]1076 stree_return_t *return_s;
[09ababb7]1077 stree_wef_t *wef_s;
1078 stree_exps_t *exp_s;
1079
[1ebc1a62]1080#ifdef DEBUG_PARSE_TRACE
1081 printf("Parse statement.\n");
1082#endif
[09ababb7]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;
[051bc69a]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;
[fa36f29]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;
[94d484a]1119 case lc_do:
[09ababb7]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
[23de644]1138/** Parse variable declaration statement.
1139 *
1140 * @param parse Parser object.
1141 * @return New syntax tree node.
1142 */
[09ababb7]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
[23de644]1169/** Parse @c if statement.
1170 *
1171 * @param parse Parser object.
1172 * @return New syntax tree node.
1173 */
[09ababb7]1174static stree_if_t *parse_if(parse_t *parse)
1175{
1176 stree_if_t *if_s;
[051bc69a]1177 stree_if_clause_t *if_c;
[09ababb7]1178
[1ebc1a62]1179#ifdef DEBUG_PARSE_TRACE
1180 printf("Parse 'if' statement.\n");
1181#endif
[09ababb7]1182 if_s = stree_if_new();
[051bc69a]1183 list_init(&if_s->if_clauses);
[09ababb7]1184
[051bc69a]1185 /* Parse @c if clause. */
[09ababb7]1186 lmatch(parse, lc_if);
[051bc69a]1187
1188 if_c = stree_if_clause_new();
1189 if_c->cond = parse_expr(parse);
[09ababb7]1190 lmatch(parse, lc_then);
[051bc69a]1191 if_c->block = parse_block(parse);
[09ababb7]1192
[051bc69a]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. */
[09ababb7]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
[23de644]1218/** Parse @c while statement.
1219 *
1220 * @param parse Parser object.
1221 */
[09ababb7]1222static stree_while_t *parse_while(parse_t *parse)
1223{
1224 stree_while_t *while_s;
1225
[1ebc1a62]1226#ifdef DEBUG_PARSE_TRACE
1227 printf("Parse 'while' statement.\n");
1228#endif
[09ababb7]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
[23de644]1240/** Parse @c for statement.
1241 *
1242 * @param parse Parser object.
1243 * @return New syntax tree node.
1244 */
[09ababb7]1245static stree_for_t *parse_for(parse_t *parse)
1246{
1247 stree_for_t *for_s;
1248
[1ebc1a62]1249#ifdef DEBUG_PARSE_TRACE
1250 printf("Parse 'for' statement.\n");
1251#endif
[09ababb7]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
[23de644]1267/** Parse @c raise statement.
1268 *
1269 * @param parse Parser object.
1270 */
[09ababb7]1271static stree_raise_t *parse_raise(parse_t *parse)
1272{
[94d484a]1273 stree_raise_t *raise_s;
1274
[1ebc1a62]1275#ifdef DEBUG_PARSE_TRACE
1276 printf("Parse 'raise' statement.\n");
1277#endif
[94d484a]1278 raise_s = stree_raise_new();
[09ababb7]1279 lmatch(parse, lc_raise);
[94d484a]1280 raise_s->expr = parse_expr(parse);
[09ababb7]1281 lmatch(parse, lc_scolon);
1282
[94d484a]1283 return raise_s;
[09ababb7]1284}
1285
[051bc69a]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
[23de644]1306/** Parse @c return statement.
1307 *
1308 * @param parse Parser object.
1309 * @return New syntax tree node.
1310 */
[fa36f29]1311static stree_return_t *parse_return(parse_t *parse)
1312{
1313 stree_return_t *return_s;
1314
[1ebc1a62]1315#ifdef DEBUG_PARSE_TRACE
1316 printf("Parse 'return' statement.\n");
1317#endif
[fa36f29]1318 return_s = stree_return_new();
1319
1320 lmatch(parse, lc_return);
[051bc69a]1321
1322 if (lcur_lc(parse) != lc_scolon)
1323 return_s->expr = parse_expr(parse);
1324
[fa36f29]1325 lmatch(parse, lc_scolon);
1326
1327 return return_s;
1328}
1329
[23de644]1330/* Parse @c with-except-finally statement.
1331 *
1332 * @param parse Parser object.
1333 * @return New syntax tree node.
1334 */
[09ababb7]1335static stree_wef_t *parse_wef(parse_t *parse)
1336{
1337 stree_wef_t *wef_s;
[94d484a]1338 stree_except_t *except_c;
[09ababb7]1339
[1ebc1a62]1340#ifdef DEBUG_PARSE_TRACE
1341 printf("Parse WEF statement.\n");
1342#endif
[09ababb7]1343 wef_s = stree_wef_new();
[94d484a]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 }
[09ababb7]1354
1355 lmatch(parse, lc_do);
1356 wef_s->with_block = parse_block(parse);
1357
[1ebc1a62]1358 while (lcur_lc(parse) == lc_except && !parse_is_error(parse)) {
[94d484a]1359 except_c = parse_except(parse);
1360 list_append(&wef_s->except_clauses, except_c);
1361 }
[09ababb7]1362
[94d484a]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;
[09ababb7]1369 }
1370
1371 lmatch(parse, lc_end);
1372
1373 return wef_s;
1374}
1375
[23de644]1376/* Parse expression statement.
1377 *
1378 * @param parse Parser object.
1379 * @return New syntax tree node.
1380 */
[09ababb7]1381static stree_exps_t *parse_exps(parse_t *parse)
1382{
1383 stree_expr_t *expr;
1384 stree_exps_t *exps;
1385
[1ebc1a62]1386#ifdef DEBUG_PARSE_TRACE
1387 printf("Parse expression statement.\n");
1388#endif
[09ababb7]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
[23de644]1398/* Parse @c except clause.
1399 *
1400 * @param parse Parser object.
1401 * @return New syntax tree node.
1402 */
[94d484a]1403static stree_except_t *parse_except(parse_t *parse)
1404{
1405 stree_except_t *except_c;
1406
[1ebc1a62]1407#ifdef DEBUG_PARSE_TRACE
1408 printf("Parse 'except' statement.\n");
1409#endif
[94d484a]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
[23de644]1423/** Parse identifier.
1424 *
1425 * @param parse Parser object.
1426 * @return New syntax tree node.
1427 */
[09ababb7]1428stree_ident_t *parse_ident(parse_t *parse)
1429{
1430 stree_ident_t *ident;
1431
[1ebc1a62]1432#ifdef DEBUG_PARSE_TRACE
1433 printf("Parse identifier.\n");
1434#endif
[09ababb7]1435 lcheck(parse, lc_ident);
1436 ident = stree_ident_new();
1437 ident->sid = lcur(parse)->u.ident.sid;
[051bc69a]1438 ident->cspan = lcur_span(parse);
[09ababb7]1439 lskip(parse);
1440
1441 return ident;
1442}
1443
[23de644]1444/** Signal a parse error, start bailing out from parser.
1445 *
1446 * @param parse Parser object.
1447 */
[1ebc1a62]1448void parse_raise_error(parse_t *parse)
1449{
1450 parse->error = b_true;
1451 parse->error_bailout = b_true;
1452}
1453
[23de644]1454/** Note a parse error that has been immediately recovered.
1455 *
1456 * @param parse Parser object.
1457 */
[1ebc1a62]1458void parse_note_error(parse_t *parse)
1459{
1460 parse->error = b_true;
1461}
1462
[23de644]1463/** Check if we are currently bailing out of parser due to a parse error.
1464 *
1465 * @param parse Parser object.
1466 */
[1ebc1a62]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.
[23de644]1475 *
1476 * @param parse Parser object.
[1ebc1a62]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
[23de644]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 */
[09ababb7]1492lem_t *lcur(parse_t *parse)
1493{
[1ebc1a62]1494#ifdef DEBUG_LPARSE_TRACE
1495 printf("lcur()\n");
1496#endif
[37f527b]1497 return lex_get_current(parse->lex);
[09ababb7]1498}
1499
[23de644]1500/** Return current lem lclass.
1501 *
[051bc69a]1502 * @param parse Parser object
1503 * @return Lclass of the current lem
[23de644]1504 */
[09ababb7]1505lclass_t lcur_lc(parse_t *parse)
1506{
[37f527b]1507 lem_t *lem;
1508
[1ebc1a62]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
[37f527b]1520 lem = lcur(parse);
1521 return lem->lclass;
[09ababb7]1522}
1523
[051bc69a]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
[23de644]1562/** Skip to next lem.
1563 *
1564 * @param parse Parser object.
1565 */
[09ababb7]1566void lskip(parse_t *parse)
1567{
[1ebc1a62]1568#ifdef DEBUG_LPARSE_TRACE
1569 printf("lskip()\n");
1570#endif
[09ababb7]1571 lex_next(parse->lex);
1572}
1573
[23de644]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 */
[09ababb7]1582void lcheck(parse_t *parse, lclass_t lc)
1583{
[1ebc1a62]1584#ifdef DEBUG_LPARSE_TRACE
1585 printf("lcheck(");
1586 lclass_print(lc);
1587 printf(")\n");
1588#endif
[09ababb7]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");
[1ebc1a62]1594 parse_raise_error(parse);
[09ababb7]1595 }
1596}
1597
[23de644]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 */
[09ababb7]1606void lmatch(parse_t *parse, lclass_t lc)
1607{
[1ebc1a62]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
[09ababb7]1624 lcheck(parse, lc);
1625 lskip(parse);
1626}
1627
[23de644]1628/** Raise and display generic parsing error.
1629 *
1630 * @param parse Parser object.
1631 */
[09ababb7]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");
[1ebc1a62]1638 parse_raise_error(parse);
[09ababb7]1639}
1640
[23de644]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 */
[09ababb7]1648bool_t terminates_block(lclass_t lclass)
1649{
1650 switch (lclass) {
[051bc69a]1651 case lc_elif:
[09ababb7]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.