86 |
return res; |
return res; |
87 |
} |
} |
88 |
|
|
89 |
|
/*------------------------. |
90 |
|
| Operations on buckets. | |
91 |
|
`------------------------*/ |
92 |
|
|
93 |
|
|
94 |
|
/*-----------------------------------------------------------. |
95 |
|
| If THIS is not defined, report an error, and consider it a | |
96 |
|
| nonterminal. | |
97 |
|
`-----------------------------------------------------------*/ |
98 |
|
|
99 |
|
static bool |
100 |
|
bucket_check_defined (bucket *this) |
101 |
|
{ |
102 |
|
if (this->class == unknown_sym) |
103 |
|
{ |
104 |
|
complain |
105 |
|
(_("symbol %s is used, but is not defined as a token and has no rules"), |
106 |
|
this->tag); |
107 |
|
this->class = nterm_sym; |
108 |
|
this->number = nvars++; |
109 |
|
} |
110 |
|
|
111 |
|
return TRUE; |
112 |
|
} |
113 |
|
|
114 |
|
|
115 |
|
/*-------------------------------------------------------------------. |
116 |
|
| Assign a symbol number, and write the definition of the token name | |
117 |
|
| into FDEFINES. Put in SYMBOLS. | |
118 |
|
`-------------------------------------------------------------------*/ |
119 |
|
|
120 |
|
static bool |
121 |
|
bucket_make_alias (bucket *symbol, char *typename) |
122 |
|
{ |
123 |
|
if (symval->alias) |
124 |
|
warn (_("symbol `%s' used more than once as a literal string"), |
125 |
|
symval->tag); |
126 |
|
else if (symbol->alias) |
127 |
|
warn (_("symbol `%s' given more than one literal string"), |
128 |
|
symbol->tag); |
129 |
|
else |
130 |
|
{ |
131 |
|
symval->class = token_sym; |
132 |
|
symval->type_name = typename; |
133 |
|
symval->user_token_number = symbol->user_token_number; |
134 |
|
symbol->user_token_number = SALIAS; |
135 |
|
symval->alias = symbol; |
136 |
|
symbol->alias = symval; |
137 |
|
/* symbol and symval combined are only one symbol */ |
138 |
|
nsyms--; |
139 |
|
ntokens--; |
140 |
|
assert (ntokens == symbol->number || ntokens == symval->number); |
141 |
|
symbol->number = symval->number = |
142 |
|
(symval->number < symbol->number) ? symval->number : symbol->number; |
143 |
|
} |
144 |
|
|
145 |
|
return TRUE; |
146 |
|
} |
147 |
|
|
148 |
|
/*---------------------------------------------------------. |
149 |
|
| Check that THIS, and its alias, have same precedence and | |
150 |
|
| associativity. | |
151 |
|
`---------------------------------------------------------*/ |
152 |
|
|
153 |
|
static bool |
154 |
|
bucket_check_alias_consistence (bucket *this) |
155 |
|
{ |
156 |
|
/* Check only those who _are_ the aliases. */ |
157 |
|
if (this->alias && this->user_token_number == SALIAS) |
158 |
|
{ |
159 |
|
if (this->prec != this->alias->prec) |
160 |
|
{ |
161 |
|
if (this->prec != 0 && this->alias->prec != 0) |
162 |
|
complain (_("conflicting precedences for %s and %s"), |
163 |
|
this->tag, this->alias->tag); |
164 |
|
if (this->prec != 0) |
165 |
|
this->alias->prec = this->prec; |
166 |
|
else |
167 |
|
this->prec = this->alias->prec; |
168 |
|
} |
169 |
|
|
170 |
|
if (this->assoc != this->alias->assoc) |
171 |
|
{ |
172 |
|
if (this->assoc != 0 && this->alias->assoc != 0) |
173 |
|
complain (_("conflicting assoc values for %s and %s"), |
174 |
|
this->tag, this->alias->tag); |
175 |
|
if (this->assoc != 0) |
176 |
|
this->alias->assoc = this->assoc; |
177 |
|
else |
178 |
|
this->assoc = this->alias->assoc; |
179 |
|
} |
180 |
|
} |
181 |
|
return TRUE; |
182 |
|
} |
183 |
|
|
184 |
|
|
185 |
|
/*-------------------------------------------------------------------. |
186 |
|
| Assign a symbol number, and write the definition of the token name | |
187 |
|
| into FDEFINES. Put in SYMBOLS. | |
188 |
|
`-------------------------------------------------------------------*/ |
189 |
|
|
190 |
|
static bool |
191 |
|
bucket_pack (bucket *this) |
192 |
|
{ |
193 |
|
if (getenv ("DEBUG")) |
194 |
|
fprintf (stderr, "Packing %s, %s, number = %d\n", |
195 |
|
this->tag, |
196 |
|
this->class == nterm_sym ? "nterm" : "TERM", |
197 |
|
this->number); |
198 |
|
if (this->class == nterm_sym) |
199 |
|
{ |
200 |
|
this->number += ntokens; |
201 |
|
} |
202 |
|
else if (this->alias) |
203 |
|
{ |
204 |
|
/* This symbol and its alias are a single token defn. |
205 |
|
Allocate a tokno, and assign to both check agreement of |
206 |
|
prec and assoc fields and make both the same */ |
207 |
|
if (this->number == -1) |
208 |
|
{ |
209 |
|
if (this == eoftoken || this->alias == eoftoken) |
210 |
|
this->number = this->alias->number = 0; |
211 |
|
else |
212 |
|
{ |
213 |
|
assert (this->alias->number != -1); |
214 |
|
this->number = this->alias->number; |
215 |
|
} |
216 |
|
} |
217 |
|
/* Do not do processing below for SALIASs. */ |
218 |
|
if (this->user_token_number == SALIAS) |
219 |
|
return TRUE; |
220 |
|
} |
221 |
|
else /* this->class == token_sym */ |
222 |
|
{ |
223 |
|
assert (this->number != -1); |
224 |
|
} |
225 |
|
|
226 |
|
if (getenv ("DEBUG")) |
227 |
|
fprintf (stderr, "Setting %d = %s\n", this->number, this->tag); |
228 |
|
symbols[this->number] = this; |
229 |
|
return TRUE; |
230 |
|
} |
231 |
|
|
232 |
|
|
233 |
|
|
234 |
|
|
235 |
|
/*--------------------------------------------------. |
236 |
|
| Put THIS in TOKEN_TRANSLATIONS if it is a token. | |
237 |
|
`--------------------------------------------------*/ |
238 |
|
|
239 |
|
static bool |
240 |
|
bucket_translation (bucket *this) |
241 |
|
{ |
242 |
|
if (getenv ("DEBUG")) |
243 |
|
fprintf (stderr, "Considering Setting UserVal %s = %d (val = %d)\n", |
244 |
|
this->tag, this->user_token_number, this->number); |
245 |
|
|
246 |
|
/* Non-terminal? */ |
247 |
|
if (this->class == token_sym |
248 |
|
&& this->user_token_number != SALIAS) |
249 |
|
{ |
250 |
|
/* A token which translation has already been set? */ |
251 |
|
if (token_translations[this->user_token_number] != 2) |
252 |
|
complain (_("tokens %s and %s both assigned number %d"), |
253 |
|
symbols[token_translations[this->user_token_number]]->tag, |
254 |
|
this->tag, this->user_token_number); |
255 |
|
|
256 |
|
if (getenv ("DEBUG")) |
257 |
|
fprintf (stderr, "Setting UserVal %s = %d (val = %d)\n", |
258 |
|
this->tag, this->user_token_number, this->number); |
259 |
|
token_translations[this->user_token_number] = this->number; |
260 |
|
} |
261 |
|
|
262 |
|
return TRUE; |
263 |
|
} |
264 |
|
|
265 |
|
|
266 |
/*===================\ |
/*===================\ |
706 |
} |
} |
707 |
else if (token == tok_identifier && *symval->tag == '\"' && symbol) |
else if (token == tok_identifier && *symval->tag == '\"' && symbol) |
708 |
{ |
{ |
709 |
if (symval->alias) |
bucket_make_alias (symbol, typename); |
|
warn (_("symbol `%s' used more than once as a literal string"), |
|
|
symval->tag); |
|
|
else if (symbol->alias) |
|
|
warn (_("symbol `%s' given more than one literal string"), |
|
|
symbol->tag); |
|
|
else |
|
|
{ |
|
|
symval->class = token_sym; |
|
|
symval->type_name = typename; |
|
|
symval->user_token_number = symbol->user_token_number; |
|
|
symbol->user_token_number = SALIAS; |
|
|
symval->alias = symbol; |
|
|
symbol->alias = symval; |
|
|
/* symbol and symval combined are only one symbol */ |
|
|
nsyms--; |
|
|
} |
|
710 |
symbol = NULL; |
symbol = NULL; |
711 |
} |
} |
712 |
else if (token == tok_identifier) |
else if (token == tok_identifier) |
719 |
symbol->class = what_is; |
symbol->class = what_is; |
720 |
if (what_is == nterm_sym && oldclass != nterm_sym) |
if (what_is == nterm_sym && oldclass != nterm_sym) |
721 |
symbol->number = nvars++; |
symbol->number = nvars++; |
722 |
|
if (what_is == token_sym && symbol->number == -1) |
723 |
|
{ |
724 |
|
symbol->number = ntokens++; |
725 |
|
if (getenv ("DEBUG")) |
726 |
|
fprintf (stderr, "Set %s to %d\n", |
727 |
|
symbol->tag, symbol->number); |
728 |
|
} |
729 |
|
|
730 |
if (typename) |
if (typename) |
731 |
{ |
{ |
740 |
symbol->user_token_number = numval; |
symbol->user_token_number = numval; |
741 |
/* User defined EOF token? */ |
/* User defined EOF token? */ |
742 |
if (numval == 0) |
if (numval == 0) |
743 |
eoftoken = symbol; |
{ |
744 |
|
eoftoken = symbol; |
745 |
|
eoftoken->number = 0; |
746 |
|
/* It is always mapped to 0, so it was already counted in |
747 |
|
NTOKENS. */ |
748 |
|
--ntokens; |
749 |
|
} |
750 |
} |
} |
751 |
else |
else |
752 |
{ |
{ |
875 |
symval->assoc = assoc; |
symval->assoc = assoc; |
876 |
if (symval->class == nterm_sym) |
if (symval->class == nterm_sym) |
877 |
complain (_("symbol %s redefined"), symval->tag); |
complain (_("symbol %s redefined"), symval->tag); |
878 |
symval->class = token_sym; |
if (symval->number == -1) |
879 |
|
{ |
880 |
|
symval->number = ntokens++; |
881 |
|
symval->class = token_sym; |
882 |
|
} |
883 |
if (name) |
if (name) |
884 |
{ /* record the type, if one is specified */ |
{ /* record the type, if one is specified */ |
885 |
if (symval->type_name == NULL) |
if (symval->type_name == NULL) |
896 |
} |
} |
897 |
else |
else |
898 |
{ |
{ |
899 |
complain (_ |
complain |
900 |
("invalid text (%s) - number should be after identifier"), |
(_("invalid text (%s) - number should be after identifier"), |
901 |
token_buffer); |
token_buffer); |
902 |
skip_to_char ('%'); |
skip_to_char ('%'); |
903 |
} |
} |
904 |
break; |
break; |
1249 |
case tok_stropt: |
case tok_stropt: |
1250 |
case tok_intopt: |
case tok_intopt: |
1251 |
case tok_obsolete: |
case tok_obsolete: |
1252 |
abort (); |
assert (0); |
1253 |
break; |
break; |
1254 |
|
|
1255 |
case tok_illegal: |
case tok_illegal: |
1407 |
bucket *lhs = NULL; |
bucket *lhs = NULL; |
1408 |
symbol_list *p = NULL; |
symbol_list *p = NULL; |
1409 |
symbol_list *p1 = NULL; |
symbol_list *p1 = NULL; |
|
bucket *bp; |
|
1410 |
|
|
1411 |
/* Points to first symbol_list of current rule. its symbol is the |
/* Points to first symbol_list of current rule. its symbol is the |
1412 |
lhs of the rule. */ |
lhs of the rule. */ |
1638 |
fatal (_("no rules in the input grammar")); |
fatal (_("no rules in the input grammar")); |
1639 |
|
|
1640 |
/* Report any undefined symbols and consider them nonterminals. */ |
/* Report any undefined symbols and consider them nonterminals. */ |
1641 |
|
buckets_do (bucket_check_defined, NULL); |
|
for (bp = firstsymbol; bp; bp = bp->next) |
|
|
if (bp->class == unknown_sym) |
|
|
{ |
|
|
complain (_ |
|
|
("symbol %s is used, but is not defined as a token and has no rules"), |
|
|
bp->tag); |
|
|
bp->class = nterm_sym; |
|
|
bp->number = nvars++; |
|
|
} |
|
1642 |
|
|
1643 |
/* Insert the initial rule, which line is that of the first rule |
/* Insert the initial rule, which line is that of the first rule |
1644 |
(not that of the start symbol): |
(not that of the start symbol): |
1659 |
fatal (_("too many symbols (tokens plus nonterminals); maximum %d"), |
fatal (_("too many symbols (tokens plus nonterminals); maximum %d"), |
1660 |
MAXSHORT); |
MAXSHORT); |
1661 |
|
|
1662 |
ntokens = nsyms - nvars; |
if (getenv ("DEBUG")) |
1663 |
|
fprintf (stderr, "nsyms == ntokens + nvars: %d == %d + %d\n", |
1664 |
|
nsyms, ntokens, nvars); |
1665 |
|
assert (nsyms == ntokens + nvars); |
1666 |
} |
} |
1667 |
|
|
1668 |
/* At the end of the grammar file, some C source code must |
/* At the end of the grammar file, some C source code must |
1699 |
static void |
static void |
1700 |
token_translations_init (void) |
token_translations_init (void) |
1701 |
{ |
{ |
1702 |
bucket *bp = NULL; |
int last_user_token_number = 256; |
1703 |
int i; |
int i; |
1704 |
|
|
1705 |
|
/* Set the user numbers. */ |
1706 |
|
for (i = 0; i < ntokens; ++i) |
1707 |
|
{ |
1708 |
|
bucket *this = symbols[i]; |
1709 |
|
if (getenv ("DEBUG")) |
1710 |
|
fprintf (stderr, "UserVal %s = %d (val = %d)\n", |
1711 |
|
this->tag, this->user_token_number, this->number); |
1712 |
|
if (this->user_token_number == SUNDEF) |
1713 |
|
this->user_token_number = ++last_user_token_number; |
1714 |
|
if (this->user_token_number > max_user_token_number) |
1715 |
|
max_user_token_number = this->user_token_number; |
1716 |
|
if (getenv ("DEBUG")) |
1717 |
|
fprintf (stderr, "Now: UserVal %s = %d (val = %d)\n", |
1718 |
|
this->tag, this->user_token_number, this->number); |
1719 |
|
} |
1720 |
|
|
1721 |
token_translations = XCALLOC (short, max_user_token_number + 1); |
token_translations = XCALLOC (short, max_user_token_number + 1); |
1722 |
|
|
1723 |
/* Initialize all entries for literal tokens to 2, the internal |
/* Initialize all entries for literal tokens to 2, the internal |
1726 |
for (i = 0; i < max_user_token_number + 1; i++) |
for (i = 0; i < max_user_token_number + 1; i++) |
1727 |
token_translations[i] = 2; |
token_translations[i] = 2; |
1728 |
|
|
1729 |
for (bp = firstsymbol; bp; bp = bp->next) |
buckets_do (bucket_translation, NULL); |
|
{ |
|
|
/* Non-terminal? */ |
|
|
if (bp->number >= ntokens) |
|
|
continue; |
|
|
/* A token string alias? */ |
|
|
if (bp->user_token_number == SALIAS) |
|
|
continue; |
|
|
|
|
|
assert (bp->user_token_number != SUNDEF); |
|
|
|
|
|
/* A token which translation has already been set? */ |
|
|
if (token_translations[bp->user_token_number] != 2) |
|
|
complain (_("tokens %s and %s both assigned number %d"), |
|
|
symbols[token_translations[bp->user_token_number]]->tag, |
|
|
bp->tag, bp->user_token_number); |
|
|
token_translations[bp->user_token_number] = bp->number; |
|
|
} |
|
1730 |
} |
} |
1731 |
|
|
1732 |
|
|
1738 |
static void |
static void |
1739 |
packsymbols (void) |
packsymbols (void) |
1740 |
{ |
{ |
|
bucket *bp = NULL; |
|
|
int tokno = 1; |
|
|
int last_user_token_number; |
|
|
|
|
1741 |
symbols = XCALLOC (bucket *, nsyms); |
symbols = XCALLOC (bucket *, nsyms); |
1742 |
|
|
1743 |
max_user_token_number = 256; |
buckets_do (bucket_check_alias_consistence, NULL); |
1744 |
last_user_token_number = 256; |
buckets_do (bucket_pack, NULL); |
|
|
|
|
for (bp = firstsymbol; bp; bp = bp->next) |
|
|
{ |
|
|
if (bp->class == nterm_sym) |
|
|
{ |
|
|
bp->number += ntokens; |
|
|
} |
|
|
else if (bp->alias) |
|
|
{ |
|
|
/* This symbol and its alias are a single token defn. |
|
|
Allocate a tokno, and assign to both check agreement of |
|
|
prec and assoc fields and make both the same */ |
|
|
if (bp->number == -1) |
|
|
{ |
|
|
if (bp == eoftoken || bp->alias == eoftoken) |
|
|
bp->number = bp->alias->number = 0; |
|
|
else |
|
|
{ |
|
|
bp->number = bp->alias->number = tokno++; |
|
|
} |
|
|
} |
|
|
|
|
|
if (bp->prec != bp->alias->prec) |
|
|
{ |
|
|
if (bp->prec != 0 && bp->alias->prec != 0 |
|
|
&& bp->user_token_number == SALIAS) |
|
|
complain (_("conflicting precedences for %s and %s"), |
|
|
bp->tag, bp->alias->tag); |
|
|
if (bp->prec != 0) |
|
|
bp->alias->prec = bp->prec; |
|
|
else |
|
|
bp->prec = bp->alias->prec; |
|
|
} |
|
|
|
|
|
if (bp->assoc != bp->alias->assoc) |
|
|
{ |
|
|
if (bp->assoc != 0 && bp->alias->assoc != 0 |
|
|
&& bp->user_token_number == SALIAS) |
|
|
complain (_("conflicting assoc values for %s and %s"), |
|
|
bp->tag, bp->alias->tag); |
|
|
if (bp->assoc != 0) |
|
|
bp->alias->assoc = bp->assoc; |
|
|
else |
|
|
bp->assoc = bp->alias->assoc; |
|
|
} |
|
|
|
|
|
/* Do not do processing below for SALIASs. */ |
|
|
if (bp->user_token_number == SALIAS) |
|
|
continue; |
|
|
|
|
|
} |
|
|
else /* bp->class == token_sym */ |
|
|
{ |
|
|
if (bp == eoftoken) |
|
|
bp->number = 0; |
|
|
else |
|
|
bp->number = tokno++; |
|
|
} |
|
|
|
|
|
if (bp->class == token_sym) |
|
|
{ |
|
|
if (bp->user_token_number == SUNDEF) |
|
|
bp->user_token_number = ++last_user_token_number; |
|
|
if (bp->user_token_number > max_user_token_number) |
|
|
max_user_token_number = bp->user_token_number; |
|
|
} |
|
|
|
|
|
symbols[bp->number] = bp; |
|
|
} |
|
1745 |
|
|
1746 |
token_translations_init (); |
token_translations_init (); |
1747 |
|
|
1845 |
obstack_init (&muscle_obstack); |
obstack_init (&muscle_obstack); |
1846 |
|
|
1847 |
/* Initialize the symbol table. */ |
/* Initialize the symbol table. */ |
1848 |
tabinit (); |
buckets_new (); |
1849 |
|
|
1850 |
/* Construct the axiom symbol. */ |
/* Construct the axiom symbol. */ |
1851 |
axiom = getsym ("$axiom"); |
axiom = getsym ("$axiom"); |
1855 |
/* Construct the error token */ |
/* Construct the error token */ |
1856 |
errtoken = getsym ("error"); |
errtoken = getsym ("error"); |
1857 |
errtoken->class = token_sym; |
errtoken->class = token_sym; |
1858 |
|
errtoken->number = ntokens++; |
1859 |
errtoken->user_token_number = 256; /* Value specified by POSIX. */ |
errtoken->user_token_number = 256; /* Value specified by POSIX. */ |
1860 |
|
|
1861 |
/* Construct a token that represents all undefined literal tokens. |
/* Construct a token that represents all undefined literal tokens. |
1862 |
It is always token number 2. */ |
It is always token number 2. */ |
1863 |
undeftoken = getsym ("$undefined."); |
undeftoken = getsym ("$undefined."); |
1864 |
undeftoken->class = token_sym; |
undeftoken->class = token_sym; |
1865 |
|
undeftoken->number = ntokens++; |
1866 |
undeftoken->user_token_number = 2; |
undeftoken->user_token_number = 2; |
1867 |
|
|
1868 |
/* Initialize the obstacks. */ |
/* Initialize the obstacks. */ |
1882 |
{ |
{ |
1883 |
eoftoken = getsym ("$"); |
eoftoken = getsym ("$"); |
1884 |
eoftoken->class = token_sym; |
eoftoken->class = token_sym; |
1885 |
|
eoftoken->number = 0; |
1886 |
/* Value specified by POSIX. */ |
/* Value specified by POSIX. */ |
1887 |
eoftoken->user_token_number = 0; |
eoftoken->user_token_number = 0; |
1888 |
} |
} |
1913 |
XFREE (ritem); |
XFREE (ritem); |
1914 |
free (rules + 1); |
free (rules + 1); |
1915 |
/* Free the symbol table data structure. */ |
/* Free the symbol table data structure. */ |
1916 |
free_symtab (); |
buckets_free (); |
1917 |
} |
} |