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

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

Add Sysel Bootstrap Interpreter (SBI) from Sysel repository rev. 53.

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