| Index: third_party/sqlite/src/tool/lemon.c
 | 
| diff --git a/third_party/sqlite/src/tool/lemon.c b/third_party/sqlite/src/tool/lemon.c
 | 
| index d704deb624d42b39ca455db5bc5617e2197d62d9..aa0f4e3e9ca39c39ebb5fa4f3877de8e4b33c648 100644
 | 
| --- a/third_party/sqlite/src/tool/lemon.c
 | 
| +++ b/third_party/sqlite/src/tool/lemon.c
 | 
| @@ -263,7 +263,8 @@ struct symbol {
 | 
|    int useCnt;              /* Number of times used */
 | 
|    char *destructor;        /* Code which executes whenever this symbol is
 | 
|                             ** popped from the stack during error processing */
 | 
| -  int destLineno;          /* Line number for start of destructor */
 | 
| +  int destLineno;          /* Line number for start of destructor.  Set to
 | 
| +                           ** -1 for duplicate destructors. */
 | 
|    char *datatype;          /* The data type of information held by this
 | 
|                             ** object. Only used if type==NONTERMINAL */
 | 
|    int dtnum;               /* The data type number.  In the parser, the value
 | 
| @@ -286,9 +287,15 @@ struct rule {
 | 
|    const char **rhsalias;   /* An alias for each RHS symbol (NULL if none) */
 | 
|    int line;                /* Line number at which code begins */
 | 
|    const char *code;        /* The code executed when this rule is reduced */
 | 
| +  const char *codePrefix;  /* Setup code before code[] above */
 | 
| +  const char *codeSuffix;  /* Breakdown code after code[] above */
 | 
| +  int noCode;              /* True if this rule has no associated C code */
 | 
| +  int codeEmitted;         /* True if the code has been emitted already */
 | 
|    struct symbol *precsym;  /* Precedence symbol for this rule */
 | 
|    int index;               /* An index number for this rule */
 | 
| +  int iRule;               /* Rule number as used in the generated tables */
 | 
|    Boolean canReduce;       /* True if this rule is ever reduced */
 | 
| +  Boolean doesReduce;      /* Reduce actions occur after optimization */
 | 
|    struct rule *nextlhs;    /* Next rule with the same LHS */
 | 
|    struct rule *next;       /* Next rule in the global list */
 | 
|  };
 | 
| @@ -336,6 +343,7 @@ struct action {
 | 
|      struct state *stp;     /* The new state, if a shift */
 | 
|      struct rule *rp;       /* The rule, if a reduce */
 | 
|    } x;
 | 
| +  struct symbol *spOpt;    /* SHIFTREDUCE optimization to this symbol */
 | 
|    struct action *next;     /* Next action for this state */
 | 
|    struct action *collide;  /* Next action with the same hash */
 | 
|  };
 | 
