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 */
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 */
struct rule *nextlhs; /* Next rule with the same LHS */
struct rule *next; /* Next rule in the global list */
@ -276,6 +277,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 */
@ -761,12 +763,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
@ -1020,9 +1022,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
@ -1414,6 +1416,54 @@ static void handle_T_option(char *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 */
static const char *minimum_size_type(int lwr, int upr, int *pnByte);
@ -1461,6 +1511,7 @@ int main(int argc, char **argv)
};
int i;
struct lemon lem;
struct rule *rp;
OptInit(argv,options,stderr);
if( version ){
@ -1507,6 +1558,16 @@ int main(int argc, char **argv)
for(i=1; ISUPPER(lem.symbols[i]->name[0]); 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 */
if( rpflag ){
Reprint(&lem);
@ -2978,13 +3039,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;
}
@ -2997,7 +3058,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 **",
@ -3014,7 +3075,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;
}
@ -3045,7 +3106,7 @@ void ReportOutput(struct lemon *lemp)
while( cfp ){
char buf[20];
if( cfp->dot==cfp->rp->nrhs ){
sprintf(buf,"(%d)",cfp->rp->index);
sprintf(buf,"(%d)",cfp->rp->iRule);
fprintf(fp," %5s ",buf);
}else{
fprintf(fp," ");
@ -3150,8 +3211,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;
@ -4174,7 +4235,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++;
@ -4269,15 +4330,15 @@ void ReportTable(
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->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */
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);
fprintf(out," case %d: /*",rp2->iRule);
writeRuleText(out, rp2);
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++;
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
rp2->code = 0;
}
}
@ -4289,11 +4350,11 @@ void ReportTable(
** 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);
writeRuleText(out, rp);
fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->index); lineno++;
if( rp->code==0 ) continue;
assert( rp->code[0]=='\n' && rp->code[1]==0 );
fprintf(out," /* (%d) ", rp->iRule);
writeRuleText(out, rp);
fprintf(out," */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
}
fprintf(out," break;\n"); 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
** look-ahead token iLookAhead.
*/
static int yy_find_shift_action(
static unsigned int yy_find_shift_action(
yyParser *pParser, /* The parser */
YYCODETYPE iLookAhead /* The look-ahead token */
){
@ -615,7 +615,7 @@ static void yy_accept(yyParser*); /* Forward Declaration */
*/
static void yy_reduce(
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 yyact; /* The next action */
@ -624,8 +624,7 @@ static void yy_reduce(
ParseARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno);
@ -670,7 +669,7 @@ static void yy_reduce(
%%
/********** End reduce actions ************************************************/
};
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
@ -774,7 +773,7 @@ void Parse(
ParseARG_PDECL /* Optional %extra_argument parameter */
){
YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */
unsigned int yyact; /* The parser action. */
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
int yyendofinput; /* True if we are at the end of input */
#endif