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

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

Update SBI to rev. 75.

  • Property mode set to 100644
File size: 13.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);
58
59/*
60 * Statements
61 */
62static stree_block_t *parse_block(parse_t *parse);
63static stree_stat_t *parse_stat(parse_t *parse);
64
65static stree_vdecl_t *parse_vdecl(parse_t *parse);
66static stree_if_t *parse_if(parse_t *parse);
67static stree_while_t *parse_while(parse_t *parse);
68static stree_for_t *parse_for(parse_t *parse);
69static stree_raise_t *parse_raise(parse_t *parse);
70static stree_return_t *parse_return(parse_t *parse);
71static stree_wef_t *parse_wef(parse_t *parse);
72static stree_exps_t *parse_exps(parse_t *parse);
73
74void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
75{
76 parse->program = prog;
77 parse->cur_mod = parse->program->module;
78 parse->lex = lex;
79 lex_next(parse->lex);
80}
81
82/** Parse module. */
83void parse_module(parse_t *parse)
84{
85 stree_csi_t *csi;
86 stree_modm_t *modm;
87 stree_symbol_t *symbol;
88
89/* do {
90 lex_next(parse->lex);
91 printf("Read token: "); lem_print(&parse->lex->current);
92 putchar('\n');
93 } while (parse->lex->current.lclass != lc_eof);
94*/
95 while (lcur_lc(parse) != lc_eof) {
96 switch (lcur_lc(parse)) {
97 case lc_class:
98 case lc_struct:
99 case lc_interface:
100 csi = parse_csi(parse, lcur_lc(parse));
101 modm = stree_modm_new(mc_csi);
102 modm->u.csi = csi;
103
104 symbol = stree_symbol_new(sc_csi);
105 symbol->u.csi = csi;
106 symbol->outer_csi = NULL;
107 csi->symbol = symbol;
108
109 list_append(&parse->cur_mod->members, modm);
110 break;
111 default:
112 lunexpected_error(parse);
113 lex_next(parse->lex);
114 break;
115 }
116
117 }
118}
119
120/** Parse class, struct or interface declaration. */
121static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass)
122{
123 stree_csi_t *csi;
124 csi_class_t cc;
125 stree_csimbr_t *csimbr;
126
127 switch (dclass) {
128 case lc_class: cc = csi_class; break;
129 case lc_struct: cc = csi_struct; break;
130 case lc_interface: cc = csi_interface; break;
131 default: assert(b_false);
132 }
133
134 lskip(parse);
135
136 csi = stree_csi_new(cc);
137 csi->name = parse_ident(parse);
138/*
139 printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
140 strtab_get_str(csi->name->sid));
141*/
142 if (lcur_lc(parse) == lc_colon) {
143 /* Inheritance list */
144 lskip(parse);
145 csi->base_csi_ref = parse_texpr(parse);
146 } else {
147 csi->base_csi_ref = NULL;
148 }
149
150 lmatch(parse, lc_is);
151 list_init(&csi->members);
152
153 /* Parse class, struct or interface members. */
154 while (lcur_lc(parse) != lc_end) {
155 csimbr = parse_csimbr(parse, csi);
156 list_append(&csi->members, csimbr);
157 }
158
159 lmatch(parse, lc_end);
160
161 return csi;
162}
163
164/** Parse class, struct or interface member. */
165static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
166{
167 stree_csimbr_t *csimbr;
168
169 stree_csi_t *csi;
170 stree_fun_t *fun;
171 stree_var_t *var;
172 stree_prop_t *prop;
173
174 stree_symbol_t *symbol;
175
176 switch (lcur_lc(parse)) {
177 case lc_class:
178 case lc_struct:
179 case lc_interface:
180 csi = parse_csi(parse, lcur_lc(parse));
181 csimbr = stree_csimbr_new(csimbr_csi);
182 csimbr->u.csi = csi;
183
184 symbol = stree_symbol_new(sc_csi);
185 symbol->u.csi = csi;
186 symbol->outer_csi = outer_csi;
187 csi->symbol = symbol;
188 break;
189 case lc_fun:
190 fun = parse_fun(parse);
191 csimbr = stree_csimbr_new(csimbr_fun);
192 csimbr->u.fun = fun;
193
194 symbol = stree_symbol_new(sc_fun);
195 symbol->u.fun = fun;
196 symbol->outer_csi = outer_csi;
197 fun->symbol = symbol;
198 break;
199 case lc_var:
200 var = parse_var(parse);
201 csimbr = stree_csimbr_new(csimbr_var);
202 csimbr->u.var = var;
203
204 symbol = stree_symbol_new(sc_var);
205 symbol->u.var = var;
206 symbol->outer_csi = outer_csi;
207 var->symbol = symbol;
208 break;
209 case lc_prop:
210 prop = parse_prop(parse);
211 csimbr = stree_csimbr_new(csimbr_prop);
212 csimbr->u.prop = prop;
213
214 symbol = stree_symbol_new(sc_prop);
215 symbol->u.prop = prop;
216 symbol->outer_csi = outer_csi;
217 prop->symbol = symbol;
218 break;
219 default:
220 lunexpected_error(parse);
221 lex_next(parse->lex);
222 }
223
224 return csimbr;
225}
226
227
228/** Parse member function. */
229static stree_fun_t *parse_fun(parse_t *parse)
230{
231 stree_fun_t *fun;
232 stree_fun_arg_t *arg;
233
234 fun = stree_fun_new();
235
236 lmatch(parse, lc_fun);
237 fun->name = parse_ident(parse);
238 lmatch(parse, lc_lparen);
239
240 list_init(&fun->args);
241
242 if (lcur_lc(parse) != lc_rparen) {
243
244 /* Parse formal parameters. */
245 while (b_true) {
246 arg = parse_fun_arg(parse);
247 list_append(&fun->args, arg);
248
249 if (lcur_lc(parse) == lc_rparen)
250 break;
251
252 lmatch(parse, lc_scolon);
253 }
254 }
255
256 lmatch(parse, lc_rparen);
257
258 if (lcur_lc(parse) == lc_colon) {
259 lskip(parse);
260 fun->rtype = parse_texpr(parse);
261 } else {
262 fun->rtype = NULL;
263 }
264
265 lmatch(parse, lc_is);
266 fun->body = parse_block(parse);
267 lmatch(parse, lc_end);
268
269 return fun;
270}
271
272/** Parse member variable. */
273static stree_var_t *parse_var(parse_t *parse)
274{
275 stree_var_t *var;
276
277 var = stree_var_new();
278
279 lmatch(parse, lc_var);
280 var->name = parse_ident(parse);
281 lmatch(parse, lc_colon);
282 var->type = parse_texpr(parse);
283 lmatch(parse, lc_scolon);
284
285 return var;
286}
287
288/** Parse member property. */
289static stree_prop_t *parse_prop(parse_t *parse)
290{
291 stree_prop_t *prop;
292
293 prop = stree_prop_new();
294
295 lmatch(parse, lc_prop);
296 prop->name = parse_ident(parse);
297 lmatch(parse, lc_colon);
298 prop->type = parse_texpr(parse);
299 lmatch(parse, lc_is);
300 lmatch(parse, lc_end);
301
302 return prop;
303}
304
305/** Parse formal function argument. */
306static stree_fun_arg_t *parse_fun_arg(parse_t *parse)
307{
308 stree_fun_arg_t *arg;
309
310 arg = stree_fun_arg_new();
311 arg->name = parse_ident(parse);
312 lmatch(parse, lc_colon);
313 arg->type = parse_texpr(parse);
314
315 return arg;
316}
317
318/** Parse statement block. */
319static stree_block_t *parse_block(parse_t *parse)
320{
321 stree_block_t *block;
322 stree_stat_t *stat;
323
324 block = stree_block_new();
325 list_init(&block->stats);
326
327 while (terminates_block(lcur_lc(parse)) != b_true) {
328 stat = parse_stat(parse);
329 list_append(&block->stats, stat);
330 }
331
332 return block;
333}
334
335/** Parse statement. */
336static stree_stat_t *parse_stat(parse_t *parse)
337{
338 stree_stat_t *stat;
339
340 stree_vdecl_t *vdecl_s;
341 stree_if_t *if_s;
342 stree_while_t *while_s;
343 stree_for_t *for_s;
344 stree_raise_t *raise_s;
345 stree_return_t *return_s;
346 stree_wef_t *wef_s;
347 stree_exps_t *exp_s;
348
349 switch (lcur_lc(parse)) {
350 case lc_var:
351 vdecl_s = parse_vdecl(parse);
352 stat = stree_stat_new(st_vdecl);
353 stat->u.vdecl_s = vdecl_s;
354 break;
355 case lc_if:
356 if_s = parse_if(parse);
357 stat = stree_stat_new(st_if);
358 stat->u.if_s = if_s;
359 break;
360 case lc_while:
361 while_s = parse_while(parse);
362 stat = stree_stat_new(st_while);
363 stat->u.while_s = while_s;
364 break;
365 case lc_for:
366 for_s = parse_for(parse);
367 stat = stree_stat_new(st_for);
368 stat->u.for_s = for_s;
369 break;
370 case lc_raise:
371 raise_s = parse_raise(parse);
372 stat = stree_stat_new(st_raise);
373 stat->u.raise_s = raise_s;
374 break;
375 case lc_return:
376 return_s = parse_return(parse);
377 stat = stree_stat_new(st_return);
378 stat->u.return_s = return_s;
379 break;
380 case lc_with:
381 wef_s = parse_wef(parse);
382 stat = stree_stat_new(st_wef);
383 stat->u.wef_s = wef_s;
384 break;
385 default:
386 exp_s = parse_exps(parse);
387 stat = stree_stat_new(st_exps);
388 stat->u.exp_s = exp_s;
389 break;
390 }
391
392#ifdef DEBUG_PARSE_TRACE
393 printf("Parsed statement %p\n", stat);
394#endif
395 return stat;
396}
397
398/** Parse variable declaration statement. */
399static stree_vdecl_t *parse_vdecl(parse_t *parse)
400{
401 stree_vdecl_t *vdecl;
402
403 vdecl = stree_vdecl_new();
404
405 lmatch(parse, lc_var);
406 vdecl->name = parse_ident(parse);
407 lmatch(parse, lc_colon);
408 vdecl->type = parse_texpr(parse);
409
410 if (lcur_lc(parse) == lc_assign) {
411 lskip(parse);
412 (void) parse_expr(parse);
413 }
414
415 lmatch(parse, lc_scolon);
416
417#ifdef DEBUG_PARSE_TRACE
418 printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
419 printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
420 vdecl, vdecl->name, vdecl->name->sid);
421#endif
422 return vdecl;
423}
424
425/** Parse @c if statement, */
426static stree_if_t *parse_if(parse_t *parse)
427{
428 stree_if_t *if_s;
429
430 if_s = stree_if_new();
431
432 lmatch(parse, lc_if);
433 if_s->cond = parse_expr(parse);
434 lmatch(parse, lc_then);
435 if_s->if_block = parse_block(parse);
436
437 if (lcur_lc(parse) == lc_else) {
438 lskip(parse);
439 if_s->else_block = parse_block(parse);
440 } else {
441 if_s->else_block = NULL;
442 }
443
444 lmatch(parse, lc_end);
445 return if_s;
446}
447
448/** Parse @c while statement. */
449static stree_while_t *parse_while(parse_t *parse)
450{
451 stree_while_t *while_s;
452
453 while_s = stree_while_new();
454
455 lmatch(parse, lc_while);
456 while_s->cond = parse_expr(parse);
457 lmatch(parse, lc_do);
458 while_s->body = parse_block(parse);
459 lmatch(parse, lc_end);
460
461 return while_s;
462}
463
464/** Parse @c for statement. */
465static stree_for_t *parse_for(parse_t *parse)
466{
467 stree_for_t *for_s;
468
469 for_s = stree_for_new();
470
471 lmatch(parse, lc_for);
472 lmatch(parse, lc_ident);
473 lmatch(parse, lc_colon);
474 (void) parse_texpr(parse);
475 lmatch(parse, lc_in);
476 (void) parse_expr(parse);
477 lmatch(parse, lc_do);
478 for_s->body = parse_block(parse);
479 lmatch(parse, lc_end);
480
481 return for_s;
482}
483
484/** Parse @c raise statement. */
485static stree_raise_t *parse_raise(parse_t *parse)
486{
487 lmatch(parse, lc_raise);
488 (void) parse_expr(parse);
489 lmatch(parse, lc_scolon);
490
491 return stree_raise_new();
492}
493
494/** Parse @c return statement. */
495static stree_return_t *parse_return(parse_t *parse)
496{
497 stree_return_t *return_s;
498
499 return_s = stree_return_new();
500
501 lmatch(parse, lc_return);
502 return_s->expr = parse_expr(parse);
503 lmatch(parse, lc_scolon);
504
505 return return_s;
506}
507
508/* Parse @c with-except-finally statement. */
509static stree_wef_t *parse_wef(parse_t *parse)
510{
511 stree_wef_t *wef_s;
512 stree_block_t *block;
513
514 wef_s = stree_wef_new();
515 list_init(&wef_s->except_blocks);
516
517 lmatch(parse, lc_with);
518 lmatch(parse, lc_ident);
519 lmatch(parse, lc_colon);
520 (void) parse_texpr(parse);
521 lmatch(parse, lc_assign);
522 (void) parse_expr(parse);
523 lmatch(parse, lc_do);
524 wef_s->with_block = parse_block(parse);
525
526 while (lcur_lc(parse) == lc_except) {
527 lmatch(parse, lc_except);
528 lmatch(parse, lc_ident);
529 lmatch(parse, lc_colon);
530 (void) parse_texpr(parse);
531 lmatch(parse, lc_do);
532
533 block = parse_block(parse);
534 list_append(&wef_s->except_blocks, block);
535 }
536
537 lmatch(parse, lc_finally);
538 lmatch(parse, lc_do);
539 wef_s->finally_block = parse_block(parse);
540 lmatch(parse, lc_end);
541
542 return wef_s;
543}
544
545/* Parse expression statement. */
546static stree_exps_t *parse_exps(parse_t *parse)
547{
548 stree_expr_t *expr;
549 stree_exps_t *exps;
550
551 expr = parse_expr(parse);
552 lmatch(parse, lc_scolon);
553
554 exps = stree_exps_new();
555 exps->expr = expr;
556
557 return exps;
558}
559
560/** Parse identifier. */
561stree_ident_t *parse_ident(parse_t *parse)
562{
563 stree_ident_t *ident;
564
565 lcheck(parse, lc_ident);
566 ident = stree_ident_new();
567 ident->sid = lcur(parse)->u.ident.sid;
568 lskip(parse);
569
570 return ident;
571}
572
573/** Return current lem. */
574lem_t *lcur(parse_t *parse)
575{
576 return &parse->lex->current;
577}
578
579/** Retturn current lem lclass. */
580lclass_t lcur_lc(parse_t *parse)
581{
582 return parse->lex->current.lclass;
583}
584
585/** Skip to next lem. */
586void lskip(parse_t *parse)
587{
588 lex_next(parse->lex);
589}
590
591/** Verify that lclass of current lem is @a lc. */
592void lcheck(parse_t *parse, lclass_t lc)
593{
594 if (lcur(parse)->lclass != lc) {
595 lem_print_coords(lcur(parse));
596 printf(" Error: expected '"); lclass_print(lc);
597 printf("', got '"); lem_print(lcur(parse));
598 printf("'.\n");
599 exit(1);
600 }
601}
602
603/** Verify that lclass of current lem is @a lc and go to next lem. */
604void lmatch(parse_t *parse, lclass_t lc)
605{
606 lcheck(parse, lc);
607 lskip(parse);
608}
609
610/** Display generic parsing error. */
611void lunexpected_error(parse_t *parse)
612{
613 lem_print_coords(lcur(parse));
614 printf(" Error: unexpected token '");
615 lem_print(lcur(parse));
616 printf("'.\n");
617 exit(1);
618}
619
620/** Basically tells us whether @a lclass is in next(block). */
621bool_t terminates_block(lclass_t lclass)
622{
623 switch (lclass) {
624 case lc_else:
625 case lc_end:
626 case lc_except:
627 case lc_finally:
628 return b_true;
629 default:
630 return b_false;
631 }
632}
Note: See TracBrowser for help on using the repository browser.