123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
- * For full copyright and restrictions on use see the file COPYING in the top
- * level of the LLgen tree.
- */
- /*
- * 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 <stdlib.h>
- #include <string.h>
- # include "types.h"
- # include "extern.h"
- # include "assert.h"
- # include "io.h"
- #include "LLgen.h"
- # 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: */
- void 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);
- #ifdef NON_CORRECTING
- illegal_gram = search(TERMINAL,"LLILLEGAL",ENTERING);
- #endif
- }
- STATIC p_entry newentry(char *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;
- #ifdef NON_CORRECTING
- p->h_type.g_erroneous = 0;
- #endif
- return p;
- }
- char *store(char *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(char *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 = 0;
- 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, NULL);
- continue;
- }
- else if (type == NONTERM) {
- error(linecount,
- "%s : is already a token",
- str, NULL);
- continue;
- }
- }
- if (option==ENTERING) {
- error(linecount,
- "%s : is already defined",str, NULL);
- }
- 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, NULL, NULL);
- }
- } 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, NULL, NULL);
- 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, NULL, NULL);
- }
- 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);
- }
- }
|