/ Check-in [28215096]
Login

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

Overview
Comment:Enhance lemon so that a @X instead of just X in the code expands to the major token value rather than the minor token value. Use this to make the parser a few hundred bytes smaller. (CVS 1895)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:28215096e0748b5b02776ddb4c964e0161bc0f16
User & Date: drh 2004-08-19 15:12:26
Context
2004-08-20
14:08
Optimizations in the hash table module. (CVS 1896) check-in: d5b0269e user: drh tags: trunk
2004-08-19
15:12
Enhance lemon so that a @X instead of just X in the code expands to the major token value rather than the minor token value. Use this to make the parser a few hundred bytes smaller. (CVS 1895) check-in: 28215096 user: drh tags: trunk
13:29
Add the SQLITE_BUSY_RESERVED_LOCK compile-time option. (CVS 1894) check-in: 25fe7a42 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.132 2004/08/01 00:10:45 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
/////////////////////////// Expression Processing /////////////////////////////
//

%type expr {Expr*}
%destructor expr {sqlite3ExprDelete($$);}

expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); }
expr(A) ::= NULL(X).             {A = sqlite3Expr(TK_NULL, 0, 0, &X);}
expr(A) ::= ID(X).               {A = sqlite3Expr(TK_ID, 0, 0, &X);}
expr(A) ::= JOIN_KW(X).          {A = sqlite3Expr(TK_ID, 0, 0, &X);}
expr(A) ::= nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &Y);
  A = sqlite3Expr(TK_DOT, temp1, temp2, 0);
}
................................................................................
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &Y);
  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &Z);
  Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
  A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
