const char *action;
int action_line;
- /* The guard is attached to the LHS of a rule. */
- const char *guard;
- int guard_line;
symbol_t *ruleprec;
} symbol_list;
res->line = lineno;
res->action = NULL;
res->action_line = 0;
- res->guard = NULL;
- res->guard_line = 0;
res->ruleprec = NULL;
return res;
}
symval->class = token_sym;
symval->type_name = typename;
symval->user_token_number = symbol->user_token_number;
- symbol->user_token_number = SALIAS;
+ symbol->user_token_number = USER_NUMBER_ALIAS;
symval->alias = symbol;
symbol->alias = symval;
/* symbol and symval combined are only one symbol */
symbol_check_alias_consistence (symbol_t *this)
{
/* Check only those who _are_ the aliases. */
- if (this->alias && this->user_token_number == SALIAS)
+ if (this->alias && this->user_token_number == USER_NUMBER_ALIAS)
{
if (this->prec != this->alias->prec)
{
/* 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->number == NUMBER_UNDEFINED)
{
if (this == eoftoken || this->alias == eoftoken)
this->number = this->alias->number = 0;
else
{
- assert (this->alias->number != -1);
+ assert (this->alias->number != NUMBER_UNDEFINED);
this->number = this->alias->number;
}
}
- /* Do not do processing below for SALIASs. */
- if (this->user_token_number == SALIAS)
+ /* 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 != -1);
+ assert (this->number != NUMBER_UNDEFINED);
}
symbols[this->number] = this;
{
/* Non-terminal? */
if (this->class == token_sym
- && this->user_token_number != SALIAS)
+ && this->user_token_number != USER_NUMBER_ALIAS)
{
/* A token which translation has already been set? */
- if (token_translations[this->user_token_number] != 2)
+ 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);
complain (_("invalid $ value"));
return NULL;
}
- i++;
+ ++i;
}
return rp->sym->type_name;
}
\f
+/*------------------------------------------------------------------.
+| Copy the character C to OOUT, and insert quadigraphs when needed. |
+`------------------------------------------------------------------*/
+
+static inline void
+copy_character (struct obstack *oout, int c)
+{
+ switch (c)
+ {
+ case '[':
+ obstack_sgrow (oout, "@<:@");
+ break;
+
+ case ']':
+ obstack_sgrow (oout, "@:>@");
+ break;
+
+ default:
+ obstack_1grow (oout, c);
+ }
+}
+
/*------------------------------------------------------------.
| Dump the string from FIN to OOUT if non null. MATCH is the |
| delimiter of the string (either ' or "). |
continue;
}
- obstack_1grow (oout, c);
+ copy_character (oout, c);
if (c == '\\')
{
c = getc (fin);
if (c == EOF)
fatal (_("unterminated string at end of file"));
- obstack_1grow (oout, c);
+ copy_character (oout, c);
if (c == '\n')
- lineno++;
+ ++lineno;
}
c = getc (fin);
}
else if (c == '\n')
{
- lineno++;
+ ++lineno;
obstack_1grow (oout, c);
if (cplus_comment)
ended = 1;
fatal (_("unterminated comment"));
else
{
- obstack_1grow (oout, c);
+ copy_character (oout, c);
c = getc (fin);
}
}
}
-/*-----------------------------------------------------------------.
-| FIN is pointing to a location (i.e., a `@'). Output to OOUT a |
-| reference to this location. STACK_OFFSET is the number of values |
-| in the current rule so far, which says where to find `$0' with |
-| respect to the top of the stack. |
-`-----------------------------------------------------------------*/
+/*-------------------------------------------------------------------.
+| FIN is pointing to a location (i.e., a `@'). Output to OOUT a |
+| reference to this location. RULE_LENGTH is the number of values in |
+| the current rule so far, which says where to find `$0' with |
+| respect to the top of the stack. |
+`-------------------------------------------------------------------*/
static inline void
-copy_at (FILE *fin, struct obstack *oout, int stack_offset)
+copy_at (FILE *fin, struct obstack *oout, int rule_length)
{
- int c;
+ int c = getc (fin);
+ locations_flag = 1;
- c = getc (fin);
if (c == '$')
{
- obstack_sgrow (oout, "yyloc");
- locations_flag = 1;
+ obstack_sgrow (oout, "]b4_lhs_location[");
}
else if (isdigit (c) || c == '-')
{
ungetc (c, fin);
n = read_signed_integer (fin);
- if (n > stack_offset)
+ if (n > rule_length)
complain (_("invalid value: %s%d"), "@", n);
else
- {
- /* Offset is always 0 if parser has already popped the stack
- pointer. */
- obstack_fgrow1 (oout, "yylsp[%d]",
- n - (semantic_parser ? 0 : stack_offset));
- locations_flag = 1;
- }
+ obstack_fgrow2 (oout, "]b4_rhs_location([%d], [%d])[",
+ rule_length, n);
}
else
{
}
-/*-------------------------------------------------------------------.
-| FIN is pointing to a wannabee semantic value (i.e., a `$'). |
-| |
-| Possible inputs: $[<TYPENAME>]($|integer) |
-| |
-| Output to OOUT a reference to this semantic value. STACK_OFFSET is |
-| the number of values in the current rule so far, which says where |
-| to find `$0' with respect to the top of the stack. |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| FIN is pointing to a wannabee semantic value (i.e., a `$'). |
+| |
+| Possible inputs: $[<TYPENAME>]($|integer) |
+| |
+| Output to OOUT a reference to this semantic value. RULE_LENGTH is |
+| the number of values in the current rule so far, which says where |
+| to find `$0' with respect to the top of the stack. |
+`------------------------------------------------------------------*/
static inline void
copy_dollar (FILE *fin, struct obstack *oout,
- symbol_list *rule, int stack_offset)
+ symbol_list *rule, int rule_length)
{
int c = getc (fin);
const char *type_name = NULL;
if (c == '$')
{
- obstack_sgrow (oout, "yyval");
-
if (!type_name)
type_name = get_type_name (0, rule);
- if (type_name)
- obstack_fgrow1 (oout, ".%s", type_name);
if (!type_name && typed)
complain (_("$$ of `%s' has no declared type"),
rule->sym->tag);
+ if (!type_name)
+ type_name = "";
+ obstack_fgrow1 (oout,
+ "]b4_lhs_value([%s])[", type_name);
}
else if (isdigit (c) || c == '-')
{
ungetc (c, fin);
n = read_signed_integer (fin);
- if (n > stack_offset)
+ if (n > rule_length)
complain (_("invalid value: %s%d"), "$", n);
else
{
if (!type_name && n > 0)
type_name = get_type_name (n, rule);
-
- /* Offset is always 0 if parser has already popped the stack
- pointer. */
- obstack_fgrow1 (oout, "yyvsp[%d]",
- n - (semantic_parser ? 0 : stack_offset));
-
- if (type_name)
- obstack_fgrow1 (oout, ".%s", type_name);
if (!type_name && typed)
complain (_("$%d of `%s' has no declared type"),
n, rule->sym->tag);
+ if (!type_name)
+ type_name = "";
+ obstack_fgrow3 (oout, "]b4_rhs_value([%d], [%d], [%s])[",
+ rule_length, n, type_name);
}
}
else
`-------------------------------------------------------------------*/
static void
-copy_definition (void)
+copy_definition (struct obstack *oout)
{
int c;
/* -1 while reading a character if prev char was %. */
if (!no_lines_flag)
{
- obstack_fgrow2 (&attrs_obstack, muscle_find ("linef"),
+ obstack_fgrow2 (oout, muscle_find ("linef"),
lineno, quotearg_style (c_quoting_style,
muscle_find ("filename")));
}
switch (c)
{
case '\n':
- obstack_1grow (&attrs_obstack, c);
- lineno++;
+ obstack_1grow (oout, c);
+ ++lineno;
break;
case '%':
case '\'':
case '"':
- copy_string (finput, &attrs_obstack, c);
+ copy_string (finput, oout, c);
break;
case '/':
- copy_comment (finput, &attrs_obstack);
+ copy_comment (finput, oout);
break;
case EOF:
fatal ("%s", _("unterminated `%{' definition"));
default:
- obstack_1grow (&attrs_obstack, c);
+ copy_character (oout, c);
}
c = getc (finput);
{
if (c == '}')
return;
- obstack_1grow (&attrs_obstack, '%');
+ obstack_1grow (oout, '%');
}
after_percent = 0;
}
symbol->class = what_is;
if (what_is == nterm_sym && oldclass != nterm_sym)
symbol->number = nvars++;
- if (what_is == token_sym && symbol->number == -1)
+ if (what_is == token_sym && symbol->number == NUMBER_UNDEFINED)
symbol->number = ntokens++;
if (typename)
char *name = NULL;
int prev = 0;
- lastprec++; /* Assign a new precedence level, never 0. */
+ /* Assign a new precedence level, never 0. */
+ ++lastprec;
for (;;)
{
symval->assoc = assoc;
if (symval->class == nterm_sym)
complain (_("symbol %s redefined"), symval->tag);
- if (symval->number == -1)
+ if (symval->number == NUMBER_UNDEFINED)
{
symval->number = ntokens++;
symval->class = token_sym;
switch (c)
{
case '\n':
- lineno++;
+ ++lineno;
break;
case '/':
break;
case '{':
- count++;
+ ++count;
break;
case '}':
| |
| Two symbols are entered in the table, one for the token symbol and |
| one for the literal. Both are given the <type>, if any, from the |
-| declaration. The ->user_token_number of the first is SALIAS and |
-| the ->user_token_number of the second is set to the number, if |
-| any, from the declaration. The two symbols are linked via |
-| pointers in their ->alias fields. |
+| declaration. The ->user_token_number of the first is |
+| USER_NUMBER_ALIAS and the ->user_token_number of the second is set |
+| to the number, if any, from the declaration. The two symbols are |
+| linked via pointers in their ->alias fields. |
| |
| During OUTPUT_DEFINES_TABLE, the symbol is reported thereafter, |
| only the literal string is retained it is the literal string that |
token_t token;
symbol_t *symbol;
char *typename = 0;
- int usrtoknum = SUNDEF;
+ int usrtoknum = USER_NUMBER_UNDEFINED;
token = lex (); /* fetch typename or first token */
if (token == tok_typename)
}
symval->class = token_sym;
symval->type_name = typename;
- symval->user_token_number = SALIAS;
+ symval->user_token_number = USER_NUMBER_ALIAS;
symbol = symval;
token = lex (); /* get number or literal string */
/*----------------------------------------------------------------.
| Read from finput until `%%' is seen. Discard the `%%'. Handle |
| any `%' declarations, and copy the contents of any `%{ ... %}' |
-| groups to ATTRS_OBSTACK. |
+| groups to PRE_PROLOGUE_OBSTACK or POST_PROLOGUE_OBSTACK. |
`----------------------------------------------------------------*/
static void
return;
case tok_percent_left_curly:
- copy_definition ();
+ if (!typed)
+ copy_definition (&pre_prologue_obstack);
+ else
+ copy_definition (&post_prologue_obstack);
break;
case tok_token:
}
}
\f
-/*-------------------------------------------------------------------.
-| Assuming that a `{' has just been seen, copy everything up to the |
-| matching `}' into the actions file. STACK_OFFSET is the number of |
-| values in the current rule so far, which says where to find `$0' |
-| with respect to the top of the stack. |
-| |
-| This routine is used both for actions and guards. Only |
-| ACTION_OBSTACK is used, but this is fine, since we use only |
-| pointers to relevant portions inside this obstack. |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| Assuming that a `{' has just been seen, copy everything up to the |
+| matching `}' into ACTION_OBSTACK. |
+| |
+| RULE_LENGTH is the number of values in the current rule so far, |
+| which says where to find `$0' with respect to the top of the |
+| stack. It is not the same as the rule->length in the case of mid |
+| rule actions. |
+| |
+| This routine is used for actions. |
+`------------------------------------------------------------------*/
static void
-parse_braces (symbol_list *rule, int stack_offset)
+parse_action (symbol_list *rule, int rule_length)
{
- int c;
- int count;
-
- count = 1;
+ int count = 1;
+ rule->action_line = lineno;
while (count > 0)
{
+ int c;
while ((c = getc (finput)) != '}')
switch (c)
{
case '\n':
- obstack_1grow (&action_obstack, c);
- lineno++;
+ copy_character (&action_obstack, c);
+ ++lineno;
break;
case '{':
- obstack_1grow (&action_obstack, c);
- count++;
+ copy_character (&action_obstack, c);
+ ++count;
break;
case '\'':
break;
case '$':
- copy_dollar (finput, &action_obstack,
- rule, stack_offset);
+ copy_dollar (finput, &action_obstack, rule, rule_length);
break;
case '@':
- copy_at (finput, &action_obstack,
- stack_offset);
+ copy_at (finput, &action_obstack, rule_length);
break;
case EOF:
fatal (_("unmatched %s"), "`{'");
default:
- obstack_1grow (&action_obstack, c);
+ copy_character (&action_obstack, c);
}
/* Above loop exits when C is '}'. */
if (--count)
- obstack_1grow (&action_obstack, c);
+ copy_character (&action_obstack, c);
}
obstack_1grow (&action_obstack, '\0');
-}
-
-
-static void
-parse_action (symbol_list *rule, int stack_offset)
-{
- rule->action_line = lineno;
- parse_braces (rule, stack_offset);
rule->action = obstack_finish (&action_obstack);
}
-
-static void
-parse_guard (symbol_list *rule, int stack_offset)
-{
- token_t t = lex ();
- if (t != tok_left_curly)
- complain (_("invalid %s declaration"), "%guard");
- rule->guard_line = lineno;
- parse_braces (rule, stack_offset);
- rule->guard = obstack_finish (&action_obstack);
-}
-
\f
/*-------------------------------------------------------------------.
| null pointer instead of a symbol to terminate the rule. The next |
| symbol is the lhs of the following rule. |
| |
-| All guards and actions are copied out to the appropriate files, |
-| labelled by the rule number they apply to. |
+| All actions are copied out, labelled by the rule number they apply |
+| to. |
| |
| Bison used to allow some %directives in the rules sections, but |
| this is no longer consider appropriate: (i) the documented grammar |
}
/* start a new rule and record its lhs. */
- nrules++;
- nitems++;
+ ++nrules;
+ ++nritems;
p = symbol_list_new (lhs);
{
lhs->class = nterm_sym;
lhs->number = nvars;
- nvars++;
+ ++nvars;
}
else if (lhs->class == token_sym)
complain (_("rule given for %s, which is a token"), lhs->tag);
/* 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;
/* Insert the dummy generated by that rule into this
rule. */
- nitems++;
+ ++nritems;
p = symbol_list_new (sdummy);
p1->next = p;
p1 = p;
if (t == tok_identifier)
{
- nitems++;
+ ++nritems;
p = symbol_list_new (symval);
p1->next = p;
p1 = p;
{
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 */
t = lex ();
}
- if (t == tok_guard)
- {
- if (!semantic_parser)
- complain (_("%%guard present but %%semantic_parser not specified"));
-
- parse_guard (crule, rulelength);
- t = lex ();
- }
-
if (t == tok_left_curly)
{
/* This case never occurs -wjh */
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
p->next->next->next = symbol_list_new (NULL);
p->next->next->next->next = grammar;
nrules += 1;
- nitems += 3;
+ nritems += 3;
grammar = p;
startval = axiom;
- if (nsyms > MAXSHORT)
+ if (nsyms > SHRT_MAX)
fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
- MAXSHORT);
+ SHRT_MAX);
assert (nsyms == ntokens + nvars);
}
}
while ((c = getc (finput)) != EOF)
- obstack_1grow (&el_obstack, c);
+ copy_character (&el_obstack, c);
obstack_1grow (&el_obstack, 0);
muscle_insert ("epilogue", obstack_finish (&el_obstack));
static void
token_translations_init (void)
{
- int last_user_token_number = 256;
+ int num_256_available_p = TRUE;
int i;
- /* Set the user numbers. */
+ /* 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 == SUNDEF)
- this->user_token_number = ++last_user_token_number;
+ 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 (short, max_user_token_number + 1);
+ 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] = 2;
-
+ token_translations[i] = undeftoken->number;
symbols_do (symbol_translation, NULL);
}
token_translations_init ();
- 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)
static void
packgram (void)
{
- int itemno;
+ unsigned int itemno;
int ruleno;
symbol_list *p;
- /* We use short to index items. */
- if (nitems >= MAXSHORT)
- fatal (_("too many items (max %d)"), MAXSHORT);
-
- ritem = XCALLOC (short, nitems + 1);
+ ritem = XCALLOC (item_number_t, nritems);
rules = XCALLOC (rule_t, nrules) - 1;
itemno = 0;
rules[ruleno].useful = TRUE;
rules[ruleno].action = p->action;
rules[ruleno].action_line = p->action_line;
- rules[ruleno].guard = p->guard;
- rules[ruleno].guard_line = p->guard_line;
p = p->next;
while (p && p->sym)
{
- ritem[itemno++] = p->sym->number;
+ /* item_number_t = symbol_number_t.
+ But the former needs to contain more: negative rule numbers. */
+ ritem[itemno++] = symbol_number_as_item_number (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 = 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);
}
\f
-/*-------------------------------------------------------------------.
-| Read in the grammar specification and record it in the format |
-| described in gram.h. All guards are copied into the GUARD_OBSTACK |
-| and all actions into ACTION_OBSTACK, in each case forming the body |
-| of a C function (YYGUARD or YYACTION) which contains a switch |
-| statement to decide which guard or action to execute. |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| Read in the grammar specification and record it in the format |
+| described in gram.h. All actions are copied into ACTION_OBSTACK, |
+| in each case forming the body of a C function (YYACTION) which |
+| contains a switch statement to decide which action to execute. |
+`------------------------------------------------------------------*/
void
reader (void)
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. */
obstack_init (&action_obstack);
- obstack_init (&attrs_obstack);
obstack_init (&output_obstack);
+ obstack_init (&pre_prologue_obstack);
+ obstack_init (&post_prologue_obstack);
finput = xfopen (infile, "r");
}
/* Read in the grammar, build grammar in list form. Write out
- guards and actions. */
+ actions. */
readgram ();
/* Some C code is given at the end of the grammar file. */
read_additionnal_code ();
/* 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 ();
-}