/ Check-in [c41d7079]
Login

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

Overview
Comment:Introduce the concept of "weak fallback" in the parser. A weak fallback only occurs if a syntax error would result otherwise.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | weak-fallback
Files: files | file ages | folders
SHA3-256: c41d7079fb63831bd2f009b64cbf5a423e8119e6b841bfd9bd5a2d85fba3b142
User & Date: drh 2018-06-28 03:38:49
Context
2018-06-28
20:05
Modifications to parse.y to better support backwards compatibility for the "window" keyword. check-in: 7c4b879b user: dan tags: weak-fallback
03:38
Introduce the concept of "weak fallback" in the parser. A weak fallback only occurs if a syntax error would result otherwise. check-in: c41d7079 user: drh tags: weak-fallback
2018-06-27
20:24
Add missing VdbeCoverage() and VdbeCoverageNeverTaken() macros to window.c. check-in: 4383cb68 user: dan tags: exp-window-functions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/parse.y.

   212    212     EACH END EXCLUSIVE EXPLAIN FAIL FOR
   213    213     IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
   214    214     QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS
   215    215     ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
   216    216   %ifdef SQLITE_OMIT_COMPOUND_SELECT
   217    217     EXCEPT INTERSECT UNION
   218    218   %endif SQLITE_OMIT_COMPOUND_SELECT
          219  +%ifndef SQLITE_OMIT_WINDOWFUNC
          220  +  CURRENT FILTER FOLLOWING ?OVER PARTITION 
          221  +  PRECEDING RANGE UNBOUNDED ?WINDOW 
          222  +%endif SQLITE_OMIT_WINDOWFUNC
   219    223     REINDEX RENAME CTIME_KW IF
   220    224     .
   221    225   %wildcard ANY.
   222    226   
   223    227   // Define operator precedence early so that this is the first occurrence
   224    228   // of the operator tokens in the grammer.  Keeping the operators together
   225    229   // causes them to be assigned integer values that are close together,

Changes to tool/lemon.c.

   268    268     char *datatype;          /* The data type of information held by this
   269    269                              ** object. Only used if type==NONTERMINAL */
   270    270     int dtnum;               /* The data type number.  In the parser, the value
   271    271                              ** stack is a union.  The .yy%d element of this
   272    272                              ** union is the correct data type for this object */
   273    273     int bContent;            /* True if this symbol ever carries content - if
   274    274                              ** it is ever more than just syntax */
          275  +  int bWeakFallback;       /* True for a weak fallback */
   275    276     /* The following fields are used by MULTITERMINALs only */
   276    277     int nsubsym;             /* Number of constituent symbols in the MULTI */
   277    278     struct symbol **subsym;  /* Array of constituent symbols */
   278    279   };
   279    280   
   280    281   /* Each production rule in the grammar is stored in the following
   281    282   ** structure.  */
................................................................................
  2205   2206     PRECEDENCE_MARK_1,
  2206   2207     PRECEDENCE_MARK_2,
  2207   2208     RESYNC_AFTER_RULE_ERROR,
  2208   2209     RESYNC_AFTER_DECL_ERROR,
  2209   2210     WAITING_FOR_DESTRUCTOR_SYMBOL,
  2210   2211     WAITING_FOR_DATATYPE_SYMBOL,
  2211   2212     WAITING_FOR_FALLBACK_ID,
         2213  +  WAITING_FOR_WEAK_FALLBACK_ID,
  2212   2214     WAITING_FOR_WILDCARD_ID,
  2213   2215     WAITING_FOR_CLASS_ID,
  2214   2216     WAITING_FOR_CLASS_TOKEN,
  2215   2217     WAITING_FOR_TOKEN_NAME
  2216   2218   };
  2217   2219   struct pstate {
  2218   2220     char *filename;       /* Name of the input file */
................................................................................
  2663   2665           ErrorMsg(psp->filename,psp->tokenlineno,
  2664   2666             "Illegal argument to %%%s: %s",psp->declkeyword,x);
  2665   2667           psp->errorcnt++;
  2666   2668           psp->state = RESYNC_AFTER_DECL_ERROR;
  2667   2669         }
  2668   2670         break;
  2669   2671       case WAITING_FOR_FALLBACK_ID:
         2672  +      if( x[0]=='?' ){
         2673  +        psp->state = WAITING_FOR_WEAK_FALLBACK_ID;
         2674  +        break;
         2675  +      }
         2676  +      /* Fall through */
         2677  +    case WAITING_FOR_WEAK_FALLBACK_ID:
  2670   2678         if( x[0]=='.' ){
  2671   2679           psp->state = WAITING_FOR_DECL_OR_RULE;
  2672   2680         }else if( !ISUPPER(x[0]) ){
  2673   2681           ErrorMsg(psp->filename, psp->tokenlineno,
  2674   2682             "%%fallback argument \"%s\" should be a token", x);
  2675   2683           psp->errorcnt++;
  2676   2684         }else{
................................................................................
  2679   2687             psp->fallback = sp;
  2680   2688           }else if( sp->fallback ){
  2681   2689             ErrorMsg(psp->filename, psp->tokenlineno,
  2682   2690               "More than one fallback assigned to token %s", x);
  2683   2691             psp->errorcnt++;
  2684   2692           }else{
  2685   2693             sp->fallback = psp->fallback;
         2694  +          sp->bWeakFallback = (psp->state==WAITING_FOR_WEAK_FALLBACK_ID);
         2695  +          psp->state = WAITING_FOR_FALLBACK_ID;
  2686   2696             psp->gp->has_fallback = 1;
  2687   2697           }
  2688   2698         }
  2689   2699         break;
  2690   2700       case WAITING_FOR_TOKEN_NAME:
  2691   2701         /* Tokens do not have to be declared before use.  But they can be
  2692   2702         ** in order to control their assigned integer number.  The number for
................................................................................
  4489   4499       int mx = lemp->nterminal - 1;
  4490   4500       while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
  4491   4501       lemp->tablesize += (mx+1)*szCodeType;
  4492   4502       for(i=0; i<=mx; i++){
  4493   4503         struct symbol *p = lemp->symbols[i];
  4494   4504         if( p->fallback==0 ){
  4495   4505           fprintf(out, "    0,  /* %10s => nothing */\n", p->name);
         4506  +      }else if( p->bWeakFallback ){
         4507  +        fprintf(out, " %4d,  /* %10s => %s (weak) */\n",
         4508  +          -p->fallback->index, p->name, p->fallback->name);
  4496   4509         }else{
  4497   4510           fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index,
  4498   4511             p->name, p->fallback->name);
  4499   4512         }
  4500   4513         lineno++;
  4501   4514       }
  4502   4515     }
