/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". * */ /* * L L G E N * * An Extended LL(1) Parser Generator * * Author : Ceriel J.H. Jacobs */ /* * name.c * Defines the symboltable search routine, a name store routine and an * initialising routine. */ # include "types.h" # include "extern.h" # include "assert.h" # include "io.h" # ifndef NORCSID static string rcsid7 = "$Header$"; # endif # define HASHSIZE 128 # define NMSIZ 2048 /* Room for names allocated NMSIZ bytes at a time */ static char *name, *maxname; static p_entry h_root[HASHSIZE]; /* hash table */ static string e_literal = "Illegal literal"; static p_entry entries, maxentries; static t_info token_info, nont_info; /* Defined in this file are: */ extern string store(); extern name_init(); STATIC int hash(); STATIC p_entry newentry(); extern p_gram search(); p_mem alloc(); p_mem new_mem(); name_init() { token_info.i_esize = sizeof (t_token); token_info.i_incr = 50; nont_info.i_esize = sizeof (t_nont); nont_info.i_incr = 50; search(TERMINAL,"EOFILE",ENTERING); } STATIC p_entry newentry(str, next) string str; p_entry next; { register p_entry p; if ((p = entries) == maxentries) { p = (p_entry) alloc(50 * sizeof(t_entry)); maxentries = p + 50; } entries = p + 1; p->h_name = str; p->h_next = next; p->h_type.g_lineno = linecount; return p; } string store(s) string s; { /* * Store a string s in the name table */ register string s1, t ,u; u = name; t = s; s1 = u; do { if (u >= maxname) { u = alloc(NMSIZ); maxname = u + NMSIZ; t = s; s1 = u; } *u++ = *t; } while (*t++); name = u; return s1; } STATIC int hash(str) string str; { /* * Compute the hash for string str */ register int i; register string l; l = str; i = 0; while (*l != '\0') i += *l++ & 0377; i += l - str; return i % HASHSIZE; } p_gram search(type,str,option) register string str; { /* * Search for object str. * It has type UNKNOWN, LITERAL, TERMINAL or NONTERM. * option can be ENTERING or BOTH (also looking). */ register int val; register p_entry p; register int i; int type1; i = hash(str); /* * Walk hash chain */ for (p = h_root[i]; p != (p_entry) 0; p = p->h_next) { if(!strcmp(p->h_name,str)) { type1 = g_gettype(&(p->h_type)); if (type1 != type) { if (type1 == LITERAL || type == LITERAL) { continue; } if (type != UNKNOWN) { error(linecount, "%s : illegal type", str); continue; } } if (option==ENTERING) { error(linecount, "%s : already defined",str); } p->h_type.g_lineno = linecount; return &(p->h_type); } } p = newentry(store(str), h_root[i]); h_root[i] = p; if (type == TERMINAL || type == LITERAL) { register p_token pt; pt = (p_token) new_mem(&token_info); tokens = (p_token) token_info.i_ptr; pt->t_string = p->h_name; if (type == LITERAL) { if (str[0] == '\\') { /* * Handle escapes in literals */ if (str[2] == '\0') { switch(str[1]) { case 'n' : val = '\n'; break; case 'r' : val = '\r'; break; case 'b' : val = '\b'; break; case 'f' : val = '\f'; break; case 't' : val = '\t'; break; case '\'': val = '\''; break; case '\\': val = '\\'; break; default : error(linecount,e_literal); } } else { /* * Here, str[2] != '\0' */ if (str[1] > '3' || str[1] < '0' || str[2] > '7' || str[2] < '0' || str[3] > '7' || str[3] < '0' || str[4] != '\0') error(linecount,e_literal); val = 64*str[1] - 73*'0' + 8*str[2] + str[3]; } } else { /* * No escape in literal */ if (str[1] == '\0') val = str[0]; else error(linecount,e_literal); } pt->t_tokno = val; g_settype(&(p->h_type), LITERAL); } else { /* * Here, type = TERMINAL */ pt->t_tokno = assval++; g_settype(&(p->h_type), TERMINAL); } g_setcont(&(p->h_type), ntokens); ntokens++; return &(p->h_type); } /* * type == NONTERM || type == UNKNOWN * UNKNOWN and not yet declared means : NONTERM */ { register p_nont q; q = (p_nont) new_mem(&nont_info); nonterms = (p_nont) nont_info.i_ptr; q->n_name = p->h_name; q->n_rule = 0; q->n_lineno = linecount; q->n_string = f_input; q->n_follow = 0; q->n_flags = 0; q->n_contains = 0; g_settype(&(p->h_type), NONTERM); g_setcont(&(p->h_type), nnonterms); g_setnpar(&(p->h_type), 0); nnonterms++; return &(p->h_type); } }