From: drh Date: Mon, 23 May 2016 16:15:02 +0000 (+0000) Subject: Lemon enhancement: avoid unnecessary reduce actions that convert one X-Git-Tag: version-3.14.0~139 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c173ad80119821b941a4615133f6f718051cf686;p=thirdparty%2Fsqlite.git Lemon enhancement: avoid unnecessary reduce actions that convert one non-terminal into another but have no side effects. FossilOrigin-Name: a86e782ad1aa6f5a8b2c54f9dcf0fa61960843f3 --- diff --git a/manifest b/manifest index 6ea5de70eb..7893a5758b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomment\stypos\sand\simprove\sclarity\sof\spresention\sin\sLemon.\s\sThe\soutput\nshould\sbe\sidentical. -D 2016-05-23T14:24:31.372 +C Lemon\senhancement:\savoid\sunnecessary\sreduce\sactions\sthat\sconvert\sone\nnon-terminal\sinto\sanother\sbut\shave\sno\sside\seffects. +D 2016-05-23T16:15:02.530 F Makefile.in f59e0763ff448719fc1bd25513882b0567286317 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 306d73e854b1a92ea06e5d1e637faa5c44de53c7 @@ -1420,7 +1420,7 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c b622032dd14dc1315fedb81d73f4658354329fca +F tool/lemon.c b4da2f0181b4defe538eb437eb96c721cf342d39 F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1492,7 +1492,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 90411a28168f6dacf08242a25bed7d6269041417 -R 996821eb90ee3795d9bf03c89106b9e7 +P b91a5b8297756289d45c8fce0d3399c253517eb0 +R e62078de0c6378c8386e96fef92b2fe6 U drh -Z b4115b7928b4702f985a5c5bf63f70fa +Z f3f44e1ca319aa39a93bd7b358420b1f diff --git a/manifest.uuid b/manifest.uuid index 3a567c6fc6..4af496871d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b91a5b8297756289d45c8fce0d3399c253517eb0 \ No newline at end of file +a86e782ad1aa6f5a8b2c54f9dcf0fa61960843f3 \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index 2ad36eec4a..d643b341e4 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -341,6 +341,7 @@ struct action { struct state *stp; /* The new state, if a shift */ struct rule *rp; /* The rule, if a reduce */ } x; + struct symbol *spOpt; /* SHIFTREDUCE optimization to this symbol */ struct action *next; /* Next action for this state */ struct action *collide; /* Next action with the same hash */ }; @@ -532,6 +533,7 @@ void Action_add( *app = newaction; newaction->type = type; newaction->sp = sp; + newaction->spOpt = 0; if( type==SHIFT ){ newaction->x.stp = (struct state *)arg; }else{ @@ -3167,6 +3169,9 @@ int PrintAction( result = 0; break; } + if( result && ap->spOpt ){ + fprintf(fp," /* because %s==%s */", ap->sp->name, ap->spOpt->name); + } return result; } @@ -4509,7 +4514,7 @@ void ReportHeader(struct lemon *lemp) void CompressTables(struct lemon *lemp) { struct state *stp; - struct action *ap, *ap2; + struct action *ap, *ap2, *nextap; struct rule *rp, *rp2, *rbest; int nbest, n; int i; @@ -4586,6 +4591,36 @@ void CompressTables(struct lemon *lemp) } } } + + /* If a SHIFTREDUCE action specifies a rule that has a single RHS term + ** (meaning that the SHIFTREDUCE will land back in the state where it + ** started) and if there is no C-code associated with the reduce action, + ** then we can go ahead and convert the action to be the same as the + ** action for the RHS of the rule. + */ + for(i=0; instate; i++){ + stp = lemp->sorted[i]; + for(ap=stp->ap; ap; ap=nextap){ + nextap = ap->next; + if( ap->type!=SHIFTREDUCE ) continue; + rp = ap->x.rp; + if( rp->noCode==0 ) continue; + if( rp->nrhs!=1 ) continue; +#if 1 + /* Only apply this optimization to non-terminals. It would be OK to + ** apply it to terminal symbols too, but that makes the parser tables + ** larger. */ + if( ap->sp->indexnterminal ) continue; +#endif + /* If we reach this point, it means the optimization can be applied */ + nextap = ap; + for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){} + assert( ap2!=0 ); + ap->spOpt = ap2->sp; + ap->type = ap2->type; + ap->x = ap2->x; + } + } }