| @@ -346,7 +354,7 @@ struct state {
 | 
|    struct config *bp;       /* The basis configurations for this state */
 | 
|    struct config *cfp;      /* All configurations in this set */
 | 
|    int statenum;            /* Sequential number for this state */
 | 
| -  struct action *ap;       /* Array of actions for this state */
 | 
| +  struct action *ap;       /* List of actions for this state */
 | 
|    int nTknAct, nNtAct;     /* Number of actions on terminals and nonterminals */
 | 
|    int iTknOfst, iNtOfst;   /* yy_action[] offset for terminals and nonterms */
 | 
|    int iDfltReduce;         /* Default action is to REDUCE by this rule */
 | 
| @@ -370,6 +378,7 @@ struct plink {
 | 
|  struct lemon {
 | 
|    struct state **sorted;   /* Table of states sorted by state number */
 | 
|    struct rule *rule;       /* List of all rules */
 | 
| +  struct rule *startRule;  /* First rule */
 | 
|    int nstate;              /* Number of states */
 | 
|    int nxstate;             /* nstate with tail degenerate states removed */
 | 
|    int nrule;               /* Number of rules */
 | 
| @@ -526,6 +535,7 @@ void Action_add(
 | 
|    *app = newaction;
 | 
|    newaction->type = type;
 | 
|    newaction->sp = sp;
 | 
| +  newaction->spOpt = 0;
 | 
|    if( type==SHIFT ){
 | 
|      newaction->x.stp = (struct state *)arg;
 | 
|    }else{
 | 
| @@ -856,12 +866,12 @@ void FindStates(struct lemon *lemp)
 | 
|        ErrorMsg(lemp->filename,0,
 | 
|  "The specified start symbol \"%s\" is not \
 | 
|  in a nonterminal of the grammar.  \"%s\" will be used as the start \
 | 
| -symbol instead.",lemp->start,lemp->rule->lhs->name);
 | 
| +symbol instead.",lemp->start,lemp->startRule->lhs->name);
 | 
|        lemp->errorcnt++;
 | 
| -      sp = lemp->rule->lhs;
 | 
| +      sp = lemp->startRule->lhs;
 | 
|      }
 | 
|    }else{
 | 
| -    sp = lemp->rule->lhs;
 | 
| +    sp = lemp->startRule->lhs;
 | 
|    }
 | 
|  
 | 
|    /* Make sure the start symbol doesn't occur on the right-hand side of
 | 
| @@ -1115,9 +1125,9 @@ void FindActions(struct lemon *lemp)
 | 
|    /* Add the accepting token */
 | 
|    if( lemp->start ){
 | 
|      sp = Symbol_find(lemp->start);
 | 
| -    if( sp==0 ) sp = lemp->rule->lhs;
 | 
| +    if( sp==0 ) sp = lemp->startRule->lhs;
 | 
|    }else{
 | 
| -    sp = lemp->rule->lhs;
 | 
| +    sp = lemp->startRule->lhs;
 | 
|    }
 | 
|    /* Add to the first state (which is always the starting state of the
 | 
|    ** finite state machine) an action to ACCEPT if the lookahead is the
 | 
| @@ -1495,6 +1505,54 @@ static void handle_T_option(char *z){
 | 
|    lemon_strcpy(user_templatename, z);
 | 
|  }
 | 
|  
 | 
| +/* Merge together to lists of rules ordered by rule.iRule */
 | 
| +static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
 | 
| +  struct rule *pFirst = 0;
 | 
| +  struct rule **ppPrev = &pFirst;
 | 
| +  while( pA && pB ){
 | 
| +    if( pA->iRule<pB->iRule ){
 | 
| +      *ppPrev = pA;
 | 
| +      ppPrev = &pA->next;
 | 
| +      pA = pA->next;
 | 
| +    }else{
 | 
| +      *ppPrev = pB;
 | 
| +      ppPrev = &pB->next;
 | 
| +      pB = pB->next;
 | 
| +    }
 | 
| +  }
 | 
| +  if( pA ){
 | 
| +    *ppPrev = pA;
 | 
| +  }else{
 | 
| +    *ppPrev = pB;
 | 
| +  }
 | 
| +  return pFirst;
 | 
| +}
 | 
| +
 | 
| +/*
 | 
| +** Sort a list of rules in order of increasing iRule value
 | 
| +*/
 | 
| +static struct rule *Rule_sort(struct rule *rp){
 | 
| +  int i;
 | 
| +  struct rule *pNext;
 | 
| +  struct rule *x[32];
 | 
| +  memset(x, 0, sizeof(x));
 | 
| +  while( rp ){
 | 
| +    pNext = rp->next;
 | 
| +    rp->next = 0;
 | 
| +    for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
 | 
| +      rp = Rule_merge(x[i], rp);
 | 
| +      x[i] = 0;
 | 
| +    }
 | 
| +    x[i] = rp;
 | 
| +    rp = pNext;
 | 
| +  }
 | 
| +  rp = 0;
 | 
| +  for(i=0; i<sizeof(x)/sizeof(x[0]); i++){
 | 
| +    rp = Rule_merge(x[i], rp);
 | 
| +  }
 | 
| +  return rp;
 | 
| +}
 | 
| +
 | 
|  /* forward reference */
 | 
|  static const char *minimum_size_type(int lwr, int upr, int *pnByte);
 | 
|  
 | 
| @@ -1543,6 +1601,7 @@ int main(int argc, char **argv)
 | 
|    int i;
 | 
|    int exitcode;
 | 
|    struct lemon lem;
 | 
| +  struct rule *rp;
 | 
|  
 | 
|    OptInit(argv,options,stderr);
 | 
|    if( version ){
 | 
| @@ -1589,6 +1648,19 @@ int main(int argc, char **argv)
 | 
|    for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++);
 | 
|    lem.nterminal = i;
 | 
|  
 | 
| +  /* Assign sequential rule numbers.  Start with 0.  Put rules that have no
 | 
| +  ** reduce action C-code associated with them last, so that the switch()
 | 
| +  ** statement that selects reduction actions will have a smaller jump table.
 | 
| +  */
 | 
| +  for(i=0, rp=lem.rule; rp; rp=rp->next){
 | 
| +    rp->iRule = rp->code ? i++ : -1;
 | 
| +  }
 | 
| +  for(rp=lem.rule; rp; rp=rp->next){
 | 
| +    if( rp->iRule<0 ) rp->iRule = i++;
 | 
| +  }
 | 
| +  lem.startRule = lem.rule;
 | 
| +  lem.rule = Rule_sort(lem.rule);
 | 
| +
 | 
|    /* Generate a reprint of the grammar, if requested on the command line */
 | 
|    if( rpflag ){
 | 
|      Reprint(&lem);
 | 
| @@ -2148,6 +2220,7 @@ to follow the previous rule.");
 | 
|          }else{
 | 
|            psp->prevrule->line = psp->tokenlineno;
 | 
|            psp->prevrule->code = &x[1];
 | 
| +          psp->prevrule->noCode = 0;
 | 
|          }
 | 
|        }else if( x[0]=='[' ){
 | 
|          psp->state = PRECEDENCE_MARK_1;
 | 
| @@ -2254,6 +2327,7 @@ to follow the previous rule.");
 | 
|            rp->lhsalias = psp->lhsalias;
 | 
|            rp->nrhs = psp->nrhs;
 | 
|            rp->code = 0;
 | 
| +          rp->noCode = 1;
 | 
|            rp->precsym = 0;
 | 
|            rp->index = psp->gp->nrule++;
 | 
|            rp->nextlhs = rp->lhs->rule;
 | 
| @@ -3052,13 +3126,13 @@ int PrintAction(
 | 
|      }
 | 
|      case REDUCE: {
 | 
|        struct rule *rp = ap->x.rp;
 | 
| -      fprintf(fp,"%*s reduce       %-7d",indent,ap->sp->name,rp->index);
 | 
| +      fprintf(fp,"%*s reduce       %-7d",indent,ap->sp->name,rp->iRule);
 | 
|        RulePrint(fp, rp, -1);
 | 
|        break;
 | 
|      }
 | 
|      case SHIFTREDUCE: {
 | 
|        struct rule *rp = ap->x.rp;
 | 
| -      fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index);
 | 
| +      fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule);
 | 
|        RulePrint(fp, rp, -1);
 | 
|        break;
 | 
|      }
 | 
