SQLite

Check-in [ef95a7d649]
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
Timelines: family | ancestors | descendants | both | parser-performance
Files: files | file ages | folders
SHA1: ef95a7d6490e33a9af4bc7b4b622de7328742ca7
User & Date: drh 2016-02-17 01:46:19.413
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: 5cfe9545d4 user: drh tags: parser-performance)
01:46
Further improvements to the Lemon-generated code for yy_reduce(). (check-in: ef95a7d649 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: 4bb94c7c4c user: drh tags: parser-performance)
Changes
Unified Diff 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
  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;







>
>
>

|


>







3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
  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;
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
    }    
  }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++){







<
<
|







3523
3524
3525
3526
3527
3528
3529


3530
3531
3532
3533
3534
3535
3536
3537
    }    
  }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++){
3626
3627
3628
3629
3630
3631
3632


3633
3634
3635
3636
3637
3638
3639
    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(







>
>







3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
    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(
4294
4295
4296
4297
4298
4299
4300

4301
4302



4303
4304
4305
4306
4307
4308
4309
  */
  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);







>

|
>
>
>







4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
  */
  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 ){