51 |
int lineno; |
int lineno; |
52 |
static symbol_list *grammar = NULL; |
static symbol_list *grammar = NULL; |
53 |
static int start_flag = 0; |
static int start_flag = 0; |
|
static symbol_t *startval = NULL; |
|
54 |
|
|
55 |
/* Nonzero if components of semantic values are used, implying |
/* Nonzero if components of semantic values are used, implying |
56 |
they must be unions. */ |
they must be unions. */ |
62 |
/* Incremented for each %left, %right or %nonassoc seen */ |
/* Incremented for each %left, %right or %nonassoc seen */ |
63 |
static int lastprec = 0; |
static int lastprec = 0; |
64 |
|
|
|
symbol_t *errtoken = NULL; |
|
|
symbol_t *undeftoken = NULL; |
|
|
symbol_t *eoftoken = NULL; |
|
|
symbol_t *axiom = NULL; |
|
|
|
|
65 |
static symbol_list * |
static symbol_list * |
66 |
symbol_list_new (symbol_t *sym) |
symbol_list_new (symbol_t *sym) |
67 |
{ |
{ |
75 |
return res; |
return res; |
76 |
} |
} |
77 |
|
|
|
/*------------------------. |
|
|
| Operations on symbols. | |
|
|
`------------------------*/ |
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------. |
|
|
| If THIS is not defined, report an error, and consider it a | |
|
|
| nonterminal. | |
|
|
`-----------------------------------------------------------*/ |
|
|
|
|
|
static bool |
|
|
symbol_check_defined (symbol_t *this) |
|
|
{ |
|
|
if (this->class == unknown_sym) |
|
|
{ |
|
|
complain |
|
|
(_("symbol %s is used, but is not defined as a token and has no rules"), |
|
|
this->tag); |
|
|
this->class = nterm_sym; |
|
|
this->number = nvars++; |
|
|
} |
|
|
|
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------. |
|
|
| Assign a symbol number, and write the definition of the token name | |
|
|
| into FDEFINES. Put in SYMBOLS. | |
|
|
`-------------------------------------------------------------------*/ |
|
|
|
|
|
static bool |
|
|
symbol_make_alias (symbol_t *symbol, char *typename) |
|
|
{ |
|
|
if (symval->alias) |
|
|
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 = USER_NUMBER_ALIAS; |
|
|
symval->alias = symbol; |
|
|
symbol->alias = symval; |
|
|
/* symbol and symval combined are only one symbol */ |
|
|
nsyms--; |
|
|
ntokens--; |
|
|
assert (ntokens == symbol->number || ntokens == symval->number); |
|
|
symbol->number = symval->number = |
|
|
(symval->number < symbol->number) ? symval->number : symbol->number; |
|
|
} |
|
|
|
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
/*---------------------------------------------------------. |
|
|
| Check that THIS, and its alias, have same precedence and | |
|
|
| associativity. | |
|
|
`---------------------------------------------------------*/ |
|
|
|
|
|
static bool |
|
|
symbol_check_alias_consistence (symbol_t *this) |
|
|
{ |
|
|
/* Check only those who _are_ the aliases. */ |
|
|
if (this->alias && this->user_token_number == USER_NUMBER_ALIAS) |
|
|
{ |
|
|
if (this->prec != this->alias->prec) |
|
|
{ |
|
|
if (this->prec != 0 && this->alias->prec != 0) |
|
|
complain (_("conflicting precedences for %s and %s"), |
|
|
this->tag, this->alias->tag); |
|
|
if (this->prec != 0) |
|
|
this->alias->prec = this->prec; |
|
|
else |
|
|
this->prec = this->alias->prec; |
|
|
} |
|
|
|
|
|
if (this->assoc != this->alias->assoc) |
|
|
{ |
|
|
if (this->assoc != 0 && this->alias->assoc != 0) |
|
|
complain (_("conflicting assoc values for %s and %s"), |
|
|
this->tag, this->alias->tag); |
|
|
if (this->assoc != 0) |
|
|
this->alias->assoc = this->assoc; |
|
|
else |
|
|
this->assoc = this->alias->assoc; |
|
|
} |
|
|
} |
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------. |
|
|
| Assign a symbol number, and write the definition of the token name | |
|
|
| into FDEFINES. Put in SYMBOLS. | |
|
|
`-------------------------------------------------------------------*/ |
|
|
|
|
|
static bool |
|
|
symbol_pack (symbol_t *this) |
|
|
{ |
|
|
if (this->class == nterm_sym) |
|
|
{ |
|
|
this->number += ntokens; |
|
|
} |
|
|
else if (this->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 (this->number == NUMBER_UNDEFINED) |
|
|
{ |
|
|
if (this == eoftoken || this->alias == eoftoken) |
|
|
this->number = this->alias->number = 0; |
|
|
else |
|
|
{ |
|
|
assert (this->alias->number != NUMBER_UNDEFINED); |
|
|
this->number = this->alias->number; |
|
|
} |
|
|
} |
|
|
/* Do not do processing below for USER_NUMBER_ALIASs. */ |
|
|
if (this->user_token_number == USER_NUMBER_ALIAS) |
|
|
return TRUE; |
|
|
} |
|
|
else /* this->class == token_sym */ |
|
|
{ |
|
|
assert (this->number != NUMBER_UNDEFINED); |
|
|
} |
|
|
|
|
|
symbols[this->number] = this; |
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------. |
|
|
| Put THIS in TOKEN_TRANSLATIONS if it is a token. | |
|
|
`--------------------------------------------------*/ |
|
|
|
|
|
static bool |
|
|
symbol_translation (symbol_t *this) |
|
|
{ |
|
|
/* Non-terminal? */ |
|
|
if (this->class == token_sym |
|
|
&& this->user_token_number != USER_NUMBER_ALIAS) |
|
|
{ |
|
|
/* A token which translation has already been set? */ |
|
|
if (token_translations[this->user_token_number] != undeftoken->number) |
|
|
complain (_("tokens %s and %s both assigned number %d"), |
|
|
symbols[token_translations[this->user_token_number]]->tag, |
|
|
this->tag, this->user_token_number); |
|
|
|
|
|
token_translations[this->user_token_number] = this->number; |
|
|
} |
|
|
|
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
|
|
78 |
/*===================\ |
/*===================\ |
79 |
| Low level lexing. | |
| Low level lexing. | |
80 |
\===================*/ |
\===================*/ |
530 |
} |
} |
531 |
else if (token == tok_identifier && *symval->tag == '\"' && symbol) |
else if (token == tok_identifier && *symval->tag == '\"' && symbol) |
532 |
{ |
{ |
533 |
symbol_make_alias (symbol, typename); |
symbol_make_alias (symbol, symval, typename); |
534 |
symbol = NULL; |
symbol = NULL; |
535 |
} |
} |
536 |
else if (token == tok_identifier) |
else if (token == tok_identifier) |
593 |
else |
else |
594 |
{ |
{ |
595 |
start_flag = 1; |
start_flag = 1; |
596 |
startval = symval; |
startsymbol = symval; |
597 |
} |
} |
598 |
} |
} |
599 |
|
|
1232 |
|
|
1233 |
if (!start_flag) |
if (!start_flag) |
1234 |
{ |
{ |
1235 |
startval = lhs; |
startsymbol = lhs; |
1236 |
start_flag = 1; |
start_flag = 1; |
1237 |
} |
} |
1238 |
|
|
1430 |
fatal (_("no rules in the input grammar")); |
fatal (_("no rules in the input grammar")); |
1431 |
|
|
1432 |
/* Report any undefined symbols and consider them nonterminals. */ |
/* Report any undefined symbols and consider them nonterminals. */ |
1433 |
symbols_do (symbol_check_defined, NULL); |
symbols_check_defined (); |
1434 |
|
|
1435 |
/* Insert the initial rule, which line is that of the first rule |
/* Insert the initial rule, which line is that of the first rule |
1436 |
(not that of the start symbol): |
(not that of the start symbol): |
1438 |
axiom: %start EOF. */ |
axiom: %start EOF. */ |
1439 |
p = symbol_list_new (axiom); |
p = symbol_list_new (axiom); |
1440 |
p->line = grammar->line; |
p->line = grammar->line; |
1441 |
p->next = symbol_list_new (startval); |
p->next = symbol_list_new (startsymbol); |
1442 |
p->next->next = symbol_list_new (eoftoken); |
p->next->next = symbol_list_new (eoftoken); |
1443 |
p->next->next->next = symbol_list_new (NULL); |
p->next->next->next = symbol_list_new (NULL); |
1444 |
p->next->next->next->next = grammar; |
p->next->next->next->next = grammar; |
1445 |
nrules += 1; |
nrules += 1; |
1446 |
nritems += 3; |
nritems += 3; |
1447 |
grammar = p; |
grammar = p; |
|
startval = axiom; |
|
1448 |
|
|
1449 |
if (nsyms > SHRT_MAX) |
if (nsyms > SHRT_MAX) |
1450 |
fatal (_("too many symbols (tokens plus nonterminals); maximum %d"), |
fatal (_("too many symbols (tokens plus nonterminals); maximum %d"), |
1479 |
} |
} |
1480 |
|
|
1481 |
|
|
|
/*------------------------------------------------------------------. |
|
|
| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same | |
|
|
| number. | |
|
|
`------------------------------------------------------------------*/ |
|
|
|
|
|
static void |
|
|
token_translations_init (void) |
|
|
{ |
|
|
int num_256_available_p = TRUE; |
|
|
int i; |
|
|
|
|
|
/* Find the highest user token number, and whether 256, the POSIX |
|
|
preferred user token number for the error token, is used. */ |
|
|
max_user_token_number = 0; |
|
|
for (i = 0; i < ntokens; ++i) |
|
|
{ |
|
|
symbol_t *this = symbols[i]; |
|
|
if (this->user_token_number != USER_NUMBER_UNDEFINED) |
|
|
{ |
|
|
if (this->user_token_number > max_user_token_number) |
|
|
max_user_token_number = this->user_token_number; |
|
|
if (this->user_token_number == 256) |
|
|
num_256_available_p = FALSE; |
|
|
} |
|
|
} |
|
|
|
|
|
/* If 256 is not used, assign it to error, to follow POSIX. */ |
|
|
if (num_256_available_p |
|
|
&& errtoken->user_token_number == USER_NUMBER_UNDEFINED) |
|
|
errtoken->user_token_number = 256; |
|
|
|
|
|
/* Set the missing user numbers. */ |
|
|
if (max_user_token_number < 256) |
|
|
max_user_token_number = 256; |
|
|
|
|
|
for (i = 0; i < ntokens; ++i) |
|
|
{ |
|
|
symbol_t *this = symbols[i]; |
|
|
if (this->user_token_number == USER_NUMBER_UNDEFINED) |
|
|
this->user_token_number = ++max_user_token_number; |
|
|
if (this->user_token_number > max_user_token_number) |
|
|
max_user_token_number = this->user_token_number; |
|
|
} |
|
|
|
|
|
token_translations = XCALLOC (symbol_number_t, max_user_token_number + 1); |
|
|
|
|
|
/* Initialize all entries for literal tokens to 2, the internal |
|
|
token number for $undefined., which represents all invalid |
|
|
inputs. */ |
|
|
for (i = 0; i < max_user_token_number + 1; i++) |
|
|
token_translations[i] = undeftoken->number; |
|
|
symbols_do (symbol_translation, NULL); |
|
|
} |
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------. |
|
|
| Assign symbol numbers, and write definition of token names into | |
|
|
| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. | |
|
|
`----------------------------------------------------------------*/ |
|
|
|
|
|
static void |
|
|
packsymbols (void) |
|
|
{ |
|
|
symbols = XCALLOC (symbol_t *, nsyms); |
|
|
|
|
|
symbols_do (symbol_check_alias_consistence, NULL); |
|
|
symbols_do (symbol_pack, NULL); |
|
|
|
|
|
token_translations_init (); |
|
|
|
|
|
if (startval->class == unknown_sym) |
|
|
fatal (_("the start symbol %s is undefined"), startval->tag); |
|
|
else if (startval->class == token_sym) |
|
|
fatal (_("the start symbol %s is a token"), startval->tag); |
|
|
|
|
|
start_symbol = startval->number; |
|
|
} |
|
|
|
|
|
|
|
1482 |
/*---------------------------------------------------------------. |
/*---------------------------------------------------------------. |
1483 |
| Convert the rules into the representation using RRHS, RLHS and | |
| Convert the rules into the representation using RRHS, RLHS and | |
1484 |
| RITEM. | |
| RITEM. | |
1613 |
|
|
1614 |
/* Assign the symbols their symbol numbers. Write #defines for the |
/* Assign the symbols their symbol numbers. Write #defines for the |
1615 |
token symbols into FDEFINES if requested. */ |
token symbols into FDEFINES if requested. */ |
1616 |
packsymbols (); |
symbols_pack (); |
1617 |
|
|
1618 |
/* Convert the grammar into the format described in gram.h. */ |
/* Convert the grammar into the format described in gram.h. */ |
1619 |
packgram (); |
packgram (); |