................................................................................
  5108   5121   {
  5109   5122     struct symbol *sp;
  5110   5123   
  5111   5124     sp = Symbol_find(x);
  5112   5125     if( sp==0 ){
  5113   5126       sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
  5114   5127       MemoryCheck(sp);
         5128  +    memset(sp, 0, sizeof(*sp));
  5115   5129       sp->name = Strsafe(x);
  5116   5130       sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
  5117         -    sp->rule = 0;
  5118         -    sp->fallback = 0;
  5119   5131       sp->prec = -1;
  5120   5132       sp->assoc = UNK;
  5121         -    sp->firstset = 0;
  5122   5133       sp->lambda = LEMON_FALSE;
  5123         -    sp->destructor = 0;
  5124         -    sp->destLineno = 0;
  5125         -    sp->datatype = 0;
  5126         -    sp->useCnt = 0;
  5127   5134       Symbol_insert(sp,sp->name);
  5128   5135     }
  5129   5136     sp->useCnt++;
  5130   5137     return sp;
  5131   5138   }
  5132   5139   
  5133   5140   /* Compare two symbols for sorting purposes.  Return negative,

Changes to tool/lempar.c.

    86     86   */
    87     87   #ifndef INTERFACE
    88     88   # define INTERFACE 1
    89     89   #endif
    90     90   /************* Begin control #defines *****************************************/
    91     91   %%
    92     92   /************* End control #defines *******************************************/
           93  +#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
    93     94   
    94     95   /* Define the yytestcase() macro to be a no-op if is not already defined
    95     96   ** otherwise.
    96     97   **
    97     98   ** Applications can choose to define yytestcase() in the %include section
    98     99   ** to a macro that can assist in verifying code coverage.  For production
    99    100   ** code the yytestcase() macro should be turned off.  But it is useful
................................................................................
   168    169   ** the parse is retried before an error is thrown.
   169    170   **
   170    171   ** This feature can be used, for example, to cause some keywords in a language
   171    172   ** to revert to identifiers if they keyword does not apply in the context where
   172    173   ** it appears.
   173    174   */
   174    175   #ifdef YYFALLBACK
   175         -static const YYCODETYPE yyFallback[] = {
          176  +static const int yyFallback[] = {
   176    177   %%
   177    178   };
   178    179   #endif /* YYFALLBACK */
   179    180   
   180    181   /* The following structure represents a single element of the
   181    182   ** parser's stack.  Information stored includes:
   182    183   **
................................................................................
   515    516     assert( stateno <= YY_SHIFT_COUNT );
   516    517   #if defined(YYCOVERAGE)
   517    518     yycoverage[stateno][iLookAhead] = 1;
   518    519   #endif
   519    520     do{
   520    521       i = yy_shift_ofst[stateno];
   521    522       assert( i>=0 );
   522         -    assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) );
          523  +    /*assert( i+YYNTOKEN<=YY_NLOOKAHEAD );*/
   523    524       assert( iLookAhead!=YYNOCODE );
   524    525       assert( iLookAhead < YYNTOKEN );
   525    526       i += iLookAhead;
   526         -    if( yy_lookahead[i]!=iLookAhead ){
          527  +    if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead
          528  +    ){
   527    529   #ifdef YYFALLBACK
   528         -      YYCODETYPE iFallback;            /* Fallback token */
          530  +      int iFallback;            /* Fallback token */
   529    531         if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
   530         -             && (iFallback = yyFallback[iLookAhead])!=0 ){
   531         -#ifndef NDEBUG
   532         -        if( yyTraceFILE ){
   533         -          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
   534         -             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
          532  +       && (iFallback = yyFallback[iLookAhead])!=0
          533  +      ){
          534  +        if( iFallback<0 && yy_default[stateno]==YY_ERROR_ACTION ){
          535  +          /* A weak fallback only happens if current lookahead is a
          536  +          ** syntax error */
          537  +          iFallback = -iFallback;
   535    538           }
          539  +        if( iFallback>0 ){
          540  +          /* A strong fallback happens regardless */
          541  +#ifndef NDEBUG
          542  +          if( yyTraceFILE ){
          543  +            fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
          544  +               yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
          545  +          }
   536    546   #endif
   537         -        assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
   538         -        iLookAhead = iFallback;
   539         -        continue;
          547  +          assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
          548  +          iLookAhead = iFallback;
          549  +          continue;
          550  +        }
   540    551         }
   541    552   #endif
   542    553   #ifdef YYWILDCARD
   543    554         {
   544    555           int j = i - iLookAhead + YYWILDCARD;
   545    556           if( 
   546    557   #if YY_SHIFT_MIN+YYWILDCARD<0