scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit eb99e511ae17e585239954aa02821a05be94eb08
parent 087c633307b818c0bd30579ba0a805e48e530cd3
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon,  4 Jun 2012 21:07:53 +0200

Added support for function declaration

Diffstat:
Mcc.h | 1+
Mdecl.c | 57+++++++++++++++++++++++++++++++++++++++------------------
Mflow.c | 9++++++---
Mmain.c | 11+++++++----
Msyntax.h | 5+++--
Mtypes.c | 6++++++
Mtypes.h | 2++
7 files changed, 64 insertions(+), 27 deletions(-)

diff --git a/cc.h b/cc.h @@ -8,6 +8,7 @@ extern const char *filename; struct { unsigned implicit_int : 1; unsigned c99 : 1; + unsigned useless_typename : 1; } user_opt; diff --git a/decl.c b/decl.c @@ -5,7 +5,7 @@ #include "cc.h" #include "tokens.h" #include "types.h" - +#include "syntax.h" char parser_out_home; @@ -233,31 +233,52 @@ duplicated: error("duplicated '%s'", yytext); } -char decl(void) +unsigned char decl(void) { - struct type *t, *spec; + auto struct type *tp, *tbase; + auto unsigned char nd = 0; puts("decl"); - if (!(spec = specifier())) - return 0; - do { - declarator(); - t = decl_type(spec); - } while (accept(',')); - expect(';'); /* TODO: initialisation */ + tbase = specifier(); + + if (!tbase) { + if (nested_level != 0) { + puts("leaving decl"); + return 0; + } + if (yytoken == IDENTIFIER) { + warning_error(user_opt.implicit_int, + "type defaults to 'int' " + "in declaration of '%s'", yytext); + tbase = T_INT; + } else { + error("declaration expected"); + } + } + if (yytoken != ';') { + do { + declarator(); + tp = decl_type(tbase); + if (isfunction(tp) && yytoken == '{') { + compound(); + puts("leaving decl"); + return 1; + } + ++nd; + } while (accept(',')); + } + + expect(';'); + if (nd == 0) { + warning_error(user_opt.useless_typename, + "useless type name in empty declaration"); + } puts("leaving decl"); return 1; } -char decl_list(void) -{ - puts("decl_list"); - while (decl()) - /* nothing */; - puts("leaving decl_list"); -} - void type_name() { } + diff --git a/flow.c b/flow.c @@ -1,10 +1,12 @@ -#include <stddef.h> +#include <stdio.h> #include "tokens.h" #include "syntax.h" +unsigned char nested_level; + void stmt(void); static void do_goto(void) @@ -84,7 +86,6 @@ static void do_switch(void) void stmt(void) { puts("stmt"); - unsigned char tok; switch (yytoken) { case '{': @@ -130,7 +131,9 @@ void compound(void) { puts("compound"); if (accept('{')) { - decl_list(); + ++nested_level; + while (decl()) + /* nothing */; while (!accept('}')) stmt(); } diff --git a/main.c b/main.c @@ -1,10 +1,13 @@ #include <stddef.h> +#include "tokens.h" +#include "syntax.h" + extern void open_file(const char *file); extern void init_lex(); -extern void next(); -extern void stmt(); + + @@ -12,8 +15,8 @@ int main(int argc, char *argv[]) { init_lex(); open_file(NULL); - next(); - compound(); + for (next(); yytoken != EOFTOK; decl()) + /* nothing */; return 0; } diff --git a/syntax.h b/syntax.h @@ -1,8 +1,9 @@ #ifndef SYNTAX_H #define SYNTAX_H -extern char decl(void); +extern unsigned char nested_level; + extern void compound(void); extern void expr(void); -extern char decl_list(void); +unsigned char decl(void); #endif diff --git a/types.c b/types.c @@ -135,3 +135,9 @@ void ptype(register struct type *t) } #endif + + +unsigned char isfunction(struct type *t) +{ + return t->op == FTN; +} diff --git a/types.h b/types.h @@ -65,4 +65,6 @@ extern void ptype(register struct type *t); #endif +extern unsigned char isfunction(struct type *t); + #endif