ack/util/LLgen/src/name.c
1984-10-08 14:14:53 +00:00

239 lines
4.8 KiB
C

/*
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
*
* This product is part of the Amsterdam Compiler Kit.
*
* Permission to use, sell, duplicate or disclose this software must be
* obtained in writing. Requests for such permissions may be sent to
*
* Dr. Andrew S. Tanenbaum
* Wiskundig Seminarium
* Vrije Universiteit
* Postbox 7161
* 1007 MC Amsterdam
* The Netherlands
*
*/
/*
* L L G E N
*
* An Extended LL(1) Parser Generator
*
* Author : Ceriel J.H. Jacobs
*/
/*
* name.c
* Defines the symboltable search routine and an initialising routine
*/
# include "types.h"
# include "tunable.h"
# include "extern.h"
# include "assert.h"
# include "io.h"
static string rcsid = "$Header$";
# define HASHSIZE 128
static char name[NAMESZ]; /* space for names */
static int iname; /* index in nametable */
static p_entry h_root[HASHSIZE]; /* hash table */
static string e_literal = "Illegal literal";
/* Defined in this file are: */
extern string store();
extern name_init();
STATIC int hash();
extern t_gram search();
string
store(s) register string s; {
/*
* Store a string s in the name table
*/
register string t,u;
u = t = &name[iname];
do { if (u > &name[NAMESZ-1]) fatal(linecount,"name table overflow");
else *u++ = *s;
} while (*s++);
iname = u - name;
return t;
}
name_init() {
/*
* Initialise hash-table and enter special terminal EOFILE
*/
register p_entry *p;
t_gram search();
for(p = h_root; p<= &h_root[HASHSIZE-1]; p++) *p = 0;
search(TERMINAL,"EOFILE",ENTERING);
}
STATIC int
hash(str) string str; {
/*
* Compute the hash for string str
*/
register i;
register string l;
l = str;
i = 0;
while (*l != '\0') i += *l++ & 0377;
i += l - str;
return i % HASHSIZE;
}
t_gram
search(type,str,option) register string str; {
/*
* Search for object str.
* It has type UNKNOWN, LITERAL, TERMINAL or NONTERM.
* option can be ENTERING, JUSTLOOKING or BOTH.
*/
register int val;
register p_entry p;
t_gram r;
register int i;
g_init(&r);
g_setcont(&r,UNDEFINED);
r.g_lineno = linecount;
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)) {
val = p - h_entry;
if (type == LITERAL &&
(val >= NTERMINALS || p->h_num >= 0400)) continue;
if (val>=NTERMINALS) {
/* Should be a nonterminal */
if (type == TERMINAL) {
error(linecount,
"%s : terminal expected",
str);
}
g_settype(&r,NONTERM);
g_setnont(&r,val - NTERMINALS);
} else {
if (type != LITERAL && p->h_num < 0400) {
continue;
}
if (type == NONTERM) {
error(linecount,
"%s : nonterminal expected",
str);
continue;
}
g_setnont(&r, val);
g_settype(&r, TERMINAL);
}
if (option==ENTERING) {
error(linecount,
"%s : already defined",str);
}
return r;
}
}
if (option == JUSTLOOKING) return r;
if (type == TERMINAL || type == LITERAL) {
if (nterminals == NTERMINALS) {
fatal(linecount,"too many terminals");
}
p = &h_entry[nterminals];
} else {
/*
* type == NONTERM || type == UNKNOWN
* UNKNOWN and not yet declared means : NONTERM
*/
if (nnonterms == NNONTERMS) {
fatal(linecount,"too many nonterminals");
}
p = &h_entry[NTERMINALS+nnonterms];
}
p->h_name = store(str);
p->h_next = h_root[i];
h_root[i] = p;
if (type == NONTERM || type == UNKNOWN) {
register p_nont q;
q = &nonterms[nnonterms];
q->n_rule = 0;
q->n_string = f_input;
q->n_follow = 0;
q->n_flags = 0;
q->n_contains = 0;
p->h_num = 0;
g_settype(&r, NONTERM);
g_setnont(&r, nnonterms);
nnonterms++;
return r;
}
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);
}
p->h_num = val;
} else {
/*
* Here, type = TERMINAL
*/
p->h_num = assval++;
}
g_settype(&r, TERMINAL);
g_setnont(&r, nterminals);
nterminals++;
return r;
}