scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 98d60a06534921e0b79dd3b0a13910f2a8ec83a9
parent 689b7bf05b8a3612c26fced0b6bf9dd3f944902b
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 24 Sep 2013 17:44:10 +0200

Add enum types

A enum defines a integer type which can store a series of symbolic
values defined in the enum definition.

Diffstat:
decl.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
symbol.h | 2+-
2 files changed, 95 insertions(+), 59 deletions(-)

diff --git a/decl.c b/decl.c @@ -82,8 +82,95 @@ dirdcl(register struct ctype *tp, unsigned char ns) } } +static void +new_struct(register struct ctype *tp) +{ + if (yytoken == IDEN) { + (namespace(NS_STRUCT, -1)->ctype = tp)->refcnt++; + next(); + } + if (nr_structs == NR_MAXSTRUCTS) + error("too much structs/unions/enum defined"); + if (structp == &structbuf[NR_STRUCT_LEVEL]) + error("too much nested structs/unions"); + tp->c_struct = *structp++ = nr_structs; +} + +static struct ctype * spec(void); + +static struct ctype * +struct_dcl(unsigned char ns) +{ + register struct ctype *tp, *base; + + if (!(base = spec())) { + base = newctype(); + base->type = INT; + warning_error(options.implicit, + "data definition has no type or storage class"); + } + if (base->c_typedef || base->c_static || base->c_auto || + base->c_register || base->c_extern) { + error("storage specifier in a struct/union field declaration"); + } + + do { /* TODO: detect unnamed structs */ + declarator(base, ns); + tp = decl_type(base); + (cursym->ctype = tp)->refcnt++; + } while (accept(',')); + + expect(';'); + return tp; +} + +static struct ctype * +struct_spec(register struct ctype *tp) +{ + new_struct(tp); + if (!accept('{')) + return tp; + + if (!tp->forward) + error("struct/union already defined"); + + do + struct_dcl(tp->c_struct); + while (!accept('}')); + tp->forward = 0; + + return tp; +} + +static struct ctype * +enum_dcl(struct ctype *base) +{ + short val = 0; + + new_struct(base); + if (!accept('{')) + return base; + + do { + register struct symbol *sym; + register struct ctype *tp = btype(NULL, INT); -static struct ctype *struct_spec(register struct ctype *); + if (yytoken == '}') + break; + + expect(IDEN); + ((sym = namespace(NS_IDEN, 1))->ctype = tp)->refcnt++; + if (accept('=')) { + expect(CONSTANT); + val = yyval.sym->val; + } + sym->val = val++; + } while (accept(',')); + + expect('}'); + + return base; +} struct ctype * spec(void) @@ -100,10 +187,13 @@ spec(void) case COMPLEX: case IMAGINARY: case FLOAT: case DOUBLE: case BOOL: case VOID: case CHAR: case SHORT: - case INT: case ENUM: case LONG: + case INT: case LONG: tp = btype(tp, yytoken); break; - /* TODO: ENUM */ + case ENUM: + tp = btype(tp, yytoken); + next(); + return enum_dcl(tp); case STRUCT: case UNION: tp = btype(tp, yytoken); next(); @@ -147,60 +237,6 @@ spec(void) } } -static struct ctype * -struct_dcl(unsigned char ns) -{ - register struct ctype *tp, *base; - - if (!(base = spec())) { - base = newctype(); - base->type = INT; - warning_error(options.implicit, - "data definition has no type or storage class"); - } - if (base->c_typedef || base->c_static || base->c_auto || - base->c_register || base->c_extern) { - error("storage specifier in a struct/union field declaration"); - } - - do { /* TODO: detect unnamed structs */ - declarator(base, ns); - tp = decl_type(base); - (cursym->ctype = tp)->refcnt++; - } while (accept(',')); - - expect(';'); - return tp; -} - -static struct ctype * -struct_spec(register struct ctype *tp) -{ - if (yytoken == IDEN) { - (namespace(NS_STRUCT, -1)->ctype = tp)->refcnt++; - next(); - } - - if (nr_structs == NR_MAXSTRUCTS) - error("too much structs/unions defined"); - if (structp == &structbuf[NR_STRUCT_LEVEL]) - error("too much nested structs/unions"); - tp->c_struct = *structp++ = nr_structs; - - if (!accept('{')) - return tp; - - if (!tp->forward) - error("struct/union already defined"); - - do - struct_dcl(tp->c_struct); - while (!accept('}')); - tp->forward = 0; - - return tp; -} - static void declarator(struct ctype *tp, unsigned char ns) { @@ -295,7 +331,7 @@ repeat: if (!(tp = spec())) { } else if (accept(';')) { register unsigned char type = tp->type; - if (type == STRUCT || type == UNION) { + if (type == STRUCT || type == UNION || type == ENUM) { if (tp->c_extern || tp->c_static || tp->c_auto || tp->c_register || tp->c_const || tp->c_volatile) { warning_error(options.useless, diff --git a/symbol.h b/symbol.h @@ -11,7 +11,7 @@ #define CTX_FUNC 2 #define CTX_ANY 0 -enum namespace { +enum { NS_IDEN, NS_KEYWORD, NS_STRUCT,