Common subdirectories: src/CVS and src-opt/CVS Common subdirectories: src/.deps and src-opt/.deps diff -u src/getargs.c src-opt/getargs.c --- src/getargs.c 2004-10-27 23:11:09.006122248 +0200 +++ src-opt/getargs.c 2004-10-27 23:05:49.588681080 +0200 @@ -50,6 +50,7 @@ bool no_parser_flag; int report_flag = report_none; bool token_table_flag; +bool optimise_flag; bool yacc_flag; /* for -y */ bool graph_flag; int trace_flag = trace_none; @@ -221,6 +222,7 @@ -l, --no-lines don't generate `#line' directives\n\ -n, --no-parser generate the tables only\n\ -k, --token-table include a table of token names\n\ + -O, --optimise remove redundant rules\n\ "), stdout); putc ('\n', stdout); @@ -284,7 +286,7 @@ `----------------------*/ /* Shorts options. */ -const char *short_options = "yvegdhr:ltknVo:b:p:S:T::"; +const char *short_options = "yvegdhr:ltkOnVo:b:p:S:T::"; /* Values for long options that do not have single-letter equivalents. */ enum @@ -328,6 +330,7 @@ { "raw", no_argument, 0, 0 }, { "skeleton", required_argument, 0, 'S' }, { "token-table", no_argument, 0, 'k' }, + { "optimise", no_argument, 0, 'O' }, {0, 0, 0, 0} }; @@ -402,6 +405,10 @@ token_table_flag = true; break; + case 'O': + optimise_flag = true; + break; + case 'n': no_parser_flag = true; break; diff -u src/getargs.h src-opt/getargs.h --- src/getargs.h 2004-10-27 23:11:09.054114952 +0200 +++ src-opt/getargs.h 2004-10-27 23:05:49.588681080 +0200 @@ -32,6 +32,7 @@ extern bool no_lines_flag; /* for -l */ extern bool no_parser_flag; /* for -n */ extern bool token_table_flag; /* for -k */ +extern bool optimise_flag; /* for -O */ extern bool graph_flag; /* for -g */ extern bool yacc_flag; /* for -y */ diff -u src/reduce.c src-opt/reduce.c --- src/reduce.c 2004-10-27 23:11:09.185095040 +0200 +++ src-opt/reduce.c 2004-10-27 23:05:49.611677584 +0200 @@ -53,11 +53,18 @@ `useless', but no warning should be issued). */ static bitset V1; +/* Set of all symbols that were optimised away */ +static bitset O; + +/* Set of all productions that were optimised away */ +static bitset OP; + static rule_number nuseful_productions; rule_number nuseless_productions; static int nuseful_nonterminals; symbol_number nuseless_nonterminals; - +static int noptimisations; + /*-------------------------------------------------------------------. | Another way to do this would be with a set for each production and | | then do subset tests against N0, but even for the C grammar the | @@ -79,6 +86,67 @@ } +static void +useless_rules (void) +{ + rule_number r, n; + unsigned int item; + int length; + + /* Remove redundant rules that do not have an action and whose + rhs consists of only one symbol. The lhs of the rules referenced + in the redundant rule is simply set to the lhs of the redundant + rule. The redundant rule is then recognised as being redundant + because its rhs consists only of a single reference to a + nonterminal which does not exist any longer. */ + + noptimisations = 0; + + for (r = 1; r < nrules; r++) + { + if (rules[r].action) + continue; + + length = rule_rhs_length (&rules[r]); + + if (length != 1 || ISTOKEN(*rules[r].rhs) || rules[r].precsym) + continue; + + for (n = 1; n < nrules; n++) + if (n != r && *rules[r].rhs == rules[n].lhs->number) + { + bool found = false; + /* do not remove rules that are used more than once */ + for (item = 0; item < nritems; item++) + if (ritem[item] == rules[n].lhs->number) + { + if(found) + goto nextrule; + found = true; + } + + /* Suppress warnings */ + noptimisations++; + bitset_set (O, rules[n].lhs->number); + bitset_set (OP, r); + + /* Set the lhs of the referenced rules to the lhs of the + redundant rule to cut the redundant rule out of the + tree. */ + for ( ; n < nrules; n++) + if (*rules[r].rhs == rules[n].lhs->number) + { + rules[n].lhs = rules[r].lhs; + rules[n].dprec = rules[r].dprec; + rules[n].merger = rules[r].merger; + } + } +nextrule: + ; + } +} + + /*---------------------------------------------------------. | Remember that rules are 1-origin, symbols are 0-origin. | `---------------------------------------------------------*/ @@ -237,9 +305,21 @@ /* Report and flag useless productions. */ { rule_number r; - for (r = 0; r < nrules; r++) - rules[r].useful = bitset_test (P, r); - grammar_rules_never_reduced_report (_("useless rule")); + if (optimise_flag) + { + bitset_or (OP, P, OP); + for (r = 0; r < nrules; r++) + rules[r].useful = bitset_test (OP, r); + grammar_rules_never_reduced_report (_("useless rule")); + for (r = 0; r < nrules; r++) + rules[r].useful = bitset_test (P, r); + } + else + { + for (r = 0; r < nrules; r++) + rules[r].useful = bitset_test (P, r); + grammar_rules_never_reduced_report (_("useless rule")); + } } /* Map the nonterminals to their new index: useful first, useless @@ -300,8 +380,9 @@ if (!bitset_test (V, i)) { nontermmap[i - ntokens] = n++; - warn_at (symbols[i]->location, _("useless nonterminal: %s"), - symbols[i]->tag); + if (!optimise_flag || !bitset_test (O, i)) + warn_at (symbols[i]->location, _("useless nonterminal: %s"), + symbols[i]->tag); } @@ -345,7 +426,7 @@ void reduce_output (FILE *out) { - if (nuseless_nonterminals > 0) + if (nuseless_nonterminals - noptimisations > 0) { int i; fprintf (out, "%s\n\n", _("Useless nonterminals")); @@ -369,11 +450,11 @@ fputs ("\n\n", out); } - if (nuseless_productions > 0) + if (nuseless_productions - noptimisations > 0) grammar_rules_partial_print (out, _("Useless rules"), rule_useless_p); } - + @@ -385,31 +466,34 @@ static void reduce_print (void) { - if (yacc_flag && nuseless_productions) + if (yacc_flag && nuseless_productions - noptimisations) fprintf (stderr, ngettext ("%d rule never reduced\n", "%d rules never reduced\n", - nuseless_productions), - nuseless_productions); + nuseless_productions - noptimisations), + nuseless_productions - noptimisations); + + if (nuseless_nonterminals - noptimisations == 0 && nuseless_productions - noptimisations == 0) + return; fprintf (stderr, "%s: %s: ", grammar_file, _("warning")); - if (nuseless_nonterminals > 0) + if (nuseless_nonterminals - noptimisations > 0) fprintf (stderr, ngettext ("%d useless nonterminal", "%d useless nonterminals", - nuseless_nonterminals), - nuseless_nonterminals); + nuseless_nonterminals - noptimisations), + nuseless_nonterminals - noptimisations); - if (nuseless_nonterminals > 0 && nuseless_productions > 0) + if (nuseless_nonterminals - noptimisations > 0 && nuseless_productions - noptimisations > 0) fprintf (stderr, _(" and ")); - if (nuseless_productions > 0) + if (nuseless_productions - noptimisations > 0) fprintf (stderr, ngettext ("%d useless rule", "%d useless rules", - nuseless_productions), - nuseless_productions); + nuseless_productions - noptimisations), + nuseless_productions - noptimisations); fprintf (stderr, "\n"); } - + void reduce_grammar (void) { @@ -422,6 +506,12 @@ V = bitset_create (nsyms, BITSET_FIXED); V1 = bitset_create (nsyms, BITSET_FIXED); + if (optimise_flag) + { + O = bitset_create (nsyms, BITSET_FIXED); + OP = bitset_create (nrules, BITSET_FIXED); + useless_rules (); + } useless_nonterminals (); inaccessable_symbols (); @@ -466,4 +556,9 @@ bitset_free (V); bitset_free (V1); bitset_free (P); + if (optimise_flag) + { + bitset_free (O); + bitset_free (OP); + } }