| @@ -3071,7 +3145,7 @@ int PrintAction(
 | 
|      case SRCONFLICT:
 | 
|      case RRCONFLICT:
 | 
|        fprintf(fp,"%*s reduce       %-7d ** Parsing conflict **",
 | 
| -        indent,ap->sp->name,ap->x.rp->index);
 | 
| +        indent,ap->sp->name,ap->x.rp->iRule);
 | 
|        break;
 | 
|      case SSCONFLICT:
 | 
|        fprintf(fp,"%*s shift        %-7d ** Parsing conflict **", 
 | 
| @@ -3088,7 +3162,7 @@ int PrintAction(
 | 
|      case RD_RESOLVED:
 | 
|        if( showPrecedenceConflict ){
 | 
|          fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
 | 
| -                indent,ap->sp->name,ap->x.rp->index);
 | 
| +                indent,ap->sp->name,ap->x.rp->iRule);
 | 
|        }else{
 | 
|          result = 0;
 | 
|        }
 | 
| @@ -3097,6 +3171,9 @@ int PrintAction(
 | 
|        result = 0;
 | 
|        break;
 | 
|    }
 | 
| +  if( result && ap->spOpt ){
 | 
| +    fprintf(fp,"  /* because %s==%s */", ap->sp->name, ap->spOpt->name);
 | 
| +  }
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
| @@ -3119,7 +3196,7 @@ void ReportOutput(struct lemon *lemp)
 | 
