19 |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 |
Boston, MA 02111-1307, USA. */ |
Boston, MA 02111-1307, USA. */ |
21 |
|
|
|
|
|
22 |
#include "system.h" |
#include "system.h" |
23 |
#include "quotearg.h" |
|
24 |
#include "getargs.h" |
#include <quotearg.h> |
25 |
|
|
26 |
|
#include "complain.h" |
27 |
|
#include "conflicts.h" |
28 |
#include "files.h" |
#include "files.h" |
29 |
#include "symtab.h" |
#include "getargs.h" |
|
#include "symlist.h" |
|
30 |
#include "gram.h" |
#include "gram.h" |
31 |
#include "complain.h" |
#include "muscle_tab.h" |
32 |
#include "output.h" |
#include "output.h" |
33 |
#include "reader.h" |
#include "reader.h" |
34 |
#include "conflicts.h" |
#include "symlist.h" |
35 |
#include "muscle_tab.h" |
#include "symtab.h" |
36 |
|
|
37 |
static symbol_list_t *grammar = NULL; |
static symbol_list *grammar = NULL; |
38 |
static int start_flag = 0; |
static int start_flag = 0; |
39 |
merger_list *merge_functions; |
merger_list *merge_functions; |
40 |
|
|
46 |
`-----------------------*/ |
`-----------------------*/ |
47 |
|
|
48 |
void |
void |
49 |
grammar_start_symbol_set (symbol_t *s, location_t l) |
grammar_start_symbol_set (symbol *s, location loc) |
50 |
{ |
{ |
51 |
if (start_flag) |
if (start_flag) |
52 |
complain_at (l, _("multiple %s declarations"), "%start"); |
complain_at (loc, _("multiple %s declarations"), "%start"); |
53 |
else |
else |
54 |
{ |
{ |
55 |
start_flag = 1; |
start_flag = 1; |
56 |
startsymbol = s; |
startsymbol = s; |
57 |
startsymbol_location = l; |
startsymbol_location = loc; |
58 |
} |
} |
59 |
} |
} |
60 |
|
|
65 |
`----------------------------------------------------------------*/ |
`----------------------------------------------------------------*/ |
66 |
|
|
67 |
void |
void |
68 |
prologue_augment (const char *prologue, location_t location) |
prologue_augment (const char *prologue, location loc) |
69 |
{ |
{ |
70 |
struct obstack *oout = |
struct obstack *oout = |
71 |
!typed ? &pre_prologue_obstack : &post_prologue_obstack; |
!typed ? &pre_prologue_obstack : &post_prologue_obstack; |
72 |
|
|
73 |
obstack_fgrow1 (oout, "]b4_syncline([[%d]], [[", |
obstack_fgrow1 (oout, "]b4_syncline([[%d]], [[", loc.start.line); |
74 |
location.start.line); |
MUSCLE_OBSTACK_SGROW (oout, |
75 |
MUSCLE_OBSTACK_SGROW (oout, quotearg_style (c_quoting_style, |
quotearg_style (c_quoting_style, loc.start.file)); |
|
location.start.file)); |
|
76 |
obstack_sgrow (oout, "]])[\n"); |
obstack_sgrow (oout, "]])[\n"); |
77 |
obstack_sgrow (oout, prologue); |
obstack_sgrow (oout, prologue); |
78 |
} |
} |
85 |
`----------------------*/ |
`----------------------*/ |
86 |
|
|
87 |
void |
void |
88 |
epilogue_augment (const char *epilogue, location_t location) |
epilogue_augment (const char *epilogue, location loc) |
89 |
{ |
{ |
90 |
char *extension = NULL; |
char *extension = NULL; |
91 |
obstack_fgrow1 (&muscle_obstack, "]b4_syncline([[%d]], [[", |
obstack_fgrow1 (&muscle_obstack, "]b4_syncline([[%d]], [[", loc.start.line); |
|
location.start.line); |
|
92 |
MUSCLE_OBSTACK_SGROW (&muscle_obstack, |
MUSCLE_OBSTACK_SGROW (&muscle_obstack, |
93 |
quotearg_style (c_quoting_style, location.start.file)); |
quotearg_style (c_quoting_style, loc.start.file)); |
94 |
obstack_sgrow (&muscle_obstack, "]])[\n"); |
obstack_sgrow (&muscle_obstack, "]])[\n"); |
95 |
obstack_sgrow (&muscle_obstack, epilogue); |
obstack_sgrow (&muscle_obstack, epilogue); |
96 |
obstack_1grow (&muscle_obstack, 0); |
obstack_1grow (&muscle_obstack, 0); |
109 |
`-------------------------------------------------------------------*/ |
`-------------------------------------------------------------------*/ |
110 |
|
|
111 |
static int |
static int |
112 |
get_merge_function (struniq_t name, struniq_t type, location_t loc) |
get_merge_function (uniqstr name, uniqstr type, location loc) |
113 |
{ |
{ |
114 |
merger_list *syms; |
merger_list *syms; |
115 |
merger_list head; |
merger_list head; |
119 |
return 0; |
return 0; |
120 |
|
|
121 |
if (type == NULL) |
if (type == NULL) |
122 |
type = struniq_new (""); |
type = uniqstr_new (""); |
123 |
|
|
124 |
head.next = merge_functions; |
head.next = merge_functions; |
125 |
for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1) |
for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1) |
126 |
if (STRUNIQ_EQ (name, syms->next->name)) |
if (UNIQSTR_EQ (name, syms->next->name)) |
127 |
break; |
break; |
128 |
if (syms->next == NULL) |
if (syms->next == NULL) |
129 |
{ |
{ |
130 |
syms->next = XMALLOC (merger_list, 1); |
syms->next = XMALLOC (merger_list, 1); |
131 |
syms->next->name = struniq_new (name); |
syms->next->name = uniqstr_new (name); |
132 |
syms->next->type = struniq_new (type); |
syms->next->type = uniqstr_new (type); |
133 |
syms->next->next = NULL; |
syms->next->next = NULL; |
134 |
merge_functions = head.next; |
merge_functions = head.next; |
135 |
} |
} |
136 |
else if (!STRUNIQ_EQ (type, syms->next->type)) |
else if (!UNIQSTR_EQ (type, syms->next->type)) |
137 |
warn_at (loc, _("result type clash on merge function %s: <%s> != <%s>"), |
warn_at (loc, _("result type clash on merge function %s: <%s> != <%s>"), |
138 |
name, type, syms->next->type); |
name, type, syms->next->type); |
139 |
return n; |
return n; |
160 |
|
|
161 |
|
|
162 |
/*-------------------------------------------------------------------. |
/*-------------------------------------------------------------------. |
163 |
| Parse the input grammar into a one symbol_list_t structure. Each | |
| Parse the input grammar into a one symbol_list structure. Each | |
164 |
| rule is represented by a sequence of symbols: the left hand side | |
| rule is represented by a sequence of symbols: the left hand side | |
165 |
| followed by the contents of the right hand side, followed by a | |
| followed by the contents of the right hand side, followed by a | |
166 |
| null pointer instead of a symbol to terminate the rule. The next | |
| null pointer instead of a symbol to terminate the rule. The next | |
178 |
`-------------------------------------------------------------------*/ |
`-------------------------------------------------------------------*/ |
179 |
|
|
180 |
/* The (currently) last symbol of GRAMMAR. */ |
/* The (currently) last symbol of GRAMMAR. */ |
181 |
symbol_list_t *grammar_end = NULL; |
symbol_list *grammar_end = NULL; |
182 |
|
|
183 |
/* Append S to the GRAMMAR. */ |
/* Append S to the GRAMMAR. */ |
184 |
void |
void |
185 |
grammar_symbol_append (symbol_t *symbol, location_t location) |
grammar_symbol_append (symbol *sym, location loc) |
186 |
{ |
{ |
187 |
symbol_list_t *p = symbol_list_new (symbol, location); |
symbol_list *p = symbol_list_new (sym, loc); |
188 |
|
|
189 |
if (grammar_end) |
if (grammar_end) |
190 |
grammar_end->next = p; |
grammar_end->next = p; |
197 |
/* The rule currently being defined, and the previous rule. |
/* The rule currently being defined, and the previous rule. |
198 |
CURRENT_RULE points to the first LHS of the current rule, while |
CURRENT_RULE points to the first LHS of the current rule, while |
199 |
PREVIOUS_RULE_END points to the *end* of the previous rule (NULL). */ |
PREVIOUS_RULE_END points to the *end* of the previous rule (NULL). */ |
200 |
symbol_list_t *current_rule = NULL; |
symbol_list *current_rule = NULL; |
201 |
symbol_list_t *previous_rule_end = NULL; |
symbol_list *previous_rule_end = NULL; |
202 |
|
|
203 |
|
|
204 |
/*----------------------------------------------. |
/*----------------------------------------------. |
206 |
`----------------------------------------------*/ |
`----------------------------------------------*/ |
207 |
|
|
208 |
void |
void |
209 |
grammar_rule_begin (symbol_t *lhs, location_t location) |
grammar_rule_begin (symbol *lhs, location loc) |
210 |
{ |
{ |
211 |
if (!start_flag) |
if (!start_flag) |
212 |
{ |
{ |
213 |
startsymbol = lhs; |
startsymbol = lhs; |
214 |
startsymbol_location = location; |
startsymbol_location = loc; |
215 |
start_flag = 1; |
start_flag = 1; |
216 |
} |
} |
217 |
|
|
220 |
++nritems; |
++nritems; |
221 |
|
|
222 |
previous_rule_end = grammar_end; |
previous_rule_end = grammar_end; |
223 |
grammar_symbol_append (lhs, location); |
grammar_symbol_append (lhs, loc); |
224 |
current_rule = grammar_end; |
current_rule = grammar_end; |
225 |
|
|
226 |
/* Mark the rule's lhs as a nonterminal if not already so. */ |
/* Mark the rule's lhs as a nonterminal if not already so. */ |
232 |
++nvars; |
++nvars; |
233 |
} |
} |
234 |
else if (lhs->class == token_sym) |
else if (lhs->class == token_sym) |
235 |
complain_at (location, _("rule given for %s, which is a token"), lhs->tag); |
complain_at (loc, _("rule given for %s, which is a token"), lhs->tag); |
236 |
} |
} |
237 |
|
|
238 |
/* Check that the last rule (CURRENT_RULE) is properly defined. For |
/* Check that the last rule (CURRENT_RULE) is properly defined. For |
241 |
static void |
static void |
242 |
grammar_current_rule_check (void) |
grammar_current_rule_check (void) |
243 |
{ |
{ |
244 |
symbol_t *lhs = current_rule->sym; |
symbol *lhs = current_rule->sym; |
245 |
char const *lhs_type = lhs->type_name; |
char const *lhs_type = lhs->type_name; |
246 |
symbol_t *first_rhs = current_rule->next->sym; |
symbol *first_rhs = current_rule->next->sym; |
247 |
|
|
248 |
/* If there is an action, then there is nothing we can do: the user |
/* If there is an action, then there is nothing we can do: the user |
249 |
is allowed to shoot herself in the foot. */ |
is allowed to shoot herself in the foot. */ |
259 |
if (first_rhs) |
if (first_rhs) |
260 |
{ |
{ |
261 |
const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : ""; |
const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : ""; |
262 |
if (!STRUNIQ_EQ (lhs_type, rhs_type)) |
if (!UNIQSTR_EQ (lhs_type, rhs_type)) |
263 |
warn_at (current_rule->location, |
warn_at (current_rule->location, |
264 |
_("type clash on default action: <%s> != <%s>"), |
_("type clash on default action: <%s> != <%s>"), |
265 |
lhs_type, rhs_type); |
lhs_type, rhs_type); |
276 |
`-------------------------------------*/ |
`-------------------------------------*/ |
277 |
|
|
278 |
void |
void |
279 |
grammar_rule_end (location_t location) |
grammar_rule_end (location loc) |
280 |
{ |
{ |
281 |
/* Put an empty link in the list to mark the end of this rule */ |
/* Put an empty link in the list to mark the end of this rule */ |
282 |
grammar_symbol_append (NULL, grammar_end->location); |
grammar_symbol_append (NULL, grammar_end->location); |
283 |
current_rule->location = location; |
current_rule->location = loc; |
284 |
grammar_current_rule_check (); |
grammar_current_rule_check (); |
285 |
} |
} |
286 |
|
|
301 |
|
|
302 |
/* Make a DUMMY nonterminal, whose location is that of the midrule |
/* Make a DUMMY nonterminal, whose location is that of the midrule |
303 |
action. Create the MIDRULE. */ |
action. Create the MIDRULE. */ |
304 |
location_t dummy_location = current_rule->action_location; |
location dummy_location = current_rule->action_location; |
305 |
symbol_t *dummy = dummy_symbol_get (dummy_location); |
symbol *dummy = dummy_symbol_get (dummy_location); |
306 |
symbol_list_t *midrule = symbol_list_new (dummy, dummy_location); |
symbol_list *midrule = symbol_list_new (dummy, dummy_location); |
307 |
|
|
308 |
/* Make a new rule, whose body is empty, before the current one, so |
/* Make a new rule, whose body is empty, before the current one, so |
309 |
that the action just read can belong to it. */ |
that the action just read can belong to it. */ |
334 |
/* Set the precedence symbol of the current rule to PRECSYM. */ |
/* Set the precedence symbol of the current rule to PRECSYM. */ |
335 |
|
|
336 |
void |
void |
337 |
grammar_current_rule_prec_set (symbol_t *precsym, location_t location) |
grammar_current_rule_prec_set (symbol *precsym, location loc) |
338 |
{ |
{ |
339 |
if (current_rule->ruleprec) |
if (current_rule->ruleprec) |
340 |
complain_at (location, _("only one %s allowed per rule"), "%prec"); |
complain_at (loc, _("only one %s allowed per rule"), "%prec"); |
341 |
current_rule->ruleprec = precsym; |
current_rule->ruleprec = precsym; |
342 |
} |
} |
343 |
|
|
344 |
/* Attach dynamic precedence DPREC to the current rule. */ |
/* Attach dynamic precedence DPREC to the current rule. */ |
345 |
|
|
346 |
void |
void |
347 |
grammar_current_rule_dprec_set (int dprec, location_t location) |
grammar_current_rule_dprec_set (int dprec, location loc) |
348 |
{ |
{ |
349 |
if (! glr_parser) |
if (! glr_parser) |
350 |
warn_at (location, _("%s affects only GLR parsers"), "%dprec"); |
warn_at (loc, _("%s affects only GLR parsers"), "%dprec"); |
351 |
if (dprec <= 0) |
if (dprec <= 0) |
352 |
complain_at (location, |
complain_at (loc, _("%s must be followed by positive number"), "%dprec"); |
|
_("%s must be followed by positive number"), "%dprec"); |
|
353 |
else if (current_rule->dprec != 0) |
else if (current_rule->dprec != 0) |
354 |
complain_at (location, _("only one %s allowed per rule"), "%dprec"); |
complain_at (loc, _("only one %s allowed per rule"), "%dprec"); |
355 |
current_rule->dprec = dprec; |
current_rule->dprec = dprec; |
356 |
} |
} |
357 |
|
|
359 |
rule. */ |
rule. */ |
360 |
|
|
361 |
void |
void |
362 |
grammar_current_rule_merge_set (struniq_t name, location_t location) |
grammar_current_rule_merge_set (uniqstr name, location loc) |
363 |
{ |
{ |
364 |
if (! glr_parser) |
if (! glr_parser) |
365 |
warn_at (location, _("%s affects only GLR parsers"), "%merge"); |
warn_at (loc, _("%s affects only GLR parsers"), "%merge"); |
366 |
if (current_rule->merger != 0) |
if (current_rule->merger != 0) |
367 |
complain_at (location, _("only one %s allowed per rule"), "%merge"); |
complain_at (loc, _("only one %s allowed per rule"), "%merge"); |
368 |
current_rule->merger = |
current_rule->merger = |
369 |
get_merge_function (name, current_rule->sym->type_name, location); |
get_merge_function (name, current_rule->sym->type_name, loc); |
370 |
} |
} |
371 |
|
|
372 |
/* Attach a SYMBOL to the current rule. If needed, move the previous |
/* Attach SYM to the current rule. If needed, move the previous |
373 |
action as a mid-rule action. */ |
action as a mid-rule action. */ |
374 |
|
|
375 |
void |
void |
376 |
grammar_current_rule_symbol_append (symbol_t *symbol, location_t location) |
grammar_current_rule_symbol_append (symbol *sym, location loc) |
377 |
{ |
{ |
378 |
if (current_rule->action) |
if (current_rule->action) |
379 |
grammar_midrule_action (); |
grammar_midrule_action (); |
380 |
++nritems; |
++nritems; |
381 |
grammar_symbol_append (symbol, location); |
grammar_symbol_append (sym, loc); |
382 |
} |
} |
383 |
|
|
384 |
/* Attach an ACTION to the current rule. If needed, move the previous |
/* Attach an ACTION to the current rule. If needed, move the previous |
385 |
action as a mid-rule action. */ |
action as a mid-rule action. */ |
386 |
|
|
387 |
void |
void |
388 |
grammar_current_rule_action_append (const char *action, location_t location) |
grammar_current_rule_action_append (const char *action, location loc) |
389 |
{ |
{ |
390 |
if (current_rule->action) |
if (current_rule->action) |
391 |
grammar_midrule_action (); |
grammar_midrule_action (); |
392 |
current_rule->action = action; |
current_rule->action = action; |
393 |
current_rule->action_location = location; |
current_rule->action_location = loc; |
394 |
} |
} |
395 |
|
|
396 |
|
|
403 |
packgram (void) |
packgram (void) |
404 |
{ |
{ |
405 |
unsigned int itemno = 0; |
unsigned int itemno = 0; |
406 |
rule_number_t ruleno = 0; |
rule_number ruleno = 0; |
407 |
symbol_list_t *p = grammar; |
symbol_list *p = grammar; |
408 |
|
|
409 |
ritem = XCALLOC (item_number_t, nritems); |
ritem = XCALLOC (item_number, nritems); |
410 |
rules = XCALLOC (rule_t, nrules); |
rules = XCALLOC (rule, nrules); |
411 |
|
|
412 |
while (p) |
while (p) |
413 |
{ |
{ |
414 |
symbol_t *ruleprec = p->ruleprec; |
symbol *ruleprec = p->ruleprec; |
415 |
rules[ruleno].user_number = ruleno; |
rules[ruleno].user_number = ruleno; |
416 |
rules[ruleno].number = ruleno; |
rules[ruleno].number = ruleno; |
417 |
rules[ruleno].lhs = p->sym; |
rules[ruleno].lhs = p->sym; |
426 |
p = p->next; |
p = p->next; |
427 |
while (p && p->sym) |
while (p && p->sym) |
428 |
{ |
{ |
429 |
/* item_number_t = symbol_number_t. |
/* item_number = symbol_number. |
430 |
But the former needs to contain more: negative rule numbers. */ |
But the former needs to contain more: negative rule numbers. */ |
431 |
ritem[itemno++] = symbol_number_as_item_number (p->sym->number); |
ritem[itemno++] = symbol_number_as_item_number (p->sym->number); |
432 |
/* A rule gets by default the precedence and associativity |
/* A rule gets by default the precedence and associativity |
526 |
|
|
527 |
accept: %start EOF. */ |
accept: %start EOF. */ |
528 |
{ |
{ |
529 |
symbol_list_t *p = symbol_list_new (accept, empty_location); |
symbol_list *p = symbol_list_new (accept, empty_location); |
530 |
p->location = grammar->location; |
p->location = grammar->location; |
531 |
p->next = symbol_list_new (startsymbol, empty_location); |
p->next = symbol_list_new (startsymbol, empty_location); |
532 |
p->next->next = symbol_list_new (endtoken, empty_location); |
p->next->next = symbol_list_new (endtoken, empty_location); |
537 |
grammar = p; |
grammar = p; |
538 |
} |
} |
539 |
|
|
540 |
if (! (nsyms <= SYMBOL_NUMBER_MAX && nsyms == ntokens + nvars)) |
if (! (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars)) |
541 |
abort (); |
abort (); |
542 |
|
|
543 |
xfclose (finput); |
xfclose (finput); |
549 |
/* Convert the grammar into the format described in gram.h. */ |
/* Convert the grammar into the format described in gram.h. */ |
550 |
packgram (); |
packgram (); |
551 |
|
|
552 |
/* The grammar as a symbol_list_t is no longer needed. */ |
/* The grammar as a symbol_list is no longer needed. */ |
553 |
LIST_FREE (symbol_list_t, grammar); |
LIST_FREE (symbol_list, grammar); |
554 |
} |
} |