> On Apr 29, 2016, at 7:29 AM, Richard Hipp <drh at sqlite.org> wrote:
> 
> On 4/28/16, Kelvin Sherlock <ksherlock at gmail.com> wrote:
>> I believe the lemon reduce action optimizer needs to compare the codePrefix
>> and codeSuffix.
> 
> Thanks for the bug report.  A fix has now been checked in.
> 
> -- 
> D. Richard Hipp
> drh at sqlite.org

Here are a couple more edge cases I noticed:

---

bug_report ::= rule.

%destructor malloc{free($$)}

rule ::= .
rule ::= malloc . /* 1 */
rule ::= malloc malloc . /* 2 */

malloc(X) ::= ID . { X = malloc(100); }

---

1. the rhs[0] destructor will not be called since the lhsalias null check 
happens first and the codePrefix is never generated.

The empty lhsalias check can be moved down to compensate:

@@ -3552,30 +3552,30 @@ PRIVATE int translate_code(struct lemon *lemp, struct 
rule *rp){
   if( rp->code==0 ){
     static char newlinestr[2] = { '\n', '\0' };
     rp->code = newlinestr;
     rp->line = rp->ruleline;
   }


-  if( rp->lhsalias==0 ){
-    /* There is no LHS value symbol. */
-    lhsdirect = 1;
-  }else if( rp->nrhs==0 ){
+  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);
       append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
                  rp->rhs[0]->index,1-rp->nrhs);
       rp->codePrefix = Strsafe(append_str(0,0,0,0));
     }
+  }else if( rp->lhsalias==0 ){
+    /* There is no LHS value symbol. */
+    lhsdirect = 1;
   }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;


2. if there is a codePrefix or codeSuffix but no code, it will be merged into 
the default rule and the prefix/suffix will be lost.

@@ -3715,7 +3715,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct 
rule *rp){

   /* Suffix code generation complete */
   cp = append_str(0,0,0,0);
-  if( cp ) rp->codeSuffix = Strsafe(cp);
+  if( cp && cp[0] ) rp->codeSuffix = Strsafe(cp);

   return rc;
 }

@@ -4397,7 +4397,8 @@ void ReportTable(
   for(rp=lemp->rule; rp; rp=rp->next){
     struct rule *rp2;               /* Other rules with the same action */
     if( rp->code==0 ) continue;
-    if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */
+    if( rp->code[0]=='\n' && rp->code[1]==0 && rp->codePrefix==0
+      && rp->codeSuffix==0 ) continue; /* Will be default: */
     fprintf(out,"      case %d: /* ", rp->iRule);
     writeRuleText(out, rp);
     fprintf(out, " */\n"); lineno++;
@@ -4419,7 +4420,8 @@ void ReportTable(
   fprintf(out,"      default:\n"); lineno++;
   for(rp=lemp->rule; rp; rp=rp->next){
     if( rp->code==0 ) continue;
-    assert( rp->code[0]=='\n' && rp->code[1]==0 );
+    assert( rp->code[0]=='\n' && rp->code[1]==0 && rp->codePrefix==0
+      && rp->codeSuffix==0 );
     fprintf(out,"      /* (%d) ", rp->iRule);
     writeRuleText(out, rp);
     fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;


Thanks,
Kelvin


Reply via email to