From: drh Date: Sat, 23 Feb 2002 19:39:46 +0000 (+0000) Subject: Modify lemon to use much less memory for its parser tables. This reduces X-Git-Tag: version-3.6.10~5628 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b29b0a52275a8df96fecce1e7b3d3e5830fe13c9;p=thirdparty%2Fsqlite.git Modify lemon to use much less memory for its parser tables. This reduces the size of the library by 50K, which is important for an embedded library. (CVS 389) FossilOrigin-Name: 67a135a051e7c96ddbfe85976539b4b8372c7026 --- diff --git a/manifest b/manifest index 721b6f8326..6d41043211 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bug\sfix\sin\slemon:\s3-way\sconflicts\s(SHIFT/REDUCE/REDUCE)\swere\snot\sdetected\sor\nresolved.\s\sThis\sis\snow\sfixed.\s\sAlso,\stable\scompression\sworks\sa\slittle\sbetter.\s(CVS\s388) -D 2002-02-23T18:45:13 +C Modify\slemon\sto\suse\smuch\sless\smemory\sfor\sits\sparser\stables.\s\sThis\sreduces\nthe\ssize\sof\sthe\slibrary\sby\s50K,\swhich\sis\simportant\sfor\san\sembedded\slibrary.\s(CVS\s389) +D 2002-02-23T19:39:47 F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -99,8 +99,8 @@ F test/unique.test 07776624b82221a80c8b4138ce0dd8b0853bb3ea F test/update.test 3cf1ca0565f678063c2dfa9a7948d2d66ae1a778 F test/vacuum.test 8acf8669f3b627e54149b25165b034aa06c2432e F test/where.test 032d581c3de4893eba33b569e581c46b941bb02a -F tool/lemon.c 7502222a5d704d9d5d1ac437f73667855d687862 -F tool/lempar.c 9b604e6a8b3d55c0b9cbcb130a7302fb8bafe2b9 +F tool/lemon.c d4b4e127e70633be1bbea49c2ccba5cdb4b77a5f +F tool/lempar.c 2ff255186fffb38a43a9f7b010e87eee6308edcc F tool/memleak.awk 296dfbce7a9ca499b95ce04e30334e64a50052e0 F tool/opNames.awk 5ba1f48aa854ee3b7c3d2b54233665bc3e649ea2 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c @@ -125,7 +125,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 39fed2df11382b9855d518502a6c2ca200fa66b8 -R bbf759a9eca350d9e39199c34c6ab1fb +P 8da0ac9a8bb859377613dd18f4f423eb49c7338b +R a10568441a27cde980e4058838f315f0 U drh -Z 95f9230334dd6740861a9a25c1c709f1 +Z 77767b7d4f55ba40f2761ab26d448e78 diff --git a/manifest.uuid b/manifest.uuid index 0115377959..ed839134c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8da0ac9a8bb859377613dd18f4f423eb49c7338b \ No newline at end of file +67a135a051e7c96ddbfe85976539b4b8372c7026 \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index 3e641a4d46..eae3c09fd4 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -2927,6 +2927,20 @@ int mhflag; /* True if generating makeheaders output */ *plineno = lineno; } +/* +** Return the name of a C datatype able to represent values between +** 0 and N, inclusive. +*/ +static const char *minimum_size_type(int N){ + if( N<=255 ){ + return "unsigned char"; + }else if( N<65535 ){ + return "unsigned short int"; + }else{ + return "unsigned int"; + } +} + /* Generate C source code for the parser */ void ReportTable(lemp, mhflag) struct lemon *lemp; @@ -2978,10 +2992,10 @@ int mhflag; /* Output in makeheaders format if true */ /* Generate the defines */ fprintf(out,"/* \001 */\n"); fprintf(out,"#define YYCODETYPE %s\n", - lemp->nsymbol>250?"int":"unsigned char"); lineno++; + minimum_size_type(lemp->nsymbol+5)); lineno++; fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++; fprintf(out,"#define YYACTIONTYPE %s\n", - lemp->nstate+lemp->nrule>250?"int":"unsigned char"); lineno++; + minimum_size_type(lemp->nstate+lemp->nrule+5)); lineno++; print_stack_union(out,lemp,&lineno,mhflag); if( lemp->stacksize ){ if( atoi(lemp->stacksize)<=0 ){ @@ -3027,13 +3041,16 @@ int mhflag; /* Output in makeheaders format if true */ ** structure: ** struct yyActionEntry { ** YYCODETYPE lookahead; + ** YYCODETYPE next; ** YYACTIONTYPE action; - ** struct yyActionEntry *next; ** } ** ** The entries are grouped into hash tables, one hash table for each - ** parser state. The hash table has a size which is the smallest - ** power of two needed to hold all entries. + ** parser state. The hash table has a size which is the number of + ** entries in that table. In case of a collision, the "next" value + ** contains one more than the index into the hash table of the next + ** entry in the collision chain. A "next" value of 0 means the end + ** of the chain has been reached. */ tablecnt = 0; @@ -3053,8 +3070,7 @@ int mhflag; /* Output in makeheaders format if true */ stp->naction++; } } - tablesize = 1; - while( tablesizenaction ) tablesize += tablesize; + tablesize = stp->naction; assert( tablesize<= sizeof(table)/sizeof(table[0]) ); for(j=0; jsp->index==lemp->nsymbol ){ stp->tabdfltact = action; }else if( action>=0 ){ - h = ap->sp->index & (tablesize-1); + h = ap->sp->index % tablesize; ap->collide = table[h]; table[h] = ap; } @@ -3089,22 +3105,13 @@ int mhflag; /* Output in makeheaders format if true */ /* Print the hash table */ fprintf(out,"/* State %d */\n",stp->index); lineno++; for(j=0; jsp->index, + collide[j]+1, compute_action(lemp,table[j])); - if( collide[j]>=0 ){ - fprintf(out,"&yyActionTable[%4d] }, /* ", - collide[j] + tablecnt); - }else{ - fprintf(out,"0 }, /* "); - } - PrintAction(table[j],out,22); - fprintf(out," */\n"); - } + PrintAction(table[j],out,22); + fprintf(out," */\n"); lineno++; } @@ -3119,18 +3126,15 @@ int mhflag; /* Output in makeheaders format if true */ ** Each entry is an element of the following structure: ** struct yyStateEntry { ** struct yyActionEntry *hashtbl; - ** int mask; + ** YYCODETYPE nEntry; ** YYACTIONTYPE actionDefault; ** } */ for(i=0; instate; i++){ - int tablesize; stp = lemp->sorted[i]; - tablesize = 1; - while( tablesizenaction ) tablesize += tablesize; - fprintf(out," { &yyActionTable[%d], %d, %d},\n", + fprintf(out," { &yyActionTable[%d],%4d,%4d },\n", stp->tabstart, - tablesize - 1, + stp->naction, stp->tabdfltact); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); diff --git a/tool/lempar.c b/tool/lempar.c index a0b066f9d8..6a2cd08747 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -76,8 +76,8 @@ */ struct yyActionEntry { YYCODETYPE lookahead; /* The value of the look-ahead token */ + YYCODETYPE next; /* Next entry + 1. Zero at end of collision chain */ YYACTIONTYPE action; /* Action to take for this look-ahead */ - struct yyActionEntry *next; /* Next look-ahead with the same hash, or NULL */ }; static struct yyActionEntry yyActionTable[] = { %% @@ -89,15 +89,14 @@ static struct yyActionEntry yyActionTable[] = { ** ** + A pointer to the start of the action hash table in yyActionTable. ** -** + A mask used to hash the look-ahead token. The mask is an integer -** which is one less than the size of the hash table. +** + The number of entries in the action hash table. ** ** + The default action. This is the action to take if no entry for ** the given look-ahead is found in the action hash table. */ struct yyStateEntry { struct yyActionEntry *hashtbl; /* Start of the hash table in yyActionTable */ - int mask; /* Mask used for hashing the look-ahead */ + YYCODETYPE nEntry; /* Number of entries in action hash table */ YYACTIONTYPE actionDefault; /* Default action if look-ahead not found */ }; static struct yyStateEntry yyStateTable[] = { @@ -297,13 +296,16 @@ static int yy_find_parser_action( /* if( pParser->idx<0 ) return YY_NO_ACTION; */ pState = &yyStateTable[pParser->top->stateno]; - if( iLookAhead!=YYNOCODE ){ - pAction = &pState->hashtbl[iLookAhead & pState->mask]; - while( pAction ){ + if( pState->nEntry==0 ){ + return pState->actionDefault; + }else if( iLookAhead!=YYNOCODE ){ + pAction = &pState->hashtbl[iLookAhead % pState->nEntry]; + while( 1 ){ if( pAction->lookahead==iLookAhead ) return pAction->action; - pAction = pAction->next; + if( pAction->next==0 ) return pState->actionDefault; + pAction = &pState->hashtbl[pAction->next-1]; } - }else if( pState->mask!=0 || pState->hashtbl->lookahead!=YYNOCODE ){ + }else if( pState->hashtbl->lookahead!=YYNOCODE ){ return YY_NO_ACTION; } return pState->actionDefault;