Lemon update 2016-03-16 19:45:54 on branch trunk

- Enhance Lemon so that it reorders the reduce rules such that rules without actions occur at the end and so that the first rule is number 0. This reduces the size of the jump table on the reduce switch, and helps the parser to run faster. (user: drh)
This commit is contained in:
Randy Heit 2016-03-20 11:03:52 -05:00
parent ec5108b2e5
commit 4641549e0e
2 changed files with 88 additions and 28 deletions

View file

@ -194,6 +194,7 @@ struct rule {
const char *codeSuffix; /* Breakdown code after code[] above */ const char *codeSuffix; /* Breakdown code after code[] above */
struct symbol *precsym; /* Precedence symbol for this rule */ struct symbol *precsym; /* Precedence symbol for this rule */
int index; /* An index number 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 canReduce; /* True if this rule is ever reduced */
struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *nextlhs; /* Next rule with the same LHS */
struct rule *next; /* Next rule in the global list */ struct rule *next; /* Next rule in the global list */
@ -276,6 +277,7 @@ struct plink {
struct lemon { struct lemon {
struct state **sorted; /* Table of states sorted by state number */ struct state **sorted; /* Table of states sorted by state number */
struct rule *rule; /* List of all rules */ struct rule *rule; /* List of all rules */
struct rule *startRule; /* First rule */
int nstate; /* Number of states */ int nstate; /* Number of states */
int nxstate; /* nstate with tail degenerate states removed */ int nxstate; /* nstate with tail degenerate states removed */
int nrule; /* Number of rules */ int nrule; /* Number of rules */
@ -761,12 +763,12 @@ void FindStates(struct lemon *lemp)
ErrorMsg(lemp->filename,0, ErrorMsg(lemp->filename,0,
"The specified start symbol \"%s\" is not \ "The specified start symbol \"%s\" is not \
in a nonterminal of the grammar. \"%s\" will be used as the start \ 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++; lemp->errorcnt++;
sp = lemp->rule->lhs; sp = lemp->startRule->lhs;
} }
}else{ }else{
sp = lemp->rule->lhs; sp = lemp->startRule->lhs;
} }
/* Make sure the start symbol doesn't occur on the right-hand side of /* Make sure the start symbol doesn't occur on the right-hand side of
@ -1020,9 +1022,9 @@ void FindActions(struct lemon *lemp)
/* Add the accepting token */ /* Add the accepting token */
if( lemp->start ){ if( lemp->start ){
sp = Symbol_find(lemp->start); sp = Symbol_find(lemp->start);
if( sp==0 ) sp = lemp->rule->lhs; if( sp==0 ) sp = lemp->startRule->lhs;
}else{ }else{
sp = lemp->rule->lhs; sp = lemp->startRule->lhs;
} }
/* Add to the first state (which is always the starting state of the /* 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 ** finite state machine) an action to ACCEPT if the lookahead is the
@ -1414,6 +1416,54 @@ static void handle_T_option(char *z){
strcpy(user_templatename, z); strcpy(user_templatename, z);
} }
/* Merge together to lists of rules order 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 */ /* forward reference */
static const char *minimum_size_type(int lwr, int upr, int *pnByte); static const char *minimum_size_type(int lwr, int upr, int *pnByte);
@ -1461,6 +1511,7 @@ int main(int argc, char **argv)
}; };
int i; int i;
struct lemon lem; struct lemon lem;
struct rule *rp;
OptInit(argv,options,stderr); OptInit(argv,options,stderr);
if( version ){ if( version ){
@ -1507,6 +1558,16 @@ int main(int argc, char **argv)
for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++);
lem.nterminal = i; lem.nterminal = i;
/* Assign sequential rule numbers */
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 */ /* Generate a reprint of the grammar, if requested on the command line */
if( rpflag ){ if( rpflag ){
Reprint(&lem); Reprint(&lem);
@ -2978,13 +3039,13 @@ int PrintAction(
} }
case REDUCE: { case REDUCE: {
struct rule *rp = ap->x.rp; 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); RulePrint(fp, rp, -1);
break; break;
} }
case SHIFTREDUCE: { case SHIFTREDUCE: {
struct rule *rp = ap->x.rp; 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); RulePrint(fp, rp, -1);
break; break;
} }
@ -2997,7 +3058,7 @@ int PrintAction(
case SRCONFLICT: case SRCONFLICT:
case RRCONFLICT: case RRCONFLICT:
fprintf(fp,"%*s reduce %-7d ** Parsing conflict **", fprintf(fp,"%*s reduce %-7d ** Parsing conflict **",
indent,ap->sp->name,ap->x.rp->index); indent,ap->sp->name,ap->x.rp->iRule);
break; break;
case SSCONFLICT: case SSCONFLICT:
fprintf(fp,"%*s shift %-7d ** Parsing conflict **", fprintf(fp,"%*s shift %-7d ** Parsing conflict **",
@ -3014,7 +3075,7 @@ int PrintAction(
case RD_RESOLVED: case RD_RESOLVED:
if( showPrecedenceConflict ){ if( showPrecedenceConflict ){
fprintf(fp,"%*s reduce %-7d -- dropped by precedence", 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{ }else{
result = 0; result = 0;
} }
@ -3045,7 +3106,7 @@ void ReportOutput(struct lemon *lemp)
while( cfp ){ while( cfp ){
char buf[20]; char buf[20];
if( cfp->dot==cfp->rp->nrhs ){ if( cfp->dot==cfp->rp->nrhs ){
sprintf(buf,"(%d)",cfp->rp->index); sprintf(buf,"(%d)",cfp->rp->iRule);
fprintf(fp," %5s ",buf); fprintf(fp," %5s ",buf);
}else{ }else{
fprintf(fp," "); fprintf(fp," ");
@ -3150,8 +3211,8 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
int act; int act;
switch( ap->type ){ switch( ap->type ){
case SHIFT: act = ap->x.stp->statenum; break; case SHIFT: act = ap->x.stp->statenum; break;
case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break; case SHIFTREDUCE: act = ap->x.rp->iRule + lemp->nstate; break;
case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break; case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break;
case ERROR: act = lemp->nstate + lemp->nrule*2; break; case ERROR: act = lemp->nstate + lemp->nrule*2; break;
case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break;
default: act = -1; break; default: act = -1; break;
@ -4174,7 +4235,7 @@ void ReportTable(
** when tracing REDUCE actions. ** when tracing REDUCE actions.
*/ */
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
assert( rp->index==i ); assert( rp->iRule==i );
fprintf(out," /* %3d */ \"", i); fprintf(out," /* %3d */ \"", i);
writeRuleText(out, rp); writeRuleText(out, rp);
fprintf(out,"\",\n"); lineno++; fprintf(out,"\",\n"); lineno++;
@ -4270,14 +4331,14 @@ void ReportTable(
struct rule *rp2; /* Other rules with the same action */ struct rule *rp2; /* Other rules with the same action */
if( rp->code==0 ) continue; if( rp->code==0 ) continue;
if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */
fprintf(out," case %d: /* ",rp->index); fprintf(out," case %d: /* ",rp->iRule);
writeRuleText(out, rp); writeRuleText(out, rp);
fprintf(out," */\n"); lineno++; fprintf(out," */\n"); lineno++;
for(rp2=rp->next; rp2; rp2=rp2->next){ for(rp2=rp->next; rp2; rp2=rp2->next){
if( rp2->code==rp->code ){ if( rp2->code==rp->code ){
fprintf(out," case %d: /*",rp2->index); fprintf(out," case %d: /*",rp2->iRule);
writeRuleText(out, rp2); writeRuleText(out, rp2);
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++; fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
rp2->code = 0; rp2->code = 0;
} }
} }
@ -4291,9 +4352,9 @@ void ReportTable(
for(rp=lemp->rule; rp; rp=rp->next){ for(rp=lemp->rule; rp; rp=rp->next){
if( rp->code==0 ) continue; if( rp->code==0 ) continue;
assert( rp->code[0]=='\n' && rp->code[1]==0 ); assert( rp->code[0]=='\n' && rp->code[1]==0 );
fprintf(out," /* (%d) ", rp->index); fprintf(out," /* (%d) ", rp->iRule);
writeRuleText(out, rp); writeRuleText(out, rp);
fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->index); lineno++; fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
} }
fprintf(out," break;\n"); lineno++; fprintf(out," break;\n"); lineno++;
tplt_xfer(lemp->name,in,out,&lineno); tplt_xfer(lemp->name,in,out,&lineno);

View file

@ -427,7 +427,7 @@ int ParseStackPeak(void *p){
** Find the appropriate action for a parser given the terminal ** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead. ** look-ahead token iLookAhead.
*/ */
static int yy_find_shift_action( static unsigned int yy_find_shift_action(
yyParser *pParser, /* The parser */ yyParser *pParser, /* The parser */
YYCODETYPE iLookAhead /* The look-ahead token */ YYCODETYPE iLookAhead /* The look-ahead token */
){ ){
@ -615,7 +615,7 @@ static void yy_accept(yyParser*); /* Forward Declaration */
*/ */
static void yy_reduce( static void yy_reduce(
yyParser *yypParser, /* The parser */ yyParser *yypParser, /* The parser */
int yyruleno /* Number of the rule by which to reduce */ unsigned int yyruleno /* Number of the rule by which to reduce */
){ ){
int yygoto; /* The next state */ int yygoto; /* The next state */
int yyact; /* The next action */ int yyact; /* The next action */
@ -624,8 +624,7 @@ static void yy_reduce(
ParseARG_FETCH; ParseARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx]; yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0 if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs; yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno); yyRuleName[yyruleno], yymsp[-yysize].stateno);
@ -670,7 +669,7 @@ static void yy_reduce(
%% %%
/********** End reduce actions ************************************************/ /********** End reduce actions ************************************************/
}; };
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) ); assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs; yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs; yysize = yyRuleInfo[yyruleno].nrhs;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
@ -774,7 +773,7 @@ void Parse(
ParseARG_PDECL /* Optional %extra_argument parameter */ ParseARG_PDECL /* Optional %extra_argument parameter */
){ ){
YYMINORTYPE yyminorunion; YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */ unsigned int yyact; /* The parser action. */
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
int yyendofinput; /* True if we are at the end of input */ int yyendofinput; /* True if we are at the end of input */
#endif #endif