Enhancements to lemon to generate more compact action tables and to avoid

making array bounds tests that can never fail on action table calculations.

FossilOrigin-Name: 27d8e684db4651155c4bcb8bb44bf1c692b8c48b
This commit is contained in:
drh 2009-11-03 19:18:31 +00:00
parent 9a5f4d64f3
commit f16371d650
5 changed files with 75 additions and 49 deletions

View File

@ -1,8 +1,8 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Force\sall\sqsort()\scalls\sin\smkkeywordhash.c\sto\sbe\sstable\sso\sthat\swe\sget\npredictable\sresults\son\sdifferent\splatforms.
D 2009-11-03T13:08:17
C Enhancements\sto\slemon\sto\sgenerate\smore\scompact\saction\stables\sand\sto\savoid\nmaking\sarray\sbounds\stests\sthat\scan\snever\sfail\son\saction\stable\scalculations.
D 2009-11-03T19:18:32
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in a77dfde96ad86aafd3f71651a4333a104debe86a
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -128,7 +128,7 @@ F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
F src/insert.c 2fe2ef7bd03d6e0120e4525727c4ae7de5a2d571
F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
F src/legacy.c 303b4ffcf1ae652fcf5ef635846c563c254564f6
F src/lempar.c 0c4d1ab0a5ef2b0381eb81a732c54f68f27a574d
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 0e88a335665db0b2fb4cece3e49dcb65d832635a
F src/main.c 5e12af46a6e6149b755830f9c035be6eb77995a6
F src/malloc.c 685561d2f1602042e349aea5d7a88c3f10a63454
@ -743,8 +743,8 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/lemon.c ee5e39ce2b344ce7c81306b27a59da7698114a2d
F tool/lempar.c 2ed70b3fc896a47e07fedfe543324f008f53d223
F tool/lemon.c 3088e4dec7f93c6b0925cf5bac04c8b7c8688835
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/mkkeywordhash.c 9216336085e7a7c226a35c0bd780239968f8304f
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@ -764,14 +764,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P d66a0f31ebcc56e6f0f462b3db6aab54f7fab816
R 91e31635600cb3800baa14d4687e1d08
P 3b02df27ab63936226a90098d88535ed19c2b782
R 9657839e8a1b2321f27513cd9ab14412
U drh
Z 0bb2002d9c9d8d6a6987522657519773
Z 79535e58caedc3efe5879d698faec6dd
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFK8CtFoxKgR168RlERAvt+AJkBQI2LJH6CUrPXrZkZDQd5FHmWKwCeNWmo
X0wFI2+tf0Wum9Vwm5FmTGU=
=YTMU
iD8DBQFK8IILoxKgR168RlERAhAJAJ9pB6KdOuaqs+7SONUxYOVTE6z/WwCfZnDD
8HkIYKOVL/iazNE6Eoivw5I=
=rFC0
-----END PGP SIGNATURE-----

View File

@ -1 +1 @@
3b02df27ab63936226a90098d88535ed19c2b782
27d8e684db4651155c4bcb8bb44bf1c692b8c48b

View File