expr(A) ::= INTEGER(X).      {A = sqlite3Expr(TK_INTEGER, 0, 0, &X);}
expr(A) ::= FLOAT(X).        {A = sqlite3Expr(TK_FLOAT, 0, 0, &X);}
expr(A) ::= STRING(X).       {A = sqlite3Expr(TK_STRING, 0, 0, &X);}
expr(A) ::= BLOB(X).         {A = sqlite3Expr(TK_BLOB, 0, 0, &X);}
expr(A) ::= VARIABLE(X).     {
  A = sqlite3Expr(TK_VARIABLE, 0, 0, &X);
  if( A ) A->iTable = ++pParse->nVar;
}
expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
  A = sqlite3ExprFunction(Y, &X);
  sqlite3ExprSpan(A,&X,&E);
}
expr(A) ::= ID(X) LP STAR RP(E). {
  A = sqlite3ExprFunction(0, &X);
  sqlite3ExprSpan(A,&X,&E);
}
expr(A) ::= expr(X) AND expr(Y).   {A = sqlite3Expr(TK_AND, X, Y, 0);}
expr(A) ::= expr(X) OR expr(Y).    {A = sqlite3Expr(TK_OR, X, Y, 0);}
expr(A) ::= expr(X) LT expr(Y).    {A = sqlite3Expr(TK_LT, X, Y, 0);}
expr(A) ::= expr(X) GT expr(Y).    {A = sqlite3Expr(TK_GT, X, Y, 0);}
expr(A) ::= expr(X) LE expr(Y).    {A = sqlite3Expr(TK_LE, X, Y, 0);}
expr(A) ::= expr(X) GE expr(Y).    {A = sqlite3Expr(TK_GE, X, Y, 0);}
expr(A) ::= expr(X) NE expr(Y).    {A = sqlite3Expr(TK_NE, X, Y, 0);}
expr(A) ::= expr(X) EQ expr(Y).    {A = sqlite3Expr(TK_EQ, X, Y, 0);}
expr(A) ::= expr(X) BITAND expr(Y). {A = sqlite3Expr(TK_BITAND, X, Y, 0);}
expr(A) ::= expr(X) BITOR expr(Y).  {A = sqlite3Expr(TK_BITOR, X, Y, 0);}
expr(A) ::= expr(X) LSHIFT expr(Y). {A = sqlite3Expr(TK_LSHIFT, X, Y, 0);}
expr(A) ::= expr(X) RSHIFT expr(Y). {A = sqlite3Expr(TK_RSHIFT, X, Y, 0);}
expr(A) ::= expr(X) likeop(OP) expr(Y).  [LIKE]  {
  ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
  pList = sqlite3ExprListAppend(pList, X, 0);
  A = sqlite3ExprFunction(pList, 0);
  if( A ) A->op = OP;
  sqlite3ExprSpan(A, &X->span, &Y->span);
}
................................................................................
  if( A ) A->op = OP;
  A = sqlite3Expr(TK_NOT, A, 0, 0);
  sqlite3ExprSpan(A,&X->span,&Y->span);
}
%type likeop {int}
likeop(A) ::= LIKE. {A = TK_LIKE;}
likeop(A) ::= GLOB. {A = TK_GLOB;}
expr(A) ::= expr(X) PLUS expr(Y).  {A = sqlite3Expr(TK_PLUS, X, Y, 0);}
expr(A) ::= expr(X) MINUS expr(Y). {A = sqlite3Expr(TK_MINUS, X, Y, 0);}
expr(A) ::= expr(X) STAR expr(Y).  {A = sqlite3Expr(TK_STAR, X, Y, 0);}
expr(A) ::= expr(X) SLASH expr(Y). {A = sqlite3Expr(TK_SLASH, X, Y, 0);}
expr(A) ::= expr(X) REM expr(Y).   {A = sqlite3Expr(TK_REM, X, Y, 0);}
expr(A) ::= expr(X) CONCAT expr(Y). {A = sqlite3Expr(TK_CONCAT, X, Y, 0);}
expr(A) ::= expr(X) ISNULL(E). {
  A = sqlite3Expr(TK_ISNULL, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IS NULL(E). {
  A = sqlite3Expr(TK_ISNULL, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
................................................................................
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IS NOT NULL(E). {
  A = sqlite3Expr(TK_NOTNULL, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= NOT(B) expr(X). {
  A = sqlite3Expr(TK_NOT, X, 0, 0);
  sqlite3ExprSpan(A,&B,&X->span);
}
expr(A) ::= BITNOT(B) expr(X). {
  A = sqlite3Expr(TK_BITNOT, X, 0, 0);
  sqlite3ExprSpan(A,&B,&X->span);
}
expr(A) ::= MINUS(B) expr(X). [UMINUS] {
  A = sqlite3Expr(TK_UMINUS, X, 0, 0);
  sqlite3ExprSpan(A,&B,&X->span);
}
expr(A) ::= PLUS(B) expr(X). [UPLUS] {







|







 







|







 







|
|
|
|












|
|
|
|
|
|
|
|
|
|
|
|







 







|
|
|
|
|
|







 







|



|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.133 2004/08/19 15:12:26 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
/////////////////////////// Expression Processing /////////////////////////////
//

%type expr {Expr*}
%destructor expr {sqlite3ExprDelete($$);}

expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); }
expr(A) ::= NULL(X).             {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= ID(X).               {A = sqlite3Expr(TK_ID, 0, 0, &X);}
expr(A) ::= JOIN_KW(X).          {A = sqlite3Expr(TK_ID, 0, 0, &X);}
expr(A) ::= nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &Y);
  A = sqlite3Expr(TK_DOT, temp1, temp2, 0);
}
................................................................................
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &Y);
  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &Z);
  Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
  A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
expr(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= VARIABLE(X).     {
  A = sqlite3Expr(TK_VARIABLE, 0, 0, &X);
  if( A ) A->iTable = ++pParse->nVar;
}
expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
  A = sqlite3ExprFunction(Y, &X);
  sqlite3ExprSpan(A,&X,&E);
}
expr(A) ::= ID(X) LP STAR RP(E). {
  A = sqlite3ExprFunction(0, &X);
  sqlite3ExprSpan(A,&X,&E);
}
expr(A) ::= expr(X) AND(OP) expr(Y).    {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) OR(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) LT(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) GT(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) LE(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) GE(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) NE(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) EQ(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) BITAND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) BITOR(OP) expr(Y).  {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) LSHIFT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) RSHIFT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) likeop(OP) expr(Y).  [LIKE]  {
  ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
  pList = sqlite3ExprListAppend(pList, X, 0);
  A = sqlite3ExprFunction(pList, 0);
  if( A ) A->op = OP;
  sqlite3ExprSpan(A, &X->span, &Y->span);
}
................................................................................
  if( A ) A->op = OP;
  A = sqlite3Expr(TK_NOT, A, 0, 0);
  sqlite3ExprSpan(A,&X->span,&Y->span);
}
%type likeop {int}
likeop(A) ::= LIKE. {A = TK_LIKE;}
likeop(A) ::= GLOB. {A = TK_GLOB;}
expr(A) ::= expr(X) PLUS(OP) expr(Y).   {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) MINUS(OP) expr(Y).  {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) STAR(OP) expr(Y).   {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) SLASH(OP) expr(Y).  {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) REM(OP) expr(Y).    {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) ISNULL(E). {
  A = sqlite3Expr(TK_ISNULL, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IS NULL(E). {
  A = sqlite3Expr(TK_ISNULL, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
................................................................................
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IS NOT NULL(E). {
  A = sqlite3Expr(TK_NOTNULL, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= NOT(B) expr(X). {
  A = sqlite3Expr(@B, X, 0, 0);
  sqlite3ExprSpan(A,&B,&X->span);
}
expr(A) ::= BITNOT(B) expr(X). {
  A = sqlite3Expr(@B, X, 0, 0);
  sqlite3ExprSpan(A,&B,&X->span);
}
expr(A) ::= MINUS(B) expr(X). [UMINUS] {
  A = sqlite3Expr(TK_UMINUS, X, 0, 0);
  sqlite3ExprSpan(A,&B,&X->span);
}
expr(A) ::= PLUS(B) expr(X). [UPLUS] {

Changes to tool/lemon.c.

2999
3000
3001
3002
3003
3004
3005







3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017





3018

3019
3020
3021
3022
3023
3024
3025
....
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068





3069
3070

3071
3072
3073
3074
3075
3076
3077
....
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
  return ret;
}

/*
** Append text to a dynamically allocated string.  If zText is 0 then
** reset the string to be empty again.  Always return the complete text
** of the string (which is overwritten with each call).







*/
PRIVATE char *append_str(char *zText, int n, int p1, int p2){
  static char *z = 0;
  static int alloced = 0;
  static int used = 0;
  int i, c;
  char zInt[40];

  if( zText==0 ){
    used = 0;
    return z;
  }





  if( n<=0 ) n = strlen(zText);

  if( n+sizeof(zInt)*2+used >= alloced ){
    alloced = n + sizeof(zInt)*2 + used + 200;
    z = realloc(z,  alloced);
  }
  if( z==0 ) return "";
  while( n-- > 0 ){
    c = *(zText++);
................................................................................
  for(cp=rp->code; *cp; cp++){
    if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
      char saved;
      for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
      saved = *xp;
      *xp = 0;
      if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
        append_str("yygotominor.yy%d",-1,rp->lhs->dtnum,0);
        cp = xp;
        lhsused = 1;
      }else{
        for(i=0; i<rp->nrhs; i++){
          if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){





            append_str("yymsp[%d].minor.yy%d",-1,
                       i-rp->nrhs+1,rp->rhs[i]->dtnum);

            cp = xp;
            used[i] = 1;
            break;
          }
        }
      }
      *xp = saved;
................................................................................
    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(%d,&yymsp[%d].minor);\n", -1,
           rp->rhs[i]->index,i-rp->nrhs+1);
      }else{
        /* No destructor defined for this term */
      }
    }
  }
  cp = append_str(0,0,0,0);







>
>
>
>
>
>
>












>
>
>
>
>
|
>







 







|





>
>
>
>
>
|
|
>







 







|







2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
....
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
....
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
  return ret;
}

/*
** Append text to a dynamically allocated string.  If zText is 0 then
** reset the string to be empty again.  Always return the complete text
** of the string (which is overwritten with each call).
**
** n bytes of zText are stored.  If n==0 then all of zText up to the first
** \000 terminator is stored.  zText can contain up to two instances of
** %d.  The values of p1 and p2 are written into the first and second
** %d.
**
** If n==-1, then the previous character is overwritten.
*/
PRIVATE char *append_str(char *zText, int n, int p1, int p2){
  static char *z = 0;
  static int alloced = 0;
  static int used = 0;
  int i, c;
  char zInt[40];

  if( zText==0 ){
    used = 0;
    return z;
  }
  if( n<=0 ){
    if( n<0 ){
      used += n;
      assert( used>=0 );
    }
    n = strlen(zText);
  }
  if( n+sizeof(zInt)*2+used >= alloced ){
    alloced = n + sizeof(zInt)*2 + used + 200;
    z = realloc(z,  alloced);
  }
  if( z==0 ) return "";
  while( n-- > 0 ){
    c = *(zText++);
................................................................................
  for(cp=rp->code; *cp; cp++){
    if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
      char saved;
      for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
      saved = *xp;
      *xp = 0;
      if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
        append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0);
        cp = xp;
        lhsused = 1;
      }else{
        for(i=0; i<rp->nrhs; i++){
          if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
            if( cp!=rp->code && cp[-1]=='@' ){
              /* If the argument is of the form @X then substituted
              ** the token number of X, not the value of X */
              append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
            }else{
              append_str("yymsp[%d].minor.yy%d",0,
                         i-rp->nrhs+1,rp->rhs[i]->dtnum);
            }
            cp = xp;
            used[i] = 1;
            break;
          }
        }
      }
      *xp = saved;
................................................................................
    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(%d,&yymsp[%d].minor);\n", 0,
           rp->rhs[i]->index,i-rp->nrhs+1);
      }else{
        /* No destructor defined for this term */
      }
    }
  }
  cp = append_str(0,0,0,0);