mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge parser enhancements and other improvements and bug fixes from trunk.
FossilOrigin-Name: 9cf3e51bcce1268dbb22cc8fa77160db3cb72746
This commit is contained in:
289
tool/lemon.c
289
tool/lemon.c
@@ -55,7 +55,7 @@ static char *msort(char*,char**,int(*)(const char*,const char*));
|
||||
** saying they are unsafe. So we define our own versions of those routines too.
|
||||
**
|
||||
** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and
|
||||
** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
|
||||
** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
|
||||
** The third is a helper routine for vsnprintf() that adds texts to the end of a
|
||||
** buffer, making sure the buffer is always zero-terminated.
|
||||
**
|
||||
@@ -316,7 +316,8 @@ enum e_action {
|
||||
RRCONFLICT, /* Was a reduce, but part of a conflict */
|
||||
SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
|
||||
RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
|
||||
NOT_USED /* Deleted by compression */
|
||||
NOT_USED, /* Deleted by compression */
|
||||
SHIFTREDUCE /* Shift first, then reduce */
|
||||
};
|
||||
|
||||
/* Every shift or reduce operation is stored as one of the following */
|
||||
@@ -340,7 +341,9 @@ struct state {
|
||||
struct action *ap; /* Array 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 iDflt; /* Default action */
|
||||
int iDfltReduce; /* Default action is to REDUCE by this rule */
|
||||
struct rule *pDfltReduce;/* The default REDUCE rule. */
|
||||
int autoReduce; /* True if this is an auto-reduce state */
|
||||
};
|
||||
#define NO_OFFSET (-2147483647)
|
||||
|
||||
@@ -360,6 +363,7 @@ struct lemon {
|
||||
struct state **sorted; /* Table of states sorted by state number */
|
||||
struct rule *rule; /* List of all rules */
|
||||
int nstate; /* Number of states */
|
||||
int nxstate; /* nstate with tail degenerate states removed */
|
||||
int nrule; /* Number of rules */
|
||||
int nsymbol; /* Number of terminal and nonterminal symbols */
|
||||
int nterminal; /* Number of terminal symbols */
|
||||
@@ -385,7 +389,8 @@ struct lemon {
|
||||
char *outname; /* Name of the current output file */
|
||||
char *tokenprefix; /* A prefix added to token names in the .h file */
|
||||
int nconflict; /* Number of parsing conflicts */
|
||||
int tablesize; /* Size of the parse tables */
|
||||
int nactiontab; /* Number of entries in the yy_action[] table */
|
||||
int tablesize; /* Total table size of all tables in bytes */
|
||||
int basisflag; /* Print only basis configurations */
|
||||
int has_fallback; /* True if any %fallback is seen in the grammar */
|
||||
int nolinenosflag; /* True if #line statements should not be printed */
|
||||
@@ -483,7 +488,7 @@ static int actioncmp(
|
||||
if( rc==0 ){
|
||||
rc = (int)ap1->type - (int)ap2->type;
|
||||
}
|
||||
if( rc==0 && ap1->type==REDUCE ){
|
||||
if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){
|
||||
rc = ap1->x.rp->index - ap2->x.rp->index;
|
||||
}
|
||||
if( rc==0 ){
|
||||
@@ -1375,14 +1380,16 @@ void Configlist_closure(struct lemon *lemp)
|
||||
|
||||
/* Sort the configuration list */
|
||||
void Configlist_sort(){
|
||||
current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp);
|
||||
current = (struct config*)msort((char*)current,(char**)&(current->next),
|
||||
Configcmp);
|
||||
currentend = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort the basis configuration list */
|
||||
void Configlist_sortbasis(){
|
||||
basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp);
|
||||
basis = (struct config*)msort((char*)current,(char**)&(current->bp),
|
||||
Configcmp);
|
||||
basisend = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1480,6 +1487,18 @@ static void handle_T_option(char *z){
|
||||
lemon_strcpy(user_templatename, z);
|
||||
}
|
||||
|
||||
/* forward reference */
|
||||
static const char *minimum_size_type(int lwr, int upr, int *pnByte);
|
||||
|
||||
/* Print a single line of the "Parser Stats" output
|
||||
*/
|
||||
static void stats_line(const char *zLabel, int iValue){
|
||||
int nLabel = lemonStrlen(zLabel);
|
||||
printf(" %s%.*s %5d\n", zLabel,
|
||||
35-nLabel, "................................",
|
||||
iValue);
|
||||
}
|
||||
|
||||
/* The main program. Parse the command line and do it... */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -1611,10 +1630,15 @@ int main(int argc, char **argv)
|
||||
if( !mhflag ) ReportHeader(&lem);
|
||||
}
|
||||
if( statistics ){
|
||||
printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
|
||||
lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
|
||||
printf(" %d states, %d parser table entries, %d conflicts\n",
|
||||
lem.nstate, lem.tablesize, lem.nconflict);
|
||||
printf("Parser statistics:\n");
|
||||
stats_line("terminal symbols", lem.nterminal);
|
||||
stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal);
|
||||
stats_line("total symbols", lem.nsymbol);
|
||||
stats_line("rules", lem.nrule);
|
||||
stats_line("states", lem.nxstate);
|
||||
stats_line("conflicts", lem.nconflict);
|
||||
stats_line("action table entries", lem.nactiontab);
|
||||
stats_line("total table size (bytes)", lem.tablesize);
|
||||
}
|
||||
if( lem.nconflict > 0 ){
|
||||
fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
|
||||
@@ -1873,7 +1897,8 @@ static int handleswitch(int i, FILE *err)
|
||||
dv = strtod(cp,&end);
|
||||
if( *end ){
|
||||
if( err ){
|
||||
fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
|
||||
fprintf(err,
|
||||
"%sillegal character in floating-point argument.\n",emsg);
|
||||
errline(i,(int)((char*)end-(char*)argv[i]),err);
|
||||
}
|
||||
errcnt++;
|
||||
@@ -2939,15 +2964,14 @@ void Reprint(struct lemon *lemp)
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigPrint(FILE *fp, struct config *cfp)
|
||||
{
|
||||
struct rule *rp;
|
||||
/* Print a single rule.
|
||||
*/
|
||||
void RulePrint(FILE *fp, struct rule *rp, int iCursor){
|
||||
struct symbol *sp;
|
||||
int i, j;
|
||||
rp = cfp->rp;
|
||||
fprintf(fp,"%s ::=",rp->lhs->name);
|
||||
for(i=0; i<=rp->nrhs; i++){
|
||||
if( i==cfp->dot ) fprintf(fp," *");
|
||||
if( i==iCursor ) fprintf(fp," *");
|
||||
if( i==rp->nrhs ) break;
|
||||
sp = rp->rhs[i];
|
||||
if( sp->type==MULTITERMINAL ){
|
||||
@@ -2961,6 +2985,12 @@ void ConfigPrint(FILE *fp, struct config *cfp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the rule for a configuration.
|
||||
*/
|
||||
void ConfigPrint(FILE *fp, struct config *cfp){
|
||||
RulePrint(fp, cfp->rp, cfp->dot);
|
||||
}
|
||||
|
||||
/* #define TEST */
|
||||
#if 0
|
||||
/* Print a set */
|
||||
@@ -3000,15 +3030,30 @@ char *tag;
|
||||
/* Print an action to the given file descriptor. Return FALSE if
|
||||
** nothing was actually printed.
|
||||
*/
|
||||
int PrintAction(struct action *ap, FILE *fp, int indent){
|
||||
int PrintAction(
|
||||
struct action *ap, /* The action to print */
|
||||
FILE *fp, /* Print the action here */
|
||||
int indent /* Indent by this amount */
|
||||
){
|
||||
int result = 1;
|
||||
switch( ap->type ){
|
||||
case SHIFT:
|
||||
fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->statenum);
|
||||
case SHIFT: {
|
||||
struct state *stp = ap->x.stp;
|
||||
fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum);
|
||||
break;
|
||||
case REDUCE:
|
||||
fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
|
||||
}
|
||||
case REDUCE: {
|
||||
struct rule *rp = ap->x.rp;
|
||||
fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index);
|
||||
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);
|
||||
RulePrint(fp, rp, -1);
|
||||
break;
|
||||
}
|
||||
case ACCEPT:
|
||||
fprintf(fp,"%*s accept",indent,ap->sp->name);
|
||||
break;
|
||||
@@ -3017,16 +3062,16 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
|
||||
break;
|
||||
case SRCONFLICT:
|
||||
case RRCONFLICT:
|
||||
fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
|
||||
fprintf(fp,"%*s reduce %-7d ** Parsing conflict **",
|
||||
indent,ap->sp->name,ap->x.rp->index);
|
||||
break;
|
||||
case SSCONFLICT:
|
||||
fprintf(fp,"%*s shift %-3d ** Parsing conflict **",
|
||||
fprintf(fp,"%*s shift %-7d ** Parsing conflict **",
|
||||
indent,ap->sp->name,ap->x.stp->statenum);
|
||||
break;
|
||||
case SH_RESOLVED:
|
||||
if( showPrecedenceConflict ){
|
||||
fprintf(fp,"%*s shift %-3d -- dropped by precedence",
|
||||
fprintf(fp,"%*s shift %-7d -- dropped by precedence",
|
||||
indent,ap->sp->name,ap->x.stp->statenum);
|
||||
}else{
|
||||
result = 0;
|
||||
@@ -3034,7 +3079,7 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
|
||||
break;
|
||||
case RD_RESOLVED:
|
||||
if( showPrecedenceConflict ){
|
||||
fprintf(fp,"%*s reduce %-3d -- dropped by precedence",
|
||||
fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
|
||||
indent,ap->sp->name,ap->x.rp->index);
|
||||
}else{
|
||||
result = 0;
|
||||
@@ -3047,7 +3092,7 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Generate the "y.output" log file */
|
||||
/* Generate the "*.out" log file */
|
||||
void ReportOutput(struct lemon *lemp)
|
||||
{
|
||||
int i;
|
||||
@@ -3058,7 +3103,7 @@ void ReportOutput(struct lemon *lemp)
|
||||
|
||||
fp = file_open(lemp,".out","wb");
|
||||
if( fp==0 ) return;
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
for(i=0; i<lemp->nxstate; i++){
|
||||
stp = lemp->sorted[i];
|
||||
fprintf(fp,"State %d:\n",stp->statenum);
|
||||
if( lemp->basisflag ) cfp=stp->bp;
|
||||
@@ -3166,10 +3211,11 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
|
||||
{
|
||||
int act;
|
||||
switch( ap->type ){
|
||||
case SHIFT: act = ap->x.stp->statenum; break;
|
||||
case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
|
||||
case ERROR: act = lemp->nstate + lemp->nrule; break;
|
||||
case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
|
||||
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 ERROR: act = lemp->nstate + lemp->nrule*2; break;
|
||||
case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break;
|
||||
default: act = -1; break;
|
||||
}
|
||||
return act;
|
||||
@@ -3228,7 +3274,8 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
|
||||
}
|
||||
in = fopen(user_templatename,"rb");
|
||||
if( in==0 ){
|
||||
fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename);
|
||||
fprintf(stderr,"Can't open the template file \"%s\".\n",
|
||||
user_templatename);
|
||||
lemp->errorcnt++;
|
||||
return 0;
|
||||
}
|
||||
@@ -3313,7 +3360,10 @@ void emit_destructor_code(
|
||||
}else if( sp->destructor ){
|
||||
cp = sp->destructor;
|
||||
fprintf(out,"{\n"); (*lineno)++;
|
||||
if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,sp->destLineno,lemp->filename); }
|
||||
if( !lemp->nolinenosflag ){
|
||||
(*lineno)++;
|
||||
tplt_linedir(out,sp->destLineno,lemp->filename);
|
||||
}
|
||||
}else if( lemp->vardest ){
|
||||
cp = lemp->vardest;
|
||||
if( cp==0 ) return;
|
||||
@@ -3510,13 +3560,19 @@ PRIVATE void emit_code(
|
||||
|
||||
/* Generate code to do the reduce action */
|
||||
if( rp->code ){
|
||||
if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,rp->line,lemp->filename); }
|
||||
if( !lemp->nolinenosflag ){
|
||||
(*lineno)++;
|
||||
tplt_linedir(out,rp->line,lemp->filename);
|
||||
}
|
||||
fprintf(out,"{%s",rp->code);
|
||||
for(cp=rp->code; *cp; cp++){
|
||||
if( *cp=='\n' ) (*lineno)++;
|
||||
} /* End loop */
|
||||
fprintf(out,"}\n"); (*lineno)++;
|
||||
if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,*lineno,lemp->outname); }
|
||||
if( !lemp->nolinenosflag ){
|
||||
(*lineno)++;
|
||||
tplt_linedir(out,*lineno,lemp->outname);
|
||||
}
|
||||
} /* End if( rp->code ) */
|
||||
|
||||
return;
|
||||
@@ -3647,24 +3703,32 @@ void print_stack_union(
|
||||
|
||||
/*
|
||||
** Return the name of a C datatype able to represent values between
|
||||
** lwr and upr, inclusive.
|
||||
** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof
|
||||
** for that type (1, 2, or 4) into *pnByte.
|
||||
*/
|
||||
static const char *minimum_size_type(int lwr, int upr){
|
||||
static const char *minimum_size_type(int lwr, int upr, int *pnByte){
|
||||
const char *zType = "int";
|
||||
int nByte = 4;
|
||||
if( lwr>=0 ){
|
||||
if( upr<=255 ){
|
||||
return "unsigned char";
|
||||
zType = "unsigned char";
|
||||
nByte = 1;
|
||||
}else if( upr<65535 ){
|
||||
return "unsigned short int";
|
||||
zType = "unsigned short int";
|
||||
nByte = 2;
|
||||
}else{
|
||||
return "unsigned int";
|
||||
zType = "unsigned int";
|
||||
nByte = 4;
|
||||
}
|
||||
}else if( lwr>=-127 && upr<=127 ){
|
||||
return "signed char";
|
||||
zType = "signed char";
|
||||
nByte = 1;
|
||||
}else if( lwr>=-32767 && upr<32767 ){
|
||||
return "short";
|
||||
}else{
|
||||
return "int";
|
||||
zType = "short";
|
||||
nByte = 2;
|
||||
}
|
||||
if( pnByte ) *pnByte = nByte;
|
||||
return zType;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3728,7 +3792,9 @@ void ReportTable(
|
||||
struct action *ap;
|
||||
struct rule *rp;
|
||||
struct acttab *pActtab;
|
||||
int i, j, n;
|
||||
int i, j, n, sz;
|
||||
int szActionType; /* sizeof(YYACTIONTYPE) */
|
||||
int szCodeType; /* sizeof(YYCODETYPE) */
|
||||
const char *name;
|
||||
int mnTknOfst, mxTknOfst;
|
||||
int mnNtOfst, mxNtOfst;
|
||||
@@ -3769,10 +3835,10 @@ void ReportTable(
|
||||
|
||||
/* Generate the defines */
|
||||
fprintf(out,"#define YYCODETYPE %s\n",
|
||||
minimum_size_type(0, lemp->nsymbol+1)); lineno++;
|
||||
minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++;
|
||||
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
|
||||
fprintf(out,"#define YYACTIONTYPE %s\n",
|
||||
minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++;
|
||||
minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++;
|
||||
if( lemp->wildcard ){
|
||||
fprintf(out,"#define YYWILDCARD %d\n",
|
||||
lemp->wildcard->index); lineno++;
|
||||
@@ -3808,36 +3874,24 @@ void ReportTable(
|
||||
if( mhflag ){
|
||||
fprintf(out,"#endif\n"); lineno++;
|
||||
}
|
||||
fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
|
||||
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
|
||||
if( lemp->errsym->useCnt ){
|
||||
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
|
||||
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
|
||||
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
|
||||
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
|
||||
}
|
||||
if( lemp->has_fallback ){
|
||||
fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the action table and its associates:
|
||||
**
|
||||
** yy_action[] A single table containing all actions.
|
||||
** yy_lookahead[] A table containing the lookahead for each entry in
|
||||
** yy_action. Used to detect hash collisions.
|
||||
** yy_shift_ofst[] For each state, the offset into yy_action for
|
||||
** shifting terminals.
|
||||
** yy_reduce_ofst[] For each state, the offset into yy_action for
|
||||
** shifting non-terminals after a reduce.
|
||||
** yy_default[] Default action for each state.
|
||||
/* Compute the action table, but do not output it yet. The action
|
||||
** table must be computed before generating the YYNSTATE macro because
|
||||
** we need to know how many states can be eliminated.
|
||||
*/
|
||||
|
||||
/* Compute the actions on all states and count them up */
|
||||
ax = (struct axset *) calloc(lemp->nstate*2, sizeof(ax[0]));
|
||||
ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
|
||||
if( ax==0 ){
|
||||
fprintf(stderr,"malloc failed\n");
|
||||
exit(1);
|
||||
}
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
for(i=0; i<lemp->nxstate; i++){
|
||||
stp = lemp->sorted[i];
|
||||
ax[i*2].stp = stp;
|
||||
ax[i*2].isTkn = 1;
|
||||
@@ -3848,15 +3902,12 @@ void ReportTable(
|
||||
}
|
||||
mxTknOfst = mnTknOfst = 0;
|
||||
mxNtOfst = mnNtOfst = 0;
|
||||
|
||||
/* Compute the action table. In order to try to keep the size of the
|
||||
** action table to a minimum, the heuristic of placing the largest action
|
||||
** sets first is used.
|
||||
*/
|
||||
for(i=0; i<lemp->nstate*2; i++) ax[i].iOrder = i;
|
||||
qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
|
||||
/* In an effort to minimize the action table size, use the heuristic
|
||||
** of placing the largest action sets first */
|
||||
for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i;
|
||||
qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare);
|
||||
pActtab = acttab_alloc();
|
||||
for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
|
||||
for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){
|
||||
stp = ax[i].stp;
|
||||
if( ax[i].isTkn ){
|
||||
for(ap=stp->ap; ap; ap=ap->next){
|
||||
@@ -3885,8 +3936,37 @@ void ReportTable(
|
||||
}
|
||||
free(ax);
|
||||
|
||||
/* Finish rendering the constants now that the action table has
|
||||
** been computed */
|
||||
fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
|
||||
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
|
||||
fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nstate-1); lineno++;
|
||||
fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++;
|
||||
i = lemp->nstate + lemp->nrule;
|
||||
fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++;
|
||||
fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++;
|
||||
i = lemp->nstate + lemp->nrule*2;
|
||||
fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
|
||||
fprintf(out,"#define YY_ERROR_ACTION %d\n", i); lineno++;
|
||||
fprintf(out,"#define YY_ACCEPT_ACTION %d\n", i+1); lineno++;
|
||||
fprintf(out,"#define YY_NO_ACTION %d\n", i+2); lineno++;
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Now output the action table and its associates:
|
||||
**
|
||||
** yy_action[] A single table containing all actions.
|
||||
** yy_lookahead[] A table containing the lookahead for each entry in
|
||||
** yy_action. Used to detect hash collisions.
|
||||
** yy_shift_ofst[] For each state, the offset into yy_action for
|
||||
** shifting terminals.
|
||||
** yy_reduce_ofst[] For each state, the offset into yy_action for
|
||||
** shifting non-terminals after a reduce.
|
||||
** yy_default[] Default action for each state.
|
||||
*/
|
||||
|
||||
/* Output the yy_action table */
|
||||
n = acttab_size(pActtab);
|
||||
lemp->nactiontab = n = acttab_size(pActtab);
|
||||
lemp->tablesize += n*szActionType;
|
||||
fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
|
||||
fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
|
||||
for(i=j=0; i<n; i++){
|
||||
@@ -3904,6 +3984,7 @@ void ReportTable(
|
||||
fprintf(out, "};\n"); lineno++;
|
||||
|
||||
/* Output the yy_lookahead table */
|
||||
lemp->tablesize += n*szCodeType;
|
||||
fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
|
||||
for(i=j=0; i<n; i++){
|
||||
int la = acttab_yylookahead(pActtab, i);
|
||||
@@ -3921,13 +4002,14 @@ void ReportTable(
|
||||
|
||||
/* Output the yy_shift_ofst[] table */
|
||||
fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
|
||||
n = lemp->nstate;
|
||||
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, "static const %s yy_shift_ofst[] = {\n",
|
||||
minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
|
||||
minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++;
|
||||
lemp->tablesize += n*sz;
|
||||
for(i=j=0; i<n; i++){
|
||||
int ofst;
|
||||
stp = lemp->sorted[i];
|
||||
@@ -3946,13 +4028,14 @@ void ReportTable(
|
||||
|
||||
/* Output the yy_reduce_ofst[] table */
|
||||
fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
|
||||
n = lemp->nstate;
|
||||
n = lemp->nxstate;
|
||||
while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
|
||||
fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
|
||||
fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
|
||||
fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
|
||||
fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
|
||||
minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
|
||||
minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++;
|
||||
lemp->tablesize += n*sz;
|
||||
for(i=j=0; i<n; i++){
|
||||
int ofst;
|
||||
stp = lemp->sorted[i];
|
||||
@@ -3971,11 +4054,12 @@ void ReportTable(
|
||||
|
||||
/* Output the default action table */
|
||||
fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
|
||||
n = lemp->nstate;
|
||||
n = lemp->nxstate;
|
||||
lemp->tablesize += n*szActionType;
|
||||
for(i=j=0; i<n; i++){
|
||||
stp = lemp->sorted[i];
|
||||
if( j==0 ) fprintf(out," /* %5d */ ", i);
|
||||
fprintf(out, " %4d,", stp->iDflt);
|
||||
fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule);
|
||||
if( j==9 || i==n-1 ){
|
||||
fprintf(out, "\n"); lineno++;
|
||||
j = 0;
|
||||
@@ -3991,6 +4075,7 @@ void ReportTable(
|
||||
if( lemp->has_fallback ){
|
||||
int mx = lemp->nterminal - 1;
|
||||
while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
|
||||
lemp->tablesize += (mx+1)*szCodeType;
|
||||
for(i=0; i<=mx; i++){
|
||||
struct symbol *p = lemp->symbols[i];
|
||||
if( p->fallback==0 ){
|
||||
@@ -4207,7 +4292,7 @@ void CompressTables(struct lemon *lemp)
|
||||
struct state *stp;
|
||||
struct action *ap, *ap2;
|
||||
struct rule *rp, *rp2, *rbest;
|
||||
int nbest, n;
|
||||
int nbest, n, nshift;
|
||||
int i;
|
||||
int usesWildcard;
|
||||
|
||||
@@ -4255,6 +4340,32 @@ void CompressTables(struct lemon *lemp)
|
||||
if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
|
||||
}
|
||||
stp->ap = Action_sort(stp->ap);
|
||||
|
||||
for(ap=stp->ap; ap; ap=ap->next){
|
||||
if( ap->type==SHIFT ) break;
|
||||
if( ap->type==REDUCE && ap->x.rp!=rbest ) break;
|
||||
}
|
||||
if( ap==0 ){
|
||||
stp->autoReduce = 1;
|
||||
stp->pDfltReduce = rbest;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a second pass over all states and actions. Convert
|
||||
** every action that is a SHIFT to an autoReduce state into
|
||||
** a SHIFTREDUCE action.
|
||||
*/
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
stp = lemp->sorted[i];
|
||||
for(ap=stp->ap; ap; ap=ap->next){
|
||||
struct state *pNextState;
|
||||
if( ap->type!=SHIFT ) continue;
|
||||
pNextState = ap->x.stp;
|
||||
if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){
|
||||
ap->type = SHIFTREDUCE;
|
||||
ap->x.rp = pNextState->pDfltReduce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4295,17 +4406,19 @@ void ResortStates(struct lemon *lemp)
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
stp = lemp->sorted[i];
|
||||
stp->nTknAct = stp->nNtAct = 0;
|
||||
stp->iDflt = lemp->nstate + lemp->nrule;
|
||||
stp->iDfltReduce = lemp->nrule; /* Init dflt action to "syntax error" */
|
||||
stp->iTknOfst = NO_OFFSET;
|
||||
stp->iNtOfst = NO_OFFSET;
|
||||
for(ap=stp->ap; ap; ap=ap->next){
|
||||
if( compute_action(lemp,ap)>=0 ){
|
||||
int iAction = compute_action(lemp,ap);
|
||||
if( iAction>=0 ){
|
||||
if( ap->sp->index<lemp->nterminal ){
|
||||
stp->nTknAct++;
|
||||
}else if( ap->sp->index<lemp->nsymbol ){
|
||||
stp->nNtAct++;
|
||||
}else{
|
||||
stp->iDflt = compute_action(lemp, ap);
|
||||
assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp );
|
||||
stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4315,6 +4428,10 @@ void ResortStates(struct lemon *lemp)
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
lemp->sorted[i]->statenum = i;
|
||||
}
|
||||
lemp->nxstate = lemp->nstate;
|
||||
while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){
|
||||
lemp->nxstate--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
112
tool/lempar.c
112
tool/lempar.c
@@ -50,15 +50,19 @@
|
||||
** ParseARG_PDECL A parameter declaration for the %extra_argument
|
||||
** ParseARG_STORE Code to store %extra_argument into yypParser
|
||||
** ParseARG_FETCH Code to extract %extra_argument from yypParser
|
||||
** YYNSTATE the combined number of states.
|
||||
** YYNRULE the number of rules in the grammar
|
||||
** YYERRORSYMBOL is the code number of the error symbol. If not
|
||||
** defined, then do no error processing.
|
||||
** YYNSTATE the combined number of states.
|
||||
** YYNRULE the number of rules in the grammar
|
||||
** YY_MAX_SHIFT Maximum value for shift actions
|
||||
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
|
||||
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
|
||||
** YY_MIN_REDUCE Maximum value for reduce actions
|
||||
** YY_ERROR_ACTION The yy_action[] code for syntax error
|
||||
** YY_ACCEPT_ACTION The yy_action[] code for accept
|
||||
** YY_NO_ACTION The yy_action[] code for no-op
|
||||
*/
|
||||
%%
|
||||
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
|
||||
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
|
||||
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
|
||||
|
||||
/* The yyzerominor constant is used to initialize instances of
|
||||
** YYMINORTYPE objects to zero. */
|
||||
@@ -85,16 +89,20 @@ static const YYMINORTYPE yyzerominor = { 0 };
|
||||
** Suppose the action integer is N. Then the action is determined as
|
||||
** follows
|
||||
**
|
||||
** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
|
||||
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
|
||||
** token onto the stack and goto state N.
|
||||
**
|
||||
** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
|
||||
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
|
||||
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
|
||||
**
|
||||
** N == YYNSTATE+YYNRULE A syntax error has occurred.
|
||||
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
|
||||
** and YY_MAX_REDUCE
|
||||
|
||||
** N == YY_ERROR_ACTION A syntax error has occurred.
|
||||
**
|
||||
** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
|
||||
** N == YY_ACCEPT_ACTION The parser accepts its input.
|
||||
**
|
||||
** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
|
||||
** N == YY_NO_ACTION No such action. Denotes unused
|
||||
** slots in the yy_action[] table.
|
||||
**
|
||||
** The action table is constructed as a single large table named yy_action[].
|
||||
@@ -153,9 +161,13 @@ static const YYCODETYPE yyFallback[] = {
|
||||
** + The semantic value stored at this level of the stack. This is
|
||||
** the information used by the action routines in the grammar.
|
||||
** It is sometimes called the "minor" token.
|
||||
**
|
||||
** After the "shift" half of a SHIFTREDUCE action, the stateno field
|
||||
** actually contains the reduce action for the second half of the
|
||||
** SHIFTREDUCE.
|
||||
*/
|
||||
struct yyStackEntry {
|
||||
YYACTIONTYPE stateno; /* The state-number */
|
||||
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
|
||||
YYCODETYPE major; /* The major token value. This is the code
|
||||
** number for the token at this stack level */
|
||||
YYMINORTYPE minor; /* The user-supplied minor token value. This
|
||||
@@ -384,11 +396,11 @@ static int yy_find_shift_action(
|
||||
){
|
||||
int i;
|
||||
int stateno = pParser->yystack[pParser->yyidx].stateno;
|
||||
|
||||
if( stateno>YY_SHIFT_COUNT
|
||||
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
|
||||
return yy_default[stateno];
|
||||
}
|
||||
|
||||
if( stateno>=YY_MIN_REDUCE ) return stateno;
|
||||
assert( stateno <= YY_SHIFT_COUNT );
|
||||
i = yy_shift_ofst[stateno];
|
||||
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
|
||||
assert( iLookAhead!=YYNOCODE );
|
||||
i += iLookAhead;
|
||||
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
|
||||
@@ -489,7 +501,29 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform a shift action.
|
||||
** Print tracing information for a SHIFT action
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
static void yyTraceShift(yyParser *yypParser, int yyNewState){
|
||||
if( yyTraceFILE ){
|
||||
int i;
|
||||
if( yyNewState<YYNSTATE ){
|
||||
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
|
||||
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
|
||||
for(i=1; i<=yypParser->yyidx; i++)
|
||||
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
|
||||
fprintf(yyTraceFILE,"\n");
|
||||
}else{
|
||||
fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define yyTraceShift(X,Y)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform a shift action. Return the number of errors.
|
||||
*/
|
||||
static void yy_shift(
|
||||
yyParser *yypParser, /* The parser to be shifted */
|
||||
@@ -522,16 +556,7 @@ static void yy_shift(
|
||||
yytos->stateno = (YYACTIONTYPE)yyNewState;
|
||||
yytos->major = (YYCODETYPE)yyMajor;
|
||||
yytos->minor = *yypMinor;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && yypParser->yyidx>0 ){
|
||||
int i;
|
||||
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
|
||||
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
|
||||
for(i=1; i<=yypParser->yyidx; i++)
|
||||
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
|
||||
fprintf(yyTraceFILE,"\n");
|
||||
}
|
||||
#endif
|
||||
yyTraceShift(yypParser, yyNewState);
|
||||
}
|
||||
|
||||
/* The following table contains information about every rule that
|
||||
@@ -564,8 +589,9 @@ static void yy_reduce(
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && yyruleno>=0
|
||||
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
|
||||
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
|
||||
yyRuleName[yyruleno]);
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
|
||||
yyRuleName[yyruleno], yymsp[-yysize].stateno);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
@@ -602,9 +628,9 @@ static void yy_reduce(
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
yypParser->yyidx -= yysize;
|
||||
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
|
||||
if( yyact < YYNSTATE ){
|
||||
#ifdef NDEBUG
|
||||
/* If we are not debugging and the reduce action popped at least
|
||||
if( yyact <= YY_MAX_SHIFTREDUCE ){
|
||||
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
|
||||
/* If the reduce action popped at least
|
||||
** one element off the stack, then we can push the new element back
|
||||
** onto the stack here, and skip the stack overflow test in yy_shift().
|
||||
** That gives a significant speed improvement. */
|
||||
@@ -614,13 +640,12 @@ static void yy_reduce(
|
||||
yymsp->stateno = (YYACTIONTYPE)yyact;
|
||||
yymsp->major = (YYCODETYPE)yygoto;
|
||||
yymsp->minor = yygotominor;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
yyTraceShift(yypParser, yyact);
|
||||
}else{
|
||||
yy_shift(yypParser,yyact,yygoto,&yygotominor);
|
||||
}
|
||||
}else{
|
||||
assert( yyact == YYNSTATE + YYNRULE + 1 );
|
||||
assert( yyact == YY_ACCEPT_ACTION );
|
||||
yy_accept(yypParser);
|
||||
}
|
||||
}
|
||||
@@ -740,13 +765,13 @@ void Parse(
|
||||
|
||||
do{
|
||||
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
|
||||
if( yyact<YYNSTATE ){
|
||||
assert( !yyendofinput ); /* Impossible to shift the $ token */
|
||||
if( yyact <= YY_MAX_SHIFTREDUCE ){
|
||||
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
|
||||
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
|
||||
yypParser->yyerrcnt--;
|
||||
yymajor = YYNOCODE;
|
||||
}else if( yyact < YYNSTATE + YYNRULE ){
|
||||
yy_reduce(yypParser,yyact-YYNSTATE);
|
||||
}else if( yyact <= YY_MAX_REDUCE ){
|
||||
yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
|
||||
}else{
|
||||
assert( yyact == YY_ERROR_ACTION );
|
||||
#ifdef YYERRORSYMBOL
|
||||
@@ -796,7 +821,7 @@ void Parse(
|
||||
yymx != YYERRORSYMBOL &&
|
||||
(yyact = yy_find_reduce_action(
|
||||
yypParser->yystack[yypParser->yyidx].stateno,
|
||||
YYERRORSYMBOL)) >= YYNSTATE
|
||||
YYERRORSYMBOL)) >= YY_MIN_REDUCE
|
||||
){
|
||||
yy_pop_parser_stack(yypParser);
|
||||
}
|
||||
@@ -846,5 +871,10 @@ void Parse(
|
||||
#endif
|
||||
}
|
||||
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user