/ Check-in [ef95a7d6]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Further improvements to the Lemon-generated code for yy_reduce().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | parser-performance
Files: files | file ages | folders
SHA1:ef95a7d6490e33a9af4bc7b4b622de7328742ca7
User & Date: drh 2016-02-17 01:46:19
Context
2016-02-17
04:33
Enhance Lemon so that if reduce code contains a comment of the form "/*A-overwrites-X*/" then a LHS label A is allowed to overwrite the RHS label X. check-in: 5cfe9545 user: drh tags: parser-performance
01:46
Further improvements to the Lemon-generated code for yy_reduce(). check-in: ef95a7d6 user: drh tags: parser-performance
01:18
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. check-in: 4bb94c7c user: drh tags: parser-performance
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/parse.y.

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

///////////////////// The CREATE TABLE statement ////////////////////////////
//
cmd ::= create_table create_table_args.
create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
   sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
}
createkw(A) ::= CREATE(X).  {
  disableLookaside(pParse);
  A = X;
}
%type ifnotexists {int}
ifnotexists(A) ::= .              {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
temp(A) ::= TEMP.  {A = 1;}
%endif  SQLITE_OMIT_TEMPDB







<
|
<
|







159
160
161
162
163
164
165

166

167
168
169
170
171
172
173
174

///////////////////// The CREATE TABLE statement ////////////////////////////
//
cmd ::= create_table create_table_args.
create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
   sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
}

createkw(A) ::= CREATE(A).  {disableLookaside(pParse);}


%type ifnotexists {int}
ifnotexists(A) ::= .              {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
temp(A) ::= TEMP.  {A = 1;}
%endif  SQLITE_OMIT_TEMPDB

Changes to tool/lemon.c.

3465
3466
3467
3468
3469
3470
3471



3472
3473
3474
3475

3476
3477
3478
3479
3480
3481
3482
....
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
....
3626
3627
3628
3629
3630
3631
3632


3633
3634
3635
3636
3637
3638
3639
....
4294
4295
4296
4297
4298
4299
4300

4301
4302



4303
4304
4305
4306
4307
4308
4309
  return z;
}

/*
** zCode is a string that is the action associated with a rule.  Expand
** the symbols in this string so that the refer to elements of the parser
** stack.



*/
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;
................................................................................
    }    
  }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);
    append_str("  YYMINORTYPE yylhsminor;\n", 0, 0, 0);
    rp->codePrefix = Strsafe(append_str(0,0,0,0));
    sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
  }

  append_str(0,0,0,0);

  /* This const cast is wrong but harmless, if we're careful. */
  for(cp=(char *)rp->code; *cp; cp++){
................................................................................
    append_str(zLhs, 0, 0, 0);
    append_str(";\n", 0, 0, 0);
  }

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


}

/* 
** Generate code which executes when the rule "rp" is reduced.  Write
** the code to "out".  Make sure lineno stays up-to-date.
*/
PRIVATE void emit_code(
................................................................................
  */
  for(rp=lemp->rule; rp; rp=rp->next){
    fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate code which execution during each REDUCE action */

  for(rp=lemp->rule; rp; rp=rp->next){
    translate_code(lemp, rp);



  }
  /* First output rules other than the default: rule */
  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: */
    fprintf(out,"      case %d: /* ", rp->index);







>
>
>

|


>







 







|
<
<







 







>
>







 







>

|
>
>
>







3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
....
3523
3524
3525
3526
3527
3528
3529
3530


3531
3532
3533
3534
3535
3536
3537
....
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
....
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
  return z;
}

/*
** zCode is a string that is the action associated with a rule.  Expand
** the symbols in this string so that the refer to elements of the parser
** stack.
**
** Return 1 if the expanded code requires that "yylhsminor" local variable
** to be defined.
*/
PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
  char *cp, *xp;
  int i;
  int rc = 0;          /* True if yylhsminor is 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 zLhs[50];       /* Convert the LHS symbol into this string */

  for(i=0; i<rp->nrhs; i++) used[i] = 0;
  lhsused = 0;
................................................................................
    }    
  }else{
    lhsdirect = 0;
  }
  if( lhsdirect ){
    sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
  }else{
    rc = 1;


    sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
  }

  append_str(0,0,0,0);

  /* This const cast is wrong but harmless, if we're careful. */
  for(cp=(char *)rp->code; *cp; cp++){
................................................................................
    append_str(zLhs, 0, 0, 0);
    append_str(";\n", 0, 0, 0);
  }

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

  return rc;
}

/* 
** Generate code which executes when the rule "rp" is reduced.  Write
** the code to "out".  Make sure lineno stays up-to-date.
*/
PRIVATE void emit_code(
................................................................................
  */
  for(rp=lemp->rule; rp; rp=rp->next){
    fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
  }
  tplt_xfer(lemp->name,in,out,&lineno);

  /* Generate code which execution during each REDUCE action */
  i = 0;
  for(rp=lemp->rule; rp; rp=rp->next){
    i += translate_code(lemp, rp);
  }
  if( i ){
    fprintf(out,"        YYMINORTYPE yylhsminor;\n"); lineno++;
  }
  /* First output rules other than the default: rule */
  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: */
    fprintf(out,"      case %d: /* ", rp->index);

Changes to tool/lempar.c.

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
  if( yyTraceFILE && yyruleno>=0 
        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
    yysize = yyRuleInfo[yyruleno].nrhs;
    fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
      yyRuleName[yyruleno], yymsp[-yysize].stateno);
  }
#endif /* NDEBUG */
  /*  yygotominor = yyzerominor; */

  /* Check that the stack is large enough to grow by a single entry
  ** if the RHS of the rule is empty.  This ensures that there is room
  ** enough on the stack to push the LHS value */
  if( yyRuleInfo[yyruleno].nrhs==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
    if( yypParser->yyidx>yypParser->yyidxMax ){







<







622
623
624
625
626
627
628

629
630
631
632
633
634
635
  if( yyTraceFILE && yyruleno>=0 
        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
    yysize = yyRuleInfo[yyruleno].nrhs;
    fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
      yyRuleName[yyruleno], yymsp[-yysize].stateno);
  }
#endif /* NDEBUG */


  /* Check that the stack is large enough to grow by a single entry
  ** if the RHS of the rule is empty.  This ensures that there is room
  ** enough on the stack to push the LHS value */
  if( yyRuleInfo[yyruleno].nrhs==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
    if( yypParser->yyidx>yypParser->yyidxMax ){