summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/tool/lemon.c
diff options
context:
space:
mode:
authorIlia Alshanetsky <iliaa@php.net>2006-08-14 16:35:23 +0000
committerIlia Alshanetsky <iliaa@php.net>2006-08-14 16:35:23 +0000
commit5c01690d9b6b84ad576787f38805a85f75b3b82f (patch)
tree701b795de27a18b9ee9e376eedd186a834cfa86a /ext/pdo_sqlite/sqlite/tool/lemon.c
parent3717342c9f6c08005cf3c32c721c81611a21d268 (diff)
downloadphp-git-5c01690d9b6b84ad576787f38805a85f75b3b82f.tar.gz
MFB: Upgraded libsqlite in pdo_sqlite to 3.3.7
Diffstat (limited to 'ext/pdo_sqlite/sqlite/tool/lemon.c')
-rw-r--r--ext/pdo_sqlite/sqlite/tool/lemon.c298
1 files changed, 239 insertions, 59 deletions
diff --git a/ext/pdo_sqlite/sqlite/tool/lemon.c b/ext/pdo_sqlite/sqlite/tool/lemon.c
index 8f6e87330a..759e1c3786 100644
--- a/ext/pdo_sqlite/sqlite/tool/lemon.c
+++ b/ext/pdo_sqlite/sqlite/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 */
@@ -119,7 +120,8 @@ struct symbol {
int index; /* Index number for this symbol */
enum {
TERMINAL,
- NONTERMINAL
+ NONTERMINAL,
+ MULTITERMINAL
} type; /* Symbols are all either TERMINALS or NTs */
struct rule *rule; /* Linked list of rules of this (if an NT) */
struct symbol *fallback; /* fallback token in case this token doesn't parse */
@@ -140,6 +142,9 @@ struct symbol {
int dtnum; /* The data type number. In the parser, the value
** stack is a union. The .yy%d element of this
** union is the correct data type for this object */
+ /* The following fields are used by MULTITERMINALs only */
+ int nsubsym; /* Number of constituent symbols in the MULTI */
+ struct symbol **subsym; /* Array of constituent symbols */
};
/* Each production rule in the grammar is stored in the following
@@ -206,7 +211,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 */
@@ -236,6 +241,7 @@ struct lemon {
struct symbol **symbols; /* Sorted array of pointers to symbols */
int errorcnt; /* Number of errors */
struct symbol *errsym; /* The error symbol */
+ struct symbol *wildcard; /* Token that matches anything */
char *name; /* Name of the generated parser */
char *arg; /* Declaration of the 3th argument to parser */
char *tokentype; /* Type of terminal symbols in the parser stack */
@@ -584,11 +590,18 @@ struct lemon *xp;
struct rule *rp;
for(rp=xp->rule; rp; rp=rp->next){
if( rp->precsym==0 ){
- int i;
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]->prec>=0 ){
+ int i, j;
+ for(i=0; i<rp->nrhs && rp->precsym==0; i++){
+ struct symbol *sp = rp->rhs[i];
+ if( sp->type==MULTITERMINAL ){
+ for(j=0; j<sp->nsubsym; j++){
+ if( sp->subsym[j]->prec>=0 ){
+ rp->precsym = sp->subsym[j];
+ break;
+ }
+ }
+ }else if( sp->prec>=0 ){
rp->precsym = rp->rhs[i];
- break;
}
}
}
@@ -604,7 +617,7 @@ struct lemon *xp;
void FindFirstSets(lemp)
struct lemon *lemp;
{
- int i;
+ int i, j;
struct rule *rp;
int progress;
@@ -621,7 +634,8 @@ struct lemon *lemp;
for(rp=lemp->rule; rp; rp=rp->next){
if( rp->lhs->lambda ) continue;
for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]->lambda==B_FALSE ) break;
+ struct symbol *sp = rp->rhs[i];
+ if( sp->type!=TERMINAL || sp->lambda==B_FALSE ) break;
}
if( i==rp->nrhs ){
rp->lhs->lambda = B_TRUE;
@@ -641,6 +655,11 @@ struct lemon *lemp;
if( s2->type==TERMINAL ){
progress += SetAdd(s1->firstset,s2->index);
break;
+ }else if( s2->type==MULTITERMINAL ){
+ for(j=0; j<s2->nsubsym; j++){
+ progress += SetAdd(s1->firstset,s2->subsym[j]->index);
+ }
+ break;
}else if( s1==s2 ){
if( s1->lambda==B_FALSE ) break;
}else{
@@ -687,7 +706,7 @@ symbol instead.",lemp->start,lemp->rule->lhs->name);
for(rp=lemp->rule; rp; rp=rp->next){
int i;
for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]==sp ){
+ if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */
ErrorMsg(lemp->filename,0,
"The start symbol \"%s\" occurs on the \
right-hand side of a rule. This will result in a parser which \
@@ -751,7 +770,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 */
@@ -759,6 +778,24 @@ struct lemon *lemp;
return stp;
}
+/*
+** Return true if two symbols are the same.
+*/
+int same_symbol(a,b)
+struct symbol *a;
+struct symbol *b;
+{
+ int i;
+ if( a==b ) return 1;
+ if( a->type!=MULTITERMINAL ) return 0;
+ if( b->type!=MULTITERMINAL ) return 0;
+ if( a->nsubsym!=b->nsubsym ) return 0;
+ for(i=0; i<a->nsubsym; i++){
+ if( a->subsym[i]!=b->subsym[i] ) return 0;
+ }
+ return 1;
+}
+
/* Construct all successor states to the given state. A "successor"
** state is any state which can be reached by a shift action.
*/
@@ -791,7 +828,7 @@ struct state *stp; /* The state from which successors are computed */
if( bcfp->status==COMPLETE ) continue; /* Already used */
if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
- if( bsp!=sp ) continue; /* Must be same as for "cfp" */
+ if( !same_symbol(bsp,sp) ) continue; /* Must be same as for "cfp" */
bcfp->status = COMPLETE; /* Mark this config as used */
new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
Plink_add(&new->bplp,bcfp);
@@ -803,7 +840,14 @@ struct state *stp; /* The state from which successors are computed */
/* The state "newstp" is reached from the state "stp" by a shift action
** on the symbol "sp" */
- Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
+ if( sp->type==MULTITERMINAL ){
+ int i;
+ for(i=0; i<sp->nsubsym; i++){
+ Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
+ }
+ }else{
+ Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
+ }
}
}
@@ -1166,6 +1210,12 @@ struct lemon *lemp;
if( xsp->type==TERMINAL ){
SetAdd(newcfp->fws,xsp->index);
break;
+ }else if( xsp->type==MULTITERMINAL ){
+ int k;
+ for(k=0; k<xsp->nsubsym; k++){
+ SetAdd(newcfp->fws, xsp->subsym[k]->index);
+ }
+ break;
}else{
SetUnion(newcfp->fws,xsp->firstset);
if( xsp->lambda==B_FALSE ) break;
@@ -1373,6 +1423,7 @@ char **argv;
fprintf(stderr,"Exactly one filename argument is required.\n");
exit(1);
}
+ memset(&lem, 0, sizeof(lem));
lem.errorcnt = 0;
/* Initialize the machine */
@@ -1382,22 +1433,13 @@ char **argv;
lem.argv0 = argv[0];
lem.filename = OptArg(0);
lem.basisflag = basisflag;
- lem.has_fallback = 0;
- lem.nconflict = 0;
- lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
- lem.vartype = 0;
- lem.stacksize = 0;
- lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
- lem.tokenprefix = lem.outname = lem.extracode = 0;
- lem.vardest = 0;
- lem.tablesize = 0;
Symbol_new("$");
lem.errsym = Symbol_new("error");
/* Parse the input file */
Parse(&lem);
if( lem.errorcnt ) exit(lem.errorcnt);
- if( lem.rule==0 ){
+ if( lem.nrule==0 ){
fprintf(stderr,"Empty grammar.\n");
exit(1);
}
@@ -1445,6 +1487,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);
@@ -1694,6 +1740,7 @@ FILE *err;
int j;
int errcnt = 0;
cp = strchr(argv[i],'=');
+ assert( cp!=0 );
*cp = 0;
for(j=0; op[j].label; j++){
if( strcmp(argv[i],op[j].label)==0 ) break;
@@ -1906,7 +1953,8 @@ struct pstate {
RESYNC_AFTER_DECL_ERROR,
WAITING_FOR_DESTRUCTOR_SYMBOL,
WAITING_FOR_DATATYPE_SYMBOL,
- WAITING_FOR_FALLBACK_ID
+ WAITING_FOR_FALLBACK_ID,
+ WAITING_FOR_WILDCARD_ID
} state; /* The state of the parser */
struct symbol *fallback; /* The fallback token */
struct symbol *lhs; /* Left-hand side of current rule */
@@ -2086,7 +2134,7 @@ to follow the previous rule.");
}else if( isalpha(x[0]) ){
if( psp->nrhs>=MAXRHS ){
ErrorMsg(psp->filename,psp->tokenlineno,
- "Too many symbol on RHS or rule beginning at \"%s\".",
+ "Too many symbols on RHS or rule beginning at \"%s\".",
x);
psp->errorcnt++;
psp->state = RESYNC_AFTER_RULE_ERROR;
@@ -2095,6 +2143,27 @@ to follow the previous rule.");
psp->alias[psp->nrhs] = 0;
psp->nrhs++;
}
+ }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
+ struct symbol *msp = psp->rhs[psp->nrhs-1];
+ if( msp->type!=MULTITERMINAL ){
+ struct symbol *origsp = msp;
+ msp = malloc(sizeof(*msp));
+ memset(msp, 0, sizeof(*msp));
+ msp->type = MULTITERMINAL;
+ msp->nsubsym = 1;
+ msp->subsym = malloc(sizeof(struct symbol*));
+ msp->subsym[0] = origsp;
+ msp->name = origsp->name;
+ psp->rhs[psp->nrhs-1] = msp;
+ }
+ msp->nsubsym++;
+ msp->subsym = realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym);
+ msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
+ if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){
+ ErrorMsg(psp->filename,psp->tokenlineno,
+ "Cannot form a compound containing a non-terminal");
+ psp->errorcnt++;
+ }
}else if( x[0]=='(' && psp->nrhs>0 ){
psp->state = RHS_ALIAS_1;
}else{
@@ -2189,6 +2258,8 @@ to follow the previous rule.");
}else if( strcmp(x,"fallback")==0 ){
psp->fallback = 0;
psp->state = WAITING_FOR_FALLBACK_ID;
+ }else if( strcmp(x,"wildcard")==0 ){
+ psp->state = WAITING_FOR_WILDCARD_ID;
}else{
ErrorMsg(psp->filename,psp->tokenlineno,
"Unknown declaration keyword: \"%%%s\".",x);
@@ -2289,6 +2360,24 @@ to follow the previous rule.");
}
}
break;
+ case WAITING_FOR_WILDCARD_ID:
+ if( x[0]=='.' ){
+ psp->state = WAITING_FOR_DECL_OR_RULE;
+ }else if( !isupper(x[0]) ){
+ ErrorMsg(psp->filename, psp->tokenlineno,
+ "%%wildcard argument \"%s\" should be a token", x);
+ psp->errorcnt++;
+ }else{
+ struct symbol *sp = Symbol_new(x);
+ if( psp->gp->wildcard==0 ){
+ psp->gp->wildcard = sp;
+ }else{
+ ErrorMsg(psp->filename, psp->tokenlineno,
+ "Extra wildcard to token: %s", x);
+ psp->errorcnt++;
+ }
+ }
+ break;
case RESYNC_AFTER_RULE_ERROR:
/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
** break; */
@@ -2482,6 +2571,10 @@ struct lemon *gp;
}else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
cp += 3;
nextcp = cp;
+ }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){
+ cp += 2;
+ while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
+ nextcp = cp;
}else{ /* All other (one character) operators */
cp++;
nextcp = cp;
@@ -2641,15 +2734,21 @@ struct lemon *lemp;
}
for(rp=lemp->rule; rp; rp=rp->next){
printf("%s",rp->lhs->name);
-/* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
+ /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
printf(" ::=");
for(i=0; i<rp->nrhs; i++){
- printf(" %s",rp->rhs[i]->name);
-/* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
+ sp = rp->rhs[i];
+ printf(" %s", sp->name);
+ if( sp->type==MULTITERMINAL ){
+ for(j=1; j<sp->nsubsym; j++){
+ printf("|%s", sp->subsym[j]->name);
+ }
+ }
+ /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
}
printf(".");
if( rp->precsym ) printf(" [%s]",rp->precsym->name);
-/* if( rp->code ) printf("\n %s",rp->code); */
+ /* if( rp->code ) printf("\n %s",rp->code); */
printf("\n");
}
}
@@ -2659,18 +2758,25 @@ FILE *fp;
struct config *cfp;
{
struct rule *rp;
- int i;
+ struct symbol *sp;
+ int i, j;
rp = cfp->rp;
fprintf(fp,"%s ::=",rp->lhs->name);
for(i=0; i<=rp->nrhs; i++){
if( i==cfp->dot ) fprintf(fp," *");
if( i==rp->nrhs ) break;
- fprintf(fp," %s",rp->rhs[i]->name);
+ sp = rp->rhs[i];
+ fprintf(fp," %s", sp->name);
+ if( sp->type==MULTITERMINAL ){
+ for(j=1; j<sp->nsubsym; j++){
+ fprintf(fp,"|%s",sp->subsym[j]->name);
+ }
+ }
}
}
/* #define TEST */
-#ifdef TEST
+#if 0
/* Print a set */
PRIVATE void SetPrint(out,set,lemp)
FILE *out;
@@ -2697,7 +2803,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 +2818,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 +2857,7 @@ struct lemon *lemp;
fprintf(fp," \b");
for(i=0; i<lemp->nstate; 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 ){
@@ -2764,7 +2870,7 @@ struct lemon *lemp;
}
ConfigPrint(fp,cfp);
fprintf(fp,"\n");
-#ifdef TEST
+#if 0
SetPrint(fp,cfp->fws,lemp);
PlinkPrint(fp,cfp->fplp,"To ");
PlinkPrint(fp,cfp->bplp,"From");
@@ -2837,7 +2943,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;
@@ -3108,8 +3214,14 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
** the token number of X, not the value of X */
append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
}else{
- append_str("yymsp[%d].minor.yy%d",0,
- i-rp->nrhs+1,rp->rhs[i]->dtnum);
+ struct symbol *sp = rp->rhs[i];
+ int dtnum;
+ if( sp->type==MULTITERMINAL ){
+ dtnum = sp->subsym[0]->dtnum;
+ }else{
+ dtnum = sp->dtnum;
+ }
+ append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
}
cp = xp;
used[i] = 1;
@@ -3391,6 +3503,10 @@ int mhflag; /* Output in makeheaders format if true */
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
fprintf(out,"#define YYACTIONTYPE %s\n",
minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++;
+ if( lemp->wildcard ){
+ fprintf(out,"#define YYWILDCARD %d\n",
+ lemp->wildcard->index); lineno++;
+ }
print_stack_union(out,lemp,&lineno,mhflag);
if( lemp->stacksize ){
if( atoi(lemp->stacksize)<=0 ){
@@ -3457,21 +3573,6 @@ int mhflag; /* Output in makeheaders format if true */
}
for(i=0; i<lemp->nstate; 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->index<lemp->nterminal ){
- stp->nTknAct++;
- }else if( ap->sp->index<lemp->nsymbol ){
- 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 +3653,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; i<n; i++){
int ofst;
stp = lemp->sorted[i];
@@ -3573,9 +3676,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; i<n; i++){
int ofst;
stp = lemp->sorted[i];
@@ -3642,7 +3747,16 @@ int mhflag; /* Output in makeheaders format if true */
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
assert( rp->index==i );
fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
- for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
+ for(j=0; j<rp->nrhs; j++){
+ struct symbol *sp = rp->rhs[j];
+ fprintf(out," %s", sp->name);
+ if( sp->type==MULTITERMINAL ){
+ int k;
+ for(k=1; k<sp->nsubsym; k++){
+ fprintf(out,"|%s",sp->subsym[k]->name);
+ }
+ }
+ }
fprintf(out,"\",\n"); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
@@ -3789,7 +3903,8 @@ 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. Except, there is no default if the wildcard token
+** is a possible look-ahead.
*/
void CompressTables(lemp)
struct lemon *lemp;
@@ -3799,13 +3914,18 @@ struct lemon *lemp;
struct rule *rp, *rp2, *rbest;
int nbest, n;
int i;
+ int usesWildcard;
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
nbest = 0;
rbest = 0;
+ usesWildcard = 0;
for(ap=stp->ap; ap; ap=ap->next){
+ if( ap->type==SHIFT && ap->sp==lemp->wildcard ){
+ usesWildcard = 1;
+ }
if( ap->type!=REDUCE ) continue;
rp = ap->x.rp;
if( rp==rbest ) continue;
@@ -3823,8 +3943,10 @@ 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 or if the wildcard token is a possible
+ ** lookahead.
+ */
+ if( nbest<1 || usesWildcard ) continue;
/* Combine matching REDUCE actions into a single default */
@@ -3840,6 +3962,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; i<lemp->nstate; 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->index<lemp->nterminal ){
+ stp->nTknAct++;
+ }else if( ap->sp->index<lemp->nsymbol ){
+ stp->nNtAct++;
+ }else{
+ stp->iDflt = compute_action(lemp, ap);
+ }
+ }
+ }
+ }
+ qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
+ stateResortCompare);
+ for(i=0; i<lemp->nstate; i++){
+ lemp->sorted[i]->statenum = i;
+ }
+}
+
+
/***************** From the file "set.c" ************************************/
/*
** Set manipulation routines for the LEMON parser generator.
@@ -3932,6 +4111,7 @@ char *y;
{
char *z;
+ if( y==0 ) return 0;
z = Strsafe_find(y);
if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
strcpy(z,y);