|      while( cfp ){
 | 
|        char buf[20];
 | 
|        if( cfp->dot==cfp->rp->nrhs ){
 | 
| -        lemon_sprintf(buf,"(%d)",cfp->rp->index);
 | 
| +        lemon_sprintf(buf,"(%d)",cfp->rp->iRule);
 | 
|          fprintf(fp,"    %5s ",buf);
 | 
|        }else{
 | 
|          fprintf(fp,"          ");
 | 
| @@ -3220,8 +3297,8 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
 | 
|    int act;
 | 
|    switch( ap->type ){
 | 
|      case SHIFT:  act = ap->x.stp->statenum;                        break;
 | 
| -    case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate;        break;
 | 
| -    case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break;
 | 
| +    case SHIFTREDUCE: act = ap->x.rp->iRule + lemp->nstate;        break;
 | 
| +    case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break;
 | 
|      case ERROR:  act = lemp->nstate + lemp->nrule*2;               break;
 | 
|      case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1;           break;
 | 
|      default:     act = -1; break;
 | 
| @@ -3430,6 +3507,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
 | 
|    int c;
 | 
|    char zInt[40];
 | 
|    if( zText==0 ){
 | 
| +    if( used==0 && z!=0 ) z[0] = 0;
 | 
|      used = 0;
 | 
|      return z;
 | 
|    }
 | 
| @@ -3463,15 +3541,23 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| -** 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.
 | 
| +** Write and transform the rp->code string so that symbols are expanded.
 | 
| +** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate.
 | 
| +**
 | 
| +** Return 1 if the expanded code requires that "yylhsminor" local variable
 | 
| +** to be defined.
 | 
|  */
 | 
| -PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
 | 
| +PRIVATE int 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 used[MAXRHS];   /* True for each RHS element which is used */
 | 
| +  int rc = 0;            /* True if yylhsminor is used */
 | 
| +  int dontUseRhs0 = 0;   /* If true, use of left-most RHS label is illegal */
 | 
| +  const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */
 | 
| +  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 */
 | 
| +  char zOvwrt[900];      /* Comment that to allow LHS to overwrite RHS */
 | 
|  
 | 
|    for(i=0; i<rp->nrhs; i++) used[i] = 0;
 | 
|    lhsused = 0;
 | 
| @@ -3480,25 +3566,89 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
 | 
|      static char newlinestr[2] = { '\n', '\0' };
 | 
|      rp->code = newlinestr;
 | 
|      rp->line = rp->ruleline;
 | 
| +    rp->noCode = 1;
 | 
| +  }else{
 | 
| +    rp->noCode = 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 no 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));
 | 
| +      rp->noCode = 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;
 | 
| +    if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){
 | 
| +      ErrorMsg(lemp->filename,rp->ruleline,
 | 
| +        "%s(%s) and %s(%s) share the same label but have "
 | 
| +        "different datatypes.",
 | 
| +        rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]);
 | 
| +      lemp->errorcnt++;
 | 
| +    }    
 | 
| +  }else{
 | 
| +    lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/",
 | 
| +                  rp->lhsalias, rp->rhsalias[0]);
 | 
| +    zSkip = strstr(rp->code, zOvwrt);
 | 
| +    if( zSkip!=0 ){
 | 
| +      /* The code contains a special comment that indicates that it is safe
 | 
| +      ** for the LHS label to overwrite left-most RHS label. */
 | 
| +      lhsdirect = 1;
 | 
| +    }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++){
 | 
| +    if( cp==zSkip ){
 | 
| +      append_str(zOvwrt,0,0,0);
 | 
| +      cp += lemonStrlen(zOvwrt)-1;
 | 
| +      dontUseRhs0 = 1;
 | 
| +      continue;
 | 
| +    }
 | 
|      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);
 | 
| +        append_str(zLhs,0,0,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( i==0 && dontUseRhs0 ){
 | 
| +              ErrorMsg(lemp->filename,rp->ruleline,
 | 
| +                 "Label %s used after '%s'.",
 | 
| +                 rp->rhsalias[0], zOvwrt);
 | 
| +              lemp->errorcnt++;
 | 
| +            }else 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);
 | 
| @@ -3523,6 +3673,11 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
 | 
|      append_str(cp, 1, 0, 0);
 | 
|    } /* End loop */
 | 
|  
 | 
| +  /* Main code generation completed */
 | 
| +  cp = append_str(0,0,0,0);
 | 
| +  if( cp && cp[0] ) rp->code = Strsafe(cp);
 | 
| +  append_str(0,0,0,0);
 | 
| +
 | 
|    /* Check to make sure the LHS has been used */
 | 
