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

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

Update SBI to rev. 90.

  • Property mode set to 100644
File size: 14.5 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Parser
30 *
31 * Consumes a sequence of lexical elements and produces a syntax tree (stree).
32 * Parsing primitives, module members, statements.
33 */
34
35#include <assert.h>
36#include <stdlib.h>
37#include "lex.h"
38#include "list.h"
39#include "mytypes.h"
40#include "p_expr.h"
41#include "p_type.h"
42#include "stree.h"
43#include "strtab.h"
44
45#include "parse.h"
46
47/*
48 * Module members
49 */
50static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass);
51static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
52
53static stree_fun_t *parse_fun(parse_t *parse);
54static stree_var_t *parse_var(parse_t *parse);
55static stree_prop_t *parse_prop(parse_t *parse);
56
57static stree_fun_arg_t *parse_fun_arg(parse_t *parse);
58static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
59
60/*
61 * Statements
62 */
63static stree_block_t *parse_block(parse_t *parse);
64static stree_stat_t *parse_stat(parse_t *parse);
65
66static stree_vdecl_t *parse_vdecl(parse_t *parse);
67static stree_if_t *parse_if(parse_t *parse);
68static stree_while_t *parse_while(parse_t *parse);
69static stree_for_t *parse_for(parse_t *parse);
70static stree_raise_t *parse_raise(parse_t *parse);
71static stree_return_t *parse_return(parse_t *parse);
72static stree_wef_t *parse_wef(parse_t *parse);
73static stree_exps_t *parse_exps(parse_t *parse);
74
75static stree_except_t *parse_except(parse_t *parse);
76
77void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
78{
79 parse->program = prog;
80 parse->cur_mod = parse->program->module;
81 parse->lex = lex;
82 lex_next(parse->lex);
83}
84
85/** Parse module. */
86void parse_module(parse_t *parse)
87{
88 stree_csi_t *csi;
89 stree_modm_t *modm;
90 stree_symbol_t *symbol;
91
92 while (lcur_lc(parse) != lc_eof) {
93 switch (lcur_lc(parse)) {
94 case lc_class:
95 case lc_struct:
96 case lc_interface:
97 csi = parse_csi(parse, lcur_lc(parse));
98 modm = stree_modm_new(mc_csi);
99 modm->u.csi = csi;
100
101 symbol = stree_symbol_new(sc_csi);
102 symbol->u.csi = csi;
103 symbol->outer_csi = NULL;
104 csi->symbol = symbol;
105
106 list_append(&parse->cur_mod->members, modm);
107 break;
108 default:
109 lunexpected_error(parse);
110 lex_next(parse->lex);
111 break;
112 }
113
114 }
115}
116
117/** Parse class, struct or interface declaration. */
118static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass)
119{
120 stree_csi_t *csi;
121 csi_class_t cc;
122 stree_csimbr_t *csimbr;
123
124 switch (dclass) {
125 case lc_class: cc = csi_class; break;
126 case lc_struct: cc = csi_struct; break;
127 case lc_interface: cc = csi_interface; break;
128 default: assert(b_false);
129 }
130
131 lskip(parse);
132
133 csi = stree_csi_new(cc);
134 csi->name = parse_ident(parse);
135/*
136 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
137 strtab_get_str(csi->name->sid));
138*/
139 if (lcur_lc(parse) == lc_colon) {
140 /* Inheritance list */
141 lskip(parse);
142 csi->base_csi_ref = parse_texpr(parse);
143 } else {
144 csi->base_csi_ref = NULL;
145 }
146
147 lmatch(parse, lc_is);
148 list_init(&csi->members);
149
150 /* Parse class, struct or interface members. */
151 while (lcur_lc(parse) != lc_end) {
152 csimbr = parse_csimbr(parse, csi);
153 list_append(&csi->members, csimbr);
154 }
155
156 lmatch(parse, lc_end);
157
158 return csi;
159}
160
161/** Parse class, struct or interface member. */
162static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
163{
164 stree_csimbr_t *csimbr;
165
166 stree_csi_t *csi;
167 stree_fun_t *fun;
168 stree_var_t *var;
169 stree_prop_t *prop;
170
171 stree_symbol_t *symbol;
172
173 switch (lcur_lc(parse)) {
174 case lc_class:
175 case lc_struct:
176 case lc_interface:
177 csi = parse_csi(parse, lcur_lc(parse));
178 csimbr = stree_csimbr_new(csimbr_csi);
179 csimbr->u.csi = csi;
180
181 symbol = stree_symbol_new(sc_csi);
182 symbol->u.csi = csi;
183 symbol->outer_csi = outer_csi;
184 csi->symbol = symbol;
185 break;
186 case lc_fun:
187 fun = parse_fun(parse);
188 csimbr = stree_csimbr_new(csimbr_fun);
189 csimbr->u.fun = fun;
190
191 symbol = stree_symbol_new(sc_fun);
192 symbol->u.fun = fun;
193 symbol->outer_csi = outer_csi;
194 fun->symbol = symbol;
195 break;
196 case lc_var:
197 var = parse_var(parse);
198 csimbr = stree_csimbr_new(csimbr_var);
199 csimbr->u.var = var;
200
201 symbol = stree_symbol_new(sc_var);
202 symbol->u.var = var;
203 symbol->outer_csi = outer_csi;
204 var->symbol = symbol;
205 break;
206 case lc_prop:
207 prop = parse_prop(parse);
208 csimbr = stree_csimbr_new(csimbr_prop);
209 csimbr->u.prop = prop;
210
211 symbol = stree_symbol_new(sc_prop);
212 symbol->u.prop = prop;
213 symbol->outer_csi = outer_csi;
214 prop->symbol = symbol;
215 break;
216 default:
217 lunexpected_error(parse);
218 lex_next(parse->lex);
219 }
220
221 return csimbr;
222}
223
224
225/** Parse member function. */
226static stree_fun_t *parse_fun(parse_t *parse)
227{
228 stree_fun_t *fun;
229 stree_fun_arg_t *arg;
230
231 fun = stree_fun_new();
232
233 lmatch(parse, lc_fun);
234 fun->name = parse_ident(parse);
235 lmatch(parse, lc_lparen);
236
237 list_init(&fun->args);
238
239 if (lcur_lc(parse) != lc_rparen) {
240
241 /* Parse formal parameters. */
242 while (b_true) {
243 arg = parse_fun_arg(parse);
244 if (stree_arg_has_attr(arg, aac_packed)) {
245 fun->varg = arg;
246 break;
247 } else {
248 list_append(&fun->args, arg);
249 }
250
251 if (lcur_lc(parse) == lc_rparen)
252 break;
253
254 lmatch(parse, lc_scolon);
255 }
256 }
257
258 lmatch(parse, lc_rparen);
259
260 if (lcur_lc(parse) == lc_colon) {
261 lskip(parse);
262 fun->rtype = parse_texpr(parse);
263 } else {
264 fun->rtype = NULL;
265 }
266
267 lmatch(parse, lc_is);
268 fun->body = parse_block(parse);
269 lmatch(parse, lc_end);
270
271 return fun;
272}
273
274/** Parse member variable. */
275static stree_var_t *parse_var(parse_t *parse)
276{
277 stree_var_t *var;
278
279 var = stree_var_new();
280
281 lmatch(parse, lc_var);
282 var->name = parse_ident(parse);
283 lmatch(parse, lc_colon);
284 var->type = parse_texpr(parse);
285 lmatch(parse, lc_scolon);
286
287 return var;
288}
289
290/** Parse member property. */
291static stree_prop_t *parse_prop(parse_t *parse)
292{
293 stree_prop_t *prop;
294
295 prop = stree_prop_new();
296
297 lmatch(parse, lc_prop);
298 prop->name = parse_ident(parse);
299 lmatch(parse, lc_colon);
300 prop->type = parse_texpr(parse);
301 lmatch(parse, lc_is);
302 lmatch(parse, lc_end);
303
304 return prop;
305}
306
307/** Parse formal function argument. */
308static stree_fun_arg_t *parse_fun_arg(parse_t *parse)
309{
310 stree_fun_arg_t *arg;
311 stree_arg_attr_t *attr;
312
313 arg = stree_fun_arg_new();
314 arg->name = parse_ident(parse);
315 lmatch(parse, lc_colon);
316 arg->type = parse_texpr(parse);
317
318 list_init(&arg->attr);
319
320 /* Parse attributes. */
321 while (lcur_lc(parse) == lc_comma) {
322 lskip(parse);
323 attr = parse_arg_attr(parse);
324 list_append(&arg->attr, attr);
325 }
326
327 return arg;
328}
329
330/** Parse argument attribute. */
331static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
332{
333 stree_arg_attr_t *attr;
334
335 if (lcur_lc(parse) != lc_packed) {
336 printf("Error: Unexpected attribute '");
337 lem_print(lcur(parse));
338 printf("'.\n");
339 exit(1);
340 }
341
342 lskip(parse);
343
344 attr = stree_arg_attr_new(aac_packed);
345 return attr;
346}
347
348/** Parse statement block. */
349static stree_block_t *parse_block(parse_t *parse)
350{
351 stree_block_t *block;
352 stree_stat_t *stat;
353
354 block = stree_block_new();
355 list_init(&block->stats);
356
357 while (terminates_block(lcur_lc(parse)) != b_true) {
358 stat = parse_stat(parse);
359 list_append(&block->stats, stat);
360 }
361
362 return block;
363}
364
365/** Parse statement. */
366static stree_stat_t *parse_stat(parse_t *parse)
367{
368 stree_stat_t *stat;
369
370 stree_vdecl_t *vdecl_s;
371 stree_if_t *if_s;
372 stree_while_t *while_s;
373 stree_for_t *for_s;
374 stree_raise_t *raise_s;
375 stree_return_t *return_s;
376 stree_wef_t *wef_s;
377 stree_exps_t *exp_s;
378
379 switch (lcur_lc(parse)) {
380 case lc_var:
381 vdecl_s = parse_vdecl(parse);
382 stat = stree_stat_new(st_vdecl);
383 stat->u.vdecl_s = vdecl_s;
384 break;
385 case lc_if:
386 if_s = parse_if(parse);
387 stat = stree_stat_new(st_if);
388 stat->u.if_s = if_s;
389 break;
390 case lc_while:
391 while_s = parse_while(parse);
392 stat = stree_stat_new(st_while);
393 stat->u.while_s = while_s;
394 break;
395 case lc_for:
396 for_s = parse_for(parse);
397 stat = stree_stat_new(st_for);
398 stat->u.for_s = for_s;
399 break;
400 case lc_raise:
401 raise_s = parse_raise(parse);
402 stat = stree_stat_new(st_raise);
403 stat->u.raise_s = raise_s;
404 break;
405 case lc_return:
406 return_s = parse_return(parse);
407 stat = stree_stat_new(st_return);
408 stat->u.return_s = return_s;
409 break;
410 case lc_do:
411 case lc_with:
412 wef_s = parse_wef(parse);
413 stat = stree_stat_new(st_wef);
414 stat->u.wef_s = wef_s;
415 break;
416 default:
417 exp_s = parse_exps(parse);
418 stat = stree_stat_new(st_exps);
419 stat->u.exp_s = exp_s;
420 break;
421 }
422
423#ifdef DEBUG_PARSE_TRACE
424 printf("Parsed statement %p\n", stat);
425#endif
426 return stat;
427}
428
429/** Parse variable declaration statement. */
430static stree_vdecl_t *parse_vdecl(parse_t *parse)
431{
432 stree_vdecl_t *vdecl;
433
434 vdecl = stree_vdecl_new();
435
436 lmatch(parse, lc_var);
437 vdecl->name = parse_ident(parse);
438 lmatch(parse, lc_colon);
439 vdecl->type = parse_texpr(parse);
440
441 if (lcur_lc(parse) == lc_assign) {
442 lskip(parse);
443 (void) parse_expr(parse);
444 }
445
446 lmatch(parse, lc_scolon);
447
448#ifdef DEBUG_PARSE_TRACE
449 printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
450 printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
451 vdecl, vdecl->name, vdecl->name->sid);
452#endif
453 return vdecl;
454}
455
456/** Parse @c if statement, */
457static stree_if_t *parse_if(parse_t *parse)
458{
459 stree_if_t *if_s;
460
461 if_s = stree_if_new();
462
463 lmatch(parse, lc_if);
464 if_s->cond = parse_expr(parse);
465 lmatch(parse, lc_then);
466 if_s->if_block = parse_block(parse);
467
468 if (lcur_lc(parse) == lc_else) {
469 lskip(parse);
470 if_s->else_block = parse_block(parse);
471 } else {
472 if_s->else_block = NULL;
473 }
474
475 lmatch(parse, lc_end);
476 return if_s;
477}
478
479/** Parse @c while statement. */
480static stree_while_t *parse_while(parse_t *parse)
481{
482 stree_while_t *while_s;
483
484 while_s = stree_while_new();
485
486 lmatch(parse, lc_while);
487 while_s->cond = parse_expr(parse);
488 lmatch(parse, lc_do);
489 while_s->body = parse_block(parse);
490 lmatch(parse, lc_end);
491
492 return while_s;
493}
494
495/** Parse @c for statement. */
496static stree_for_t *parse_for(parse_t *parse)
497{
498 stree_for_t *for_s;
499
500 for_s = stree_for_new();
501
502 lmatch(parse, lc_for);
503 lmatch(parse, lc_ident);
504 lmatch(parse, lc_colon);
505 (void) parse_texpr(parse);
506 lmatch(parse, lc_in);
507 (void) parse_expr(parse);
508 lmatch(parse, lc_do);
509 for_s->body = parse_block(parse);
510 lmatch(parse, lc_end);
511
512 return for_s;
513}
514
515/** Parse @c raise statement. */
516static stree_raise_t *parse_raise(parse_t *parse)
517{
518 stree_raise_t *raise_s;
519
520 raise_s = stree_raise_new();
521 lmatch(parse, lc_raise);
522 raise_s->expr = parse_expr(parse);
523 lmatch(parse, lc_scolon);
524
525 return raise_s;
526}
527
528/** Parse @c return statement. */
529static stree_return_t *parse_return(parse_t *parse)
530{
531 stree_return_t *return_s;
532
533 return_s = stree_return_new();
534
535 lmatch(parse, lc_return);
536 return_s->expr = parse_expr(parse);
537 lmatch(parse, lc_scolon);
538
539 return return_s;
540}
541
542/* Parse @c with-except-finally statement. */
543static stree_wef_t *parse_wef(parse_t *parse)
544{
545 stree_wef_t *wef_s;
546 stree_except_t *except_c;
547
548 wef_s = stree_wef_new();
549 list_init(&wef_s->except_clauses);
550
551 if (lcur_lc(parse) == lc_with) {
552 lmatch(parse, lc_with);
553 lmatch(parse, lc_ident);
554 lmatch(parse, lc_colon);
555 (void) parse_texpr(parse);
556 lmatch(parse, lc_assign);
557 (void) parse_expr(parse);
558 }
559
560 lmatch(parse, lc_do);
561 wef_s->with_block = parse_block(parse);
562
563 while (lcur_lc(parse) == lc_except) {
564 except_c = parse_except(parse);
565 list_append(&wef_s->except_clauses, except_c);
566 }
567
568 if (lcur_lc(parse) == lc_finally) {
569 lmatch(parse, lc_finally);
570 lmatch(parse, lc_do);
571 wef_s->finally_block = parse_block(parse);
572 } else {
573 wef_s->finally_block = NULL;
574 }
575
576 lmatch(parse, lc_end);
577
578 return wef_s;
579}
580
581/* Parse expression statement. */
582static stree_exps_t *parse_exps(parse_t *parse)
583{
584 stree_expr_t *expr;
585 stree_exps_t *exps;
586
587 expr = parse_expr(parse);
588 lmatch(parse, lc_scolon);
589
590 exps = stree_exps_new();
591 exps->expr = expr;
592
593 return exps;
594}
595
596/* Parse @c except clause. */
597static stree_except_t *parse_except(parse_t *parse)
598{
599 stree_except_t *except_c;
600
601 except_c = stree_except_new();
602
603 lmatch(parse, lc_except);
604 except_c->evar = parse_ident(parse);
605 lmatch(parse, lc_colon);
606 except_c->etype = parse_texpr(parse);
607 lmatch(parse, lc_do);
608
609 except_c->block = parse_block(parse);
610
611 return except_c;
612}
613
614/** Parse identifier. */
615stree_ident_t *parse_ident(parse_t *parse)
616{
617 stree_ident_t *ident;
618
619 lcheck(parse, lc_ident);
620 ident = stree_ident_new();
621 ident->sid = lcur(parse)->u.ident.sid;
622 lskip(parse);
623
624 return ident;
625}
626
627/** Return current lem. */
628lem_t *lcur(parse_t *parse)
629{
630 return &parse->lex->current;
631}
632
633/** Retturn current lem lclass. */
634lclass_t lcur_lc(parse_t *parse)
635{
636 return parse->lex->current.lclass;
637}
638
639/** Skip to next lem. */
640void lskip(parse_t *parse)
641{
642 lex_next(parse->lex);
643}
644
645/** Verify that lclass of current lem is @a lc. */
646void lcheck(parse_t *parse, lclass_t lc)
647{
648 if (lcur(parse)->lclass != lc) {
649 lem_print_coords(lcur(parse));
650 printf(" Error: expected '"); lclass_print(lc);
651 printf("', got '"); lem_print(lcur(parse));
652 printf("'.\n");
653 exit(1);
654 }
655}
656
657/** Verify that lclass of current lem is @a lc and go to next lem. */
658void lmatch(parse_t *parse, lclass_t lc)
659{
660 lcheck(parse, lc);
661 lskip(parse);
662}
663
664/** Display generic parsing error. */
665void lunexpected_error(parse_t *parse)
666{
667 lem_print_coords(lcur(parse));
668 printf(" Error: unexpected token '");
669 lem_print(lcur(parse));
670 printf("'.\n");
671 exit(1);
672}
673
674/** Basically tells us whether @a lclass is in next(block). */
675bool_t terminates_block(lclass_t lclass)
676{
677 switch (lclass) {
678 case lc_else:
679 case lc_end:
680 case lc_except:
681 case lc_finally:
682 return b_true;
683 default:
684 return b_false;
685 }
686}
Note: See TracBrowser for help on using the repository browser.