mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-21 18:23:03 +00:00
Warn about unused values.
* src/symlist.h, src/symlist.c (symbol_list, symbol_list_new): Add
a `used' member.
(symbol_list_n_get, symbol_list_n_used_set): New.
(symbol_list_n_type_name_get): Use symbol_list_n_get.
* src/scan-gram.l (handle_action_dollar): Flag used symbols.
* src/reader.c (grammar_current_rule_check): Check that values are
used.
* src/symtab.c (symbol_print): Accept 0.
* tests/existing.at: Remove the type information.
Empty the actions.
Remove useless actions (beware of mid-rule actions: perl -000
-pi -e 's/s*{}(?=[ns]*[|;])//g').
* tests/actions.at (Exotic Dollars): Use unused values.
* tests/calc.at: Likewise.
* tests/glr-regression.at (No users destructors if stack 0 deleted):
Likewise.
* src/gram.c (rule_useful_p, rule_never_reduced_p): Use
rule_useful_p.
This commit is contained in:
23
ChangeLog
23
ChangeLog
@@ -1,3 +1,26 @@
|
|||||||
|
2005-12-22 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
|
Warn about unused values.
|
||||||
|
* src/symlist.h, src/symlist.c (symbol_list, symbol_list_new): Add
|
||||||
|
a `used' member.
|
||||||
|
(symbol_list_n_get, symbol_list_n_used_set): New.
|
||||||
|
(symbol_list_n_type_name_get): Use symbol_list_n_get.
|
||||||
|
* src/scan-gram.l (handle_action_dollar): Flag used symbols.
|
||||||
|
* src/reader.c (grammar_current_rule_check): Check that values are
|
||||||
|
used.
|
||||||
|
* src/symtab.c (symbol_print): Accept 0.
|
||||||
|
* tests/existing.at: Remove the type information.
|
||||||
|
Empty the actions.
|
||||||
|
Remove useless actions (beware of mid-rule actions: perl -000
|
||||||
|
-pi -e 's/\s*\{\}(?=[\n\s]*[|;])//g').
|
||||||
|
* tests/actions.at (Exotic Dollars): Use unused values.
|
||||||
|
* tests/calc.at: Likewise.
|
||||||
|
* tests/glr-regression.at (No users destructors if stack 0 deleted):
|
||||||
|
Likewise.
|
||||||
|
|
||||||
|
* src/gram.c (rule_useful_p, rule_never_reduced_p): Use
|
||||||
|
rule_useful_p.
|
||||||
|
|
||||||
2005-12-21 Paul Eggert <eggert@cs.ucla.edu>
|
2005-12-21 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
Undo 2005-12-01 tentative license wording change. The wording is
|
Undo 2005-12-01 tentative license wording change. The wording is
|
||||||
|
|||||||
18
NEWS
18
NEWS
@@ -3,6 +3,24 @@ Bison News
|
|||||||
|
|
||||||
Changes in version 2.1a:
|
Changes in version 2.1a:
|
||||||
|
|
||||||
|
* New warning: unused values
|
||||||
|
Typed right-hand side symbols whose value are not used are reported.
|
||||||
|
For instance
|
||||||
|
|
||||||
|
exp: exp "?" exp ":" exp { $$ = $1 + $3; }
|
||||||
|
| exp "+" exp
|
||||||
|
;
|
||||||
|
|
||||||
|
will trigger a warning about $5 of the first rule, and $3 in the
|
||||||
|
second ($1 is copied to $$ by the default rule). To avoid this
|
||||||
|
warning, let Bison believe the value is used, e.g.
|
||||||
|
|
||||||
|
exp: exp "?" exp ":" exp { $$ = $1 + $3; $5; }
|
||||||
|
| exp "+" exp { $$ = $1; $3; }
|
||||||
|
|
||||||
|
This helps catching lost values and memory leaks: if a value is
|
||||||
|
ignored, its associated memory will never be reclaimed.
|
||||||
|
|
||||||
* %destructor vs. YYABORT, YYACCEPT, and YYERROR.
|
* %destructor vs. YYABORT, YYACCEPT, and YYERROR.
|
||||||
Destructors are now called when user code invokes YYABORT, YYACCEPT,
|
Destructors are now called when user code invokes YYABORT, YYACCEPT,
|
||||||
and YYERROR, for all objects on the stack, other than objects
|
and YYERROR, for all objects on the stack, other than objects
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ rule_useful_p (rule *r)
|
|||||||
bool
|
bool
|
||||||
rule_useless_p (rule *r)
|
rule_useless_p (rule *r)
|
||||||
{
|
{
|
||||||
return r->number >= nrules;
|
return !rule_useful_p (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ rule_useless_p (rule *r)
|
|||||||
bool
|
bool
|
||||||
rule_never_reduced_p (rule *r)
|
rule_never_reduced_p (rule *r)
|
||||||
{
|
{
|
||||||
return !r->useful && r->number < nrules;
|
return !r->useful && rule_useful_p (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -317,8 +317,7 @@ grammar_rules_never_reduced_report (const char *message)
|
|||||||
if (!rules[r].useful)
|
if (!rules[r].useful)
|
||||||
{
|
{
|
||||||
location_print (stderr, rules[r].location);
|
location_print (stderr, rules[r].location);
|
||||||
fprintf (stderr, ": %s: %s: ",
|
fprintf (stderr, ": %s: %s: ", _("warning"), message);
|
||||||
_("warning"), message);
|
|
||||||
rule_print (&rules[r], stderr);
|
rule_print (&rules[r], stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
77
src/reader.c
77
src/reader.c
@@ -40,7 +40,7 @@ static symbol_list *grammar = NULL;
|
|||||||
static bool start_flag = false;
|
static bool start_flag = false;
|
||||||
merger_list *merge_functions;
|
merger_list *merge_functions;
|
||||||
|
|
||||||
/* Has %union been seen? */
|
/* Was %union seen? */
|
||||||
bool typed = false;
|
bool typed = false;
|
||||||
|
|
||||||
/* Should rules have a default precedence? */
|
/* Should rules have a default precedence? */
|
||||||
@@ -104,7 +104,7 @@ get_merge_function (uniqstr name, uniqstr type, location loc)
|
|||||||
type = uniqstr_new ("");
|
type = uniqstr_new ("");
|
||||||
|
|
||||||
head.next = merge_functions;
|
head.next = merge_functions;
|
||||||
for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1)
|
for (syms = &head, n = 1; syms->next; syms = syms->next, n += 1)
|
||||||
if (UNIQSTR_EQ (name, syms->next->name))
|
if (UNIQSTR_EQ (name, syms->next->name))
|
||||||
break;
|
break;
|
||||||
if (syms->next == NULL)
|
if (syms->next == NULL)
|
||||||
@@ -128,11 +128,8 @@ get_merge_function (uniqstr name, uniqstr type, location loc)
|
|||||||
void
|
void
|
||||||
free_merger_functions (void)
|
free_merger_functions (void)
|
||||||
{
|
{
|
||||||
merger_list *L0;
|
merger_list *L0 = merge_functions;
|
||||||
if (! glr_parser)
|
while (L0)
|
||||||
return;
|
|
||||||
L0 = merge_functions;
|
|
||||||
while (L0 != NULL)
|
|
||||||
{
|
{
|
||||||
merger_list *L1 = L0->next;
|
merger_list *L1 = L0->next;
|
||||||
free (L0);
|
free (L0);
|
||||||
@@ -150,13 +147,6 @@ free_merger_functions (void)
|
|||||||
| |
|
| |
|
||||||
| All actions are copied out, labelled by the rule number they apply |
|
| All actions are copied out, labelled by the rule number they apply |
|
||||||
| to. |
|
| to. |
|
||||||
| |
|
|
||||||
| Bison used to allow some %directives in the rules sections, but |
|
|
||||||
| this is no longer consider appropriate: (i) the documented grammar |
|
|
||||||
| doesn't claim it, (ii), it would promote bad style, (iii), error |
|
|
||||||
| recovery for %directives consists in skipping the junk until a `%' |
|
|
||||||
| is seen and helrp synchronizing. This scheme is definitely wrong |
|
|
||||||
| in the rules section. |
|
|
||||||
`-------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* The (currently) last symbol of GRAMMAR. */
|
/* The (currently) last symbol of GRAMMAR. */
|
||||||
@@ -206,7 +196,6 @@ grammar_rule_begin (symbol *lhs, location loc)
|
|||||||
current_rule = grammar_end;
|
current_rule = grammar_end;
|
||||||
|
|
||||||
/* Mark the rule's lhs as a nonterminal if not already so. */
|
/* Mark the rule's lhs as a nonterminal if not already so. */
|
||||||
|
|
||||||
if (lhs->class == unknown_sym)
|
if (lhs->class == unknown_sym)
|
||||||
{
|
{
|
||||||
lhs->class = nterm_sym;
|
lhs->class = nterm_sym;
|
||||||
@@ -217,39 +206,55 @@ grammar_rule_begin (symbol *lhs, location loc)
|
|||||||
complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
|
complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the last rule (CURRENT_RULE) is properly defined. For
|
|
||||||
instance, there should be no type clash on the default action. */
|
/*------------------------------------------------------------------.
|
||||||
|
| Check that the last rule (CURRENT_RULE) is properly defined. For |
|
||||||
|
| instance, there should be no type clash on the default action. |
|
||||||
|
`------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grammar_current_rule_check (void)
|
grammar_current_rule_check (void)
|
||||||
{
|
{
|
||||||
symbol *lhs = current_rule->sym;
|
symbol *lhs = current_rule->sym;
|
||||||
char const *lhs_type = lhs->type_name;
|
char const *lhs_type = lhs->type_name;
|
||||||
symbol *first_rhs = current_rule->next->sym;
|
|
||||||
|
|
||||||
/* If there is an action, then there is nothing we can do: the user
|
/* Type check.
|
||||||
is allowed to shoot herself in the foot. */
|
|
||||||
if (current_rule->action)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Don't worry about the default action if $$ is untyped, since $$'s
|
If there is an action, then there is nothing we can do: the user
|
||||||
|
is allowed to shoot herself in the foot.
|
||||||
|
|
||||||
|
Don't worry about the default action if $$ is untyped, since $$'s
|
||||||
value can't be used. */
|
value can't be used. */
|
||||||
if (! lhs_type)
|
if (!current_rule->action && lhs_type)
|
||||||
return;
|
|
||||||
|
|
||||||
/* If $$ is being set in default way, report if any type mismatch. */
|
|
||||||
if (first_rhs)
|
|
||||||
{
|
{
|
||||||
const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : "";
|
symbol *first_rhs = current_rule->next->sym;
|
||||||
if (!UNIQSTR_EQ (lhs_type, rhs_type))
|
/* If $$ is being set in default way, report if any type mismatch. */
|
||||||
|
if (first_rhs)
|
||||||
|
{
|
||||||
|
const char *rhs_type =
|
||||||
|
first_rhs->type_name ? first_rhs->type_name : "";
|
||||||
|
if (!UNIQSTR_EQ (lhs_type, rhs_type))
|
||||||
|
warn_at (current_rule->location,
|
||||||
|
_("type clash on default action: <%s> != <%s>"),
|
||||||
|
lhs_type, rhs_type);
|
||||||
|
}
|
||||||
|
/* Warn if there is no default for $$ but we need one. */
|
||||||
|
else
|
||||||
warn_at (current_rule->location,
|
warn_at (current_rule->location,
|
||||||
_("type clash on default action: <%s> != <%s>"),
|
_("empty rule for typed nonterminal, and no action"));
|
||||||
lhs_type, rhs_type);
|
}
|
||||||
|
|
||||||
|
/* Check that all the symbol values are used. */
|
||||||
|
if (typed)
|
||||||
|
{
|
||||||
|
symbol_list *l = current_rule;
|
||||||
|
int n = 1;
|
||||||
|
for (l = current_rule->next; l && l->sym; l = l->next, ++n)
|
||||||
|
/* The default action `uses' $1. */
|
||||||
|
if (! (!current_rule->action && n == 1)
|
||||||
|
&& l->sym->type_name && !l->used)
|
||||||
|
warn_at (current_rule->location, _("unused value: $%d"), n);
|
||||||
}
|
}
|
||||||
/* Warn if there is no default for $$ but we need one. */
|
|
||||||
else
|
|
||||||
warn_at (current_rule->location,
|
|
||||||
_("empty rule for typed nonterminal, and no action"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,10 @@ void free_merger_functions (void);
|
|||||||
|
|
||||||
extern merger_list *merge_functions;
|
extern merger_list *merge_functions;
|
||||||
|
|
||||||
|
/* Was %union seen? */
|
||||||
extern bool typed;
|
extern bool typed;
|
||||||
|
|
||||||
|
/* Should rules have a default precedence? */
|
||||||
extern bool default_prec;
|
extern bool default_prec;
|
||||||
|
|
||||||
#endif /* !READER_H_ */
|
#endif /* !READER_H_ */
|
||||||
|
|||||||
@@ -825,9 +825,9 @@ handle_action_dollar (char *text, location loc)
|
|||||||
if (INT_MIN <= num && num <= rule_length && ! get_errno ())
|
if (INT_MIN <= num && num <= rule_length && ! get_errno ())
|
||||||
{
|
{
|
||||||
int n = num;
|
int n = num;
|
||||||
if (1-n > max_left_semantic_context)
|
if (max_left_semantic_context < 1 - n)
|
||||||
max_left_semantic_context = 1-n;
|
max_left_semantic_context = 1 - n;
|
||||||
if (!type_name && n > 0)
|
if (!type_name && 0 < n)
|
||||||
type_name = symbol_list_n_type_name_get (current_rule, loc, n);
|
type_name = symbol_list_n_type_name_get (current_rule, loc, n);
|
||||||
if (!type_name && typed)
|
if (!type_name && typed)
|
||||||
complain_at (loc, _("$%d of `%s' has no declared type"),
|
complain_at (loc, _("$%d of `%s' has no declared type"),
|
||||||
@@ -837,6 +837,8 @@ handle_action_dollar (char *text, location loc)
|
|||||||
obstack_fgrow3 (&obstack_for_string,
|
obstack_fgrow3 (&obstack_for_string,
|
||||||
"]b4_rhs_value(%d, %d, [%s])[",
|
"]b4_rhs_value(%d, %d, [%s])[",
|
||||||
rule_length, n, type_name);
|
rule_length, n, type_name);
|
||||||
|
if (typed)
|
||||||
|
symbol_list_n_used_set (current_rule, n, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
complain_at (loc, _("integer out of range: %s"), quote (text));
|
complain_at (loc, _("integer out of range: %s"), quote (text));
|
||||||
|
|||||||
@@ -34,13 +34,19 @@ symbol_list *
|
|||||||
symbol_list_new (symbol *sym, location loc)
|
symbol_list_new (symbol *sym, location loc)
|
||||||
{
|
{
|
||||||
symbol_list *res = xmalloc (sizeof *res);
|
symbol_list *res = xmalloc (sizeof *res);
|
||||||
res->next = NULL;
|
|
||||||
res->sym = sym;
|
res->sym = sym;
|
||||||
res->location = loc;
|
res->location = loc;
|
||||||
|
|
||||||
res->action = NULL;
|
res->action = NULL;
|
||||||
|
res->used = false;
|
||||||
|
|
||||||
res->ruleprec = NULL;
|
res->ruleprec = NULL;
|
||||||
res->dprec = 0;
|
res->dprec = 0;
|
||||||
res->merger = 0;
|
res->merger = 0;
|
||||||
|
|
||||||
|
res->next = NULL;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +62,7 @@ symbol_list_print (symbol_list *l, FILE *f)
|
|||||||
{
|
{
|
||||||
symbol_print (l->sym, f);
|
symbol_print (l->sym, f);
|
||||||
if (l && l->sym)
|
if (l && l->sym)
|
||||||
fputc (' ', f);
|
fprintf (f, ", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,43 +96,64 @@ symbol_list_free (symbol_list *list)
|
|||||||
`--------------------*/
|
`--------------------*/
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
symbol_list_length (symbol_list *list)
|
symbol_list_length (symbol_list *l)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
for (/* Nothing. */; list; list = list->next)
|
for (/* Nothing. */; l; l = l->next)
|
||||||
++res;
|
++res;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------.
|
/*--------------------------------.
|
||||||
| Get the data type (alternative in the union) of the value for |
|
| Get symbol N in symbol list L. |
|
||||||
| symbol N in symbol list RP. |
|
`--------------------------------*/
|
||||||
`--------------------------------------------------------------*/
|
|
||||||
|
|
||||||
uniqstr
|
symbol_list *
|
||||||
symbol_list_n_type_name_get (symbol_list *rp, location loc, int n)
|
symbol_list_n_get (symbol_list *l, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
l = l->next;
|
||||||
|
if (l == NULL || l->sym == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------.
|
||||||
|
| Get the data type (alternative in the union) of the value for |
|
||||||
|
| symbol N in symbol list L. |
|
||||||
|
`--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
uniqstr
|
||||||
|
symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
|
||||||
|
{
|
||||||
|
l = symbol_list_n_get (l, n);
|
||||||
|
if (!l)
|
||||||
{
|
{
|
||||||
complain_at (loc, _("invalid $ value: $%d"), n);
|
complain_at (loc, _("invalid $ value: $%d"), n);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return l->sym->type_name;
|
||||||
i = 0;
|
}
|
||||||
|
|
||||||
while (i < n)
|
|
||||||
{
|
/*----------------------------------------.
|
||||||
rp = rp->next;
|
| The symbol N in symbol list L is USED. |
|
||||||
if (rp == NULL || rp->sym == NULL)
|
`----------------------------------------*/
|
||||||
{
|
|
||||||
complain_at (loc, _("invalid $ value: $%d"), n);
|
void
|
||||||
return NULL;
|
symbol_list_n_used_set (symbol_list *l, int n, bool used)
|
||||||
}
|
{
|
||||||
++i;
|
l = symbol_list_n_get (l, n);
|
||||||
}
|
if (l)
|
||||||
|
l->used = used;
|
||||||
return rp->sym->type_name;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,10 @@
|
|||||||
# include "location.h"
|
# include "location.h"
|
||||||
# include "symtab.h"
|
# include "symtab.h"
|
||||||
|
|
||||||
|
/* A list of symbols, used during the parsing to store the rules. */
|
||||||
typedef struct symbol_list
|
typedef struct symbol_list
|
||||||
{
|
{
|
||||||
struct symbol_list *next;
|
/* The symbol. */
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
location location;
|
location location;
|
||||||
|
|
||||||
@@ -35,9 +36,16 @@ typedef struct symbol_list
|
|||||||
const char *action;
|
const char *action;
|
||||||
location action_location;
|
location action_location;
|
||||||
|
|
||||||
|
/* Whether this symbol's value is used in the current action. */
|
||||||
|
bool used;
|
||||||
|
|
||||||
|
/* Precedence/associativity. */
|
||||||
symbol *ruleprec;
|
symbol *ruleprec;
|
||||||
int dprec;
|
int dprec;
|
||||||
int merger;
|
int merger;
|
||||||
|
|
||||||
|
/* The list. */
|
||||||
|
struct symbol_list *next;
|
||||||
} symbol_list;
|
} symbol_list;
|
||||||
|
|
||||||
|
|
||||||
@@ -48,18 +56,24 @@ symbol_list *symbol_list_new (symbol *sym, location loc);
|
|||||||
void symbol_list_print (symbol_list *l, FILE *f);
|
void symbol_list_print (symbol_list *l, FILE *f);
|
||||||
|
|
||||||
/* Prepend SYM at LOC to the LIST. */
|
/* Prepend SYM at LOC to the LIST. */
|
||||||
symbol_list *symbol_list_prepend (symbol_list *list,
|
symbol_list *symbol_list_prepend (symbol_list *l,
|
||||||
symbol *sym,
|
symbol *sym,
|
||||||
location loc);
|
location loc);
|
||||||
|
|
||||||
/* Free the LIST, but not the symbols it contains. */
|
/* Free the LIST, but not the symbols it contains. */
|
||||||
void symbol_list_free (symbol_list *list);
|
void symbol_list_free (symbol_list *l);
|
||||||
|
|
||||||
/* Return its length. */
|
/* Return its length. */
|
||||||
unsigned int symbol_list_length (symbol_list *list);
|
unsigned int symbol_list_length (symbol_list *l);
|
||||||
|
|
||||||
|
/* Get symbol N in symbol list L. */
|
||||||
|
symbol_list *symbol_list_n_get (symbol_list *l, int n);
|
||||||
|
|
||||||
/* Get the data type (alternative in the union) of the value for
|
/* Get the data type (alternative in the union) of the value for
|
||||||
symbol N in rule RULE. */
|
symbol N in rule RULE. */
|
||||||
uniqstr symbol_list_n_type_name_get (symbol_list *rp, location loc, int n);
|
uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n);
|
||||||
|
|
||||||
|
/* The symbol N in symbol list L is USED. */
|
||||||
|
void symbol_list_n_used_set (symbol_list *l, int n, bool used);
|
||||||
|
|
||||||
#endif /* !SYMLIST_H_ */
|
#endif /* !SYMLIST_H_ */
|
||||||
|
|||||||
13
src/symtab.c
13
src/symtab.c
@@ -85,10 +85,15 @@ symbol_new (uniqstr tag, location loc)
|
|||||||
void
|
void
|
||||||
symbol_print (symbol *s, FILE *f)
|
symbol_print (symbol *s, FILE *f)
|
||||||
{
|
{
|
||||||
fprintf (f, "\"%s\"", s->tag);
|
if (s)
|
||||||
SYMBOL_ATTR_PRINT (type_name);
|
{
|
||||||
SYMBOL_ATTR_PRINT (destructor);
|
fprintf (f, "\"%s\"", s->tag);
|
||||||
SYMBOL_ATTR_PRINT (printer);
|
SYMBOL_ATTR_PRINT (type_name);
|
||||||
|
SYMBOL_ATTR_PRINT (destructor);
|
||||||
|
SYMBOL_ATTR_PRINT (printer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf (f, "<NULL>");
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SYMBOL_ATTR_PRINT
|
#undef SYMBOL_ATTR_PRINT
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ AT_DATA_GRAMMAR([[input.y]],
|
|||||||
static int yylex (void);
|
static int yylex (void);
|
||||||
# define YYDEBUG 1
|
# define YYDEBUG 1
|
||||||
# define YYERROR_VERBOSE 1
|
# define YYERROR_VERBOSE 1
|
||||||
|
# define USE(Var)
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union
|
%union
|
||||||
@@ -112,6 +113,7 @@ AT_DATA_GRAMMAR([[input.y]],
|
|||||||
exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
|
exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
|
||||||
sum_of_the_five_previous_values
|
sum_of_the_five_previous_values
|
||||||
{
|
{
|
||||||
|
USE (($1, $2, $5));
|
||||||
printf ("%d\n", $6);
|
printf ("%d\n", $6);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ AT_LALR1_CC_IF(
|
|||||||
# define alarm(seconds) /* empty */
|
# define alarm(seconds) /* empty */
|
||||||
#endif
|
#endif
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#define USE(Var)
|
||||||
|
|
||||||
/* Exercise pre-prologue dependency to %union. */
|
/* Exercise pre-prologue dependency to %union. */
|
||||||
typedef int semantic_value;
|
typedef int semantic_value;
|
||||||
@@ -109,7 +110,7 @@ input:
|
|||||||
|
|
||||||
line:
|
line:
|
||||||
'\n'
|
'\n'
|
||||||
| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;])[ }
|
| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1], [USE ($1)])[; }
|
||||||
;
|
;
|
||||||
|
|
||||||
exp:
|
exp:
|
||||||
|
|||||||
1636
tests/existing.at
1636
tests/existing.at
File diff suppressed because it is too large
Load Diff
@@ -746,13 +746,14 @@ AT_SETUP([No users destructors if stack 0 deleted])
|
|||||||
AT_DATA_GRAMMAR([glr-regr9.y],
|
AT_DATA_GRAMMAR([glr-regr9.y],
|
||||||
[[
|
[[
|
||||||
%{
|
%{
|
||||||
#include <stdio.h>
|
# include <stdio.h>
|
||||||
#include <stdlib.h>
|
# include <stdlib.h>
|
||||||
static void yyerror (char const *);
|
static void yyerror (char const *);
|
||||||
static int yylex (void);
|
static int yylex (void);
|
||||||
#define YYSTACKEXPANDABLE 0
|
# define YYSTACKEXPANDABLE 0
|
||||||
static int tokens = 0;
|
static int tokens = 0;
|
||||||
static int destructors = 0;
|
static int destructors = 0;
|
||||||
|
# define USE(Var)
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%glr-parser
|
%glr-parser
|
||||||
@@ -766,7 +767,7 @@ AT_DATA_GRAMMAR([glr-regr9.y],
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
start:
|
start:
|
||||||
ambig0 'a' { destructors += 2; }
|
ambig0 'a' { destructors += 2; USE ($2); }
|
||||||
| ambig1 start { destructors += 1; }
|
| ambig1 start { destructors += 1; }
|
||||||
| ambig2 start { destructors += 1; }
|
| ambig2 start { destructors += 1; }
|
||||||
;
|
;
|
||||||
|
|||||||
Reference in New Issue
Block a user