|    if( rp->lhsalias && !lhsused ){
 | 
|      ErrorMsg(lemp->filename,rp->ruleline,
 | 
| @@ -3531,27 +3686,58 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
 | 
|      lemp->errorcnt++;
 | 
|    }
 | 
|  
 | 
| -  /* Generate destructor code for RHS symbols which are not used in the
 | 
| -  ** reduce code */
 | 
| +  /* Generate destructor code for RHS minor values which are not referenced.
 | 
| +  ** Generate error messages for unused labels and duplicate labels.
 | 
| +  */
 | 
|    for(i=0; i<rp->nrhs; i++){
 | 
| -    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(yypParser,%d,&yymsp[%d].minor);\n", 0,
 | 
| -           rp->rhs[i]->index,i-rp->nrhs+1);
 | 
| -      }else{
 | 
| -        /* No destructor defined for this term */
 | 
| +    if( rp->rhsalias[i] ){
 | 
| +      if( i>0 ){
 | 
| +        int j;
 | 
| +        if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
 | 
| +          ErrorMsg(lemp->filename,rp->ruleline,
 | 
| +            "%s(%s) has the same label as the LHS but is not the left-most "
 | 
| +            "symbol on the RHS.",
 | 
| +            rp->rhs[i]->name, rp->rhsalias);
 | 
| +          lemp->errorcnt++;
 | 
| +        }
 | 
| +        for(j=0; j<i; j++){
 | 
| +          if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
 | 
| +            ErrorMsg(lemp->filename,rp->ruleline,
 | 
| +              "Label %s used for multiple symbols on the RHS of a rule.",
 | 
| +              rp->rhsalias[i]);
 | 
| +            lemp->errorcnt++;
 | 
| +            break;
 | 
| +          }
 | 
| +        }
 | 
| +      }
 | 
| +      if( !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( i>0 && has_destructor(rp->rhs[i],lemp) ){
 | 
| +      append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
 | 
| +         rp->rhs[i]->index,i-rp->nrhs+1);
 | 
|      }
 | 
|    }
 | 
| -  if( rp->code ){
 | 
| -    cp = append_str(0,0,0,0);
 | 
| -    rp->code = Strsafe(cp?cp:"");
 | 
| +
 | 
| +  /* If unable to write LHS values directly into the stack, write the
 | 
| +  ** saved LHS value now. */
 | 
| +  if( lhsdirect==0 ){
 | 
| +    append_str("  yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum);
 | 
| +    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 && cp[0] ){
 | 
| +    rp->codeSuffix = Strsafe(cp);
 | 
| +    rp->noCode = 0;
 | 
| +  }
 | 
| +
 | 
| +  return rc;
 | 
|  }
 | 
|  
 | 
|  /* 
 | 
| @@ -3566,6 +3752,12 @@ PRIVATE void emit_code(
 | 
|  ){
 | 
|   const char *cp;
 | 
|  
 | 
| + /* Setup code prior to the #line directive */
 | 
| + if( rp->codePrefix && rp->codePrefix[0] ){
 | 
| +   fprintf(out, "{%s", rp->codePrefix);
 | 
| +   for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
 | 
| + }
 | 
| +
 | 
|   /* Generate code to do the reduce action */
 | 
|   if( rp->code ){
 | 
|     if( !lemp->nolinenosflag ){
 | 
| @@ -3573,15 +3765,23 @@ PRIVATE void emit_code(
 | 
|       tplt_linedir(out,rp->line,lemp->filename);
 | 
|     }
 | 
|     fprintf(out,"{%s",rp->code);
 | 
| -   for(cp=rp->code; *cp; cp++){
 | 
| -     if( *cp=='\n' ) (*lineno)++;
 | 
| -   } /* End loop */
 | 
| +   for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
 | 
|     fprintf(out,"}\n"); (*lineno)++;
 | 
|     if( !lemp->nolinenosflag ){
 | 
|       (*lineno)++;
 | 
|       tplt_linedir(out,*lineno,lemp->outname);
 | 
|     }
 | 
| - } /* End if( rp->code ) */
 | 
| + }
 | 
| +
 | 
| + /* Generate breakdown code that occurs after the #line directive */
 | 
| + if( rp->codeSuffix && rp->codeSuffix[0] ){
 | 
| +   fprintf(out, "%s", rp->codeSuffix);
 | 
| +   for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
 | 
| + }
 | 
| +
 | 
| + if( rp->codePrefix ){
 | 
| +   fprintf(out, "}\n"); (*lineno)++;
 | 
| + }
 | 
|  
 | 
|   return;
 | 
|  }
 | 
