From: drh Date: Sat, 5 Nov 2005 15:03:59 +0000 (+0000) Subject: Improved table compression in lemon reduces the overall library size X-Git-Tag: version-3.6.10~3399 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ada354db0e1ceb8cfd47656de011d66c0f7b2dc5;p=thirdparty%2Fsqlite.git Improved table compression in lemon reduces the overall library size by about 1.5KiB. (CVS 2761) FossilOrigin-Name: 86ac11476962727d2d40b62ce87d689c01969537 --- diff --git a/manifest b/manifest index 310cb46760..40232dddcf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C VACUUM\sworks\seven\son\san\sempty\sdatabase.\s\sTicket\s#1512.\s(CVS\s2760) -D 2005-11-04T22:03:30 +C Improved\stable\scompression\sin\slemon\sreduces\sthe\soverall\slibrary\ssize\nby\sabout\s1.5KiB.\s(CVS\s2761) +D 2005-11-05T15:04:00 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -249,8 +249,8 @@ F test/view.test ce0f0ad39fa4a3572acffcf1e634850ee151aae0 F test/where.test 752728413eab42e5854690d84c7319cdf7edc515 F test/where2.test 503e2e2b6abe14c5c10222e72d08ef84c1bf1ffb F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b -F tool/lemon.c c88936c67f6411608db8fa4254d254f509fa40f6 -F tool/lempar.c f0c30abcae762a7d1eb37cd88b2232ab8dd625fb +F tool/lemon.c 0cedabac11734ec2a40286552de4af01cc859f6e +F tool/lempar.c 424df14a48736bb961ed47acf30c26d66ed85a62 F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133 F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8 F tool/memleak3.tcl 009da0ea82dc5893edca76cf1a21fb7260e9412e @@ -317,7 +317,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 7780f5e9d504926f11bd0662c03c88c76fb1d416 -R 1a3d1b527330224886b9cff041619a5d +P 1b6bf4188e8ebf55cf1972b7081f6d31bf525555 +R 0643dda995921861878ddcf931a00061 U drh -Z f1e5a520d02502b659fb8d9e06e8fb3d +Z 1e38b5f3f01e11660fc6060d64bb658c diff --git a/manifest.uuid b/manifest.uuid index 5d4d99eddd..e80907e0ef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b6bf4188e8ebf55cf1972b7081f6d31bf525555 \ No newline at end of file +86ac11476962727d2d40b62ce87d689c01969537 \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index 8f6e87330a..6cfd2c0bff 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -94,6 +94,7 @@ void ReportOutput(/* struct lemon * */); void ReportTable(/* struct lemon * */); void ReportHeader(/* struct lemon * */); void CompressTables(/* struct lemon * */); +void ResortStates(/* struct lemon * */); /********** From the file "set.h" ****************************************/ void SetSize(/* int N */); /* All sets will be of size N */ @@ -206,7 +207,7 @@ struct action { struct state { struct config *bp; /* The basis configurations for this state */ struct config *cfp; /* All configurations in this set */ - int index; /* Sequencial number for this state */ + int statenum; /* Sequencial number for this state */ struct action *ap; /* Array of actions for this state */ int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ @@ -751,7 +752,7 @@ struct lemon *lemp; MemoryCheck(stp); stp->bp = bp; /* Remember the configuration basis */ stp->cfp = cfp; /* Remember the configuration closure */ - stp->index = lemp->nstate++; /* Every state gets a sequence number */ + stp->statenum = lemp->nstate++; /* Every state gets a sequence number */ stp->ap = 0; /* No actions, yet. */ State_insert(stp,stp->bp); /* Add to the state table */ buildshifts(lemp,stp); /* Recursively compute successor states */ @@ -1445,6 +1446,10 @@ char **argv; /* Compress the action tables */ if( compress==0 ) CompressTables(&lem); + /* Reorder and renumber the states so that states with fewer choices + ** occur at the end. */ + ResortStates(&lem); + /* Generate a report of the parser generated. (the "y.output" file) */ if( !quiet ) ReportOutput(&lem); @@ -2697,7 +2702,7 @@ struct plink *plp; char *tag; { while( plp ){ - fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index); + fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum); ConfigPrint(out,plp->cfp); fprintf(out,"\n"); plp = plp->next; @@ -2712,7 +2717,7 @@ int PrintAction(struct action *ap, FILE *fp, int indent){ int result = 1; switch( ap->type ){ case SHIFT: - fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->index); + fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->statenum); break; case REDUCE: fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index); @@ -2751,7 +2756,7 @@ struct lemon *lemp; fprintf(fp," \b"); for(i=0; instate; i++){ stp = lemp->sorted[i]; - fprintf(fp,"State %d:\n",stp->index); + fprintf(fp,"State %d:\n",stp->statenum); if( lemp->basisflag ) cfp=stp->bp; else cfp=stp->cfp; while( cfp ){ @@ -2837,7 +2842,7 @@ struct action *ap; { int act; switch( ap->type ){ - case SHIFT: act = ap->x.stp->index; break; + case SHIFT: act = ap->x.stp->statenum; break; case REDUCE: act = ap->x.rp->index + lemp->nstate; break; case ERROR: act = lemp->nstate + lemp->nrule; break; case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break; @@ -3457,21 +3462,6 @@ int mhflag; /* Output in makeheaders format if true */ } for(i=0; instate; i++){ stp = lemp->sorted[i]; - stp->nTknAct = stp->nNtAct = 0; - stp->iDflt = lemp->nstate + lemp->nrule; - stp->iTknOfst = NO_OFFSET; - stp->iNtOfst = NO_OFFSET; - for(ap=stp->ap; ap; ap=ap->next){ - if( compute_action(lemp,ap)>=0 ){ - if( ap->sp->indexnterminal ){ - stp->nTknAct++; - }else if( ap->sp->indexnsymbol ){ - stp->nNtAct++; - }else{ - stp->iDflt = compute_action(lemp, ap); - } - } - } ax[i*2].stp = stp; ax[i*2].isTkn = 1; ax[i*2].nAction = stp->nTknAct; @@ -3552,9 +3542,11 @@ int mhflag; /* Output in makeheaders format if true */ /* Output the yy_shift_ofst[] table */ fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; + n = lemp->nstate; + while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; + fprintf(out, "#define YY_SHIFT_MAX %d\n", n-1); lineno++; fprintf(out, "static const %s yy_shift_ofst[] = {\n", minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++; - n = lemp->nstate; for(i=j=0; isorted[i]; @@ -3573,9 +3565,11 @@ int mhflag; /* Output in makeheaders format if true */ /* Output the yy_reduce_ofst[] table */ fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; + n = lemp->nstate; + while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--; + fprintf(out, "#define YY_REDUCE_MAX %d\n", n-1); lineno++; fprintf(out, "static const %s yy_reduce_ofst[] = {\n", minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++; - n = lemp->nstate; for(i=j=0; isorted[i]; @@ -3789,7 +3783,7 @@ struct lemon *lemp; ** of defaults. ** ** In this version, we take the most frequent REDUCE action and make -** it the default. Only default a reduce if there are more than one. +** it the default. */ void CompressTables(lemp) struct lemon *lemp; @@ -3823,8 +3817,8 @@ struct lemon *lemp; } /* Do not make a default if the number of rules to default - ** is not at least 2 */ - if( nbest<2 ) continue; + ** is not at least 1 */ + if( nbest<1 ) continue; /* Combine matching REDUCE actions into a single default */ @@ -3840,6 +3834,63 @@ struct lemon *lemp; } } + +/* +** Compare two states for sorting purposes. The smaller state is the +** one with the most non-terminal actions. If they have the same number +** of non-terminal actions, then the smaller is the one with the most +** token actions. +*/ +static int stateResortCompare(const void *a, const void *b){ + const struct state *pA = *(const struct state**)a; + const struct state *pB = *(const struct state**)b; + int n; + + n = pB->nNtAct - pA->nNtAct; + if( n==0 ){ + n = pB->nTknAct - pA->nTknAct; + } + return n; +} + + +/* +** Renumber and resort states so that states with fewer choices +** occur at the end. Except, keep state 0 as the first state. +*/ +void ResortStates(lemp) +struct lemon *lemp; +{ + int i; + struct state *stp; + struct action *ap; + + for(i=0; instate; i++){ + stp = lemp->sorted[i]; + stp->nTknAct = stp->nNtAct = 0; + stp->iDflt = lemp->nstate + lemp->nrule; + stp->iTknOfst = NO_OFFSET; + stp->iNtOfst = NO_OFFSET; + for(ap=stp->ap; ap; ap=ap->next){ + if( compute_action(lemp,ap)>=0 ){ + if( ap->sp->indexnterminal ){ + stp->nTknAct++; + }else if( ap->sp->indexnsymbol ){ + stp->nNtAct++; + }else{ + stp->iDflt = compute_action(lemp, ap); + } + } + } + } + qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]), + stateResortCompare); + for(i=0; instate; i++){ + lemp->sorted[i]->statenum = i; + } +} + + /***************** From the file "set.c" ************************************/ /* ** Set manipulation routines for the LEMON parser generator. diff --git a/tool/lempar.c b/tool/lempar.c index 57ec97f6a8..7a549a7c52 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -326,9 +326,7 @@ static int yy_find_shift_action( int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ){ + if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ @@ -370,8 +368,8 @@ static int yy_find_reduce_action( int i; /* int stateno = pParser->yystack[pParser->yyidx].stateno; */ - i = yy_reduce_ofst[stateno]; - if( i==YY_REDUCE_USE_DFLT ){ + if( stateno>YY_REDUCE_MAX || + (i = yy_reduce_ofst[stateno])==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){