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.

FossilOrigin-Name: d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d
This commit is contained in:
drh 2016-03-16 19:45:54 +00:00
parent 3f77389bb4
commit 4ef07708df
4 changed files with 92 additions and 33 deletions

View File

@ -1,5 +1,5 @@
C Avoid\sa\sfew\sunnecessary\sfstat()s\son\sjournal\sfiles.
D 2016-03-16T19:10:46.537
C Enhance\sLemon\sso\sthat\sit\sreorders\sthe\sreduce\srules\ssuch\sthat\srules\swithout\nactions\soccur\sat\sthe\send\sand\sso\sthat\sthe\sfirst\srule\sis\snumber\s0.\s\sThis\nreduces\sthe\ssize\sof\sthe\sjump\stable\son\sthe\sreduce\sswitch,\sand\shelps\sthe\sparser\nto\srun\sfaster.
D 2016-03-16T19:45:54.638
F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66
@ -1386,8 +1386,8 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 251f5c3f21b553240cbdd42dd187a51bb2372cd3
F tool/lempar.c d5114c7d13aa3af1e27ff3d02e4dea6eadec7ddf
F tool/lemon.c cfbfe061a4b2766512f6b484882eee2c86a14506
F tool/lempar.c 404ea3dc27dbeed343f0e61b1d36e97b9f5f0fb6
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
@ -1456,8 +1456,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 96ea9909429f0b3b4a67002e8340ae3f7dc0b73f f3c0579e931799088e9a83757e25bae229120697
R 2179dd350d027a0023ff0b4d274ede19
T +closed f3c0579e931799088e9a83757e25bae229120697
P dbf84705913c0845ca4e75eb30c91536c754efeb
R 864f536bc3cc564acb40b05c95555e64
U drh
Z 6f4affaf464559d5d4fad621b1dda7eb
Z 3c44460af79cebe8997bb55087f66950

View File

@ -1 +1 @@
dbf84705913c0845ca4e75eb30c91536c754efeb
d5712f21ec758ff096a7b1bb8ed4fc5ec400ca5d

View File

@ -290,6 +290,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 */
@ -372,6 +373,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 */
@ -858,12 +860,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
@ -1117,9 +1119,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
@ -1497,6 +1499,54 @@ static void handle_T_option(char *z){
lemon_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);
@ -1545,6 +1595,7 @@ int main(int argc, char **argv)
int i;
int exitcode;
struct lemon lem;
struct rule *rp;
OptInit(argv,options,stderr);
if( version ){
@ -1591,6 +1642,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);
@ -3054,13 +3115,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;
}
@ -3073,7 +3134,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 **",
@ -3090,7 +3151,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;
}
@ -3121,7 +3182,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," ");
@ -3222,8 +3283,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;
@ -4241,7 +4302,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++;
@ -4337,14 +4398,14 @@ void ReportTable(
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);
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;
}
}
@ -4358,9 +4419,9 @@ void ReportTable(
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);
fprintf(out," /* (%d) ", rp->iRule);
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++;
tplt_xfer(lemp->name,in,out,&lineno);

View File

@ -418,7 +418,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 */
){
@ -606,7 +606,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 */
@ -615,8 +615,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);
@ -661,7 +660,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);
@ -765,7 +764,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