20 |
|
|
21 |
|
|
22 |
#include "system.h" |
#include "system.h" |
23 |
#include "quotearg.h" |
|
24 |
#include "hash.h" |
#include <hash.h> |
25 |
|
#include <quotearg.h> |
26 |
|
|
27 |
#include "complain.h" |
#include "complain.h" |
|
#include "symtab.h" |
|
28 |
#include "gram.h" |
#include "gram.h" |
29 |
|
#include "symtab.h" |
30 |
|
|
31 |
/*------------------------. |
/*------------------------. |
32 |
| Distinguished symbols. | |
| Distinguished symbols. | |
33 |
`------------------------*/ |
`------------------------*/ |
34 |
|
|
35 |
symbol_t *errtoken = NULL; |
symbol *errtoken = NULL; |
36 |
symbol_t *undeftoken = NULL; |
symbol *undeftoken = NULL; |
37 |
symbol_t *endtoken = NULL; |
symbol *endtoken = NULL; |
38 |
symbol_t *accept = NULL; |
symbol *accept = NULL; |
39 |
symbol_t *startsymbol = NULL; |
symbol *startsymbol = NULL; |
40 |
location_t startsymbol_location; |
location startsymbol_location; |
41 |
|
|
42 |
/*---------------------------------. |
/*---------------------------------. |
43 |
| Create a new symbol, named TAG. | |
| Create a new symbol, named TAG. | |
44 |
`---------------------------------*/ |
`---------------------------------*/ |
45 |
|
|
46 |
static symbol_t * |
static symbol * |
47 |
symbol_new (struniq_t tag, location_t location) |
symbol_new (uniqstr tag, location loc) |
48 |
{ |
{ |
49 |
symbol_t *res = XMALLOC (symbol_t, 1); |
symbol *res = XMALLOC (symbol, 1); |
50 |
|
|
51 |
struniq_assert (tag); |
uniqstr_assert (tag); |
52 |
res->tag = tag; |
res->tag = tag; |
53 |
res->location = location; |
res->location = loc; |
54 |
|
|
55 |
res->type_name = NULL; |
res->type_name = NULL; |
56 |
res->destructor = NULL; |
res->destructor = NULL; |
69 |
} |
} |
70 |
|
|
71 |
|
|
72 |
/*------------------------------------------------------------------. |
/*-----------------------------------------------------------------. |
73 |
| Set the TYPE_NAME associated to SYMBOL. Does nothing if passed 0 | |
| Set the TYPE_NAME associated with SYM. Does nothing if passed 0 | |
74 |
| as TYPE_NAME. | |
| as TYPE_NAME. | |
75 |
`------------------------------------------------------------------*/ |
`-----------------------------------------------------------------*/ |
76 |
|
|
77 |
void |
void |
78 |
symbol_type_set (symbol_t *symbol, struniq_t type_name, location_t location) |
symbol_type_set (symbol *sym, uniqstr type_name, location loc) |
79 |
{ |
{ |
80 |
if (type_name) |
if (type_name) |
81 |
{ |
{ |
82 |
if (symbol->type_name) |
if (sym->type_name) |
83 |
complain_at (location, |
complain_at (loc, _("type redeclaration for %s"), sym->tag); |
84 |
_("type redeclaration for %s"), symbol->tag); |
uniqstr_assert (type_name); |
85 |
struniq_assert (type_name); |
sym->type_name = type_name; |
|
symbol->type_name = type_name; |
|
86 |
} |
} |
87 |
} |
} |
88 |
|
|
89 |
|
|
90 |
/*-------------------------------------------------------------------. |
/*------------------------------------------------------------------. |
91 |
| Set the DESTRUCTOR associated to SYMBOL. Do nothing if passed 0. | |
| Set the DESTRUCTOR associated with SYM. Do nothing if passed 0. | |
92 |
`-------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
93 |
|
|
94 |
void |
void |
95 |
symbol_destructor_set (symbol_t *symbol, char *destructor, location_t location) |
symbol_destructor_set (symbol *sym, char *destructor, location loc) |
96 |
{ |
{ |
97 |
if (destructor) |
if (destructor) |
98 |
{ |
{ |
99 |
if (symbol->destructor) |
if (sym->destructor) |
100 |
complain_at (location, |
complain_at (loc, _("%s redeclaration for %s"), |
101 |
_("%s redeclaration for %s"), |
"%destructor", sym->tag); |
102 |
"%destructor", symbol->tag); |
sym->destructor = destructor; |
103 |
symbol->destructor = destructor; |
sym->destructor_location = loc; |
|
symbol->destructor_location = location; |
|
104 |
} |
} |
105 |
} |
} |
106 |
|
|
107 |
|
|
108 |
/*----------------------------------------------------------------. |
/*---------------------------------------------------------------. |
109 |
| Set the PRINTER associated to SYMBOL. Do nothing if passed 0. | |
| Set the PRINTER associated with SYM. Do nothing if passed 0. | |
110 |
`----------------------------------------------------------------*/ |
`---------------------------------------------------------------*/ |
111 |
|
|
112 |
void |
void |
113 |
symbol_printer_set (symbol_t *symbol, char *printer, location_t location) |
symbol_printer_set (symbol *sym, char *printer, location loc) |
114 |
{ |
{ |
115 |
if (printer) |
if (printer) |
116 |
{ |
{ |
117 |
if (symbol->printer) |
if (sym->printer) |
118 |
complain_at (location, |
complain_at (loc, _("%s redeclaration for %s"), |
119 |
_("%s redeclaration for %s"), |
"%printer", sym->tag); |
120 |
"%printer", symbol->tag); |
sym->printer = printer; |
121 |
symbol->printer = printer; |
sym->printer_location = loc; |
|
symbol->printer_location = location; |
|
122 |
} |
} |
123 |
} |
} |
124 |
|
|
125 |
|
|
126 |
/*------------------------------------------------------------------. |
/*-----------------------------------------------------------------. |
127 |
| Set the PRECEDENCE associated to SYMBOL. Does nothing if invoked | |
| Set the PRECEDENCE associated with SYM. Does nothing if invoked | |
128 |
| with UNDEF_ASSOC as ASSOC. | |
| with UNDEF_ASSOC as ASSOC. | |
129 |
`------------------------------------------------------------------*/ |
`-----------------------------------------------------------------*/ |
130 |
|
|
131 |
void |
void |
132 |
symbol_precedence_set (symbol_t *symbol, |
symbol_precedence_set (symbol *sym, int prec, assoc a, location loc) |
|
int prec, assoc_t assoc, location_t location) |
|
133 |
{ |
{ |
134 |
if (assoc != undef_assoc) |
if (a != undef_assoc) |
135 |
{ |
{ |
136 |
if (symbol->prec != 0) |
if (sym->prec != 0) |
137 |
complain_at (location, |
complain_at (loc, _("redefining precedence of %s"), sym->tag); |
138 |
_("redefining precedence of %s"), |
sym->prec = prec; |
139 |
symbol->tag); |
sym->assoc = a; |
|
symbol->prec = prec; |
|
|
symbol->assoc = assoc; |
|
140 |
} |
} |
141 |
|
|
142 |
/* Only terminals have a precedence. */ |
/* Only terminals have a precedence. */ |
143 |
symbol_class_set (symbol, token_sym, location); |
symbol_class_set (sym, token_sym, loc); |
144 |
} |
} |
145 |
|
|
146 |
|
|
147 |
/*-------------------------------------. |
/*------------------------------------. |
148 |
| Set the CLASS associated to SYMBOL. | |
| Set the CLASS associated with SYM. | |
149 |
`-------------------------------------*/ |
`------------------------------------*/ |
150 |
|
|
151 |
void |
void |
152 |
symbol_class_set (symbol_t *symbol, symbol_class class, location_t location) |
symbol_class_set (symbol *sym, symbol_class class, location loc) |
153 |
{ |
{ |
154 |
if (symbol->class != unknown_sym && symbol->class != class) |
if (sym->class != unknown_sym && sym->class != class) |
155 |
complain_at (location, _("symbol %s redefined"), symbol->tag); |
complain_at (loc, _("symbol %s redefined"), sym->tag); |
156 |
|
|
157 |
if (class == nterm_sym && symbol->class != nterm_sym) |
if (class == nterm_sym && sym->class != nterm_sym) |
158 |
symbol->number = nvars++; |
sym->number = nvars++; |
159 |
else if (class == token_sym && symbol->number == NUMBER_UNDEFINED) |
else if (class == token_sym && sym->number == NUMBER_UNDEFINED) |
160 |
symbol->number = ntokens++; |
sym->number = ntokens++; |
161 |
|
|
162 |
symbol->class = class; |
sym->class = class; |
163 |
} |
} |
164 |
|
|
165 |
|
|
166 |
/*-------------------------------------------------. |
/*------------------------------------------------. |
167 |
| Set the USER_TOKEN_NUMBER associated to SYMBOL. | |
| Set the USER_TOKEN_NUMBER associated with SYM. | |
168 |
`-------------------------------------------------*/ |
`------------------------------------------------*/ |
169 |
|
|
170 |
void |
void |
171 |
symbol_user_token_number_set (symbol_t *symbol, |
symbol_user_token_number_set (symbol *sym, int user_token_number, location loc) |
|
int user_token_number, location_t location) |
|
172 |
{ |
{ |
173 |
if (symbol->class != token_sym) |
if (sym->class != token_sym) |
174 |
abort (); |
abort (); |
175 |
|
|
176 |
if (symbol->user_token_number != USER_NUMBER_UNDEFINED |
if (sym->user_token_number != USER_NUMBER_UNDEFINED |
177 |
&& symbol->user_token_number != user_token_number) |
&& sym->user_token_number != user_token_number) |
178 |
complain_at (location, _("redefining user token number of %s"), |
complain_at (loc, _("redefining user token number of %s"), sym->tag); |
|
symbol->tag); |
|
179 |
|
|
180 |
symbol->user_token_number = user_token_number; |
sym->user_token_number = user_token_number; |
181 |
/* User defined $end token? */ |
/* User defined $end token? */ |
182 |
if (user_token_number == 0) |
if (user_token_number == 0) |
183 |
{ |
{ |
184 |
endtoken = symbol; |
endtoken = sym; |
185 |
endtoken->number = 0; |
endtoken->number = 0; |
186 |
/* It is always mapped to 0, so it was already counted in |
/* It is always mapped to 0, so it was already counted in |
187 |
NTOKENS. */ |
NTOKENS. */ |
190 |
} |
} |
191 |
|
|
192 |
|
|
193 |
/*------------. |
/*-----------. |
194 |
| Free THIS. | |
| Free SYM. | |
195 |
`------------*/ |
`-----------*/ |
196 |
|
|
197 |
static void |
static void |
198 |
symbol_free (symbol_t *this) |
symbol_free (symbol *sym) |
199 |
{ |
{ |
200 |
free (this); |
free (sym); |
201 |
} |
} |
202 |
|
|
203 |
|
|
204 |
/*-----------------------------------------------------------. |
/*----------------------------------------------------------. |
205 |
| If THIS is not defined, report an error, and consider it a | |
| If SYM is not defined, report an error, and consider it a | |
206 |
| nonterminal. | |
| nonterminal. | |
207 |
`-----------------------------------------------------------*/ |
`----------------------------------------------------------*/ |
208 |
|
|
209 |
static bool |
static bool |
210 |
symbol_check_defined (symbol_t *this) |
symbol_check_defined (symbol *sym) |
211 |
{ |
{ |
212 |
if (this->class == unknown_sym) |
if (sym->class == unknown_sym) |
213 |
{ |
{ |
214 |
complain_at |
complain_at |
215 |
(this->location, |
(sym->location, |
216 |
_("symbol %s is used, but is not defined as a token and has no rules"), |
_("symbol %s is used, but is not defined as a token and has no rules"), |
217 |
this->tag); |
sym->tag); |
218 |
this->class = nterm_sym; |
sym->class = nterm_sym; |
219 |
this->number = nvars++; |
sym->number = nvars++; |
220 |
} |
} |
221 |
|
|
222 |
return true; |
return true; |
223 |
} |
} |
224 |
|
|
225 |
|
|
226 |
/*-------------------------------------------------------------------. |
/*------------------------------------------------------------------. |
227 |
| Declare the new SYMBOL. Make it an alias of SYMVAL, and type them | |
| Declare the new symbol SYM. Make it an alias of SYMVAL, and type | |
228 |
| with TYPENAME. | |
| them with TYPENAME. | |
229 |
`-------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
230 |
|
|
231 |
void |
void |
232 |
symbol_make_alias (symbol_t *symbol, symbol_t *symval, location_t loc) |
symbol_make_alias (symbol *sym, symbol *symval, location loc) |
233 |
{ |
{ |
234 |
if (symval->alias) |
if (symval->alias) |
235 |
warn_at (loc, _("symbol `%s' used more than once as a literal string"), |
warn_at (loc, _("symbol `%s' used more than once as a literal string"), |
236 |
symval->tag); |
symval->tag); |
237 |
else if (symbol->alias) |
else if (sym->alias) |
238 |
warn_at (loc, _("symbol `%s' given more than one literal string"), |
warn_at (loc, _("symbol `%s' given more than one literal string"), |
239 |
symbol->tag); |
sym->tag); |
240 |
else |
else |
241 |
{ |
{ |
242 |
symval->class = token_sym; |
symval->class = token_sym; |
243 |
symval->user_token_number = symbol->user_token_number; |
symval->user_token_number = sym->user_token_number; |
244 |
symbol->user_token_number = USER_NUMBER_ALIAS; |
sym->user_token_number = USER_NUMBER_ALIAS; |
245 |
symval->alias = symbol; |
symval->alias = sym; |
246 |
symbol->alias = symval; |
sym->alias = symval; |
247 |
/* symbol and symval combined are only one symbol */ |
/* sym and symval combined are only one symbol. */ |
248 |
nsyms--; |
nsyms--; |
249 |
ntokens--; |
ntokens--; |
250 |
if (ntokens != symbol->number && ntokens != symval->number) |
if (ntokens != sym->number && ntokens != symval->number) |
251 |
abort (); |
abort (); |
252 |
symbol->number = symval->number = |
sym->number = symval->number = |
253 |
(symval->number < symbol->number) ? symval->number : symbol->number; |
(symval->number < sym->number) ? symval->number : sym->number; |
254 |
} |
} |
255 |
} |
} |
256 |
|
|
261 |
`---------------------------------------------------------*/ |
`---------------------------------------------------------*/ |
262 |
|
|
263 |
static bool |
static bool |
264 |
symbol_check_alias_consistence (symbol_t *this) |
symbol_check_alias_consistence (symbol *this) |
265 |
{ |
{ |
266 |
/* Check only those who _are_ the aliases. */ |
/* Check only those who _are_ the aliases. */ |
267 |
if (this->alias && this->user_token_number == USER_NUMBER_ALIAS) |
if (this->alias && this->user_token_number == USER_NUMBER_ALIAS) |
301 |
`-------------------------------------------------------------------*/ |
`-------------------------------------------------------------------*/ |
302 |
|
|
303 |
static bool |
static bool |
304 |
symbol_pack (symbol_t *this) |
symbol_pack (symbol *this) |
305 |
{ |
{ |
306 |
if (this->class == nterm_sym) |
if (this->class == nterm_sym) |
307 |
{ |
{ |
345 |
`--------------------------------------------------*/ |
`--------------------------------------------------*/ |
346 |
|
|
347 |
static bool |
static bool |
348 |
symbol_translation (symbol_t *this) |
symbol_translation (symbol *this) |
349 |
{ |
{ |
350 |
/* Non-terminal? */ |
/* Non-terminal? */ |
351 |
if (this->class == token_sym |
if (this->class == token_sym |
375 |
static struct hash_table *symbol_table = NULL; |
static struct hash_table *symbol_table = NULL; |
376 |
|
|
377 |
static bool |
static bool |
378 |
hash_compare_symbol (const symbol_t *m1, const symbol_t *m2) |
hash_compare_symbol (const symbol *m1, const symbol *m2) |
379 |
{ |
{ |
380 |
/* Since tags are unique, we can compare the pointers themselves. */ |
/* Since tags are unique, we can compare the pointers themselves. */ |
381 |
return STRUNIQ_EQ (m1->tag, m2->tag); |
return UNIQSTR_EQ (m1->tag, m2->tag); |
382 |
} |
} |
383 |
|
|
384 |
static unsigned int |
static unsigned int |
385 |
hash_symbol (const symbol_t *m, unsigned int tablesize) |
hash_symbol (const symbol *m, unsigned int tablesize) |
386 |
{ |
{ |
387 |
/* Since tags are unique, we can hash the pointer itself. */ |
/* Since tags are unique, we can hash the pointer itself. */ |
388 |
return ((size_t) m->tag) % tablesize; |
return ((size_t) m->tag) % tablesize; |
409 |
| yet, create it. | |
| yet, create it. | |
410 |
`----------------------------------------------------------------*/ |
`----------------------------------------------------------------*/ |
411 |
|
|
412 |
symbol_t * |
symbol * |
413 |
symbol_get (const char *key, location_t location) |
symbol_get (const char *key, location loc) |
414 |
{ |
{ |
415 |
symbol_t probe; |
symbol probe; |
416 |
symbol_t *entry; |
symbol *entry; |
417 |
|
|
418 |
/* Keep the symbol in a printable form. */ |
/* Keep the symbol in a printable form. */ |
419 |
key = struniq_new (quotearg_style (escape_quoting_style, key)); |
key = uniqstr_new (quotearg_style (escape_quoting_style, key)); |
420 |
*(char const **) &probe.tag = key; |
*(char const **) &probe.tag = key; |
421 |
entry = hash_lookup (symbol_table, &probe); |
entry = hash_lookup (symbol_table, &probe); |
422 |
|
|
423 |
if (!entry) |
if (!entry) |
424 |
{ |
{ |
425 |
/* First insertion in the hash. */ |
/* First insertion in the hash. */ |
426 |
entry = symbol_new (key, location); |
entry = symbol_new (key, loc); |
427 |
hash_insert (symbol_table, entry); |
hash_insert (symbol_table, entry); |
428 |
} |
} |
429 |
return entry; |
return entry; |
435 |
| user's names. | |
| user's names. | |
436 |
`------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
437 |
|
|
438 |
symbol_t * |
symbol * |
439 |
dummy_symbol_get (location_t location) |
dummy_symbol_get (location loc) |
440 |
{ |
{ |
441 |
/* Incremented for each generated symbol. */ |
/* Incremented for each generated symbol. */ |
442 |
static int dummy_count = 0; |
static int dummy_count = 0; |
443 |
static char buf[256]; |
static char buf[256]; |
444 |
|
|
445 |
symbol_t *sym; |
symbol *sym; |
446 |
|
|
447 |
sprintf (buf, "@%d", ++dummy_count); |
sprintf (buf, "@%d", ++dummy_count); |
448 |
sym = symbol_get (buf, location); |
sym = symbol_get (buf, loc); |
449 |
sym->class = nterm_sym; |
sym->class = nterm_sym; |
450 |
sym->number = nvars++; |
sym->number = nvars++; |
451 |
return sym; |
return sym; |
505 |
max_user_token_number = 0; |
max_user_token_number = 0; |
506 |
for (i = 0; i < ntokens; ++i) |
for (i = 0; i < ntokens; ++i) |
507 |
{ |
{ |
508 |
symbol_t *this = symbols[i]; |
symbol *this = symbols[i]; |
509 |
if (this->user_token_number != USER_NUMBER_UNDEFINED) |
if (this->user_token_number != USER_NUMBER_UNDEFINED) |
510 |
{ |
{ |
511 |
if (this->user_token_number > max_user_token_number) |
if (this->user_token_number > max_user_token_number) |
526 |
|
|
527 |
for (i = 0; i < ntokens; ++i) |
for (i = 0; i < ntokens; ++i) |
528 |
{ |
{ |
529 |
symbol_t *this = symbols[i]; |
symbol *this = symbols[i]; |
530 |
if (this->user_token_number == USER_NUMBER_UNDEFINED) |
if (this->user_token_number == USER_NUMBER_UNDEFINED) |
531 |
this->user_token_number = ++max_user_token_number; |
this->user_token_number = ++max_user_token_number; |
532 |
if (this->user_token_number > max_user_token_number) |
if (this->user_token_number > max_user_token_number) |
533 |
max_user_token_number = this->user_token_number; |
max_user_token_number = this->user_token_number; |
534 |
} |
} |
535 |
|
|
536 |
token_translations = XCALLOC (symbol_number_t, max_user_token_number + 1); |
token_translations = XCALLOC (symbol_number, max_user_token_number + 1); |
537 |
|
|
538 |
/* Initialize all entries for literal tokens to 2, the internal |
/* Initialize all entries for literal tokens to 2, the internal |
539 |
token number for $undefined, which represents all invalid inputs. |
token number for $undefined, which represents all invalid inputs. |
552 |
void |
void |
553 |
symbols_pack (void) |
symbols_pack (void) |
554 |
{ |
{ |
555 |
symbols = XCALLOC (symbol_t *, nsyms); |
symbols = XCALLOC (symbol *, nsyms); |
556 |
|
|
557 |
symbols_do (symbol_check_alias_consistence, NULL); |
symbols_do (symbol_check_alias_consistence, NULL); |
558 |
symbols_do (symbol_pack, NULL); |
symbols_do (symbol_pack, NULL); |