ref: b95cc0c19c628ad8cf1f0e99548dadaff35a786f
parent: 3ebea5faa5010e59f17ad4df846d0b5440c5f82c
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Jun 8 11:34:01 EDT 2012
Added symbol table The symbol table is a hash table, where collation area is implemented like a double linked list with a dummy header. All the item presents in the table are stored in a single linked list, so it is easy run over the last symbols and remove all of them each time a block ends.
--- a/decl.c
+++ b/decl.c
@@ -6,6 +6,7 @@
#include "tokens.h"
#include "types.h"
#include "syntax.h"
+#include "symbol.h"
char parser_out_home;
@@ -20,8 +21,11 @@
if (accept('(')) {
declarator();
expect(')');
- } else if (accept(IDENTIFIER)) {
- ;
+ } else if (yytoken == IDENTIFIER) {
+ if (yyval.sym && yyval.sym->level == nested_level)
+ error("redeclaration of '%s'", yytext);
+ addsym(yytext, yyhash);
+ next();
} else {
error("expected '(' or identifier before of '%s'", yytext);
}
--- a/expr.c
+++ b/expr.c
@@ -14,6 +14,8 @@
puts("primary");
switch (yytoken) {
case IDENTIFIER:
+ if (!yyval.sym)
+ error("'%s' undeclared", yytext);
case CONSTANT:
case STRING_LITERAL:
next();
--- a/flow.c
+++ b/flow.c
@@ -1,12 +1,10 @@
#include <stdio.h>
+#include "symbol.h"
#include "tokens.h"
#include "syntax.h"
-
-unsigned char nested_level;
-
void stmt(void);
static void do_goto(void)
@@ -131,11 +129,14 @@
{
puts("compound");
if (accept('{')) {
- ++nested_level;
+ struct symctx ctx;
+
+ new_ctx(&ctx);
while (decl())
/* nothing */;
while (!accept('}'))
stmt();
+ del_ctx();
}
puts("leaving compound");
}
--- a/lex.c
+++ b/lex.c
@@ -55,6 +55,7 @@
static struct keyword *khash[NR_KWD_HASH];
static FILE *yyin;
+union yyval yyval;
unsigned char yytoken;
unsigned char yyhash;
char yytext[TOKSIZ_MAX + 1];
@@ -200,6 +201,7 @@
if (!strcmp(kwp->str, yytext))
return kwp->tok;
}
+ yyval.sym = lookupsym(yytext, yyhash);
return IDENTIFIER;
}
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
extern void open_file(const char *file);
extern void init_lex();
+extern void init_symbol();
struct user_opt user_opt;
@@ -15,6 +16,7 @@
int main(int argc, char *argv[])
{
init_lex();
+ init_symbol();
open_file(NULL);
for (next(); yytoken != EOFTOK; decl())
/* nothing */;
--- a/symbol.c
+++ b/symbol.c
@@ -1,99 +1,87 @@
-
+#include <stdlib.h>
#include <string.h>
#include "symbol.h"
+#define xmalloc malloc
+#define xstrdup strdup
#define NR_SYM_HASH 32
struct symhash {
- struct symbol *buf[NR_SYM_HASH];
+ struct symbol buf[NR_SYM_HASH];
struct symbol *top;
};
-struct symctx {
- struct symbol *siden;
- struct symbol *sstruct;
- struct symbol *sgoto;
- struct symctx *next;
-};
+unsigned char nested_level;
+static struct symhash iden_hash;
+static struct symctx ctx_base;
+static struct symctx *ctx_head = &ctx_base;
+static void del_hash_ctx(struct symhash *htable, struct symbol *lim)
+{
+ register struct symbol *bp;
+ for (bp = htable->top; bp && bp != lim; bp = bp->next) {
+ register struct symbol *next = bp->h_next, *prev = bp->h_prev;
+ prev->h_next = next;
+ next->h_prev = prev;
+ free(bp->str);
+ free(bp);
+ }
+}
-static struct symctx global_ctx;
-static struct symctx *ctxp = &global_ctx;
-struct symhash *siden = (struct symhash *) {0};
-struct symhash *sgoto = (struct symhash *) {0};
-
-struct symhash *sstruct = (struct symhash *) {0};
-
-
-
-
-
void new_ctx(struct symctx *ctx)
{
- ctx->siden = siden->top;
- ctx->sstruct = sstruct->top;
- ctx->sgoto = sgoto->top;
- ctx->next = ctxp;
- ctxp = ctx;
+ ++nested_level;
+ ctx->next = ctx_head;
+ ctx_head = ctx;
+ ctx->iden = iden_hash.top;
}
-
-/*
- * WARNING: This function is not portable and waits that incremental calls
- * to alloca return decremented address
- */
-static void del_hash_ctx(struct symhash *h, struct symbol *const top)
+void del_ctx(void)
{
- register struct symbol **bp;
- static struct symbol **lim;
-
- lim = h->buf + NR_SYM_HASH;
- for (bp = h->buf; bp < lim; bp++) {
- register struct symbol *aux;
- for (aux = *bp; aux < top; *bp = aux = aux->next) {
- if (aux == h->top)
- h->top = aux;
- }
- }
+ --nested_level;
+ del_hash_ctx(&iden_hash, ctx_head->next->iden);
}
-
-void del_ctx(void)
+struct symbol *addsym(const char *s, unsigned char key)
{
- del_hash_ctx(siden, ctxp->siden);
- del_hash_ctx(sstruct, ctxp->sstruct);
- del_hash_ctx(sgoto, ctxp->sgoto); /* TODO: correct handling in goto */
-}
+ static struct symbol *head;
+ register struct symbol *sym, *next;
+ sym = xmalloc(sizeof(*sym));
+ sym->str = xstrdup(s);
+ sym->next = iden_hash.top;
+ iden_hash.top = sym;
+ head = &iden_hash.buf[key], next = head->h_next;
+ sym->h_next = next;
+ sym->h_prev = next->h_prev;
+ head->h_next = sym;
+ next->h_prev = sym;
-struct symbol *addsym(struct symhash *h,
- struct symbol *sym, unsigned char hash)
-
-{
- static unsigned char key;
-
- key = hash % NR_SYM_HASH;
- h->top = sym;
- sym->next = h->buf[key];
- return h->buf[key] = sym;
+ return sym;
}
-
-
-
-struct symbol *findsym(struct symhash *h, char *s, unsigned char hash)
+struct symbol *lookupsym(char *s, unsigned char key)
{
- register struct symbol *bp;
+ register struct symbol *bp, *head;
- for (bp = h->buf[hash % NR_SYM_HASH]; bp; bp = bp->next) {
+ head = &iden_hash.buf[key];
+ for (bp = head->h_next; bp != head; bp = bp->next) {
if (!strcmp(bp->str, s))
return bp;
}
return NULL;
+}
+
+void init_symbol(void)
+{
+ struct symbol *bp;
+
+ for (bp = iden_hash.buf; bp < &iden_hash.buf[NR_SYM_HASH]; ++bp)
+ bp->h_next = bp->h_prev = bp;
}
--- a/symbol.h
+++ b/symbol.h
@@ -8,15 +8,22 @@
struct symbol {
char *str;
+ unsigned char level;
struct type *type;
struct symbol *next;
+ struct symbol *h_next, *h_prev;
};
-struct symhash;
-extern struct symhash *siden, *sgoto, *sstruct;
+struct symctx {
+ struct symbol *iden;
+ struct symctx *next;
+};
-struct symbol *
-addsym(struct symhash *h, struct symbol *sym, unsigned char hash);
+
+extern void new_ctx(struct symctx *ctx);
+extern void del_ctx(void);
+extern struct symbol *addsym(const char *s, unsigned char key);
+extern struct symbol *lookupsym(char *s, unsigned char key);
#endif
--- a/tokens.h
+++ b/tokens.h
@@ -37,10 +37,10 @@
union yyval {
struct symbol *sym;
-} yyval;
+};
-
+extern union yyval yyval;
extern char yytext[];
extern unsigned char yyhash;
extern size_t yylen;