/* * (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; }