| Index: third_party/sqlite/sqlite-src-3100200/tool/lemon.c
|
| diff --git a/third_party/sqlite/sqlite-src-3080704/tool/lemon.c b/third_party/sqlite/sqlite-src-3100200/tool/lemon.c
|
| similarity index 91%
|
| copy from third_party/sqlite/sqlite-src-3080704/tool/lemon.c
|
| copy to third_party/sqlite/sqlite-src-3100200/tool/lemon.c
|
| index 85e94f7007f905754127fd81472f9ff64e631a2d..d704deb624d42b39ca455db5bc5617e2197d62d9 100644
|
| --- a/third_party/sqlite/sqlite-src-3080704/tool/lemon.c
|
| +++ b/third_party/sqlite/sqlite-src-3100200/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];
|
|
|