aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2014-04-04 00:06:23 +0800
committerTeddy <ted.sybil@gmail.com>2014-04-04 00:06:23 +0800
commitef1c46b1eef2b22100d9eca9c4d0e6ffab7c7eab (patch)
treed77ea2311d25b608b1e1a951668319ec4359bbf3
parentcd34e28676aa32fdc60c2ba54d6f4f6dbba33132 (diff)
some basic semantics analysis
-rw-r--r--ast.h5
-rw-r--r--const.h5
-rw-r--r--semantics.c180
-rw-r--r--semantics.h16
4 files changed, 202 insertions, 4 deletions
diff --git a/ast.h b/ast.h
index 9412fa7..55a0e8a 100644
--- a/ast.h
+++ b/ast.h
@@ -2,6 +2,7 @@
#define AST_H
#include <stdarg.h>
#include "const.h"
+#include "semantics.h"
#include "cibic.tab.h"
typedef struct CNode {
@@ -44,6 +45,10 @@ typedef struct CNode {
int subtype;
char *strval;
} rec;
+ union {
+ CType *type;
+ CVar *var_ref;
+ } ext;
struct CNode *chd, *next;
/* For error reporting */
struct Location {
diff --git a/const.h b/const.h
index 342888e..72fff2a 100644
--- a/const.h
+++ b/const.h
@@ -21,3 +21,8 @@
#define MAX_DEBUG_PRINT_BUFF 1024
#define MAX_DEBUG_PRINT_LVL 1024
#define MAX_TABLE_SIZE 1021
+#define INT_SIZE 4
+#define CHAR_SIZE 1
+#ifndef CIBIC_DEBUG
+#define CIBIC_DEBUG
+#endif
diff --git a/semantics.c b/semantics.c
index b38b150..30a24f7 100644
--- a/semantics.c
+++ b/semantics.c
@@ -3,7 +3,9 @@
#include <string.h>
#include <stdio.h>
#include "semantics.h"
+#include "ast.h"
#define NEW(type) ((type *)malloc(sizeof(type)))
+#define CHECK_TYPE(p, _type) assert(p->type == _type)
#ifdef CIBIC_DEBUG
CTable_t ctable_create(Hashfunc_t hfunc, Printfunc_t pfunc) {
@@ -199,5 +201,183 @@ CType_t ctype_create(const char *name, int type) {
CType *ct = NEW(CType);
ct->name = name;
ct->type = type;
+ switch (type)
+ {
+ case CINT: ct->size = INT_SIZE; break;
+ case CCHAR: ct->size = CHAR_SIZE; break;
+ case CVOID: ct->size = 0; break;
+ }
+ return ct;
+}
+
+
+CTable_t semantics_fields(CNode *);
+CType *semantics_type_spec(CNode *p) {
+ CHECK_TYPE(p, TYPE_SPEC);
+ CType *type;
+ switch (p->rec.subtype)
+ {
+ case KW_VOID: type = ctype_create("", CVOID); break;
+ case KW_CHAR: type = ctype_create("", CCHAR); break;
+ case KW_INT: type = ctype_create("", CINT); break;
+ case KW_STRUCT: case KW_UNION:
+ {
+ CNode *id = p->chd,
+ *fields = p->chd->next;
+ type = ctype_create(id->type == NOP ? "" : id->rec.strval,
+ p->rec.subtype == KW_STRUCT ? CSTRUCT : CUNION);
+ if (fields->type == NOP)
+ type->rec.fields = NULL;
+ else
+ type->rec.fields = semantics_fields(fields);
+ }
+ break;
+ default: assert(0);
+ }
+ return type;
+}
+
+CVar *semantics_declr(CNode *, CType *);
+CVar *semantics_p_decl(CNode *p) {
+ CHECK_TYPE(p, PLAIN_DECL);
+ return semantics_declr(p->chd->next,
+ semantics_type_spec(p->chd));
+}
+
+CVar *semantics_params(CNode *p) {
+ CHECK_TYPE(p, PARAMS);
+ p = p->chd;
+ if (p->type == NOP) return NULL; /* void arguments */
+ CVar *params = semantics_p_decl(p);
+ for (; p; p = p->next)
+ {
+ CVar *t = semantics_p_decl(p);
+ t->next = params;
+ params = t;
+ }
+ return params;
+}
+
+CVar *semantics_p_declr(CNode *p, CType *type_spec) {
+ /* deal with pointer prefix */
+ CNode *t;
+ CType *tt, *ptype;
+ const char *name;
+ if (p->type == ID)
+ {
+ ptype = type_spec; /* filled by type spec */
+ name = p->rec.strval;
+ }
+ else
+ {
+ ptype = ctype_create("", CPTR); /* pointer */
+ for (t = p, tt = ptype;; t = t->chd)
+ {
+ if (t->chd->type == ID)
+ {
+ tt->rec.ref = type_spec; /* filled by type spec */
+ name = t->chd->rec.strval;
+ break;
+ }
+ tt->rec.ref = ctype_create("", CPTR);
+ tt = tt->rec.ref;
+ }
+ }
+ return cvar_create(name, ptype);
+}
+
+CVar *semantics_declr(CNode *p, CType *type_spec) {
+ CType *type;
+ CHECK_TYPE(p, DECLR);
+ const char *name;
+ switch (p->rec.subtype)
+ {
+ case DECLR_FUNC:
+ {
+ CVar *p_declr = semantics_p_declr(p->chd, type_spec);
+ type = ctype_create("", CFUNC); /* function declr */
+ type->rec.func.params = semantics_params(p->chd->next);
+ /* incomplete type */
+ type->rec.func.local = NULL;
+ type->rec.func.ret = p_declr->type;
+ name = p_declr->name;
+ free(p_declr);
+ }
+ break;
+ case DECLR_ARR:
+ {
+ CNode *t;
+ CType *tt;
+ type = ctype_create("", CARR); /* array declr */
+ for (t = p, tt = type;; t = t->chd)
+ {
+ /* TODO: range checking */
+ tt->rec.arr.len = t->chd->next->rec.intval; /* array length */
+ if (t->chd->type == ID || t->chd->rec.subtype == '*')
+ {
+ CVar *p_declr = semantics_p_declr(t->chd, type_spec);
+ tt->rec.arr.elem = p_declr->type;
+ name = p_declr->name;
+ free(p_declr);
+ break;
+ }
+ tt->rec.arr.elem = ctype_create("", CARR);
+ tt = tt->rec.arr.elem;
+ }
+ }
+ break;
+ default: assert(0);
+ }
+ return cvar_create(name, type);
+}
+
+CTable_t semantics_fields(CNode *p) {
+#ifdef CIBIC_DEBUG
+ CTable_t ct = ctable_create(bkdr_hash, cvar_print);
+#else
+ CTable_t ct = ctable_create(bkdr_hash);
+#endif
+ for (p = p->chd; p; p = p->next)
+ {
+ CNode *declr = p->chd->next->chd;
+ for (; declr; declr = declr->next)
+ {
+ CVar *var = semantics_declr(declr,
+ semantics_type_spec(p->chd));
+ /* TODO: conflicts report */
+ ctable_insert(ct, var->name, var, 0);
+ }
+ }
return ct;
}
+
+CVar *semantics_blk(CNode *p, CScope_t scope) {
+}
+
+CType *semantics_func(CNode *p, CScope_t scope) {
+ CHECK_TYPE(p, FUNC_DEF);
+ CNode *chd = p->chd->next;
+ CType *func = ctype_create(chd->rec.strval, CFUNC);
+ chd = chd->next;
+ func->rec.func.ret = semantics_type_spec(p->chd); /* check return type */
+ func->rec.func.params = semantics_params(chd); /* check params */
+ func->rec.func.local = semantics_blk(chd->next, scope); /* check blk */
+ return func;
+}
+
+void semantics_check_(CNode *p, CScope_t scope) {
+ switch (p->type)
+ {
+ case FUNC_DEF: semantics_func(p, scope); break;
+ default: ;
+ }
+}
+
+void semantics_check(CNode *ast) {
+ CScope_t scope = cscope_create();
+ /* add top-level basic types */
+ cscope_push_type(scope, ctype_create("int", CINT));
+ cscope_push_type(scope, ctype_create("char", CCHAR));
+ cscope_push_type(scope, ctype_create("void", CVOID));
+ semantics_check_(ast, scope);
+}
diff --git a/semantics.h b/semantics.h
index 166f9a8..4a53f7b 100644
--- a/semantics.h
+++ b/semantics.h
@@ -1,9 +1,10 @@
#ifndef SEMANTICS_H
#define SEMANTICS_H
#include "const.h"
-#define CIBIC_DEBUG
+typedef struct CNode CNode;
struct CTable;
+typedef struct CTable *CTable_t;
struct CType;
typedef struct CVar{
@@ -24,17 +25,23 @@ typedef struct CType {
CSTRUCT,
CUNION,
CARR,
- CPTR
+ CPTR,
+ CFUNC
} type;
const char *name;
struct CType *next;
union {
- struct CType *fields; /* for a struct or union */
+ CTable_t fields; /* for a struct or union */
struct CType *ref; /* for a pointer */
struct {
struct CType *elem;
int len;
} arr; /* for an array */
+ struct {
+ CVar *params;
+ CVar *local;
+ struct CType *ret;
+ } func; /* for a function */
} rec;
int size; /* memory footprint */
} CType;
@@ -46,7 +53,6 @@ typedef unsigned int (*Hashfunc_t) (const char *);
#ifdef CIBIC_DEBUG
typedef const char *(*Printfunc_t) (void *);
#endif
-typedef struct CTable *CTable_t;
typedef struct CTNode {
const char *key;
@@ -100,4 +106,6 @@ void cscope_debug_print(CScope_t cs);
unsigned int bkdr_hash(const char *str);
const char *cvar_print(void *var);
const char *ctype_print(void *type);
+
+void semantics_check(CNode *ast);
#endif