Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: third_party/sqlite/src/tool/lemon.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/sqlite/src/tool/kvtest-speed.sh ('k') | third_party/sqlite/src/tool/lempar.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
+ }
+ }
}
« no previous file with comments | « third_party/sqlite/src/tool/kvtest-speed.sh ('k') | third_party/sqlite/src/tool/lempar.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698