mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
* src/state.h, src/state.c (transitions_t): Holds state_t*'s, not
state_number_t. (errs_t): symbol_t*, not symbol_number_t. (reductions_t): rule_t*, not rule_number_t. (FOR_EACH_SHIFT): New. * src/LR0.c, src/conflicts.c, src/lalr.c, src/output.c * src/print.c, src/print_graph.c: Adjust.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
|||||||
|
2002-07-29 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
|
* src/state.h, src/state.c (transitions_t): Holds state_t*'s, not
|
||||||
|
state_number_t.
|
||||||
|
(errs_t): symbol_t*, not symbol_number_t.
|
||||||
|
(reductions_t): rule_t*, not rule_number_t.
|
||||||
|
(FOR_EACH_SHIFT): New.
|
||||||
|
* src/LR0.c, src/conflicts.c, src/lalr.c, src/output.c
|
||||||
|
* src/print.c, src/print_graph.c: Adjust.
|
||||||
|
|
||||||
2002-07-29 Akim Demaille <akim@epita.fr>
|
2002-07-29 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
Use $accept and $end, as BYacc and BTYacc do, instead of $axiom and $.
|
Use $accept and $end, as BYacc and BTYacc do, instead of $axiom and $.
|
||||||
|
|||||||
36
src/LR0.c
36
src/LR0.c
@@ -83,8 +83,8 @@ state_list_append (symbol_number_t symbol,
|
|||||||
static int nshifts;
|
static int nshifts;
|
||||||
static symbol_number_t *shift_symbol = NULL;
|
static symbol_number_t *shift_symbol = NULL;
|
||||||
|
|
||||||
static short *redset = NULL;
|
static rule_t **redset = NULL;
|
||||||
static state_number_t *shiftset = NULL;
|
static state_t **shiftset = NULL;
|
||||||
|
|
||||||
static item_number_t **kernel_base = NULL;
|
static item_number_t **kernel_base = NULL;
|
||||||
static int *kernel_size = NULL;
|
static int *kernel_size = NULL;
|
||||||
@@ -139,8 +139,8 @@ allocate_storage (void)
|
|||||||
{
|
{
|
||||||
allocate_itemsets ();
|
allocate_itemsets ();
|
||||||
|
|
||||||
shiftset = XCALLOC (state_number_t, nsyms);
|
shiftset = XCALLOC (state_t *, nsyms);
|
||||||
redset = XCALLOC (short, nrules);
|
redset = XCALLOC (rule_t *, nrules);
|
||||||
state_hash_new ();
|
state_hash_new ();
|
||||||
shift_symbol = XCALLOC (symbol_number_t, nsyms);
|
shift_symbol = XCALLOC (symbol_number_t, nsyms);
|
||||||
}
|
}
|
||||||
@@ -204,13 +204,13 @@ new_itemsets (state_t *state)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------.
|
/*-----------------------------------------------------------------.
|
||||||
| Find the state number for the state we would get to (from the |
|
| Find the state we would get to (from the current state) by |
|
||||||
| current state) by shifting symbol. Create a new state if no |
|
| shifting SYMBOL. Create a new state if no equivalent one exists |
|
||||||
| equivalent one exists already. Used by append_states. |
|
| already. Used by append_states. |
|
||||||
`--------------------------------------------------------------*/
|
`-----------------------------------------------------------------*/
|
||||||
|
|
||||||
static state_number_t
|
static state_t *
|
||||||
get_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
get_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
||||||
{
|
{
|
||||||
state_t *sp;
|
state_t *sp;
|
||||||
@@ -226,15 +226,15 @@ get_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
|||||||
if (trace_flag)
|
if (trace_flag)
|
||||||
fprintf (stderr, "Exiting get_state => %d\n", sp->number);
|
fprintf (stderr, "Exiting get_state => %d\n", sp->number);
|
||||||
|
|
||||||
return sp->number;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------.
|
/*---------------------------------------------------------------.
|
||||||
| Use the information computed by new_itemsets to find the state |
|
| Use the information computed by new_itemsets to find the state |
|
||||||
| numbers reached by each shift transition from STATE. |
|
| numbers reached by each shift transition from STATE. |
|
||||||
| |
|
| |
|
||||||
| SHIFTSET is set up as a vector of state numbers of those states. |
|
| SHIFTSET is set up as a vector of those states. |
|
||||||
`------------------------------------------------------------------*/
|
`---------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_states (state_t *state)
|
append_states (state_t *state)
|
||||||
@@ -292,7 +292,7 @@ save_reductions (state_t *state)
|
|||||||
{
|
{
|
||||||
int item = ritem[itemset[i]];
|
int item = ritem[itemset[i]];
|
||||||
if (item < 0)
|
if (item < 0)
|
||||||
redset[count++] = item_number_as_rule_number (item);
|
redset[count++] = &rules[item_number_as_rule_number (item)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make a reductions structure and copy the data into it. */
|
/* Make a reductions structure and copy the data into it. */
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ flush_reduce (bitset lookaheads, int token)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
resolve_sr_conflict (state_t *state, int lookahead,
|
resolve_sr_conflict (state_t *state, int lookahead,
|
||||||
symbol_number_t *errs)
|
symbol_t **errs)
|
||||||
{
|
{
|
||||||
symbol_number_t i;
|
symbol_number_t i;
|
||||||
/* Find the rule to reduce by to get precedence of reduction. */
|
/* Find the rule to reduce by to get precedence of reduction. */
|
||||||
@@ -226,7 +226,7 @@ resolve_sr_conflict (state_t *state, int lookahead,
|
|||||||
flush_shift (state, i);
|
flush_shift (state, i);
|
||||||
flush_reduce (lookaheads, i);
|
flush_reduce (lookaheads, i);
|
||||||
/* Record an explicit error for this token. */
|
/* Record an explicit error for this token. */
|
||||||
errs[nerrs++] = i;
|
errs[nerrs++] = symbols[i];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case undef_assoc:
|
case undef_assoc:
|
||||||
@@ -255,7 +255,7 @@ resolve_sr_conflict (state_t *state, int lookahead,
|
|||||||
`-------------------------------------------------------------------*/
|
`-------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_conflicts (state_t *state, symbol_number_t *errs)
|
set_conflicts (state_t *state, symbol_t **errs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
transitions_t *transitions = state->transitions;
|
transitions_t *transitions = state->transitions;
|
||||||
@@ -265,9 +265,8 @@ set_conflicts (state_t *state, symbol_number_t *errs)
|
|||||||
|
|
||||||
bitset_zero (lookaheadset);
|
bitset_zero (lookaheadset);
|
||||||
|
|
||||||
for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
|
FOR_EACH_SHIFT (transitions, i)
|
||||||
if (!TRANSITION_IS_DISABLED (transitions, i))
|
bitset_set (lookaheadset, TRANSITION_SYMBOL (transitions, i));
|
||||||
bitset_set (lookaheadset, TRANSITION_SYMBOL (transitions, i));
|
|
||||||
|
|
||||||
/* Loop over all rules which require lookahead in this state. First
|
/* Loop over all rules which require lookahead in this state. First
|
||||||
check for shift-reduce conflict, and try to resolve using
|
check for shift-reduce conflict, and try to resolve using
|
||||||
@@ -303,7 +302,7 @@ conflicts_solve (void)
|
|||||||
{
|
{
|
||||||
state_number_t i;
|
state_number_t i;
|
||||||
/* List of lookaheads on which we explicitly raise a parse error. */
|
/* List of lookaheads on which we explicitly raise a parse error. */
|
||||||
symbol_number_t *errs = XMALLOC (symbol_number_t, ntokens + 1);
|
symbol_t **errs = XMALLOC (symbol_t *, ntokens + 1);
|
||||||
|
|
||||||
conflicts = XCALLOC (char, nstates);
|
conflicts = XCALLOC (char, nstates);
|
||||||
shiftset = bitset_create (ntokens, BITSET_FIXED);
|
shiftset = bitset_create (ntokens, BITSET_FIXED);
|
||||||
@@ -341,9 +340,8 @@ count_sr_conflicts (state_t *state)
|
|||||||
bitset_zero (lookaheadset);
|
bitset_zero (lookaheadset);
|
||||||
bitset_zero (shiftset);
|
bitset_zero (shiftset);
|
||||||
|
|
||||||
for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
|
FOR_EACH_SHIFT (transitions, i)
|
||||||
if (!TRANSITION_IS_DISABLED (transitions, i))
|
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
|
||||||
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
|
|
||||||
|
|
||||||
for (i = 0; i < state->nlookaheads; ++i)
|
for (i = 0; i < state->nlookaheads; ++i)
|
||||||
bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
|
bitset_or (lookaheadset, lookaheadset, state->lookaheads[i]);
|
||||||
@@ -434,17 +432,41 @@ void
|
|||||||
conflicts_output (FILE *out)
|
conflicts_output (FILE *out)
|
||||||
{
|
{
|
||||||
bool printed_sth = FALSE;
|
bool printed_sth = FALSE;
|
||||||
|
bool *used_rules = XCALLOC (bool, nrules);
|
||||||
state_number_t i;
|
state_number_t i;
|
||||||
for (i = 0; i < nstates; i++)
|
for (i = 0; i < nstates; i++)
|
||||||
if (conflicts[i])
|
{
|
||||||
{
|
state_t *s = states[i];
|
||||||
fprintf (out, _("State %d contains "), i);
|
int j;
|
||||||
fputs (conflict_report (count_sr_conflicts (states[i]),
|
for (j = 0; j < s->reductions->num; ++j)
|
||||||
count_rr_conflicts (states[i], TRUE)), out);
|
used_rules[s->reductions->rules[j]->number] = TRUE;
|
||||||
printed_sth = TRUE;
|
if (conflicts[i])
|
||||||
}
|
{
|
||||||
|
fprintf (out, _("State %d contains "), i);
|
||||||
|
fputs (conflict_report (count_sr_conflicts (s),
|
||||||
|
count_rr_conflicts (s, TRUE)), out);
|
||||||
|
printed_sth = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (printed_sth)
|
if (printed_sth)
|
||||||
fputs ("\n\n", out);
|
fputs ("\n\n", out);
|
||||||
|
|
||||||
|
for (i = 0; i < nstates; i++)
|
||||||
|
{
|
||||||
|
state_t *s = states[i];
|
||||||
|
reductions_t *r = s->reductions;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < r->num; ++j)
|
||||||
|
if (!used_rules[r->rules[j]->number])
|
||||||
|
{
|
||||||
|
LOCATION_PRINT (stderr, r->rules[j]->location);
|
||||||
|
fprintf (stderr, ": %s: %s: ",
|
||||||
|
_("warning"),
|
||||||
|
_("rule never reduced because of conflicts"));
|
||||||
|
rule_print (r->rules[j], stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free (used_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------.
|
/*--------------------------------------------------------.
|
||||||
|
|||||||
11
src/lalr.c
11
src/lalr.c
@@ -86,7 +86,7 @@ initialize_LA (void)
|
|||||||
for (i = 0; i < nstates; i++)
|
for (i = 0; i < nstates; i++)
|
||||||
if (!states[i]->consistent)
|
if (!states[i]->consistent)
|
||||||
for (j = 0; j < states[i]->reductions->num; j++)
|
for (j = 0; j < states[i]->reductions->num; j++)
|
||||||
*np++ = &rules[states[i]->reductions->rules[j]];
|
*np++ = states[i]->reductions->rules[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ set_goto_map (void)
|
|||||||
{
|
{
|
||||||
int k = temp_map[TRANSITION_SYMBOL (sp, i)]++;
|
int k = temp_map[TRANSITION_SYMBOL (sp, i)]++;
|
||||||
from_state[k] = state;
|
from_state[k] = state;
|
||||||
to_state[k] = sp->states[i];
|
to_state[k] = sp->states[i]->number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ initialize_F (void)
|
|||||||
transitions_t *sp = states[stateno]->transitions;
|
transitions_t *sp = states[stateno]->transitions;
|
||||||
|
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < sp->num && TRANSITION_IS_SHIFT (sp, j); j++)
|
FOR_EACH_SHIFT (sp, j)
|
||||||
bitset_set (F[i], TRANSITION_SYMBOL (sp, j));
|
bitset_set (F[i], TRANSITION_SYMBOL (sp, j));
|
||||||
|
|
||||||
for (; j < sp->num; j++)
|
for (; j < sp->num; j++)
|
||||||
@@ -375,13 +375,14 @@ states_lookaheads_count (void)
|
|||||||
reduction from a shift. Otherwise, it is straightforward,
|
reduction from a shift. Otherwise, it is straightforward,
|
||||||
and the state is `consistent'. */
|
and the state is `consistent'. */
|
||||||
if (rp->num > 1
|
if (rp->num > 1
|
||||||
|| (rp->num == 1 && sp->num && TRANSITION_IS_SHIFT (sp, 0)))
|
|| (rp->num == 1 && sp->num &&
|
||||||
|
!TRANSITION_IS_DISABLED (sp, 0) && TRANSITION_IS_SHIFT (sp, 0)))
|
||||||
nlookaheads += rp->num;
|
nlookaheads += rp->num;
|
||||||
else
|
else
|
||||||
states[i]->consistent = 1;
|
states[i]->consistent = 1;
|
||||||
|
|
||||||
for (k = 0; k < sp->num; k++)
|
for (k = 0; k < sp->num; k++)
|
||||||
if (TRANSITION_IS_ERROR (sp, k))
|
if (!TRANSITION_IS_DISABLED (sp, k) && TRANSITION_IS_ERROR (sp, k))
|
||||||
{
|
{
|
||||||
states[i]->consistent = 0;
|
states[i]->consistent = 0;
|
||||||
break;
|
break;
|
||||||
|
|||||||
40
src/main.c
40
src/main.c
@@ -39,10 +39,24 @@
|
|||||||
#include "conflicts.h"
|
#include "conflicts.h"
|
||||||
#include "print_graph.h"
|
#include "print_graph.h"
|
||||||
#include "muscle_tab.h"
|
#include "muscle_tab.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
|
||||||
/* The name this program was run with, for messages. */
|
/* The name this program was run with, for messages. */
|
||||||
char *program_name;
|
char *program_name;
|
||||||
|
|
||||||
|
static void
|
||||||
|
stage (const char *title)
|
||||||
|
{
|
||||||
|
struct mallinfo minfo = mallinfo ();
|
||||||
|
struct tms tinfo;
|
||||||
|
times (&tinfo);
|
||||||
|
fprintf (stderr, "STAGE: %30s: %9d (%9d): %ldu %lds\n",
|
||||||
|
title,
|
||||||
|
minfo.uordblks, minfo.arena,
|
||||||
|
tinfo.tms_utime, tinfo.tms_stime);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -58,16 +72,23 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
muscle_init ();
|
muscle_init ();
|
||||||
|
|
||||||
|
stage ("initialized muscles");
|
||||||
|
|
||||||
/* Read the input. Copy some parts of it to FGUARD, FACTION, FTABLE
|
/* Read the input. Copy some parts of it to FGUARD, FACTION, FTABLE
|
||||||
and FATTRS. In file reader.c. The other parts are recorded in
|
and FATTRS. In file reader.c. The other parts are recorded in
|
||||||
the grammar; see gram.h. */
|
the grammar; see gram.h. */
|
||||||
reader ();
|
reader ();
|
||||||
|
|
||||||
|
stage ("reader");
|
||||||
|
|
||||||
if (complain_message_count)
|
if (complain_message_count)
|
||||||
exit (1);
|
exit (1);
|
||||||
|
|
||||||
/* Find useless nonterminals and productions and reduce the grammar. */
|
/* Find useless nonterminals and productions and reduce the grammar. */
|
||||||
reduce_grammar ();
|
reduce_grammar ();
|
||||||
|
|
||||||
|
stage ("reduced grammar");
|
||||||
|
|
||||||
/* Record other info about the grammar. In files derives and
|
/* Record other info about the grammar. In files derives and
|
||||||
nullable. */
|
nullable. */
|
||||||
set_derives ();
|
set_derives ();
|
||||||
@@ -77,9 +98,11 @@ main (int argc, char *argv[])
|
|||||||
See state.h for more info. */
|
See state.h for more info. */
|
||||||
generate_states ();
|
generate_states ();
|
||||||
|
|
||||||
|
stage ("generated states");
|
||||||
/* make it deterministic. In file lalr. */
|
/* make it deterministic. In file lalr. */
|
||||||
lalr ();
|
lalr ();
|
||||||
|
|
||||||
|
stage ("lalred");
|
||||||
/* Find and record any conflicts: places where one token of
|
/* Find and record any conflicts: places where one token of
|
||||||
lookahead is not enough to disambiguate the parsing. In file
|
lookahead is not enough to disambiguate the parsing. In file
|
||||||
conflicts. Also resolve s/r conflicts based on precedence
|
conflicts. Also resolve s/r conflicts based on precedence
|
||||||
@@ -87,6 +110,7 @@ main (int argc, char *argv[])
|
|||||||
conflicts_solve ();
|
conflicts_solve ();
|
||||||
conflicts_print ();
|
conflicts_print ();
|
||||||
|
|
||||||
|
stage ("solved conflicts");
|
||||||
/* Output file names. */
|
/* Output file names. */
|
||||||
compute_output_file_names ();
|
compute_output_file_names ();
|
||||||
|
|
||||||
@@ -94,6 +118,7 @@ main (int argc, char *argv[])
|
|||||||
if (report_flag)
|
if (report_flag)
|
||||||
print_results ();
|
print_results ();
|
||||||
|
|
||||||
|
stage ("printed results");
|
||||||
/* Stop if there were errors, to avoid trashing previous output
|
/* Stop if there were errors, to avoid trashing previous output
|
||||||
files. */
|
files. */
|
||||||
if (complain_message_count)
|
if (complain_message_count)
|
||||||
@@ -105,26 +130,35 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
/* Output the tables and the parser to ftable. In file output. */
|
/* Output the tables and the parser to ftable. In file output. */
|
||||||
output ();
|
output ();
|
||||||
|
stage ("made output");
|
||||||
|
|
||||||
states_free ();
|
states_free ();
|
||||||
|
stage ("freed states");
|
||||||
reduce_free ();
|
reduce_free ();
|
||||||
|
stage ("freed reduce");
|
||||||
conflicts_free ();
|
conflicts_free ();
|
||||||
|
stage ("freed conflicts");
|
||||||
free_nullable ();
|
free_nullable ();
|
||||||
|
stage ("freed nullable");
|
||||||
free_derives ();
|
free_derives ();
|
||||||
|
stage ("freed derives");
|
||||||
grammar_free ();
|
grammar_free ();
|
||||||
|
stage ("freed grammar");
|
||||||
|
|
||||||
/* The scanner memory cannot be released right after parsing, as it
|
/* The scanner memory cannot be released right after parsing, as it
|
||||||
contains things such as user actions, prologue, epilogue etc. */
|
contains things such as user actions, prologue, epilogue etc. */
|
||||||
scanner_free ();
|
scanner_free ();
|
||||||
|
stage ("freed scanner");
|
||||||
muscle_free ();
|
muscle_free ();
|
||||||
|
stage ("freed muscles");
|
||||||
/* If using alloca.c, flush the alloca'ed memory for the benefit of
|
/* If using alloca.c, flush the alloca'ed memory for the benefit of
|
||||||
people running Bison as a library in IDEs. */
|
people running Bison as a library in IDEs. */
|
||||||
#if C_ALLOCA
|
#if C_ALLOCA
|
||||||
alloca (0);
|
alloca (0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (trace_flag)
|
if (trace_flag)
|
||||||
bitset_stats_dump (stderr);
|
bitset_stats_dump (stderr);
|
||||||
|
|
||||||
return complain_message_count ? EXIT_FAILURE : EXIT_SUCCESS;
|
return complain_message_count ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
46
src/output.c
46
src/output.c
@@ -494,15 +494,15 @@ conflict_row (state_t *state)
|
|||||||
| that has any such conflicts. |
|
| that has any such conflicts. |
|
||||||
`------------------------------------------------------------------*/
|
`------------------------------------------------------------------*/
|
||||||
|
|
||||||
static rule_number_t
|
static rule_t *
|
||||||
action_row (state_t *state)
|
action_row (state_t *state)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
rule_number_t default_rule = -1;
|
rule_t *default_rule = NULL;
|
||||||
reductions_t *redp = state->reductions;
|
reductions_t *redp = state->reductions;
|
||||||
transitions_t *transitions = state->transitions;
|
transitions_t *transitions = state->transitions;
|
||||||
errs_t *errp = state->errs;
|
errs_t *errp = state->errs;
|
||||||
/* set nonzero to inhibit having any default reduction */
|
/* Set to nonzero to inhibit having any default reduction. */
|
||||||
int nodefault = 0;
|
int nodefault = 0;
|
||||||
int conflicted = 0;
|
int conflicted = 0;
|
||||||
|
|
||||||
@@ -531,28 +531,27 @@ action_row (state_t *state)
|
|||||||
/* Now see which tokens are allowed for shifts in this state. For
|
/* Now see which tokens are allowed for shifts in this state. For
|
||||||
them, record the shift as the thing to do. So shift is preferred
|
them, record the shift as the thing to do. So shift is preferred
|
||||||
to reduce. */
|
to reduce. */
|
||||||
for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
|
FOR_EACH_SHIFT (transitions, i)
|
||||||
if (!TRANSITION_IS_DISABLED (transitions, i))
|
{
|
||||||
{
|
symbol_number_t symbol = TRANSITION_SYMBOL (transitions, i);
|
||||||
symbol_number_t symbol = TRANSITION_SYMBOL (transitions, i);
|
state_t *shift_state = transitions->states[i];
|
||||||
state_number_t shift_state = transitions->states[i];
|
|
||||||
|
|
||||||
if (actrow[symbol] != 0)
|
if (actrow[symbol] != 0)
|
||||||
conflicted = conflrow[symbol] = 1;
|
conflicted = conflrow[symbol] = 1;
|
||||||
actrow[symbol] = state_number_as_int (shift_state);
|
actrow[symbol] = state_number_as_int (shift_state->number);
|
||||||
|
|
||||||
/* Do not use any default reduction if there is a shift for
|
/* Do not use any default reduction if there is a shift for
|
||||||
error */
|
error */
|
||||||
if (symbol == errtoken->number)
|
if (symbol == errtoken->number)
|
||||||
nodefault = 1;
|
nodefault = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See which tokens are an explicit error in this state (due to
|
/* See which tokens are an explicit error in this state (due to
|
||||||
%nonassoc). For them, record ACTION_MIN as the action. */
|
%nonassoc). For them, record ACTION_MIN as the action. */
|
||||||
for (i = 0; i < errp->num; i++)
|
for (i = 0; i < errp->num; i++)
|
||||||
{
|
{
|
||||||
symbol_number_t symbol = errp->symbols[i];
|
symbol_t *symbol = errp->symbols[i];
|
||||||
actrow[symbol] = ACTION_MIN;
|
actrow[symbol->number] = ACTION_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now find the most common reduction and make it the default action
|
/* Now find the most common reduction and make it the default action
|
||||||
@@ -568,11 +567,11 @@ action_row (state_t *state)
|
|||||||
for (i = 0; i < state->nlookaheads; i++)
|
for (i = 0; i < state->nlookaheads; i++)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
rule_number_t rule = state->lookaheads_rule[i]->number;
|
rule_t *rule = state->lookaheads_rule[i];
|
||||||
symbol_number_t j;
|
symbol_number_t j;
|
||||||
|
|
||||||
for (j = 0; j < ntokens; j++)
|
for (j = 0; j < ntokens; j++)
|
||||||
if (actrow[j] == rule_number_as_item_number (rule))
|
if (actrow[j] == rule_number_as_item_number (rule->number))
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count > max)
|
if (count > max)
|
||||||
@@ -592,7 +591,7 @@ action_row (state_t *state)
|
|||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < ntokens; j++)
|
for (j = 0; j < ntokens; j++)
|
||||||
if (actrow[j] == rule_number_as_item_number (default_rule)
|
if (actrow[j] == rule_number_as_item_number (default_rule->number)
|
||||||
&& ! (glr_parser && conflrow[j]))
|
&& ! (glr_parser && conflrow[j]))
|
||||||
actrow[j] = 0;
|
actrow[j] = 0;
|
||||||
}
|
}
|
||||||
@@ -602,7 +601,7 @@ action_row (state_t *state)
|
|||||||
/* If have no default rule, the default is an error.
|
/* If have no default rule, the default is an error.
|
||||||
So replace any action which says "error" with "use default". */
|
So replace any action which says "error" with "use default". */
|
||||||
|
|
||||||
if (default_rule == -1)
|
if (!default_rule)
|
||||||
for (i = 0; i < ntokens; i++)
|
for (i = 0; i < ntokens; i++)
|
||||||
if (actrow[i] == ACTION_MIN)
|
if (actrow[i] == ACTION_MIN)
|
||||||
actrow[i] = 0;
|
actrow[i] = 0;
|
||||||
@@ -690,7 +689,8 @@ token_actions (void)
|
|||||||
|
|
||||||
for (i = 0; i < nstates; ++i)
|
for (i = 0; i < nstates; ++i)
|
||||||
{
|
{
|
||||||
yydefact[i] = action_row (states[i]) + 1;
|
rule_t *default_rule = action_row (states[i]);
|
||||||
|
yydefact[i] = default_rule ? default_rule->number + 1 : 0;
|
||||||
save_row (i);
|
save_row (i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
src/print.c
34
src/print.c
@@ -152,16 +152,16 @@ print_transitions (state_t *state, FILE *out, bool display_transitions_p)
|
|||||||
{
|
{
|
||||||
symbol_t *symbol = symbols[TRANSITION_SYMBOL (transitions, i)];
|
symbol_t *symbol = symbols[TRANSITION_SYMBOL (transitions, i)];
|
||||||
const char *tag = symbol->tag;
|
const char *tag = symbol->tag;
|
||||||
state_number_t state1 = transitions->states[i];
|
state_t *state1 = transitions->states[i];
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
fprintf (out, " %s", tag);
|
fprintf (out, " %s", tag);
|
||||||
for (j = width - strlen (tag); j > 0; --j)
|
for (j = width - strlen (tag); j > 0; --j)
|
||||||
fputc (' ', out);
|
fputc (' ', out);
|
||||||
if (display_transitions_p)
|
if (display_transitions_p)
|
||||||
fprintf (out, _("shift, and go to state %d\n"), state1);
|
fprintf (out, _("shift, and go to state %d\n"), state1->number);
|
||||||
else
|
else
|
||||||
fprintf (out, _("go to state %d\n"), state1);
|
fprintf (out, _("go to state %d\n"), state1->number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ print_errs (FILE *out, state_t *state)
|
|||||||
/* Compute the width of the lookaheads column. */
|
/* Compute the width of the lookaheads column. */
|
||||||
for (i = 0; i < errp->num; ++i)
|
for (i = 0; i < errp->num; ++i)
|
||||||
if (errp->symbols[i])
|
if (errp->symbols[i])
|
||||||
max_length (&width, symbols[errp->symbols[i]]->tag);
|
max_length (&width, errp->symbols[i]->tag);
|
||||||
|
|
||||||
/* Nothing to report. */
|
/* Nothing to report. */
|
||||||
if (!width)
|
if (!width)
|
||||||
@@ -193,7 +193,7 @@ print_errs (FILE *out, state_t *state)
|
|||||||
for (i = 0; i < errp->num; ++i)
|
for (i = 0; i < errp->num; ++i)
|
||||||
if (errp->symbols[i])
|
if (errp->symbols[i])
|
||||||
{
|
{
|
||||||
const char *tag = symbols[errp->symbols[i]]->tag;
|
const char *tag = errp->symbols[i]->tag;
|
||||||
int j;
|
int j;
|
||||||
fprintf (out, " %s", tag);
|
fprintf (out, " %s", tag);
|
||||||
for (j = width - strlen (tag); j > 0; --j)
|
for (j = width - strlen (tag); j > 0; --j)
|
||||||
@@ -218,22 +218,21 @@ state_default_rule (state_t *state)
|
|||||||
|
|
||||||
/* No need for a lookahead. */
|
/* No need for a lookahead. */
|
||||||
if (state->consistent)
|
if (state->consistent)
|
||||||
return &rules[redp->rules[0]];
|
return redp->rules[0];
|
||||||
|
|
||||||
/* 1. Each reduction is possibly masked by the lookaheads on which
|
/* 1. Each reduction is possibly masked by the lookaheads on which
|
||||||
we shift (S/R conflicts)... */
|
we shift (S/R conflicts)... */
|
||||||
bitset_zero (shiftset);
|
bitset_zero (shiftset);
|
||||||
{
|
{
|
||||||
transitions_t *transitions = state->transitions;
|
transitions_t *transitions = state->transitions;
|
||||||
for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
|
FOR_EACH_SHIFT (transitions, i)
|
||||||
if (!TRANSITION_IS_DISABLED (transitions, i))
|
{
|
||||||
{
|
/* If this state has a shift for the error token, don't use a
|
||||||
/* If this state has a shift for the error token, don't use a
|
|
||||||
default rule. */
|
default rule. */
|
||||||
if (TRANSITION_IS_ERROR (transitions, i))
|
if (TRANSITION_IS_ERROR (transitions, i))
|
||||||
return NULL;
|
return NULL;
|
||||||
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
|
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. Each reduction is possibly masked by the lookaheads on which
|
/* 2. Each reduction is possibly masked by the lookaheads on which
|
||||||
@@ -242,7 +241,7 @@ state_default_rule (state_t *state)
|
|||||||
errs_t *errp = state->errs;
|
errs_t *errp = state->errs;
|
||||||
for (i = 0; i < errp->num; i++)
|
for (i = 0; i < errp->num; i++)
|
||||||
if (errp->symbols[i])
|
if (errp->symbols[i])
|
||||||
bitset_set (shiftset, errp->symbols[i]);
|
bitset_set (shiftset, errp->symbols[i]->number);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < state->nlookaheads; ++i)
|
for (i = 0; i < state->nlookaheads; ++i)
|
||||||
@@ -314,9 +313,8 @@ print_reductions (FILE *out, state_t *state)
|
|||||||
default_rule = state_default_rule (state);
|
default_rule = state_default_rule (state);
|
||||||
|
|
||||||
bitset_zero (shiftset);
|
bitset_zero (shiftset);
|
||||||
for (i = 0; i < transitions->num && TRANSITION_IS_SHIFT (transitions, i); i++)
|
FOR_EACH_SHIFT (transitions, i)
|
||||||
if (!TRANSITION_IS_DISABLED (transitions, i))
|
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
|
||||||
bitset_set (shiftset, TRANSITION_SYMBOL (transitions, i));
|
|
||||||
|
|
||||||
/* Compute the width of the lookaheads column. */
|
/* Compute the width of the lookaheads column. */
|
||||||
if (default_rule)
|
if (default_rule)
|
||||||
|
|||||||
@@ -137,17 +137,17 @@ print_actions (state_t *state, const char *node_name)
|
|||||||
for (i = 0; i < transitions->num; i++)
|
for (i = 0; i < transitions->num; i++)
|
||||||
if (!TRANSITION_IS_DISABLED (transitions, i))
|
if (!TRANSITION_IS_DISABLED (transitions, i))
|
||||||
{
|
{
|
||||||
state_number_t state1 = transitions->states[i];
|
state_t *state1 = transitions->states[i];
|
||||||
symbol_number_t symbol = states[state1]->accessing_symbol;
|
symbol_number_t symbol = state1->accessing_symbol;
|
||||||
|
|
||||||
new_edge (&edge);
|
new_edge (&edge);
|
||||||
|
|
||||||
if (state->number > state1)
|
if (state->number > state1->number)
|
||||||
edge.type = back_edge;
|
edge.type = back_edge;
|
||||||
open_edge (&edge, fgraph);
|
open_edge (&edge, fgraph);
|
||||||
/* The edge source is the current node. */
|
/* The edge source is the current node. */
|
||||||
edge.sourcename = node_name;
|
edge.sourcename = node_name;
|
||||||
sprintf (buff, "%d", state1);
|
sprintf (buff, "%d", state1->number);
|
||||||
edge.targetname = buff;
|
edge.targetname = buff;
|
||||||
/* Shifts are blue, gotos are green, and error is red. */
|
/* Shifts are blue, gotos are green, and error is red. */
|
||||||
if (TRANSITION_IS_ERROR (transitions, i))
|
if (TRANSITION_IS_ERROR (transitions, i))
|
||||||
|
|||||||
28
src/state.c
28
src/state.c
@@ -35,12 +35,12 @@
|
|||||||
| Create a new array of N shifts/gotos. |
|
| Create a new array of N shifts/gotos. |
|
||||||
`---------------------------------------*/
|
`---------------------------------------*/
|
||||||
|
|
||||||
#define TRANSITIONS_ALLOC(Num) \
|
#define TRANSITIONS_ALLOC(Num) \
|
||||||
(transitions_t *) xcalloc ((sizeof (transitions_t) \
|
(transitions_t *) xcalloc ((sizeof (transitions_t) \
|
||||||
+ (Num - 1) * sizeof (state_number_t)), 1)
|
+ (Num - 1) * sizeof (state_t *)), 1)
|
||||||
|
|
||||||
static transitions_t *
|
static transitions_t *
|
||||||
transitions_new (int num, state_number_t *the_states)
|
transitions_new (int num, state_t **the_states)
|
||||||
{
|
{
|
||||||
transitions_t *res = TRANSITIONS_ALLOC (num);
|
transitions_t *res = TRANSITIONS_ALLOC (num);
|
||||||
res->num = num;
|
res->num = num;
|
||||||
@@ -60,7 +60,7 @@ transitions_to (transitions_t *shifts, symbol_number_t s)
|
|||||||
int j;
|
int j;
|
||||||
for (j = 0; j < shifts->num; j++)
|
for (j = 0; j < shifts->num; j++)
|
||||||
if (TRANSITION_SYMBOL (shifts, j) == s)
|
if (TRANSITION_SYMBOL (shifts, j) == s)
|
||||||
return states[shifts->states[j]];
|
return shifts->states[j];
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,11 +76,11 @@ transitions_to (transitions_t *shifts, symbol_number_t s)
|
|||||||
|
|
||||||
#define ERRS_ALLOC(Nerrs) \
|
#define ERRS_ALLOC(Nerrs) \
|
||||||
(errs_t *) xcalloc ((sizeof (errs_t) \
|
(errs_t *) xcalloc ((sizeof (errs_t) \
|
||||||
+ (Nerrs - 1) * sizeof (symbol_number_t)), 1)
|
+ (Nerrs - 1) * sizeof (symbol_t *)), 1)
|
||||||
|
|
||||||
|
|
||||||
errs_t *
|
errs_t *
|
||||||
errs_new (int num, symbol_number_t *tokens)
|
errs_new (int num, symbol_t **tokens)
|
||||||
{
|
{
|
||||||
errs_t *res = ERRS_ALLOC (num);
|
errs_t *res = ERRS_ALLOC (num);
|
||||||
res->num = num;
|
res->num = num;
|
||||||
@@ -102,10 +102,10 @@ errs_new (int num, symbol_number_t *tokens)
|
|||||||
|
|
||||||
#define REDUCTIONS_ALLOC(Nreductions) \
|
#define REDUCTIONS_ALLOC(Nreductions) \
|
||||||
(reductions_t *) xcalloc ((sizeof (reductions_t) \
|
(reductions_t *) xcalloc ((sizeof (reductions_t) \
|
||||||
+ (Nreductions - 1) * sizeof (rule_number_t)), 1)
|
+ (Nreductions - 1) * sizeof (rule_t *)), 1)
|
||||||
|
|
||||||
static reductions_t *
|
static reductions_t *
|
||||||
reductions_new (int num, rule_number_t *reductions)
|
reductions_new (int num, rule_t **reductions)
|
||||||
{
|
{
|
||||||
reductions_t *res = REDUCTIONS_ALLOC (num);
|
reductions_t *res = REDUCTIONS_ALLOC (num);
|
||||||
res->num = num;
|
res->num = num;
|
||||||
@@ -126,8 +126,8 @@ state_number_t nstates = 0;
|
|||||||
state_t *final_state = NULL;
|
state_t *final_state = NULL;
|
||||||
|
|
||||||
#define STATE_ALLOC(Nitems) \
|
#define STATE_ALLOC(Nitems) \
|
||||||
(state_t *) xcalloc ((unsigned) (sizeof (state_t) \
|
(state_t *) xcalloc ((sizeof (state_t) \
|
||||||
+ (Nitems - 1) * sizeof (item_number_t)), 1)
|
+ (Nitems - 1) * sizeof (item_number_t)), 1)
|
||||||
|
|
||||||
/*------------------------------------------------------------------.
|
/*------------------------------------------------------------------.
|
||||||
| Create a new state with ACCESSING_SYMBOL, for those items. Store |
|
| Create a new state with ACCESSING_SYMBOL, for those items. Store |
|
||||||
@@ -177,7 +177,7 @@ state_free (state_t *state)
|
|||||||
`-------------------------------*/
|
`-------------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
state_transitions_set (state_t *state, int num, state_number_t *transitions)
|
state_transitions_set (state_t *state, int num, state_t **transitions)
|
||||||
{
|
{
|
||||||
assert (!state->transitions);
|
assert (!state->transitions);
|
||||||
state->transitions = transitions_new (num, transitions);
|
state->transitions = transitions_new (num, transitions);
|
||||||
@@ -189,7 +189,7 @@ state_transitions_set (state_t *state, int num, state_number_t *transitions)
|
|||||||
`------------------------------*/
|
`------------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
state_reductions_set (state_t *state, int num, rule_number_t *reductions)
|
state_reductions_set (state_t *state, int num, rule_t **reductions)
|
||||||
{
|
{
|
||||||
assert (!state->reductions);
|
assert (!state->reductions);
|
||||||
state->reductions = reductions_new (num, reductions);
|
state->reductions = reductions_new (num, reductions);
|
||||||
@@ -201,7 +201,7 @@ state_reductions_set (state_t *state, int num, rule_number_t *reductions)
|
|||||||
`------------------------*/
|
`------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
state_errs_set (state_t *state, int num, symbol_number_t *tokens)
|
state_errs_set (state_t *state, int num, symbol_t **tokens)
|
||||||
{
|
{
|
||||||
assert (!state->errs);
|
assert (!state->errs);
|
||||||
state->errs = errs_new (num, tokens);
|
state->errs = errs_new (num, tokens);
|
||||||
|
|||||||
44
src/state.h
44
src/state.h
@@ -95,6 +95,9 @@ typedef short state_number_t;
|
|||||||
/* Be ready to map a state_number_t to an int. */
|
/* Be ready to map a state_number_t to an int. */
|
||||||
# define state_number_as_int(Tok) ((int) (Tok))
|
# define state_number_as_int(Tok) ((int) (Tok))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct state_s state_t;
|
||||||
|
|
||||||
/*--------------.
|
/*--------------.
|
||||||
| Transitions. |
|
| Transitions. |
|
||||||
`--------------*/
|
`--------------*/
|
||||||
@@ -102,7 +105,7 @@ typedef short state_number_t;
|
|||||||
typedef struct transtion_s
|
typedef struct transtion_s
|
||||||
{
|
{
|
||||||
short num;
|
short num;
|
||||||
state_number_t states[1];
|
state_t *states[1];
|
||||||
} transitions_t;
|
} transitions_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -111,7 +114,7 @@ typedef struct transtion_s
|
|||||||
token), or non terminals in case of gotos. */
|
token), or non terminals in case of gotos. */
|
||||||
|
|
||||||
#define TRANSITION_SYMBOL(Transitions, Num) \
|
#define TRANSITION_SYMBOL(Transitions, Num) \
|
||||||
(states[Transitions->states[Num]]->accessing_symbol)
|
(Transitions->states[Num]->accessing_symbol)
|
||||||
|
|
||||||
/* Is the TRANSITIONS->states[Num] a shift? (as opposed to gotos). */
|
/* Is the TRANSITIONS->states[Num] a shift? (as opposed to gotos). */
|
||||||
|
|
||||||
@@ -132,10 +135,21 @@ typedef struct transtion_s
|
|||||||
disabled. */
|
disabled. */
|
||||||
|
|
||||||
#define TRANSITION_DISABLE(Transitions, Num) \
|
#define TRANSITION_DISABLE(Transitions, Num) \
|
||||||
(Transitions->states[Num] = 0)
|
(Transitions->states[Num] = NULL)
|
||||||
|
|
||||||
#define TRANSITION_IS_DISABLED(Transitions, Num) \
|
#define TRANSITION_IS_DISABLED(Transitions, Num) \
|
||||||
(Transitions->states[Num] == 0)
|
(Transitions->states[Num] == NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/* Iterate over each transition over a token (shifts). */
|
||||||
|
#define FOR_EACH_SHIFT(Transitions, Iter) \
|
||||||
|
for (Iter = 0; \
|
||||||
|
Iter < Transitions->num \
|
||||||
|
&& (TRANSITION_IS_DISABLED (Transitions, Iter) \
|
||||||
|
|| TRANSITION_IS_SHIFT (Transitions, Iter)); \
|
||||||
|
++Iter) \
|
||||||
|
if (!TRANSITION_IS_DISABLED (Transitions, Iter))
|
||||||
|
|
||||||
|
|
||||||
/* Return the state such these TRANSITIONS contain a shift/goto to it on
|
/* Return the state such these TRANSITIONS contain a shift/goto to it on
|
||||||
SYMBOL. Aborts if none found. */
|
SYMBOL. Aborts if none found. */
|
||||||
@@ -151,10 +165,10 @@ struct state_s *transitions_to PARAMS ((transitions_t *state,
|
|||||||
typedef struct errs_s
|
typedef struct errs_s
|
||||||
{
|
{
|
||||||
short num;
|
short num;
|
||||||
symbol_number_t symbols[1];
|
symbol_t *symbols[1];
|
||||||
} errs_t;
|
} errs_t;
|
||||||
|
|
||||||
errs_t *errs_new PARAMS ((int num, symbol_number_t *tokens));
|
errs_t *errs_new PARAMS ((int num, symbol_t **tokens));
|
||||||
|
|
||||||
|
|
||||||
/*-------------.
|
/*-------------.
|
||||||
@@ -164,16 +178,16 @@ errs_t *errs_new PARAMS ((int num, symbol_number_t *tokens));
|
|||||||
typedef struct reductions_s
|
typedef struct reductions_s
|
||||||
{
|
{
|
||||||
short num;
|
short num;
|
||||||
rule_number_t rules[1];
|
rule_t *rules[1];
|
||||||
} reductions_t;
|
} reductions_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----------.
|
/*---------.
|
||||||
| State_t. |
|
| States. |
|
||||||
`----------*/
|
`---------*/
|
||||||
|
|
||||||
typedef struct state_s
|
struct state_s
|
||||||
{
|
{
|
||||||
state_number_t number;
|
state_number_t number;
|
||||||
symbol_number_t accessing_symbol;
|
symbol_number_t accessing_symbol;
|
||||||
@@ -203,7 +217,7 @@ typedef struct state_s
|
|||||||
*/
|
*/
|
||||||
unsigned short nitems;
|
unsigned short nitems;
|
||||||
item_number_t items[1];
|
item_number_t items[1];
|
||||||
} state_t;
|
};
|
||||||
|
|
||||||
extern state_number_t nstates;
|
extern state_number_t nstates;
|
||||||
extern state_t *final_state;
|
extern state_t *final_state;
|
||||||
@@ -214,15 +228,15 @@ state_t *state_new PARAMS ((symbol_number_t accessing_symbol,
|
|||||||
|
|
||||||
/* Set the transitions of STATE. */
|
/* Set the transitions of STATE. */
|
||||||
void state_transitions_set PARAMS ((state_t *state,
|
void state_transitions_set PARAMS ((state_t *state,
|
||||||
int num, state_number_t *transitions));
|
int num, state_t **transitions));
|
||||||
|
|
||||||
/* Set the reductions of STATE. */
|
/* Set the reductions of STATE. */
|
||||||
void state_reductions_set PARAMS ((state_t *state,
|
void state_reductions_set PARAMS ((state_t *state,
|
||||||
int num, rule_number_t *reductions));
|
int num, rule_t **reductions));
|
||||||
|
|
||||||
/* Set the errs of STATE. */
|
/* Set the errs of STATE. */
|
||||||
void state_errs_set PARAMS ((state_t *state,
|
void state_errs_set PARAMS ((state_t *state,
|
||||||
int num, symbol_number_t *errs));
|
int num, symbol_t **errs));
|
||||||
|
|
||||||
/* Print on OUT all the lookaheads such that this STATE wants to
|
/* Print on OUT all the lookaheads such that this STATE wants to
|
||||||
reduce this RULE. */
|
reduce this RULE. */
|
||||||
|
|||||||
Reference in New Issue
Block a user