Lemon update 2016-02-17 01:18:33 on branch parser-performance

- In Lemon, add the ability for the left-most RHS label to be the same as the LHS label, causing the LHS values to be written directly into the stack. (user: drh)
This commit is contained in:
Randy Heit 2016-03-20 10:50:28 -05:00
parent 75f6d3a438
commit 8a18e5c7eb
2 changed files with 112 additions and 23 deletions

View file

@ -190,6 +190,8 @@ struct rule {
const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */ const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
int line; /* Line number at which code begins */ int line; /* Line number at which code begins */
const char *code; /* The code executed when this rule is reduced */ const char *code; /* The code executed when this rule is reduced */
const char *codePrefix; /* Setup code before code[] above */
const char *codeSuffix; /* Breakdown code after code[] above */
struct symbol *precsym; /* Precedence symbol for this rule */ struct symbol *precsym; /* Precedence symbol for this rule */
int index; /* An index number for this rule */ int index; /* An index number for this rule */
Boolean canReduce; /* True if this rule is ever reduced */ Boolean canReduce; /* True if this rule is ever reduced */
@ -3365,6 +3367,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2, int bNoSubst)
int c; int c;
char zInt[40]; char zInt[40];
if( zText==0 ){ if( zText==0 ){
if( used==0 && z!=0 ) z[0] = 0;
used = 0; used = 0;
return z; return z;
} }
@ -3406,7 +3409,9 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
char *cp, *xp; char *cp, *xp;
int i; int i;
char lhsused = 0; /* True if the LHS element has been used */ char lhsused = 0; /* True if the LHS element has been used */
char lhsdirect; /* True if LHS writes directly into stack */
char used[MAXRHS]; /* True for each RHS element which is used */ char used[MAXRHS]; /* True for each RHS element which is used */
char zLhs[50]; /* Convert the LHS symbol into this string */
for(i=0; i<rp->nrhs; i++) used[i] = 0; for(i=0; i<rp->nrhs; i++) used[i] = 0;
lhsused = 0; lhsused = 0;
@ -3417,6 +3422,47 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
rp->line = rp->ruleline; rp->line = rp->ruleline;
} }
if( rp->lhsalias==0 ){
/* There is no LHS value symbol. */
lhsdirect = 1;
}else if( rp->nrhs==0 ){
/* If there are no RHS symbols, then writing directly to the LHS is ok */
lhsdirect = 1;
}else if( rp->rhsalias[0]==0 ){
/* The left-most RHS symbol has not value. LHS direct is ok. But
** we have to call the distructor on the RHS symbol first. */
lhsdirect = 1;
if( has_destructor(rp->rhs[0],lemp) ){
append_str(0,0,0,0,0);
append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
rp->rhs[0]->index,1-rp->nrhs,0);
rp->codePrefix = Strsafe(append_str(0,0,0,0,0));
}
}else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
/* The LHS symbol and the left-most RHS symbol are the same, so
** direct writing is allowed */
lhsdirect = 1;
lhsused = 1;
used[0] = 1;
if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){
ErrorMsg(lemp->filename,rp->ruleline,
"%s(%s) and %s(%s) share the same label but have "
"different datatypes.",
rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]);
lemp->errorcnt++;
}
}else{
lhsdirect = 0;
}
if( lhsdirect ){
sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
}else{
append_str(0,0,0,0,0);
append_str(" YYMINORTYPE yylhsminor;\n", 0, 0, 0, 0);
rp->codePrefix = Strsafe(append_str(0,0,0,0,0));
sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
}
append_str(0,0,0,0,0); append_str(0,0,0,0,0);
/* This const cast is wrong but harmless, if we're careful. */ /* This const cast is wrong but harmless, if we're careful. */
@ -3427,7 +3473,7 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
saved = *xp; saved = *xp;
*xp = 0; *xp = 0;
if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0,0); append_str(zLhs,0,0,0,0);
cp = xp; cp = xp;
lhsused = 1; lhsused = 1;
}else{ }else{
@ -3458,6 +3504,11 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
append_str(cp, 1, 0, 0, 1); append_str(cp, 1, 0, 0, 1);
} /* End loop */ } /* End loop */
/* Main code generation completed */
cp = append_str(0,0,0,0,0);
if( cp && cp[0] ) rp->code = Strsafe(cp);
append_str(0,0,0,0,0);
/* Check to make sure the LHS has been used */ /* Check to make sure the LHS has been used */
if( rp->lhsalias && !lhsused ){ if( rp->lhsalias && !lhsused ){
ErrorMsg(lemp->filename,rp->ruleline, ErrorMsg(lemp->filename,rp->ruleline,
@ -3466,27 +3517,53 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
lemp->errorcnt++; lemp->errorcnt++;
} }
/* Generate destructor code for RHS symbols which are not used in the /* Generate destructor code for RHS minor values which are not referenced.
** reduce code */ ** Generate error messages for unused labels and duplicate labels.
*/
for(i=0; i<rp->nrhs; i++){ for(i=0; i<rp->nrhs; i++){
if( rp->rhsalias[i] && !used[i] ){ if( rp->rhsalias[i] ){
ErrorMsg(lemp->filename,rp->ruleline, if( i>0 ){
"Label %s for \"%s(%s)\" is never used.", int j;
rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
lemp->errorcnt++; ErrorMsg(lemp->filename,rp->ruleline,
}else if( rp->rhsalias[i]==0 ){ "%s(%s) has the same label as the LHS but is not the left-most "
if( has_destructor(rp->rhs[i],lemp) ){ "symbol on the RHS.",
append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, rp->rhs[i]->name, rp->rhsalias);
rp->rhs[i]->index,i-rp->nrhs+1,0); lemp->errorcnt++;
}else{ }
/* No destructor defined for this term */ for(j=0; j<i; j++){
if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
ErrorMsg(lemp->filename,rp->ruleline,
"Label %s used for multiple symbols on the RHS of a rule.",
rp->rhsalias[i]);
lemp->errorcnt++;
break;
}
}
} }
if( !used[i] ){
ErrorMsg(lemp->filename,rp->ruleline,
"Label %s for \"%s(%s)\" is never used.",
rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
lemp->errorcnt++;
}
}else if( i>0 && has_destructor(rp->rhs[i],lemp) ){
append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
rp->rhs[i]->index,i-rp->nrhs+1,0);
} }
} }
if( rp->code ){
cp = append_str(0,0,0,0,0); /* If unable to write LHS values directly into the stack, write the
rp->code = Strsafe(cp?cp:""); ** saved LHS value now. */
if( lhsdirect==0 ){
append_str(" yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum, 0);
append_str(zLhs, 0, 0, 0, 0);
append_str(";\n", 0, 0, 0, 0);
} }
/* Suffix code generation complete */
cp = append_str(0,0,0,0,0);
if( cp ) rp->codeSuffix = Strsafe(cp);
} }
/* /*
@ -3501,6 +3578,12 @@ PRIVATE void emit_code(
){ ){
const char *cp; const char *cp;
/* Setup code prior to the #line directive */
if( rp->codePrefix && rp->codePrefix[0] ){
fprintf(out, "{%s", rp->codePrefix);
for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
}
/* Generate code to do the reduce action */ /* Generate code to do the reduce action */
if( rp->code ){ if( rp->code ){
if( !lemp->nolinenosflag ){ if( !lemp->nolinenosflag ){
@ -3508,15 +3591,23 @@ PRIVATE void emit_code(
tplt_linedir(out,rp->line,lemp->filename); tplt_linedir(out,rp->line,lemp->filename);
} }
fprintf(out,"{%s",rp->code); fprintf(out,"{%s",rp->code);
for(cp=rp->code; *cp; cp++){ for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
if( *cp=='\n' ) (*lineno)++;
} /* End loop */
fprintf(out,"}\n"); (*lineno)++; fprintf(out,"}\n"); (*lineno)++;
if( !lemp->nolinenosflag ){ if( !lemp->nolinenosflag ){
(*lineno)++; (*lineno)++;
tplt_linedir(out,*lineno,lemp->outname); tplt_linedir(out,*lineno,lemp->outname);
} }
} /* End if( rp->code ) */ }
/* Generate breakdown code that occurs after the #line directive */
if( rp->codeSuffix && rp->codeSuffix[0] ){
fprintf(out, "%s", rp->codeSuffix);
for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
}
if( rp->codePrefix ){
fprintf(out, "}\n"); (*lineno)++;
}
return; return;
} }

View file

@ -623,7 +623,6 @@ static void yy_reduce(
){ ){
int yygoto; /* The next state */ int yygoto; /* The next state */
int yyact; /* The next action */ int yyact; /* The next action */
YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
yyStackEntry *yymsp; /* The top of the parser's stack */ yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */ int yysize; /* Amount to pop the stack */
ParseARG_FETCH; ParseARG_FETCH;
@ -687,7 +686,6 @@ static void yy_reduce(
yymsp -= yysize-1; yymsp -= yysize-1;
yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto; yymsp->major = (YYCODETYPE)yygoto;
yymsp->minor = yygotominor;
yyTraceShift(yypParser, yyact); yyTraceShift(yypParser, yyact);
}else{ }else{
assert( yyact == YY_ACCEPT_ACTION ); assert( yyact == YY_ACCEPT_ACTION );