| @@ -3954,6 +4154,18 @@ void ReportTable(
 | 
|    }
 | 
|    free(ax);
 | 
|  
 | 
| +  /* Mark rules that are actually used for reduce actions after all
 | 
| +  ** optimizations have been applied
 | 
| +  */
 | 
| +  for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE;
 | 
| +  for(i=0; i<lemp->nxstate; i++){
 | 
| +    for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
 | 
| +      if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
 | 
| +        ap->x.rp->doesReduce = i;
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    /* Finish rendering the constants now that the action table has
 | 
|    ** been computed */
 | 
|    fprintf(out,"#define YYNSTATE             %d\n",lemp->nxstate);  lineno++;
 | 
| @@ -4019,20 +4231,21 @@ void ReportTable(
 | 
|    fprintf(out, "};\n"); lineno++;
 | 
|  
 | 
|    /* Output the yy_shift_ofst[] table */
 | 
| -  fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
 | 
|    n = lemp->nxstate;
 | 
|    while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
 | 
| -  fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
 | 
| -  fprintf(out, "#define YY_SHIFT_MIN   (%d)\n", mnTknOfst); lineno++;
 | 
| -  fprintf(out, "#define YY_SHIFT_MAX   (%d)\n", mxTknOfst); lineno++;
 | 
| +  fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++;
 | 
| +  fprintf(out, "#define YY_SHIFT_COUNT    (%d)\n", n-1); lineno++;
 | 
| +  fprintf(out, "#define YY_SHIFT_MIN      (%d)\n", mnTknOfst); lineno++;
 | 
| +  fprintf(out, "#define YY_SHIFT_MAX      (%d)\n", mxTknOfst); lineno++;
 | 
|    fprintf(out, "static const %s yy_shift_ofst[] = {\n", 
 | 
| -          minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++;
 | 
| +       minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz));
 | 
| +       lineno++;
 | 
|    lemp->tablesize += n*sz;
 | 
|    for(i=j=0; i<n; i++){
 | 
|      int ofst;
 | 
|      stp = lemp->sorted[i];
 | 
|      ofst = stp->iTknOfst;
 | 
| -    if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
 | 
| +    if( ofst==NO_OFFSET ) ofst = lemp->nactiontab;
 | 
|      if( j==0 ) fprintf(out," /* %5d */ ", i);
 | 
|      fprintf(out, " %4d,", ofst);
 | 
|      if( j==9 || i==n-1 ){
 | 
| @@ -4122,7 +4335,7 @@ void ReportTable(
 | 
|    ** when tracing REDUCE actions.
 | 
|    */
 | 
|    for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
 | 
| -    assert( rp->index==i );
 | 
| +    assert( rp->iRule==i );
 | 
|      fprintf(out," /* %3d */ \"", i);
 | 
|      writeRuleText(out, rp);
 | 
|      fprintf(out,"\",\n"); lineno++;
 | 
| @@ -4172,6 +4385,7 @@ void ReportTable(
 | 
|    for(i=0; i<lemp->nsymbol; i++){
 | 
|      struct symbol *sp = lemp->symbols[i];
 | 
|      if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
 | 
| +    if( sp->destLineno<0 ) continue;  /* Already emitted */
 | 
|      fprintf(out,"    case %d: /* %s */\n", sp->index, sp->name); lineno++;
 | 
|  
 | 
|      /* Combine duplicate destructors into a single case */
 | 
| @@ -4182,7 +4396,7 @@ void ReportTable(
 | 
|            && strcmp(sp->destructor,sp2->destructor)==0 ){
 | 
|           fprintf(out,"    case %d: /* %s */\n",
 | 
|                   sp2->index, sp2->name); lineno++;
 | 
| -         sp2->destructor = 0;
 | 
| +         sp2->destLineno = -1;  /* Avoid emitting this destructor again */
 | 
|        }
 | 
|      }
 | 
|  
 | 
| @@ -4206,38 +4420,51 @@ void ReportTable(
 | 
|    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){
 | 
| -    translate_code(lemp, rp);
 | 
| +    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);
 | 
| +    if( rp->codeEmitted ) continue;
 | 
| +    if( rp->noCode ){
 | 
| +      /* No C code actions, so this will be part of the "default:" rule */
 | 
| +      continue;
 | 
| +    }
 | 
| +    fprintf(out,"      case %d: /* ", rp->iRule);
 | 
|      writeRuleText(out, rp);
 | 
|      fprintf(out, " */\n"); lineno++;
 | 
|      for(rp2=rp->next; rp2; rp2=rp2->next){
 | 
| -      if( rp2->code==rp->code ){
 | 
| -        fprintf(out,"      case %d: /* ", rp2->index);
 | 
| +      if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
 | 
| +             && rp2->codeSuffix==rp->codeSuffix ){
 | 
| +        fprintf(out,"      case %d: /* ", rp2->iRule);
 | 
|          writeRuleText(out, rp2);
 | 
| -        fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++;
 | 
| -        rp2->code = 0;
 | 
| +        fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
 | 
| +        rp2->codeEmitted = 1;
 | 
|        }
 | 
|      }
 | 
|      emit_code(out,rp,lemp,&lineno);
 | 
|      fprintf(out,"        break;\n"); lineno++;
 | 
| -    rp->code = 0;
 | 
| +    rp->codeEmitted = 1;
 | 
|    }
 | 
|    /* Finally, output the default: rule.  We choose as the default: all
 | 
|    ** empty actions. */
 | 
|    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 );
 | 
| -    fprintf(out,"      /* (%d) ", rp->index);
 | 
| +    if( rp->codeEmitted ) continue;
 | 
| +    assert( rp->noCode );
 | 
| +    fprintf(out,"      /* (%d) ", rp->iRule);
 | 
|      writeRuleText(out, rp);
 | 
| -    fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->index); lineno++;
 | 
| +    if( rp->doesReduce ){
 | 
| +      fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
 | 
| +    }else{
 | 
| +      fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
 | 
| +              rp->iRule); lineno++;
 | 
| +    }
 | 
|    }
 | 
