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:
M | cc.h | | | 31 | +++++++++++++++++++++++++++++++ |
M | code.c | | | 42 | +++++++++++++++++++++++++++++++++++++++++- |
M | expr.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;
}