@ -131,7 +131,6 @@ static const YYMINORTYPE yyzerominor = { 0 };
** yy_default[] Default action for each state.
*/
%%
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
@ -396,14 +395,13 @@ static int yy_find_shift_action(
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
if( stateno>YY_SHIFT_COUNT
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
/* The user of ";" instead of "\000" as a statement terminator in SQLite
** means that we always have a look-ahead token. */
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
@ -421,7 +419,15 @@ static int yy_find_shift_action(
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
yy_lookahead[j]==YYWILDCARD
){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
@ -453,22 +459,22 @@ static int yy_find_reduce_action(
){
int i;
#ifdef YYERRORSYMBOL
if( stateno>YY_REDUCE_MAX ){
if( stateno>YY_REDUCE_COUNT ){
return yy_default[stateno];
}
#else
assert( stateno<=YY_REDUCE_MAX );
assert( stateno<=YY_REDUCE_COUNT );
#endif
i = yy_reduce_ofst[stateno];
assert( i!=YY_REDUCE_USE_DFLT );
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
#ifdef YYERRORSYMBOL
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}
#else
assert( i>=0 && i<YY_SZ_ACTTAB );
assert( i>=0 && i<YY_ACTTAB_COUNT );
assert( yy_lookahead[i]==iLookAhead );
#endif
return yy_action[i];

View File

@ -520,21 +520,9 @@ int acttab_insert(acttab *p){
**
** i is the index in p->aAction[] where p->mnLookahead is inserted.
*/
for(i=0; i<p->nAction+p->mnLookahead; i++){
if( p->aAction[i].lookahead<0 ){
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
if( k<0 ) break;
if( p->aAction[k].lookahead>=0 ) break;
}
if( j<p->nLookahead ) continue;
for(j=0; j<p->nAction; j++){
if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
}
if( j==p->nAction ){
break; /* Fits in empty slots */
}
}else if( p->aAction[i].lookahead==p->mnLookahead ){
for(i=p->nAction-1; i>=0; i--){
/* First look for an existing action table entry that can be reused */
if( p->aAction[i].lookahead==p->mnLookahead ){
if( p->aAction[i].action!=p->mnAction ) continue;
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
@ -553,6 +541,25 @@ int acttab_insert(acttab *p){
}
}
}
if( i<0 ){
/* If no reusable entry is found, look for an empty slot */
for(i=0; i<p->nAction; i++){
if( p->aAction[i].lookahead<0 ){
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
if( k<0 ) break;
if( p->aAction[k].lookahead>=0 ) break;
}
if( j<p->nLookahead ) continue;
for(j=0; j<p->nAction; j++){
if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
}
if( j==p->nAction ){
break; /* Fits in empty slots */
}
}
}
}
/* Insert transaction set at index i. */
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
@ -3568,7 +3575,7 @@ int mhflag; /* Output in makeheaders format if true */
struct action *ap;
struct rule *rp;
struct acttab *pActtab;
int i, j, n;
int i, j, k, n;
char *name;
int mnTknOfst, mxTknOfst;
int mnNtOfst, mxNtOfst;
@ -3727,8 +3734,9 @@ int mhflag; /* Output in makeheaders format if true */
free(ax);
/* Output the yy_action table */
fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
n = acttab_size(pActtab);
fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
for(i=j=0; i<n; i++){
int action = acttab_yyaction(pActtab, i);
if( action<0 ) action = lemp->nstate + lemp->nrule + 2;
@ -3763,7 +3771,9 @@ int mhflag; /* Output in makeheaders format if true */
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, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
fprintf(out, "static const %s yy_shift_ofst[] = {\n",
minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
for(i=j=0; i<n; i++){
@ -3786,7 +3796,9 @@ int mhflag; /* Output in makeheaders format if true */
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, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
for(i=j=0; i<n; i++){

View File

@ -125,7 +125,6 @@ static const YYMINORTYPE yyzerominor = { 0 };
** yy_default[] Default action for each state.
*/
%%
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
@ -386,12 +385,13 @@ static int yy_find_shift_action(
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
if( stateno>YY_SHIFT_COUNT
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
@ -409,7 +409,15 @@ static int yy_find_shift_action(
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
yy_lookahead[j]==YYWILDCARD
){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
@ -441,22 +449,22 @@ static int yy_find_reduce_action(
){
int i;
#ifdef YYERRORSYMBOL
if( stateno>YY_REDUCE_MAX ){
if( stateno>YY_REDUCE_COUNT ){
return yy_default[stateno];
}
#else
assert( stateno<=YY_REDUCE_MAX );
assert( stateno<=YY_REDUCE_COUNT );
#endif
i = yy_reduce_ofst[stateno];
assert( i!=YY_REDUCE_USE_DFLT );
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
#ifdef YYERRORSYMBOL
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}
#else
assert( i>=0 && i<YY_SZ_ACTTAB );
assert( i>=0 && i<YY_ACTTAB_COUNT );
assert( yy_lookahead[i]==iLookAhead );
#endif
return yy_action[i];