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) */
int line; /* Line number at which code begins */
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 */
int index; /* An index number for this rule */
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;
char zInt[40];
if( zText==0 ){
if( used==0 && z!=0 ) z[0] = 0;
used = 0;
return z;
}
@ -3406,7 +3409,9 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
char *cp, *xp;
int i;
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 zLhs[50]; /* Convert the LHS symbol into this string */
for(i=0; i<rp->nrhs; i++) used[i] = 0;
lhsused = 0;
@ -3417,6 +3422,47 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
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);
/* 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;
*xp = 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;
lhsused = 1;
}else{
@ -3458,6 +3504,11 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
append_str(cp, 1, 0, 0, 1);
} /* 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 */
if( rp->lhsalias && !lhsused ){
ErrorMsg(lemp->filename,rp->ruleline,
@ -3466,27 +3517,53 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
lemp->errorcnt++;
}
/* Generate destructor code for RHS symbols which are not used in the
** reduce code */
/* Generate destructor code for RHS minor values which are not referenced.
** Generate error messages for unused labels and duplicate labels.
*/
for(i=0; i<rp->nrhs; i++){
if( rp->rhsalias[i] && !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( rp->rhsalias[i]==0 ){
if( 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);
}else{
/* No destructor defined for this term */
if( rp->rhsalias[i] ){
if( i>0 ){
int j;
if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
ErrorMsg(lemp->filename,rp->ruleline,
"%s(%s) has the same label as the LHS but is not the left-most "
"symbol on the RHS.",
rp->rhs[i]->name, rp->rhsalias);
lemp->errorcnt++;
}
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);
rp->code = Strsafe(cp?cp:"");
/* If unable to write LHS values directly into the stack, write the
** 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;
/* 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 */
if( rp->code ){
if( !lemp->nolinenosflag ){
@ -3508,15 +3591,23 @@ PRIVATE void emit_code(
tplt_linedir(out,rp->line,lemp->filename);
}
fprintf(out,"{%s",rp->code);
for(cp=rp->code; *cp; cp++){
if( *cp=='\n' ) (*lineno)++;
} /* End loop */
for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
fprintf(out,"}\n"); (*lineno)++;
if( !lemp->nolinenosflag ){
(*lineno)++;
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;
}

View file

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