ack/util/LLgen/src/name.c
1987-06-03 19:05:14 +00:00

247 lines
4.8 KiB
C

/*
* (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 == TERMINAL) {
error(linecount,
"%s: is already a nonterminal",
str);
continue;
}
else if (type == NONTERM) {
error(linecount,
"%s : is already a token",
str);
continue;
}
}
if (option==ENTERING) {
error(linecount,
"%s : is 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);
}
}