Initial revision
This commit is contained in:
239
util/LLgen/src/name.c
Normal file
239
util/LLgen/src/name.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* (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;
|
||||
}
|
||||
Reference in New Issue
Block a user