String literals, proper compound statement parsing.
[mcc.git] / parse.c
blob76f2fb127af91166ae81ae153922596d0d0d8bc7
1 #include "parse.h"
2 #include "cc.h"
3 #include "scanner.h"
4 #include "const.h"
5 #include "errors.h"
6 #include "stdlib.h"
7 #include "stdio.h"
8 #include "stdarg.h"
10 // make-it-easier macros
11 #define LEX (&cc->lex) // struct lexer *
12 #define TOK (cc->lex.tok) // tok_t
14 static void cc_accept(struct cc *cc, const char *description, ...);
15 static void cc_sync(struct cc *cc, ...);
16 static int get_precedence(tok_t tok);
17 static bool cc_isglobal(struct cc *cc);
18 static struct stree *cc_get_current_func(struct cc *cc);
19 static struct stree *cc_parse_factor(struct cc *cc);
20 static struct stree *cc_parse_expr(struct cc *cc);
21 static struct stree *cc_parse_expr_nocomma(struct cc *cc);
22 static bool cc_parse_struct(struct cc *cc, struct btype *struct_type_info);
23 static bool cc_parse_type(struct cc *cc, struct btype *type_info);
24 static struct stree *cc_parse_pointer_type(struct cc *cc, struct btype *type_info);
25 static struct stree *cc_parse_parameters(struct cc *cc);
26 static bool type_identical(struct btype *type1, struct btype *type2);
27 static void cc_compare_functions(struct cc *cc, struct stree *func1, struct stree *func2);
28 static void cc_parse_decl_function(struct cc *cc, struct stree **psym_node);
29 static void cc_parse_decl_variable(struct cc *cc, struct stree *sym_node);
30 static void cc_parse_statement(struct cc *cc);
31 static void cc_parse_compound_stat(struct cc *cc);
32 static void cc_parse_defn_function(struct cc *cc, struct stree *func);
33 static bool cc_parse_decl(struct cc *cc, struct stree *insert_here);
35 // throw a 'foo expected but bar found' error
36 void cc_expect(struct cc *cc, const char *fmt, ...)
38 va_list ap;
39 va_start(ap, fmt);
40 fprintf(stderr, "%s:%d: error: ", LEX->tok_sloc.name, LEX->tok_sloc.line);
41 vfprintf(stderr, fmt, ap);
42 va_end(ap);
43 fprintf(stderr, " expected but \"%s\" found\n", lex_get_tok_str(LEX, TOK, LEX->tok_str));
46 // throw a compile error with explicit source code location (va_list form)
47 void cc_error_loc_v(struct cc *cc, struct sloc *sloc, const char *fmt, va_list ap)
49 fprintf(stderr, "%s:%d: error: ", sloc->name, sloc->line);
50 vfprintf(stderr, fmt, ap);
51 fputc('\n', stderr);
54 // throw a compile error with explicit source code location (... form)
55 void cc_error_loc(struct cc *cc, struct sloc *sloc, const char *fmt, ...)
57 va_list ap;
58 va_start(ap, fmt);
59 cc_error_loc_v(cc, sloc, fmt, ap);
60 va_end(ap);
63 // throw a compile error at current token
64 void cc_error(struct cc *cc, const char *fmt, ...)
66 va_list ap;
67 va_start(ap, fmt);
68 cc_error_loc_v(cc, &LEX->tok_sloc, fmt, ap);
69 va_end(ap);
72 // If the next token is in the given set of tokens,
73 // then accept it, otherwise throw an error.
74 // 'description' describes what is wanted. This could be
75 // a token or a non-terminal name (eg. "type" or "expression").
76 // Token set is a zero-terminated list of tokens. Eg.:
77 // > cc_accept(cc, "operator", '+', '-', TOK_SHL, 0);
78 // would throw "operator expected, but '*' found" if the next
79 // token wasn't either '+', '-' or TOK_SHL (<<)
80 static void cc_accept(struct cc *cc, const char *description, ...)
82 va_list ap;
83 tok_t tok;
84 va_start(ap, description);
85 while ((tok = va_arg(ap, int))){
86 if (TOK == tok){
87 // ok
88 lex_next(LEX);
89 return;
92 cc_expect(cc, "%s", description);
95 // keep eating tokens until the current token is in the given set.
96 // The set is a zero-terminated list of tokens, eg.:
97 // > cc_sync(cc, ')', ';', 0);
98 static void cc_sync(struct cc *cc, ...)
100 va_list ap;
101 tok_t tok;
102 for (;;){
103 va_start(ap, cc);
104 while ((tok = va_arg(ap, int))){
105 if (TOK == tok)
106 return;
108 va_end(ap);
109 lex_next(LEX);
113 static struct {
114 int prec; // operator precedence level (1=highest)
115 tok_t tok; // operator token
116 } operator_table[] = {
117 {1, '*'}, {1, '/'}, {1, '%'}, // multiplicative
118 {2, '+'}, {2, '-'}, // additive
119 {3, TOK_SHL}, {3, TOK_SHR}, // shiftive?
120 {4, '<'}, {4, TOK_LE}, {4, '>'}, {4, TOK_GE}, // comparison
121 {5, TOK_EQ}, {5, TOK_NE}, // equality
122 {6, '&'}, // bitwise and
123 {7, '^'}, // bitwise xor
124 {8, '|'}, // bitwise or
125 {9, TOK_LAND}, // logical and
126 {10, TOK_LOR}, // logical or
127 {11, '?'}, // ternary
128 {12, '='}, {12, TOK_EADD}, {12, TOK_ESUB}, // augmented assignment
129 {12, TOK_EMUL}, {12, TOK_EDIV}, {12, TOK_EMOD},// .
130 {12, TOK_ESHL}, {12, TOK_ESHR}, {12, TOK_EAND},// .
131 {12, TOK_EXOR}, {12, TOK_EOR}, // .
132 {13, ','}, // comma operator
135 static int get_precedence(tok_t tok)
137 int i;
138 for (i=0; i<(sizeof operator_table / sizeof *operator_table); i++){
139 if (operator_table[i].tok == tok){
140 return operator_table[i].prec;
143 return 0;
146 // return true if parser state is in global scope
147 // (i.e. what is being passed is at global (file) scope)
148 static bool cc_isglobal(struct cc *cc)
150 return (cc->scope == cc->stree);
153 // return the current function node
154 static struct stree *cc_get_current_func(struct cc *cc)
156 // TODO!
157 return NULL;
160 // parse a factor, except subexpressions (...),
161 // due to cast/subexpression ambiguity
162 static struct stree *cc_parse_factor(struct cc *cc)
164 struct stree *fac = NULL;
165 if (lex_is_ident(LEX, TOK)){
166 fac = stree_create();
167 fac->form = STF_FACTOR;
168 fac->tok = TOK;
169 lex_next(LEX);
170 } else if (TOK == TOK_NUMBER){
171 fac = stree_create();
172 fac->form = STF_FACTOR;
173 fac->tok = TOK_NUMBER;
174 const_parse_number(&fac->cv, LEX->tok_str);
175 lex_next(LEX);
176 } else if (TOK == TOK_STR){
177 fac = stree_create();
178 fac->form = STF_FACTOR;
179 fac->tok = TOK_STR;
180 fac->cv.type = CBT_STRING;
181 fac->cv.v.string = LEX->tok_str; // steal the string data :)
182 LEX->tok_str = NULL;
183 lex_next(LEX);
184 } else {
185 cc_expect(cc, "expression");
187 return fac;
190 static struct stree *cc_parse_unary(struct cc *cc)
192 struct stree *fac, *un, *prefix_first = NULL, *prefix_last = NULL;
194 // prefix unary operators
195 while (TOK == TOK_INC || TOK == TOK_DEC || TOK == '+'
196 || TOK == '-' || TOK == '!' || TOK == '~' || TOK == '*'
197 || TOK == '&' || TOK == TOK_sizeof){
198 un = stree_create();
199 un->form = STF_UNOP;
200 un->tok = TOK;
201 if (TOK == '+'){
202 // The '+' does nothing. Does anyone ever use it?!
203 fprintf(stderr, "You're using a unary plus? Weird.\n");
205 link_prefix_unop:
206 if (prefix_last){
207 stree_append_child(prefix_last, un);
208 } else {
209 prefix_first = un;
211 prefix_last = un;
212 lex_next(LEX);
215 // subexpression or cast
216 // (a bit ambiguous)
217 if (TOK == '('){
218 struct stree *type_node;
219 struct btype btype;
220 lex_next(LEX);
221 if (cc_parse_type(cc, &btype)){
222 // cast
223 type_node = cc_parse_pointer_type(cc, &btype);
224 un = stree_create();
225 un->form = STF_UNOP;
226 un->tok = TOK_CAST;
227 un->btype = btype;
228 if (type_node){
229 // excessive type information
230 stree_append_child(un, type_node);
232 // I could choose between one goto, or reams and reams
233 // of tangled spaghetti-loops.
234 // I preferred the goto.
235 // Sorry Dijkstra.
236 goto link_prefix_unop;
237 } else {
238 fac = cc_parse_expr(cc);
239 cc_accept(cc, "\")\"", ')', 0);
241 } else {
242 fac = cc_parse_factor(cc);
245 // postfix unary operators
246 while (TOK == TOK_INC || TOK == TOK_DEC || TOK == '[' ||
247 TOK == TOK_ARROW || TOK == '.' || TOK == '('){
248 un = stree_create();
249 un->form = STF_UNOP;
250 stree_append_child(un, fac);
251 if (TOK == TOK_INC){
252 un->tok = TOK_POSTINC;
253 lex_next(LEX);
254 } else if (TOK == TOK_DEC){
255 un->tok = TOK_POSTDEC;
256 lex_next(LEX);
257 } else if (TOK == '['){
258 // array subscript
259 struct stree *subscript;
260 un->tok = '[';
261 lex_next(LEX);
262 subscript = cc_parse_expr(cc);
263 if (subscript){
264 stree_append_child(un, subscript);
265 cc_accept(cc, "\"]\"", ']', 0);
267 } else if (TOK == '.' || TOK == TOK_ARROW){
268 // struct/union member access
269 struct stree *member_name;
270 un->tok = TOK;
271 lex_next(LEX);
272 if (lex_is_ident(LEX, TOK)){
273 member_name = stree_create();
274 member_name->form = STF_ATOM;
275 member_name->tok = TOK;
276 stree_append_child(un, member_name);
277 lex_next(LEX);
278 } else {
279 cc_expect(cc, "identifier (member name)");
281 } else if (TOK == '('){
282 struct stree *argument;
283 // function call
284 un->tok = '(';
285 lex_next(LEX);
286 if (TOK != ')'){
287 do {
288 argument = cc_parse_expr_nocomma(cc);
289 if (argument){
290 stree_append_child(un, argument);
292 } while (TOK == ',' ? (lex_next(LEX), 1) : 0);
294 cc_accept(cc, "\")\"", ')', 0);
296 fac = un;
299 if (prefix_last){
300 stree_append_child(prefix_last, fac);
301 return prefix_first;
302 } else {
303 return fac;
307 static struct stree *cc_parse_expr_internal(struct cc *cc, int min_prec)
309 struct stree *lhs, *rhs, *op_node, *node, *node_parent, *node_right;
310 int prec, node_prec, op_tok;
311 lhs = cc_parse_unary(cc);
312 if (!lhs)
313 return NULL;
314 prec = get_precedence(TOK);
315 while (prec != 0 && prec <= min_prec){
316 op_tok = TOK;
317 lex_next(LEX);
318 rhs = cc_parse_unary(cc);
319 if (!rhs){
320 return lhs;
322 // find where to insert it
323 node = lhs;
324 node_parent = NULL;
325 while (node && node->form == STF_BINOP){
326 node_prec = get_precedence(node->tok);
327 if (prec < node_prec){
328 // carry on descending
329 node_right = stree_right(node);
330 if (node_right){
331 node_parent = node;
332 node = node_right;
333 } else {
334 break;
336 } else {
337 break;
340 if (node){
341 // insert between node and node_parent
342 op_node = stree_create();
343 op_node->form = STF_BINOP;
344 op_node->tok = op_tok;
345 if (node_parent){
346 stree_remove_child(node);
347 stree_append_child(op_node, node);
348 stree_append_child(op_node, rhs);
349 stree_append_child(node_parent, op_node);
350 } else {
351 stree_append_child(op_node, node);
352 stree_append_child(op_node, rhs);
353 lhs = op_node;
355 } else {
356 die("not sure");
358 prec = get_precedence(TOK);
360 return lhs;
363 static struct stree *cc_parse_expr(struct cc *cc)
365 return cc_parse_expr_internal(cc, 13);
368 // same as cc_parse_expr, but don't parse the comma operator
369 // used in function calls
370 static struct stree *cc_parse_expr_nocomma(struct cc *cc)
372 return cc_parse_expr_internal(cc, 12);
375 // parse struct or union (they're syntactically identical)
376 static bool cc_parse_struct(struct cc *cc, struct btype *struct_type_info)
378 struct stree *tag;
379 struct btype type_info, original_type_info;
380 struct stree *type_node, *sym_node;
381 tag = stree_create();
382 tag->form = STF_TAG;
383 tag->sloc = LEX->tok_sloc;
384 lex_next(LEX);
385 if (lex_is_ident(LEX, TOK)){
386 // prev_tag = stree_find(cc->scope, STF_TAG, TOK); TODO
387 tag->tok = TOK;
388 tag->sloc = LEX->tok_sloc;
389 lex_next(LEX);
391 if (TOK == '{'){
392 // struct definition
393 lex_next(LEX);
394 while (TOK != 0 && TOK != '}'){
395 if (cc_parse_type(cc, &original_type_info)){
396 do {
397 type_info = original_type_info;
398 type_node = cc_parse_pointer_type(cc, &type_info);
399 if (!lex_is_ident(LEX, TOK)){
400 cc_expect(cc, "identifier");
401 if (type_node){
402 stree_destroy(type_node);
404 return false; // XXX: LEAKS?
406 sym_node = stree_create();
407 sym_node->form = STF_VARIABLE;
408 sym_node->btype = type_info;
409 sym_node->tok = TOK;
410 sym_node->sloc = LEX->tok_sloc;
411 if (type_node){
412 stree_append_child(sym_node, type_node);
414 stree_append_child(tag, sym_node);
415 lex_next(LEX);
416 // TODO: check for duplicate fields
417 } while (TOK == ',' ? (lex_next(LEX), true) : false);
418 } else {
419 // ???
420 cc_expect(cc, "field or \"}\"");
422 cc_accept(cc, "\";\"", ';', 0);
424 cc_accept(cc, "\"}\"", '}', 0);
425 } else {
427 stree_append_child(cc->scope, tag);
428 struct_type_info->base_type = BT_STRUCT;
429 struct_type_info->node = tag;
430 return true;
433 static bool cc_parse_type(struct cc *cc, struct btype *type_info)
435 type_info->base_type = 0;
436 type_info->qualifiers = 0;
437 switch (TOK){
438 case TOK_void:
439 type_info->base_type = BT_VOID; // well, it's a type, isn't it?
440 // (HINT: the check for variables of type void is not done here)
441 break;
442 case TOK_char:
443 type_info->base_type = BT_CHAR;
444 break;
445 case TOK_int:
446 type_info->base_type = BT_INT;
447 break;
448 case TOK_float:
449 type_info->base_type = BT_FLOAT;
450 break;
451 case TOK_double:
452 type_info->base_type = BT_DOUBLE;
453 break;
454 case TOK_struct:
455 case TOK_union:
456 return cc_parse_struct(cc, type_info);
457 default:
458 return false;
460 lex_next(LEX);
461 return true;
464 // Parse a pointer type: next token must be after initial type declaration
465 // i.e.: int *foo;
466 // ^--current token: '*'
467 // Returns a sub-stree of additional type information.
468 // THIS MUST BE PUT SOMEWHERE IN A TREE.
469 // *type_info will be modified to represent the new pointer type
470 static struct stree *cc_parse_pointer_type(struct cc *cc, struct btype *type_info)
472 struct stree *type_node = NULL, *new_type_node;
473 while (TOK == '*'){
474 // create a type node to store the excess type information
475 new_type_node = stree_create();
476 new_type_node->form = STF_TYPE;
477 new_type_node->btype = *type_info;
478 if (type_node){
479 stree_append_child(type_node, new_type_node);
481 type_node = new_type_node;
482 // create pointer type
483 type_info->base_type = BT_POINTER;
484 type_info->qualifiers = 0; // TODO: parse qualifiers
485 type_info->node = new_type_node;
486 // eat '*'
487 lex_next(LEX);
489 return type_node;
492 // Parse function parameters
493 // void foo(int a, int b);
494 // ^-- current token: 'int'
495 // returns an STF_PARAMETERS node full of parameters, or
496 // NULL if there aren't any.
497 static struct stree *cc_parse_parameters(struct cc *cc)
499 struct stree *parameters = NULL;
500 if (TOK == TOK_void){
501 // just 'void' - no parameters
502 lex_next(LEX);
503 } else if (TOK != ')'){
504 parameters = stree_create(); // create parameter list
505 parameters->form = STF_PARAMETERS;
506 do {
507 struct btype type_info;
508 struct stree *type_node, *param_node;
509 if (TOK == TOK_ELLIPSIS){
510 // variadic function
511 param_node = stree_create();
512 param_node->form = STF_VARIABLE;
513 param_node->tok = TOK_ELLIPSIS;
514 if (stree_child_count(parameters) == 0){
515 cc_error(cc, "a named argument is required before \"...\"");
517 lex_next(LEX);
518 if (TOK != ')'){
519 cc_error(cc, "variadic function's \"...\" must be placed at the end of the parameter list");
520 cc_sync(cc, ')', ';', 0);
522 } else {
523 // parse parameter's type
524 if (!cc_parse_type(cc, &type_info)){
525 cc_expect(cc, "type");
527 type_node = cc_parse_pointer_type(cc, &type_info);
528 // create parameter node
529 param_node = stree_create();
530 param_node->form = STF_VARIABLE;
531 param_node->btype = type_info;
532 // save extra type info, if there is any
533 if (type_node){
534 stree_append_child(param_node, type_node);
536 // does the parameter have a name yet? it may not.
537 if (lex_is_ident(LEX, TOK)){
538 // parameter has a name
539 param_node->tok = TOK;
540 lex_next(LEX);
542 // if it doesn't, that's ok too
543 // as long as it's not a function definition;
544 // we don't know yet, though.
546 // Now, put the parameter in the list
547 stree_append_child(parameters, param_node);
548 } while (TOK == ',' ? (lex_next(LEX), true) : false);
550 cc_accept(cc, "\")\"", ')', 0);
551 return parameters;
554 // return true if the two types are identical
555 static bool type_identical(struct btype *type1, struct btype *type2)
557 top:
558 if (type1->base_type != type2->base_type)
559 return false;
560 // TODO: check qualifiers?
561 if (type1->base_type == BT_POINTER){
562 // compare pointed types
563 type1 = &type1->node->btype;
564 type2 = &type2->node->btype;
565 goto top;
567 return true; // all checks passed
570 // compare two functions, func1 and func2, for compatibility
571 static void cc_compare_functions(struct cc *cc, struct stree *func1, struct stree *func2)
573 struct stree *param_list_1, *param_list_2, *param_1, *param_2;
574 int n;
575 if (!type_identical(&func1->btype, &func2->btype)){
576 cc_error_loc(cc, &func2->sloc, "conflicting types for \"%s\"",
577 lex_get_tok_str(LEX, func2->tok, NULL));
578 cc_error_loc(cc, &func1->sloc, "previous declaration of \"%s\" was here",
579 lex_get_tok_str(LEX, func1->tok, NULL));
581 // check parameters
582 param_list_1 = stree_get_child_by_form(func1, STF_PARAMETERS);
583 param_list_2 = stree_get_child_by_form(func2, STF_PARAMETERS);
584 if (stree_child_count(param_list_1) != stree_child_count(param_list_2)){
585 cc_error_loc(cc, &func2->sloc, "conflicting number of parameters for \"%s\"",
586 lex_get_tok_str(LEX, func2->tok, NULL));
587 cc_error_loc(cc, &func1->sloc, "previous declaration of \"%s\" was here",
588 lex_get_tok_str(LEX, func1->tok, NULL));
589 } else {
590 param_1 = NULL;
591 param_2 = NULL;
592 n = 0;
593 while (stree_next_child(param_list_1, &param_1),
594 stree_next_child(param_list_2, &param_2),
595 (param_1 && param_2)){
596 n++;
597 if (param_1->tok == TOK_ELLIPSIS || param_2->tok == TOK_ELLIPSIS){
598 // variadic function
599 if (param_1->tok == TOK_ELLIPSIS && param_2->tok == TOK_ELLIPSIS){
600 // that's ok
601 } else {
602 cc_error_loc(cc, &func2->sloc, "\"%s\" is %svariadic, unlike previous declaration",
603 lex_get_tok_str(LEX, func2->tok, NULL),
604 param_1->tok == TOK_ELLIPSIS ? "not " : "");
605 cc_error_loc(cc, &func1->sloc, "previous declaration of \"%s\" was here",
606 lex_get_tok_str(LEX, func1->tok, NULL));
609 // compare parameter types
610 else if (!type_identical(&param_1->btype, &param_2->btype)){
611 cc_error_loc(cc, &func2->sloc, "conflicting types for parameter %d of \"%s\"",
612 n, lex_get_tok_str(LEX, func2->tok, NULL));
613 cc_error_loc(cc, &func1->sloc, "previous declaration of \"%s\" was here",
614 lex_get_tok_str(LEX, func1->tok, NULL));
616 // merge name information
617 if (param_2->tok)
618 param_1->tok = param_2->tok;
623 static void cc_parse_decl_function(struct cc *cc, struct stree **psym_node)
625 struct stree *parameters, *prev_decl;
626 struct stree *sym_node = *psym_node;
627 if (!cc_isglobal(cc)){
628 struct stree *current_func;
629 current_func = cc_get_current_func(cc);
630 cc_error(cc, "nested functions are not permitted: \"%s\" inside \"%s\"",
631 lex_get_tok_str(LEX, sym_node->tok, NULL),
632 current_func ? lex_get_tok_str(LEX, current_func->tok, NULL) : "???");
634 // find previous declaration of this symbol
635 prev_decl = stree_find_local(cc->scope, STF_FUNCTION, sym_node->tok);
636 if (!prev_decl) prev_decl = stree_find_local(cc->scope, STF_VARIABLE, sym_node->tok);
637 if (prev_decl){
638 if (prev_decl->form == STF_FUNCTION){
639 // must check that declarations match later
640 } else {
641 cc_error_loc(cc, &sym_node->sloc,
642 "\"%s\" declared as different kind of symbol",
643 lex_get_tok_str(LEX, sym_node->tok, NULL));
644 cc_error_loc(cc, &prev_decl->sloc,
645 "previous declaration of \"%s\" was here",
646 lex_get_tok_str(LEX, sym_node->tok, NULL));
649 sym_node->form = STF_FUNCTION;
650 // parse parameters
651 lex_next(LEX); // eat '('
652 parameters = cc_parse_parameters(cc);
653 if (parameters){
654 stree_append_child(sym_node, parameters);
656 if (prev_decl && prev_decl->form == STF_FUNCTION){
657 // make sure declarations match
658 cc_compare_functions(cc, prev_decl, sym_node);
659 // either way, we don't want two copies, so delete the later one
660 stree_destroy(sym_node);
661 *psym_node = NULL;
665 static void cc_parse_decl_variable(struct cc *cc, struct stree *sym_node)
667 struct stree *prev_defn;
668 if (sym_node->btype.base_type == BT_VOID){
669 cc_error_loc(cc, &sym_node->sloc, "cannot declare variable \"%s\" of type void: impossible without vacuum pump",
670 lex_get_tok_str(LEX, sym_node->tok, NULL));
672 prev_defn = stree_find_local(cc->scope, STF_VARIABLE, sym_node->tok);
673 if (prev_defn){
674 cc_error_loc(cc, &sym_node->sloc, "redefinition of \"%s\"",
675 lex_get_tok_str(LEX, sym_node->tok, NULL));
676 cc_error_loc(cc, &prev_defn->sloc,
677 "previous definition of \"%s\" was here",
678 lex_get_tok_str(LEX, sym_node->tok, NULL));
680 sym_node->form = STF_VARIABLE;
683 static void cc_parse_ifstat(struct cc *cc)
685 struct stree *stat, *expr, *old_scope;
686 stat = stree_create();
687 stat->form = STF_STAT;
688 stat->tok = TOK;
689 stree_append_child(cc->scope, stat);
690 lex_next(LEX);
691 cc_accept(cc, "\"(\"", '(', 0);
692 expr = cc_parse_expr(cc);
693 cc_accept(cc, "\")\"", ')', 0);
694 stree_append_child(stat, expr);
695 old_scope = cc->scope;
696 cc->scope = stat;
697 cc_parse_statement(cc);
698 cc->scope = old_scope;
701 static void cc_parse_statement(struct cc *cc)
703 struct stree *expr, *block, *old_scope;
704 if (TOK == TOK_if){
705 cc_parse_ifstat(cc);
706 } else if (TOK == '{'){
707 lex_next(LEX);
708 block = stree_create();
709 block->form = STF_BLOCK;
710 stree_append_child(cc->scope, block);
711 old_scope = cc->scope;
712 cc->scope = block;
713 cc_parse_compound_stat(cc);
714 cc->scope = old_scope;
715 cc_accept(cc, "\"}\"", '}', 0);
716 } else {
717 expr = cc_parse_expr(cc);
718 if (expr){
719 stree_append_child(cc->scope, expr);
720 cc_accept(cc, "\";\"", ';', 0);
725 static void cc_parse_compound_stat(struct cc *cc)
727 while (TOK != 0 && TOK != '}'){
728 if (cc_parse_decl(cc, cc->scope)){
730 } else {
731 cc_parse_statement(cc);
736 static void cc_parse_defn_function(struct cc *cc, struct stree *func)
738 struct stree *old_scope, *block;
739 // TODO: check presence of parameter names
740 // TODO: parse body
741 block = stree_create();
742 block->sloc = LEX->tok_sloc;
743 block->form = STF_BLOCK;
744 stree_append_child(func, block);
745 old_scope = cc->scope;
746 cc->scope = block;
747 cc_parse_compound_stat(cc);
748 cc->scope = old_scope;
751 // Parse a declaration/definition.
752 // Returns true if it found one, false if there's no declaration (no tokens will have been eaten).
753 // Will return true on syntax error, since tokens were eaten.
754 static bool cc_parse_decl(struct cc *cc, struct stree *insert_here)
756 struct btype type_info, original_type_info;
757 struct stree *type_node, *sym_node = NULL;
758 bool was_func_defn = false;
759 if (cc_parse_type(cc, &original_type_info)){
760 do {
761 // restore the type before the '*'s (pointer types)
762 type_info = original_type_info;
763 type_node = cc_parse_pointer_type(cc, &type_info);
764 if (!lex_is_ident(LEX, TOK)){
765 cc_expect(cc, "identifier");
766 if (type_node){
767 stree_destroy(type_node);
769 return true;
772 // variable declaration or definition
773 // or function declaration or definition
774 sym_node = stree_create();
775 sym_node->btype = type_info;
776 sym_node->tok = TOK;
777 sym_node->sloc = LEX->tok_sloc;
778 lex_next(LEX);
779 // put the type info somewhere
780 if (type_node){
781 stree_append_child(sym_node, type_node);
783 if (TOK == '('){
784 // it is a function
785 cc_parse_decl_function(cc, &sym_node);
786 if (TOK == '{'){
787 // function definition
788 lex_next(LEX);
789 cc_parse_defn_function(cc, sym_node);
790 cc_accept(cc, "\"}\"", '}', 0);
791 was_func_defn = true;
793 } else {
794 // it is a variable
795 cc_parse_decl_variable(cc, sym_node);
797 if (sym_node){
798 stree_append_child(insert_here, sym_node);
800 } while (TOK == ',' ? (lex_next(LEX), true) : false);
801 if (!was_func_defn){
802 cc_accept(cc, "\";\"", ';', 0);
804 return true;
805 } else {
806 // hmm.
807 return false;
811 void cc_parse(struct cc *cc)
813 cc->stree = cc->scope = stree_create();
814 while (TOK != 0){
815 if (!cc_parse_decl(cc, cc->scope)){
816 break;