|    fprintf(out,"        break;\n"); lineno++;
 | 
|    tplt_xfer(lemp->name,in,out,&lineno);
 | 
| @@ -4308,7 +4535,7 @@ void ReportHeader(struct lemon *lemp)
 | 
|  void CompressTables(struct lemon *lemp)
 | 
|  {
 | 
|    struct state *stp;
 | 
| -  struct action *ap, *ap2;
 | 
| +  struct action *ap, *ap2, *nextap;
 | 
|    struct rule *rp, *rp2, *rbest;
 | 
|    int nbest, n;
 | 
|    int i;
 | 
| @@ -4385,6 +4612,36 @@ void CompressTables(struct lemon *lemp)
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| +
 | 
| +  /* If a SHIFTREDUCE action specifies a rule that has a single RHS term
 | 
| +  ** (meaning that the SHIFTREDUCE will land back in the state where it
 | 
| +  ** started) and if there is no C-code associated with the reduce action,
 | 
| +  ** then we can go ahead and convert the action to be the same as the
 | 
| +  ** action for the RHS of the rule.
 | 
| +  */
 | 
| +  for(i=0; i<lemp->nstate; i++){
 | 
| +    stp = lemp->sorted[i];
 | 
| +    for(ap=stp->ap; ap; ap=nextap){
 | 
| +      nextap = ap->next;
 | 
| +      if( ap->type!=SHIFTREDUCE ) continue;
 | 
| +      rp = ap->x.rp;
 | 
| +      if( rp->noCode==0 ) continue;
 | 
| +      if( rp->nrhs!=1 ) continue;
 | 
| +#if 1
 | 
| +      /* Only apply this optimization to non-terminals.  It would be OK to
 | 
| +      ** apply it to terminal symbols too, but that makes the parser tables
 | 
| +      ** larger. */
 | 
| +      if( ap->sp->index<lemp->nterminal ) continue;
 | 
| +#endif
 | 
| +      /* If we reach this point, it means the optimization can be applied */
 | 
| +      nextap = ap;
 | 
| +      for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){}
 | 
| +      assert( ap2!=0 );
 | 
| +      ap->spOpt = ap2->sp;
 | 
| +      ap->type = ap2->type;
 | 
| +      ap->x = ap2->x;
 | 
| +    }
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |