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 85e94f7007f905754127fd81472f9ff64e631a2d..d704deb624d42b39ca455db5bc5617e2197d62d9 100644 |
--- a/third_party/sqlite/src/tool/lemon.c |
+++ b/third_party/sqlite/src/tool/lemon.c |
@@ -13,6 +13,14 @@ |
#include <stdlib.h> |
#include <assert.h> |
+#define ISSPACE(X) isspace((unsigned char)(X)) |
+#define ISDIGIT(X) isdigit((unsigned char)(X)) |
+#define ISALNUM(X) isalnum((unsigned char)(X)) |
+#define ISALPHA(X) isalpha((unsigned char)(X)) |
+#define ISUPPER(X) isupper((unsigned char)(X)) |
+#define ISLOWER(X) islower((unsigned char)(X)) |
+ |
+ |
#ifndef __WIN32__ |
# if defined(_WIN32) || defined(WIN32) |
# define __WIN32__ |
@@ -55,7 +63,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. |
** |
@@ -93,9 +101,9 @@ static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){ |
int iWidth = 0; |
lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); |
c = zFormat[++i]; |
- if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){ |
+ if( ISDIGIT(c) || (c=='-' && ISDIGIT(zFormat[i+1])) ){ |
if( c=='-' ) i++; |
- while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; |
+ while( ISDIGIT(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; |
if( c=='-' ) iWidth = -iWidth; |
c = zFormat[i]; |
} |
@@ -316,7 +324,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 +349,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 +371,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 +397,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 +496,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 ){ |
@@ -1114,7 +1127,6 @@ void FindActions(struct lemon *lemp) |
/* Resolve conflicts */ |
for(i=0; i<lemp->nstate; i++){ |
struct action *ap, *nap; |
- struct state *stp; |
stp = lemp->sorted[i]; |
/* assert( stp->ap ); */ |
stp->ap = Action_sort(stp->ap); |
@@ -1376,14 +1388,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; |
} |
@@ -1481,6 +1495,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) |
{ |
@@ -1497,10 +1523,12 @@ int main(int argc, char **argv) |
{OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, |
{OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, |
{OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, |
- {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, |
+ {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"}, |
{OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, |
+ {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"}, |
{OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, |
{OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, |
+ {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"}, |
{OPT_FLAG, "p", (char*)&showPrecedenceConflict, |
"Show conflicts resolved by precedence rules"}, |
{OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."}, |
@@ -1508,6 +1536,8 @@ int main(int argc, char **argv) |
{OPT_FLAG, "s", (char*)&statistics, |
"Print parser stats to standard output."}, |
{OPT_FLAG, "x", (char*)&version, "Print the version number."}, |
+ {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, |
+ {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"}, |
{OPT_FLAG,0,0,0} |
}; |
int i; |
@@ -1556,7 +1586,7 @@ int main(int argc, char **argv) |
while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } |
assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); |
lem.nsymbol = i - 1; |
- for(i=1; isupper(lem.symbols[i]->name[0]); i++); |
+ for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); |
lem.nterminal = i; |
/* Generate a reprint of the grammar, if requested on the command line */ |
@@ -1608,10 +1638,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); |
@@ -1727,7 +1762,7 @@ static char *msort( |
char *ep; |
char *set[LISTSIZE]; |
int i; |
- offset = (unsigned long)next - (unsigned long)list; |
+ offset = (unsigned long)((char*)next - (char*)list); |
for(i=0; i<LISTSIZE; i++) set[i] = 0; |
while( list ){ |
ep = list; |
@@ -1812,6 +1847,8 @@ static int handleflags(int i, FILE *err) |
errline(i,1,err); |
} |
errcnt++; |
+ }else if( op[j].arg==0 ){ |
+ /* Ignore this option */ |
}else if( op[j].type==OPT_FLAG ){ |
*((int*)op[j].arg) = v; |
}else if( op[j].type==OPT_FFLAG ){ |
@@ -1868,8 +1905,9 @@ 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); |
- errline(i,((unsigned long)end)-(unsigned long)argv[i],err); |
+ fprintf(err, |
+ "%sillegal character in floating-point argument.\n",emsg); |
+ errline(i,(int)((char*)end-(char*)argv[i]),err); |
} |
errcnt++; |
} |
@@ -1880,7 +1918,7 @@ static int handleswitch(int i, FILE *err) |
if( *end ){ |
if( err ){ |
fprintf(err,"%sillegal character in integer argument.\n",emsg); |
- errline(i,((unsigned long)end)-(unsigned long)argv[i],err); |
+ errline(i,(int)((char*)end-(char*)argv[i]),err); |
} |
errcnt++; |
} |
@@ -2001,17 +2039,17 @@ void OptPrint(){ |
break; |
case OPT_INT: |
case OPT_FINT: |
- fprintf(errstream," %s=<integer>%*s %s\n",op[i].label, |
+ fprintf(errstream," -%s<integer>%*s %s\n",op[i].label, |
(int)(max-lemonStrlen(op[i].label)-9),"",op[i].message); |
break; |
case OPT_DBL: |
case OPT_FDBL: |
- fprintf(errstream," %s=<real>%*s %s\n",op[i].label, |
+ fprintf(errstream," -%s<real>%*s %s\n",op[i].label, |
(int)(max-lemonStrlen(op[i].label)-6),"",op[i].message); |
break; |
case OPT_STR: |
case OPT_FSTR: |
- fprintf(errstream," %s=<string>%*s %s\n",op[i].label, |
+ fprintf(errstream," -%s<string>%*s %s\n",op[i].label, |
(int)(max-lemonStrlen(op[i].label)-8),"",op[i].message); |
break; |
} |
@@ -2091,7 +2129,7 @@ static void parseonetoken(struct pstate *psp) |
case WAITING_FOR_DECL_OR_RULE: |
if( x[0]=='%' ){ |
psp->state = WAITING_FOR_DECL_KEYWORD; |
- }else if( islower(x[0]) ){ |
+ }else if( ISLOWER(x[0]) ){ |
psp->lhs = Symbol_new(x); |
psp->nrhs = 0; |
psp->lhsalias = 0; |
@@ -2121,7 +2159,7 @@ to follow the previous rule."); |
} |
break; |
case PRECEDENCE_MARK_1: |
- if( !isupper(x[0]) ){ |
+ if( !ISUPPER(x[0]) ){ |
ErrorMsg(psp->filename,psp->tokenlineno, |
"The precedence symbol must be a terminal."); |
psp->errorcnt++; |
@@ -2161,7 +2199,7 @@ to follow the previous rule."); |
} |
break; |
case LHS_ALIAS_1: |
- if( isalpha(x[0]) ){ |
+ if( ISALPHA(x[0]) ){ |
psp->lhsalias = x; |
psp->state = LHS_ALIAS_2; |
}else{ |
@@ -2230,7 +2268,7 @@ to follow the previous rule."); |
psp->prevrule = rp; |
} |
psp->state = WAITING_FOR_DECL_OR_RULE; |
- }else if( isalpha(x[0]) ){ |
+ }else if( ISALPHA(x[0]) ){ |
if( psp->nrhs>=MAXRHS ){ |
ErrorMsg(psp->filename,psp->tokenlineno, |
"Too many symbols on RHS of rule beginning at \"%s\".", |
@@ -2259,7 +2297,7 @@ to follow the previous rule."); |
msp->subsym = (struct symbol **) realloc(msp->subsym, |
sizeof(struct symbol*)*msp->nsubsym); |
msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); |
- if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){ |
+ if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){ |
ErrorMsg(psp->filename,psp->tokenlineno, |
"Cannot form a compound containing a non-terminal"); |
psp->errorcnt++; |
@@ -2274,7 +2312,7 @@ to follow the previous rule."); |
} |
break; |
case RHS_ALIAS_1: |
- if( isalpha(x[0]) ){ |
+ if( ISALPHA(x[0]) ){ |
psp->alias[psp->nrhs-1] = x; |
psp->state = RHS_ALIAS_2; |
}else{ |
@@ -2296,7 +2334,7 @@ to follow the previous rule."); |
} |
break; |
case WAITING_FOR_DECL_KEYWORD: |
- if( isalpha(x[0]) ){ |
+ if( ISALPHA(x[0]) ){ |
psp->declkeyword = x; |
psp->declargslot = 0; |
psp->decllinenoslot = 0; |
@@ -2376,7 +2414,7 @@ to follow the previous rule."); |
} |
break; |
case WAITING_FOR_DESTRUCTOR_SYMBOL: |
- if( !isalpha(x[0]) ){ |
+ if( !ISALPHA(x[0]) ){ |
ErrorMsg(psp->filename,psp->tokenlineno, |
"Symbol name missing after %%destructor keyword"); |
psp->errorcnt++; |
@@ -2390,7 +2428,7 @@ to follow the previous rule."); |
} |
break; |
case WAITING_FOR_DATATYPE_SYMBOL: |
- if( !isalpha(x[0]) ){ |
+ if( !ISALPHA(x[0]) ){ |
ErrorMsg(psp->filename,psp->tokenlineno, |
"Symbol name missing after %%type keyword"); |
psp->errorcnt++; |
@@ -2415,7 +2453,7 @@ to follow the previous rule."); |
case WAITING_FOR_PRECEDENCE_SYMBOL: |
if( x[0]=='.' ){ |
psp->state = WAITING_FOR_DECL_OR_RULE; |
- }else if( isupper(x[0]) ){ |
+ }else if( ISUPPER(x[0]) ){ |
struct symbol *sp; |
sp = Symbol_new(x); |
if( sp->prec>=0 ){ |
@@ -2433,10 +2471,10 @@ to follow the previous rule."); |
} |
break; |
case WAITING_FOR_DECL_ARG: |
- if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ |
+ if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){ |
const char *zOld, *zNew; |
char *zBuf, *z; |
- int nOld, n, nLine, nNew, nBack; |
+ int nOld, n, nLine = 0, nNew, nBack; |
int addLineMacro; |
char zLine[50]; |
zNew = x; |
@@ -2494,7 +2532,7 @@ to follow the previous rule."); |
case WAITING_FOR_FALLBACK_ID: |
if( x[0]=='.' ){ |
psp->state = WAITING_FOR_DECL_OR_RULE; |
- }else if( !isupper(x[0]) ){ |
+ }else if( !ISUPPER(x[0]) ){ |
ErrorMsg(psp->filename, psp->tokenlineno, |
"%%fallback argument \"%s\" should be a token", x); |
psp->errorcnt++; |
@@ -2515,7 +2553,7 @@ to follow the previous rule."); |
case WAITING_FOR_WILDCARD_ID: |
if( x[0]=='.' ){ |
psp->state = WAITING_FOR_DECL_OR_RULE; |
- }else if( !isupper(x[0]) ){ |
+ }else if( !ISUPPER(x[0]) ){ |
ErrorMsg(psp->filename, psp->tokenlineno, |
"%%wildcard argument \"%s\" should be a token", x); |
psp->errorcnt++; |
@@ -2531,7 +2569,7 @@ to follow the previous rule."); |
} |
break; |
case WAITING_FOR_CLASS_ID: |
- if( !islower(x[0]) ){ |
+ if( !ISLOWER(x[0]) ){ |
ErrorMsg(psp->filename, psp->tokenlineno, |
"%%token_class must be followed by an identifier: ", x); |
psp->errorcnt++; |
@@ -2550,12 +2588,12 @@ to follow the previous rule."); |
case WAITING_FOR_CLASS_TOKEN: |
if( x[0]=='.' ){ |
psp->state = WAITING_FOR_DECL_OR_RULE; |
- }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ |
+ }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ |
struct symbol *msp = psp->tkclass; |
msp->nsubsym++; |
msp->subsym = (struct symbol **) realloc(msp->subsym, |
sizeof(struct symbol*)*msp->nsubsym); |
- if( !isupper(x[0]) ) x++; |
+ if( !ISUPPER(x[0]) ) x++; |
msp->subsym[msp->nsubsym-1] = Symbol_new(x); |
}else{ |
ErrorMsg(psp->filename, psp->tokenlineno, |
@@ -2588,7 +2626,7 @@ static void preprocess_input(char *z){ |
for(i=0; z[i]; i++){ |
if( z[i]=='\n' ) lineno++; |
if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; |
- if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){ |
+ if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){ |
if( exclude ){ |
exclude--; |
if( exclude==0 ){ |
@@ -2596,13 +2634,13 @@ static void preprocess_input(char *z){ |
} |
} |
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; |
- }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6])) |
- || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){ |
+ }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6])) |
+ || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){ |
if( exclude ){ |
exclude++; |
}else{ |
- for(j=i+7; isspace(z[j]); j++){} |
- for(n=0; z[j+n] && !isspace(z[j+n]); n++){} |
+ for(j=i+7; ISSPACE(z[j]); j++){} |
+ for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){} |
exclude = 1; |
for(k=0; k<nDefine; k++){ |
if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){ |
@@ -2635,7 +2673,7 @@ void Parse(struct lemon *gp) |
struct pstate ps; |
FILE *fp; |
char *filebuf; |
- int filesize; |
+ unsigned int filesize; |
int lineno; |
int c; |
char *cp, *nextcp; |
@@ -2682,7 +2720,7 @@ void Parse(struct lemon *gp) |
lineno = 1; |
for(cp=filebuf; (c= *cp)!=0; ){ |
if( c=='\n' ) lineno++; /* Keep track of the line number */ |
- if( isspace(c) ){ cp++; continue; } /* Skip all white space */ |
+ if( ISSPACE(c) ){ cp++; continue; } /* Skip all white space */ |
if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */ |
cp+=2; |
while( (c= *cp)!=0 && c!='\n' ) cp++; |
@@ -2752,15 +2790,15 @@ void Parse(struct lemon *gp) |
}else{ |
nextcp = cp+1; |
} |
- }else if( isalnum(c) ){ /* Identifiers */ |
- while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++; |
+ }else if( ISALNUM(c) ){ /* Identifiers */ |
+ while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++; |
nextcp = cp; |
}else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ |
cp += 3; |
nextcp = cp; |
- }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){ |
+ }else if( (c=='/' || c=='|') && ISALPHA(cp[1]) ){ |
cp += 2; |
- while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++; |
+ while( (c = *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++; |
nextcp = cp; |
}else{ /* All other (one character) operators */ |
cp++; |
@@ -2769,7 +2807,7 @@ void Parse(struct lemon *gp) |
c = *cp; |
*cp = 0; /* Null terminate the token */ |
parseonetoken(&ps); /* Parse the token */ |
- *cp = c; /* Restore the buffer */ |
+ *cp = (char)c; /* Restore the buffer */ |
cp = nextcp; |
} |
free(filebuf); /* Release the buffer after parsing */ |
@@ -2934,15 +2972,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 ){ |
@@ -2956,6 +2993,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 */ |
@@ -2995,15 +3038,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: { |
+ struct rule *rp = ap->x.rp; |
+ fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index); |
+ RulePrint(fp, rp, -1); |
break; |
- case REDUCE: |
- fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index); |
+ } |
+ 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; |
@@ -3012,16 +3070,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; |
@@ -3029,7 +3087,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; |
@@ -3042,7 +3100,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; |
@@ -3053,7 +3111,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; |
@@ -3161,10 +3219,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; |
@@ -3190,7 +3249,7 @@ PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno) |
if( name ){ |
for(i=0; line[i]; i++){ |
if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 |
- && (i==0 || !isalpha(line[i-1])) |
+ && (i==0 || !ISALPHA(line[i-1])) |
){ |
if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); |
fprintf(out,"%s",name); |
@@ -3223,7 +3282,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; |
} |
@@ -3308,7 +3368,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; |
@@ -3392,7 +3455,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ |
zText++; |
n--; |
}else{ |
- z[used++] = c; |
+ z[used++] = (char)c; |
} |
} |
z[used] = 0; |
@@ -3423,9 +3486,9 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ |
/* This const cast is wrong but harmless, if we're careful. */ |
for(cp=(char *)rp->code; *cp; cp++){ |
- if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ |
+ if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ |
char saved; |
- for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); |
+ for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++); |
saved = *xp; |
*xp = 0; |
if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ |
@@ -3505,13 +3568,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; |
@@ -3584,9 +3653,9 @@ void print_stack_union( |
cp = sp->datatype; |
if( cp==0 ) cp = lemp->vartype; |
j = 0; |
- while( isspace(*cp) ) cp++; |
+ while( ISSPACE(*cp) ) cp++; |
while( *cp ) stddt[j++] = *cp++; |
- while( j>0 && isspace(stddt[j-1]) ) j--; |
+ while( j>0 && ISSPACE(stddt[j-1]) ) j--; |
stddt[j] = 0; |
if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){ |
sp->dtnum = 0; |
@@ -3642,24 +3711,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; |
} |
/* |
@@ -3684,7 +3761,7 @@ static int axset_compare(const void *a, const void *b){ |
int c; |
c = p2->nAction - p1->nAction; |
if( c==0 ){ |
- c = p2->iOrder - p1->iOrder; |
+ c = p1->iOrder - p2->iOrder; |
} |
assert( c!=0 || p1==p2 ); |
return c; |
@@ -3723,7 +3800,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; |
@@ -3742,9 +3821,9 @@ void ReportTable( |
/* Generate the include code, if any */ |
tplt_print(out,lemp,lemp->include,&lineno); |
if( mhflag ){ |
- char *name = file_makename(lemp, ".h"); |
- fprintf(out,"#include \"%s\"\n", name); lineno++; |
- free(name); |
+ char *incName = file_makename(lemp, ".h"); |
+ fprintf(out,"#include \"%s\"\n", incName); lineno++; |
+ free(incName); |
} |
tplt_xfer(lemp->name,in,out,&lineno); |
@@ -3764,10 +3843,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++; |
@@ -3785,10 +3864,9 @@ void ReportTable( |
} |
name = lemp->name ? lemp->name : "Parse"; |
if( lemp->arg && lemp->arg[0] ){ |
- int i; |
i = lemonStrlen(lemp->arg); |
- while( i>=1 && isspace(lemp->arg[i-1]) ) i--; |
- while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; |
+ while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--; |
+ while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; |
fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; |
fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; |
fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", |
@@ -3804,36 +3882,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; |
@@ -3844,15 +3910,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){ |
@@ -3878,11 +3941,50 @@ void ReportTable( |
if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst; |
if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst; |
} |
+#if 0 /* Uncomment for a trace of how the yy_action[] table fills out */ |
+ { int jj, nn; |
+ for(jj=nn=0; jj<pActtab->nAction; jj++){ |
+ if( pActtab->aAction[jj].action<0 ) nn++; |
+ } |
+ printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n", |
+ i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", |
+ ax[i].nAction, pActtab->nAction, nn); |
+ } |
+#endif |
} |
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->nxstate-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++){ |
@@ -3900,6 +4002,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); |
@@ -3917,13 +4020,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]; |
@@ -3942,13 +4046,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]; |
@@ -3967,11 +4072,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; |
@@ -3987,6 +4093,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 ){ |
@@ -4251,6 +4358,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; |
+ } |
+ } |
} |
} |
@@ -4291,17 +4424,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; |
} |
} |
} |
@@ -4311,6 +4446,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--; |
+ } |
} |
@@ -4473,18 +4612,18 @@ int Strsafe_insert(const char *data) |
} |
if( x1a->count>=x1a->size ){ |
/* Need to make the hash table bigger */ |
- int i,size; |
+ int i,arrSize; |
struct s_x1 array; |
- array.size = size = x1a->size*2; |
+ array.size = arrSize = x1a->size*2; |
array.count = x1a->count; |
- array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); |
+ array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*)); |
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
- array.ht = (x1node**)&(array.tbl[size]); |
- for(i=0; i<size; i++) array.ht[i] = 0; |
+ array.ht = (x1node**)&(array.tbl[arrSize]); |
+ for(i=0; i<arrSize; i++) array.ht[i] = 0; |
for(i=0; i<x1a->count; i++){ |
x1node *oldnp, *newnp; |
oldnp = &(x1a->tbl[i]); |
- h = strhash(oldnp->data) & (size-1); |
+ h = strhash(oldnp->data) & (arrSize-1); |
newnp = &(array.tbl[i]); |
if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
newnp->next = array.ht[h]; |
@@ -4535,7 +4674,7 @@ struct symbol *Symbol_new(const char *x) |
sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); |
MemoryCheck(sp); |
sp->name = Strsafe(x); |
- sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; |
+ sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL; |
sp->rule = 0; |
sp->fallback = 0; |
sp->prec = -1; |
@@ -4640,18 +4779,18 @@ int Symbol_insert(struct symbol *data, const char *key) |
} |
if( x2a->count>=x2a->size ){ |
/* Need to make the hash table bigger */ |
- int i,size; |
+ int i,arrSize; |
struct s_x2 array; |
- array.size = size = x2a->size*2; |
+ array.size = arrSize = x2a->size*2; |
array.count = x2a->count; |
- array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); |
+ array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*)); |
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
- array.ht = (x2node**)&(array.tbl[size]); |
- for(i=0; i<size; i++) array.ht[i] = 0; |
+ array.ht = (x2node**)&(array.tbl[arrSize]); |
+ for(i=0; i<arrSize; i++) array.ht[i] = 0; |
for(i=0; i<x2a->count; i++){ |
x2node *oldnp, *newnp; |
oldnp = &(x2a->tbl[i]); |
- h = strhash(oldnp->key) & (size-1); |
+ h = strhash(oldnp->key) & (arrSize-1); |
newnp = &(array.tbl[i]); |
if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
newnp->next = array.ht[h]; |
@@ -4716,12 +4855,12 @@ int Symbol_count() |
struct symbol **Symbol_arrayof() |
{ |
struct symbol **array; |
- int i,size; |
+ int i,arrSize; |
if( x2a==0 ) return 0; |
- size = x2a->count; |
- array = (struct symbol **)calloc(size, sizeof(struct symbol *)); |
+ arrSize = x2a->count; |
+ array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *)); |
if( array ){ |
- for(i=0; i<size; i++) array[i] = x2a->tbl[i].data; |
+ for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data; |
} |
return array; |
} |
@@ -4837,18 +4976,18 @@ int State_insert(struct state *data, struct config *key) |
} |
if( x3a->count>=x3a->size ){ |
/* Need to make the hash table bigger */ |
- int i,size; |
+ int i,arrSize; |
struct s_x3 array; |
- array.size = size = x3a->size*2; |
+ array.size = arrSize = x3a->size*2; |
array.count = x3a->count; |
- array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); |
+ array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*)); |
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
- array.ht = (x3node**)&(array.tbl[size]); |
- for(i=0; i<size; i++) array.ht[i] = 0; |
+ array.ht = (x3node**)&(array.tbl[arrSize]); |
+ for(i=0; i<arrSize; i++) array.ht[i] = 0; |
for(i=0; i<x3a->count; i++){ |
x3node *oldnp, *newnp; |
oldnp = &(x3a->tbl[i]); |
- h = statehash(oldnp->key) & (size-1); |
+ h = statehash(oldnp->key) & (arrSize-1); |
newnp = &(array.tbl[i]); |
if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
newnp->next = array.ht[h]; |
@@ -4895,12 +5034,12 @@ struct state *State_find(struct config *key) |
struct state **State_arrayof() |
{ |
struct state **array; |
- int i,size; |
+ int i,arrSize; |
if( x3a==0 ) return 0; |
- size = x3a->count; |
- array = (struct state **)calloc(size, sizeof(struct state *)); |
+ arrSize = x3a->count; |
+ array = (struct state **)calloc(arrSize, sizeof(struct state *)); |
if( array ){ |
- for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; |
+ for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data; |
} |
return array; |
} |
@@ -4977,18 +5116,18 @@ int Configtable_insert(struct config *data) |
} |
if( x4a->count>=x4a->size ){ |
/* Need to make the hash table bigger */ |
- int i,size; |
+ int i,arrSize; |
struct s_x4 array; |
- array.size = size = x4a->size*2; |
+ array.size = arrSize = x4a->size*2; |
array.count = x4a->count; |
- array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); |
+ array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*)); |
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
- array.ht = (x4node**)&(array.tbl[size]); |
- for(i=0; i<size; i++) array.ht[i] = 0; |
+ array.ht = (x4node**)&(array.tbl[arrSize]); |
+ for(i=0; i<arrSize; i++) array.ht[i] = 0; |
for(i=0; i<x4a->count; i++){ |
x4node *oldnp, *newnp; |
oldnp = &(x4a->tbl[i]); |
- h = confighash(oldnp->data) & (size-1); |
+ h = confighash(oldnp->data) & (arrSize-1); |
newnp = &(array.tbl[i]); |
if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
newnp->next = array.ht[h]; |