X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/8419d367e1c296fa98b42a35820147fe5588b125..5123689ba05a181aedd892e2e2164a2288e42b22:/src/reader.c diff --git a/src/reader.c b/src/reader.c index 93bbe827..98b7b803 100644 --- a/src/reader.c +++ b/src/reader.c @@ -1,5 +1,5 @@ /* Input parser for bison - Copyright 1984, 1986, 1989, 1992, 1998, 2000, 2001 + Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -38,7 +38,7 @@ typedef struct symbol_list { struct symbol_list *next; - bucket *sym; + symbol_t *sym; int line; /* The action is attached to the LHS of a rule. */ @@ -48,31 +48,31 @@ typedef struct symbol_list /* The guard is attached to the LHS of a rule. */ const char *guard; int guard_line; - bucket *ruleprec; + symbol_t *ruleprec; } symbol_list; int lineno; -static symbol_list *grammar; -static int start_flag; -static bucket *startval; +static symbol_list *grammar = NULL; +static int start_flag = 0; +static symbol_t *startval = NULL; /* Nonzero if components of semantic values are used, implying they must be unions. */ static int value_components_used; /* Nonzero if %union has been seen. */ -static int typed; +static int typed = 0; /* Incremented for each %left, %right or %nonassoc seen */ -static int lastprec; +static int lastprec = 0; -static bucket *errtoken = NULL; -static bucket *undeftoken = NULL; -static bucket *eoftoken = NULL; -static bucket *axiom = NULL; +symbol_t *errtoken = NULL; +symbol_t *undeftoken = NULL; +symbol_t *eoftoken = NULL; +symbol_t *axiom = NULL; static symbol_list * -symbol_list_new (bucket *sym) +symbol_list_new (symbol_t *sym) { symbol_list *res = XMALLOC (symbol_list, 1); res->next = NULL; @@ -86,6 +86,167 @@ symbol_list_new (bucket *sym) return res; } +/*------------------------. +| 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 = SALIAS; + 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 == SALIAS) + { + 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 == -1) + { + if (this == eoftoken || this->alias == eoftoken) + this->number = this->alias->number = 0; + else + { + assert (this->alias->number != -1); + this->number = this->alias->number; + } + } + /* Do not do processing below for SALIASs. */ + if (this->user_token_number == SALIAS) + return TRUE; + } + else /* this->class == token_sym */ + { + assert (this->number != -1); + } + + 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 != SALIAS) + { + /* A token which translation has already been set? */ + if (token_translations[this->user_token_number] != 2) + 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; +} /*===================\ @@ -165,7 +326,7 @@ get_type_name (int n, symbol_list *rule) complain (_("invalid $ value")); return NULL; } - i++; + ++i; } return rp->sym->type_name; @@ -208,7 +369,7 @@ copy_string2 (FILE *fin, struct obstack *oout, int match, int store) obstack_1grow (oout, c); if (c == '\n') - lineno++; + ++lineno; } c = getc (fin); @@ -291,7 +452,7 @@ copy_comment (FILE *fin, struct obstack *oout) } else if (c == '\n') { - lineno++; + ++lineno; obstack_1grow (oout, c); if (cplus_comment) ended = 1; @@ -453,7 +614,7 @@ copy_definition (void) { case '\n': obstack_1grow (&attrs_obstack, c); - lineno++; + ++lineno; break; case '%': @@ -502,7 +663,7 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not) char *typename = NULL; /* The symbol being defined. */ - struct bucket *symbol = NULL; + symbol_t *symbol = NULL; /* After `%token' and `%nterm', any number of symbols maybe be defined. */ @@ -531,23 +692,7 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not) } else if (token == tok_identifier && *symval->tag == '\"' && symbol) { - 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 = SALIAS; - symval->alias = symbol; - symbol->alias = symval; - /* symbol and symval combined are only one symbol */ - nsyms--; - } + symbol_make_alias (symbol, typename); symbol = NULL; } else if (token == tok_identifier) @@ -559,7 +704,9 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not) complain (_("symbol %s redefined"), symbol->tag); symbol->class = what_is; if (what_is == nterm_sym && oldclass != nterm_sym) - symbol->value = nvars++; + symbol->number = nvars++; + if (what_is == token_sym && symbol->number == -1) + symbol->number = ntokens++; if (typename) { @@ -574,7 +721,13 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not) symbol->user_token_number = numval; /* User defined EOF token? */ if (numval == 0) - eoftoken = symbol; + { + eoftoken = symbol; + eoftoken->number = 0; + /* It is always mapped to 0, so it was already counted in + NTOKENS. */ + --ntokens; + } } else { @@ -673,7 +826,8 @@ parse_assoc_decl (associativity assoc) char *name = NULL; int prev = 0; - lastprec++; /* Assign a new precedence level, never 0. */ + /* Assign a new precedence level, never 0. */ + ++lastprec; for (;;) { @@ -703,7 +857,11 @@ parse_assoc_decl (associativity assoc) symval->assoc = assoc; if (symval->class == nterm_sym) complain (_("symbol %s redefined"), symval->tag); - symval->class = token_sym; + if (symval->number == -1) + { + symval->number = ntokens++; + symval->class = token_sym; + } if (name) { /* record the type, if one is specified */ if (symval->type_name == NULL) @@ -720,9 +878,9 @@ parse_assoc_decl (associativity assoc) } else { - complain (_ - ("invalid text (%s) - number should be after identifier"), -token_buffer); + complain + (_("invalid text (%s) - number should be after identifier"), + token_buffer); skip_to_char ('%'); } break; @@ -759,6 +917,7 @@ parse_union_decl (void) typed = 1; + MUSCLE_INSERT_INT ("stype_line", lineno); obstack_init (&union_obstack); obstack_sgrow (&union_obstack, "union"); @@ -773,7 +932,7 @@ parse_union_decl (void) switch (c) { case '\n': - lineno++; + ++lineno; break; case '/': @@ -781,7 +940,7 @@ parse_union_decl (void) break; case '{': - count++; + ++count; break; case '}': @@ -846,7 +1005,7 @@ static void parse_thong_decl (void) { token_t token; - struct bucket *symbol; + symbol_t *symbol; char *typename = 0; int usrtoknum = SUNDEF; @@ -1072,7 +1231,7 @@ read_declarations (void) case tok_stropt: case tok_intopt: case tok_obsolete: - abort (); + assert (0); break; case tok_illegal: @@ -1118,12 +1277,12 @@ parse_braces (symbol_list *rule, int stack_offset) { case '\n': obstack_1grow (&action_obstack, c); - lineno++; + ++lineno; break; case '{': obstack_1grow (&action_obstack, c); - count++; + ++count; break; case '\'': @@ -1154,10 +1313,7 @@ parse_braces (symbol_list *rule, int stack_offset) /* Above loop exits when C is '}'. */ if (--count) - { - obstack_1grow (&action_obstack, c); - c = getc (finput); - } + obstack_1grow (&action_obstack, c); } obstack_1grow (&action_obstack, '\0'); @@ -1191,20 +1347,20 @@ parse_guard (symbol_list *rule, int stack_offset) | with the user's names. | `-------------------------------------------------------------------*/ -static bucket * +static symbol_t * gensym (void) { /* Incremented for each generated symbol */ static int gensym_count = 0; static char buf[256]; - bucket *sym; + symbol_t *sym; sprintf (buf, "@%d", ++gensym_count); token_buffer = buf; sym = getsym (token_buffer); sym->class = nterm_sym; - sym->value = nvars++; + sym->number = nvars++; return sym; } @@ -1230,10 +1386,9 @@ static void readgram (void) { token_t t; - bucket *lhs = NULL; + symbol_t *lhs = NULL; symbol_list *p = NULL; symbol_list *p1 = NULL; - bucket *bp; /* Points to first symbol_list of current rule. its symbol is the lhs of the rule. */ @@ -1250,7 +1405,7 @@ readgram (void) /* Number of symbols in rhs of this rule so far */ int rulelength = 0; int xactions = 0; /* JF for error checking */ - bucket *first_rhs = 0; + symbol_t *first_rhs = 0; if (t == tok_identifier) { @@ -1277,8 +1432,8 @@ readgram (void) } /* start a new rule and record its lhs. */ - nrules++; - nitems++; + ++nrules; + ++nritems; p = symbol_list_new (lhs); @@ -1296,8 +1451,8 @@ readgram (void) if (lhs->class == unknown_sym) { lhs->class = nterm_sym; - lhs->value = nvars; - nvars++; + lhs->number = nvars; + ++nvars; } else if (lhs->class == token_sym) complain (_("rule given for %s, which is a token"), lhs->tag); @@ -1321,7 +1476,7 @@ readgram (void) If one does, exit this rule now. */ if (t == tok_identifier) { - bucket *ssave; + symbol_t *ssave; token_t t1; ssave = symval; @@ -1329,7 +1484,10 @@ readgram (void) unlex (t1); symval = ssave; if (t1 == tok_colon) - break; + { + warn (_("previous rule lacks an ending `;'")); + break; + } if (!first_rhs) /* JF */ first_rhs = symval; @@ -1347,16 +1505,21 @@ readgram (void) inserting the new rule before it. */ /* Make a dummy nonterminal, a gensym. */ - bucket *sdummy = gensym (); + symbol_t *sdummy = gensym (); /* Make a new rule, whose body is empty, before the current one, so that the action just read can belong to it. */ - nrules++; - nitems++; + ++nrules; + ++nritems; p = symbol_list_new (sdummy); /* Attach its lineno to that of the host rule. */ p->line = crule->line; + /* Move the action from the host rule to this one. */ + p->action = crule->action; + p->action_line = crule->action_line; + crule->action = NULL; + if (crule1) crule1->next = p; else @@ -1369,7 +1532,7 @@ readgram (void) /* Insert the dummy generated by that rule into this rule. */ - nitems++; + ++nritems; p = symbol_list_new (sdummy); p1->next = p; p1 = p; @@ -1379,7 +1542,7 @@ readgram (void) if (t == tok_identifier) { - nitems++; + ++nritems; p = symbol_list_new (symval); p1->next = p; p1 = p; @@ -1388,9 +1551,9 @@ readgram (void) { parse_action (crule, rulelength); action_flag = 1; - xactions++; /* JF */ + ++xactions; /* JF */ } - rulelength++; + ++rulelength; } /* end of read rhs of rule */ /* Put an empty link in the list to mark the end of this rule */ @@ -1422,7 +1585,7 @@ readgram (void) complain (_("two actions at end of one rule")); parse_action (crule, rulelength); action_flag = 1; - xactions++; /* -wjh */ + ++xactions; /* -wjh */ t = lex (); } /* If $$ is being set in default way, report if any type @@ -1440,6 +1603,8 @@ readgram (void) /* Warn if there is no default for $$ but we need one. */ else if (!xactions && !first_rhs && lhs->type_name != 0) complain (_("empty rule for typed nonterminal, and no action")); + if (t == tok_two_percents || t == tok_eof) + warn (_("previous rule lacks an ending `;'")); if (t == tok_semicolon) t = lex (); } @@ -1455,16 +1620,7 @@ readgram (void) fatal (_("no rules in the input grammar")); /* Report any undefined symbols and consider them nonterminals. */ - - 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->value = nvars++; - } + symbols_do (symbol_check_defined, NULL); /* Insert the initial rule, which line is that of the first rule (not that of the start symbol): @@ -1477,7 +1633,7 @@ readgram (void) p->next->next->next = symbol_list_new (NULL); p->next->next->next->next = grammar; nrules += 1; - nitems += 3; + nritems += 3; grammar = p; startval = axiom; @@ -1485,7 +1641,7 @@ readgram (void) fatal (_("too many symbols (tokens plus nonterminals); maximum %d"), MAXSHORT); - ntokens = nsyms - nvars; + assert (nsyms == ntokens + nvars); } /* At the end of the grammar file, some C source code must @@ -1494,7 +1650,7 @@ readgram (void) static void read_additionnal_code (void) { - char c; + int c; struct obstack el_obstack; obstack_init (&el_obstack); @@ -1522,35 +1678,28 @@ read_additionnal_code (void) static void token_translations_init (void) { - bucket *bp = NULL; + int last_user_token_number = 256; int i; + /* Set the user numbers. */ + for (i = 0; i < ntokens; ++i) + { + symbol_t *this = symbols[i]; + if (this->user_token_number == SUNDEF) + this->user_token_number = ++last_user_token_number; + if (this->user_token_number > max_user_token_number) + max_user_token_number = this->user_token_number; + } + token_translations = XCALLOC (short, 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; i++) + for (i = 0; i < max_user_token_number + 1; i++) token_translations[i] = 2; - for (bp = firstsymbol; bp; bp = bp->next) - { - /* Non-terminal? */ - if (bp->value >= 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->value; - } + symbols_do (symbol_translation, NULL); } @@ -1562,150 +1711,27 @@ token_translations_init (void) static void packsymbols (void) { - bucket *bp = NULL; - int tokno = 1; - int last_user_token_number; + symbols = XCALLOC (symbol_t *, nsyms); - symbols = XCALLOC (bucket *, nsyms); - - max_user_token_number = 256; - last_user_token_number = 256; - - for (bp = firstsymbol; bp; bp = bp->next) - { - if (bp->class == nterm_sym) - { - bp->value += 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->value == -1) - { - if (bp == eoftoken || bp->alias == eoftoken) - bp->value = bp->alias->value = 0; - else - { - bp->value = bp->alias->value = 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->value = 0; - else - bp->value = 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->value] = bp; - } + symbols_do (symbol_check_alias_consistence, NULL); + symbols_do (symbol_pack, NULL); token_translations_init (); - error_token_number = errtoken->value; + error_token_number = errtoken->number; 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->value; -} - - -/*---------------------------------------------------------------. -| Save the definition of token names in the `TOKENDEFS' muscle. | -`---------------------------------------------------------------*/ - -static void -symbols_save (void) -{ - struct obstack tokendefs; - bucket *bp; - obstack_init (&tokendefs); - - for (bp = firstsymbol; bp; bp = bp->next) - { - char *symbol = bp->tag; /* get symbol */ - - if (bp->value >= ntokens) - continue; - if (bp->user_token_number == SALIAS) - continue; - if ('\'' == *symbol) - continue; /* skip literal character */ - if (bp == errtoken) - continue; /* skip error token */ - if ('\"' == *symbol) - { - /* use literal string only if given a symbol with an alias */ - if (bp->alias) - symbol = bp->alias->tag; - else - continue; - } - - /* Don't #define nonliteral tokens whose names contain periods. */ - if (strchr (symbol, '.')) - continue; - - obstack_fgrow2 (&tokendefs, "# define %s\t%d\n", - symbol, bp->user_token_number); - if (semantic_parser) - /* FIXME: This is probably wrong, and should be just as - above. --akim. */ - obstack_fgrow2 (&tokendefs, "# define T%s\t%d\n", symbol, bp->value); - } - - obstack_1grow (&tokendefs, 0); - muscle_insert ("tokendef", xstrdup (obstack_finish (&tokendefs))); - obstack_free (&tokendefs, NULL); + start_symbol = startval->number; } /*---------------------------------------------------------------. | Convert the rules into the representation using RRHS, RLHS and | -| RITEMS. | +| RITEM. | `---------------------------------------------------------------*/ static void @@ -1716,10 +1742,10 @@ packgram (void) symbol_list *p; /* We use short to index items. */ - if (nitems >= MAXSHORT) + if (nritems >= MAXSHORT) fatal (_("too many items (max %d)"), MAXSHORT); - ritem = XCALLOC (short, nitems + 1); + ritem = XCALLOC (short, nritems + 1); rules = XCALLOC (rule_t, nrules) - 1; itemno = 0; @@ -1728,9 +1754,11 @@ packgram (void) p = grammar; while (p) { - bucket *ruleprec = p->ruleprec; - rules[ruleno].lhs = p->sym->value; - rules[ruleno].rhs = itemno; + symbol_t *ruleprec = p->ruleprec; + rules[ruleno].user_number = ruleno; + rules[ruleno].number = ruleno; + rules[ruleno].lhs = p->sym; + rules[ruleno].rhs = ritem + itemno; rules[ruleno].line = p->line; rules[ruleno].useful = TRUE; rules[ruleno].action = p->action; @@ -1741,14 +1769,11 @@ packgram (void) p = p->next; while (p && p->sym) { - ritem[itemno++] = p->sym->value; + ritem[itemno++] = p->sym->number; /* A rule gets by default the precedence and associativity of the last token in it. */ if (p->sym->class == token_sym) - { - rules[ruleno].prec = p->sym->prec; - rules[ruleno].assoc = p->sym->assoc; - } + rules[ruleno].prec = p->sym; if (p) p = p->next; } @@ -1757,21 +1782,18 @@ packgram (void) the specified symbol's precedence replaces the default. */ if (ruleprec) { - rules[ruleno].prec = ruleprec->prec; - rules[ruleno].assoc = ruleprec->assoc; - rules[ruleno].precsym = ruleprec->value; + rules[ruleno].precsym = ruleprec; + rules[ruleno].prec = ruleprec; } - ritem[itemno++] = -ruleno; - ruleno++; + ++ruleno; if (p) p = p->next; } ritem[itemno] = 0; - nritems = itemno; - assert (nritems == nitems); + assert (itemno == nritems); if (trace_flag) ritem_print (stderr); @@ -1788,22 +1810,6 @@ packgram (void) void reader (void) { - start_flag = 0; - startval = NULL; /* start symbol not specified yet. */ - - nsyms = 0; - nvars = 0; - nrules = 0; - nitems = 0; - - typed = 0; - lastprec = 0; - - semantic_parser = 0; - pure_parser = 0; - - grammar = NULL; - lex_init (); lineno = 1; @@ -1811,22 +1817,24 @@ reader (void) obstack_init (&muscle_obstack); /* Initialize the symbol table. */ - tabinit (); + symbols_new (); /* Construct the axiom symbol. */ axiom = getsym ("$axiom"); axiom->class = nterm_sym; - axiom->value = nvars++; + axiom->number = nvars++; /* Construct the error token */ errtoken = getsym ("error"); errtoken->class = token_sym; + errtoken->number = ntokens++; errtoken->user_token_number = 256; /* Value specified by POSIX. */ /* Construct a token that represents all undefined literal tokens. It is always token number 2. */ undeftoken = getsym ("$undefined."); undeftoken->class = token_sym; + undeftoken->number = ntokens++; undeftoken->user_token_number = 2; /* Initialize the obstacks. */ @@ -1846,6 +1854,7 @@ reader (void) { eoftoken = getsym ("$"); eoftoken->class = token_sym; + eoftoken->number = 0; /* Value specified by POSIX. */ eoftoken->user_token_number = 0; } @@ -1862,8 +1871,6 @@ reader (void) /* Assign the symbols their symbol numbers. Write #defines for the token symbols into FDEFINES if requested. */ packsymbols (); - /* Save them. */ - symbols_save (); /* Convert the grammar into the format described in gram.h. */ packgram (); @@ -1871,3 +1878,12 @@ reader (void) /* The grammar as a symbol_list is no longer needed. */ LIST_FREE (symbol_list, grammar); } + +void +grammar_free (void) +{ + XFREE (ritem); + free (rules + 1); + /* Free the symbol table data structure. */ + symbols_free (); +}