scc

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

commit acfcdefc522706869302970518bb7b06c1455867
parent b22f2a06bf01cfc183aee424bf99b6bc1ebb2ad7
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 30 Mar 2014 13:28:11 +0200

Add tree structure to expressinons

Diffstat:
Mcc.h | 31+++++++++++++++++++++++++++++++
Mcode.c | 42+++++++++++++++++++++++++++++++++++++++++-
Mexpr.c | 131++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 188 insertions(+), 16 deletions(-)

diff --git a/cc.h b/cc.h @@ -31,6 +31,8 @@ extern void *xcalloc(size_t nmemb, size_t size); extern char *xstrdup(const char *s); extern void *xrealloc(void *buff, register size_t size); +/* definitions of types */ + #define CTX_OUTER 0 #define CTX_FUNC 1 @@ -75,6 +77,8 @@ struct funpar { struct funpar *next; }; +/* definition of symbols */ + union value { char c; int i; @@ -206,4 +210,31 @@ extern uint8_t yytoken, yyntoken; extern uint8_t next(void); extern void expect(uint8_t tok); + + +typedef struct node { + void (*code)(struct node *); + Type *type; + union unode { + Symbol *sym; + char op; + } u; + struct node *childs[]; +} Node; + +typedef void (*Inst)(Node *); + +enum { + OCAST, OPTR, OADD, OARY +}; + +extern void emitsym(Node *), emitunary(Node *), emitbin(Node *); +extern Node + *node(void (*code)(Node *), Type *tp, union unode u, uint8_t nchilds), + *unarycode(char op, Type *tp, Node *child), + *bincode(char op, Node *np1, Node *np2); + +#define SYM(s) ((union unode) {.sym = s}) +#define OP(s) ((union unode) {.op = s}) + #endif diff --git a/code.c b/code.c @@ -4,9 +4,39 @@ #include "cc.h" +Node * +node(Inst code, Type *tp, union unode u, uint8_t nchilds) +{ + Node *np = xmalloc(sizeof(*np) + nchilds * sizeof(np)); + + np->code = code; + np->type = tp; + np->u = u; + + return np; +} + +Node * +unarycode(char op, Type *tp, Node *child) +{ + Node *np = node(emitunary, tp, OP(op), 1); + np->childs[0] = child; + return np; +} + +Node * +bincode(char op, Node *np1, Node *np2) +{ + Node *np = node(emitbin, np1->type, OP(op), 2); + np->childs[0] = np1; + np->childs[1] = np2; + return np; +} + void -emitsym(Symbol *sym) +emitsym(Node *np) { + Symbol *sym = np->u.sym; char c; if (sym->s.isglobal) @@ -21,6 +51,16 @@ emitsym(Symbol *sym) } void +emitunary(Node *np) +{ +} + +void +emitbin(Node *np) +{ +} + +void emitfun(Symbol *sym) { printf("X%s\n", sym->name); diff --git a/expr.c b/expr.c @@ -3,17 +3,21 @@ #include "cc.h" -void expr(void); +#define SWAP(x1, x2, t) (t = x1, x1 = x2, x2 = t) -static struct node * +Node *expr(void); + +static Node * primary(void) { - register struct node *np; + Node *np; + Symbol *sym; switch (yytoken) { case IDEN: - if (yylval.sym == NULL) + if ((sym = yylval.sym) == NULL) error("'%s' undeclared", yytext); + np = node(emitsym, sym->type, SYM(sym), 0); next(); break; case CONSTANT: @@ -22,37 +26,134 @@ primary(void) break; case '(': next(); - expr(); + np = expr(); expect(')'); break; default: - np = NULL; + ; } return np; } +void +intconv(Node **np1, Node **np2) +{ +} -static void -ary(void) +void +floatconv(Node **np1, Node **np2) { } -static void +static Node * +add(Node *np1, Node *np2) +{ + Node *naux; + Type *tp1, *tp2; + uint8_t t1, t2, taux; + + tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np1->type); + t1 = tp1->op, t2 = tp2->op; + + switch (t1) { + case BOOL: case INT: + switch (t2) { + case BOOL: case INT: + if (tp1 != tp2) + intconv(&np1, &np2); + break; + case FLOAT: + SWAP(np1, np2, naux); + goto int_float; + case PTR: case FTN: case ARY: + SWAP(np1, np2, naux); + SWAP(t1, t2, taux); + goto pointer; + default: + goto incorrect; + } + break; + case FLOAT: + switch (t2) { + case FLOAT: + if (tp1 != tp2) + floatconv(&np1, &np2); + break; + case BOOL: case INT: +int_float: np2 = unarycode(OCAST, np1->type, np2); + break; + default: + goto incorrect; + } + break; + case PTR: case FTN: case ARY: +pointer: if (t1 == PTR) + np1 = unarycode(OPTR, np1->type, np1); + if (t2 != INT) + goto incorrect; + np2 = unarycode(OCAST, np1->type, np2); + break; + default: + goto incorrect; + } + + return bincode(OADD, np1, np2); + +incorrect: + error("incorrect arithmetic operands"); /*TODO: print type names */ +} + +static Node * +array(Node *np1, Node *np2) +{ + Type *tp; + uint8_t t1, t2; + char *err; + + t1 = BTYPE(np1->type); + t2 = BTYPE(np2->type); + if (!isaddr(t1) && !isaddr(t2)) + goto bad_vector; + if (t1 != INT && t2 != INT) + goto bad_subs; + np1 = add(np1, np2); + return unarycode(OARY, UNQUAL(np1->type)->type , np1); + +bad_vector: + err = "subscripted value is neither array nor pointer nor vector"; + goto error; +bad_subs: + err = "array subscript is not an integer"; +error: error(err); +} + +static Node * postfix(void) { - primary(); + Node *np1, *np2; + + np1 = primary(); for (;;) { switch (yytoken) { - case '[': next(); ary(); break; - default: return; + case '[': + next(); + np2 = expr(); + np1 = array(np1, np2); + expect(']'); + break; + default: + return np1; } - } + } } -void +Node * expr(void) { + Node *np; + do - postfix(); + np = postfix(); while (yytoken == ','); + return np; }