diff options
author | Anders Broman <anders.broman@ericsson.com> | 2008-07-29 12:40:03 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2008-07-29 12:40:03 +0000 |
commit | 27111e59f32706b5eb1656da7f6ccafa707f9e25 (patch) | |
tree | 46ad6f89d68e5cd4a6c6ce100b9fae118124c656 /tools/lemon | |
parent | 9bf9f8615f7d0a3268945428b278f9fe8d531f17 (diff) |
Update to sqlite lemon.c 1.60 and lempar.c 1.36
svn path=/trunk/; revision=25858
Diffstat (limited to 'tools/lemon')
-rw-r--r-- | tools/lemon/lemon.c | 158 | ||||
-rw-r--r-- | tools/lemon/lempar.c | 69 |
2 files changed, 156 insertions, 71 deletions
diff --git a/tools/lemon/lemon.c b/tools/lemon/lemon.c index 406388ef54..75f39c15ce 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -25,7 +25,7 @@ ** drh@acm.org ** http://www.hwaci.com/drh/ ** -** Updated to sqlite lemon version 1.54 +** Updated to sqlite lemon version 1.59 ** $Id$ */ #include <stdio.h> @@ -102,13 +102,13 @@ struct symbol { RIGHT, NONE, UNK - } assoc; /* Associativity if predecence is defined */ + } assoc; /* Associativity if precedence is defined */ char *firstset; /* First-set for all rules of this symbol */ Boolean lambda; /* True if NT and can generate an empty string */ int useCnt; /* Number of times used */ char *destructor; /* Code which executes whenever this symbol is ** popped from the stack during error processing */ - int destructorln; /* Line number of destructor code */ + int destLineno; /* Line number for start of destructor */ char *datatype; /* The data type of information held by this ** object. Only used if type==NONTERMINAL */ int dtnum; /* The data type number. In the parser, the value @@ -186,7 +186,7 @@ struct action { struct state { struct config *bp; /* The basis configurations for this state */ struct config *cfp; /* All configurations in this set */ - int statenum; /* Sequencial number for this state */ + int statenum; /* Sequential number for this 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 */ @@ -224,21 +224,13 @@ struct lemon { char *start; /* Name of the start symbol for the grammar */ char *stacksize; /* Size of the parser stack */ char *include; /* Code to put at the start of the C file */ - int includeln; /* Line number for start of include code */ char *error; /* Code to execute when an error is seen */ - int errorln; /* Line number for start of error code */ char *overflow; /* Code to execute on a stack overflow */ - int overflowln; /* Line number for start of overflow code */ char *failure; /* Code to execute on parser failure */ - int failureln; /* Line number for start of failure code */ char *accept; /* Code to execute when the parser excepts */ - int acceptln; /* Line number for the start of accept code */ char *extracode; /* Code appended to the generated file */ - int extracodeln; /* Line number for the start of the extra code */ char *tokendest; /* Code to execute to destroy token data */ - int tokendestln; /* Line number for token destroyer code */ char *vardest; /* Code for the default non-terminal destructor */ - int vardestln; /* Line number for default non-term destructor code*/ char *filename; /* Name of the input file */ char *basename; /* Basename of inputer file (no directory or path */ char *outname; /* Name of the current output file */ @@ -248,7 +240,7 @@ struct lemon { int nconflict; /* Number of parsing conflicts */ int tablesize; /* Size of the parse tables */ int basisflag; /* Print only basis configurations */ - int has_fallback; /* True if any %fallback is seen in the grammer */ + int has_fallback; /* True if any %fallback is seen in the grammar */ char *argv0; /* Name of the program */ }; @@ -1024,7 +1016,7 @@ void FindActions(struct lemon *lemp) } /* Resolve a conflict between the two given actions. If the -** conflict can't be resolve, return non-zero. +** conflict can't be resolved, return non-zero. ** ** NO LONGER TRUE: ** To resolve a conflict, first look to see if either action @@ -2020,7 +2012,8 @@ struct pstate { struct rule *prevrule; /* Previous rule parsed */ char *declkeyword; /* Keyword of a declaration */ char **declargslot; /* Where the declaration argument should be put */ - int *decllnslot; /* Where the declaration linenumber is put */ + int insertLineMacro; /* Add #line before declaration insert */ + int *decllinenoslot; /* Where to write declaration line number */ enum e_assoc declassoc; /* Assign this association to decl arguments */ int preccounter; /* Assign this precedence to decl arguments */ struct rule *firstrule; /* Pointer to first rule in the grammar */ @@ -2054,7 +2047,7 @@ static void parseonetoken(struct pstate *psp) }else if( x[0]=='{' ){ if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, -"There is not prior rule opon which to attach the code \ +"There is no prior rule opon which to attach the code \ fragment which begins on this line."); psp->errorcnt++; }else if( psp->prevrule->code!=0 ){ @@ -2253,46 +2246,46 @@ to follow the previous rule."); if( safe_isalpha(x[0]) ){ psp->declkeyword = x; psp->declargslot = 0; - psp->decllnslot = 0; + psp->decllinenoslot = 0; + psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; if( strcmp(x,"name")==0 ){ psp->declargslot = &(psp->gp->name); + psp->insertLineMacro = 0; }else if( strcmp(x,"include")==0 ){ psp->declargslot = &(psp->gp->include); - psp->decllnslot = &psp->gp->includeln; }else if( strcmp(x,"code")==0 ){ psp->declargslot = &(psp->gp->extracode); - psp->decllnslot = &psp->gp->extracodeln; }else if( strcmp(x,"token_destructor")==0 ){ psp->declargslot = &psp->gp->tokendest; - psp->decllnslot = &psp->gp->tokendestln; }else if( strcmp(x,"default_destructor")==0 ){ psp->declargslot = &psp->gp->vardest; - psp->decllnslot = &psp->gp->vardestln; }else if( strcmp(x,"token_prefix")==0 ){ psp->declargslot = &psp->gp->tokenprefix; + psp->insertLineMacro = 0; }else if( strcmp(x,"syntax_error")==0 ){ psp->declargslot = &(psp->gp->error); - psp->decllnslot = &psp->gp->errorln; }else if( strcmp(x,"parse_accept")==0 ){ psp->declargslot = &(psp->gp->accept); - psp->decllnslot = &psp->gp->acceptln; }else if( strcmp(x,"parse_failure")==0 ){ psp->declargslot = &(psp->gp->failure); - psp->decllnslot = &psp->gp->failureln; }else if( strcmp(x,"stack_overflow")==0 ){ psp->declargslot = &(psp->gp->overflow); - psp->decllnslot = &psp->gp->overflowln; }else if( strcmp(x,"extra_argument")==0 ){ psp->declargslot = &(psp->gp->arg); + psp->insertLineMacro = 0; }else if( strcmp(x,"token_type")==0 ){ psp->declargslot = &(psp->gp->tokentype); + psp->insertLineMacro = 0; }else if( strcmp(x,"default_type")==0 ){ psp->declargslot = &(psp->gp->vartype); + psp->insertLineMacro = 0; }else if( strcmp(x,"stack_size")==0 ){ psp->declargslot = &(psp->gp->stacksize); + psp->insertLineMacro = 0; }else if( strcmp(x,"start_symbol")==0 ){ psp->declargslot = &(psp->gp->start); + psp->insertLineMacro = 0; }else if( strcmp(x,"left")==0 ){ psp->preccounter++; psp->declassoc = LEFT; @@ -2336,7 +2329,8 @@ to follow the previous rule."); }else{ struct symbol *sp = Symbol_new(x); psp->declargslot = &sp->destructor; - psp->decllnslot = &sp->destructorln; + psp->decllinenoslot = &sp->destLineno; + psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; } break; @@ -2349,7 +2343,7 @@ to follow the previous rule."); }else{ struct symbol *sp = Symbol_new(x); psp->declargslot = &sp->datatype; - psp->decllnslot = 0; + psp->insertLineMacro = 0; psp->state = WAITING_FOR_DECL_ARG; } break; @@ -2375,17 +2369,55 @@ to follow the previous rule."); break; case WAITING_FOR_DECL_ARG: if( (x[0]=='{' || x[0]=='\"' || safe_isalnum(x[0])) ){ - if( *(psp->declargslot)!=0 ){ - ErrorMsg(psp->filename,psp->tokenlineno, - "The argument \"%s\" to declaration \"%%%s\" is not the first.", - x[0]=='\"' ? &x[1] : x,psp->declkeyword); - psp->errorcnt++; - psp->state = RESYNC_AFTER_DECL_ERROR; - }else{ - *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x; - if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno; - psp->state = WAITING_FOR_DECL_OR_RULE; - } + char *zOld, *zNew, *zBuf, *z; + int nOld, n, nLine, nNew, nBack; + int addLineMacro; + char zLine[50]; + zNew = x; + if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; + nNew = strlen(zNew); + if( *psp->declargslot ){ + zOld = *psp->declargslot; + }else{ + zOld = ""; + } + nOld = strlen(zOld); + n = nOld + nNew + 20; + addLineMacro = psp->insertLineMacro && + (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0); + if( addLineMacro ){ + for(z=psp->filename, nBack=0; *z; z++){ + if( *z=='\\' ) nBack++; + } + sprintf(zLine, "#line %d ", psp->tokenlineno); + nLine = strlen(zLine); + n += nLine + strlen(psp->filename) + nBack; + } + *psp->declargslot = zBuf = realloc(*psp->declargslot, n); + zBuf += nOld; + if( addLineMacro ){ + if( nOld && zBuf[-1]!='\n' ){ + *(zBuf++) = '\n'; + } + memcpy(zBuf, zLine, nLine); + zBuf += nLine; + *(zBuf++) = '"'; + for(z=psp->filename; *z; z++){ + if( *z=='\\' ){ + *(zBuf++) = '\\'; + } + *(zBuf++) = *z; + } + *(zBuf++) = '"'; + *(zBuf++) = '\n'; + } + if( psp->decllinenoslot && psp->decllinenoslot[0]==0 ){ + psp->decllinenoslot[0] = psp->tokenlineno; + } + memcpy(zBuf, zNew, nNew); + zBuf += nNew; + *zBuf = 0; + psp->state = WAITING_FOR_DECL_OR_RULE; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal argument to %%%s: %s",psp->declkeyword,x); @@ -2443,7 +2475,7 @@ to follow the previous rule."); } } -/* Run the proprocessor over the input file text. The global variables +/* Run the preprocessor over the input file text. The global variables ** azDefine[0] through azDefine[nDefine-1] contains the names of all defined ** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and ** comments them out. Text in between is also commented out as appropriate. @@ -2524,7 +2556,6 @@ void Parse(struct lemon *gp) ps.lhsalias = NULL; ps.declkeyword = NULL; ps.declargslot = NULL; - ps.decllnslot = NULL; ps.declassoc = UNK; ps.fallback = NULL; @@ -3151,10 +3182,9 @@ PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename) /* Print a string to the file and keep the linenumber up to date */ PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, - int strln, int *lineno) + int *lineno) { if( str==0 ) return; - tplt_linedir(out,strln,lemp->filename); (*lineno)++; while( *str ){ if( *str=='\n' ) (*lineno)++; @@ -3183,17 +3213,15 @@ PRIVATE void emit_destructor_code(FILE *out, struct symbol *sp, struct lemon *le if( sp->type==TERMINAL ){ cp = lemp->tokendest; if( cp==0 ) return; - tplt_linedir(out,lemp->tokendestln,lemp->filename); - fprintf(out,"{"); + fprintf(out,"{\n"); (*lineno)++; }else if( sp->destructor ){ cp = sp->destructor; - tplt_linedir(out,sp->destructorln,lemp->filename); - fprintf(out,"{"); + fprintf(out,"{\n"); (*lineno)++; + tplt_linedir(out,sp->destLineno,lemp->outname); (*lineno)++; }else if( lemp->vardest ){ cp = lemp->vardest; if( cp==0 ) return; - tplt_linedir(out,lemp->vardestln,lemp->filename); - fprintf(out,"{"); + fprintf(out,"{\n"); (*lineno)++; }else{ assert( 0 ); /* Cannot happen */ } @@ -3207,8 +3235,9 @@ PRIVATE void emit_destructor_code(FILE *out, struct symbol *sp, struct lemon *le fputc(*cp,out); } (*lineno) += 3 + linecnt; - fprintf(out,"}\n"); + fprintf(out,"\n"); tplt_linedir(out,*lineno,lemp->outname); + fprintf(out,"}\n"); return; } @@ -3459,6 +3488,10 @@ PRIVATE void print_stack_union( while( *cp ) stddt[j++] = *cp++; while( j>0 && safe_isspace(stddt[j-1]) ) j--; stddt[j] = 0; + if( strcmp(stddt, lemp->tokentype)==0 ){ + sp->dtnum = 0; + continue; + } hash = 0; for(j=0; stddt[j]; j++){ hash = hash*53 + stddt[j]; @@ -3607,7 +3640,7 @@ void ReportTable( tplt_xfer(lemp->name,in,out,&lineno); /* Generate the include code, if any */ - tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno); + tplt_print(out,lemp,lemp->include,&lineno); if( mhflag ){ char *name = file_makename_using_basename(lemp, ".h"); fprintf(out,"#include \"%s\"\n", name); lineno++; @@ -3870,7 +3903,7 @@ void ReportTable( tplt_xfer(lemp->name,in,out,&lineno); /* Generate a table containing a text string that describes every - ** rule in the rule set of the grammer. This information is used + ** rule in the rule set of the grammar. This information is used ** when tracing REDUCE actions. */ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ @@ -3886,24 +3919,34 @@ void ReportTable( ** (In other words, generate the %destructor actions) */ if( lemp->tokendest ){ + int once = 1; for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type!=TERMINAL ) continue; + if( once ){ + fprintf(out, " /* TERMINAL Destructor */\n"); lineno++; + once = 0; + } fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; } for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++); if( i<lemp->nsymbol ){ emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); - fprintf(out," break;\n"); lineno++; } + fprintf(out," break;\n"); lineno++; } if( lemp->vardest ){ struct symbol *dflt_sp = 0; + int once = 1; for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->index<=0 || sp->destructor!=0 ) continue; + if( once ){ + fprintf(out, " /* Default NON-TERMINAL Destructor */\n"); lineno++; + once = 0; + } fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; dflt_sp = sp; @@ -3937,7 +3980,7 @@ void ReportTable( tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes whenever the parser stack overflows */ - tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno); + tplt_print(out,lemp,lemp->overflow,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Generate the table of rule information @@ -3974,19 +4017,19 @@ void ReportTable( tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes if a parse fails */ - tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno); + tplt_print(out,lemp,lemp->failure,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes when a syntax error occurs */ - tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno); + tplt_print(out,lemp,lemp->error,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes when the parser accepts its input */ - tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno); + tplt_print(out,lemp,lemp->accept,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Append any addition code the user desires */ - tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno); + tplt_print(out,lemp,lemp->extracode,&lineno); fclose(in); fclose(out); @@ -4374,6 +4417,7 @@ struct symbol *Symbol_new(const char *x) sp->firstset = 0; sp->lambda = LEMON_FALSE; sp->destructor = 0; + sp->destLineno = 0; sp->datatype = 0; sp->useCnt = 0; Symbol_insert(sp,sp->name); diff --git a/tools/lemon/lempar.c b/tools/lemon/lempar.c index c315484afd..6f53bcacbf 100644 --- a/tools/lemon/lempar.c +++ b/tools/lemon/lempar.c @@ -1,4 +1,6 @@ /* Driver template for the LEMON parser generator. +* $Id$ +* ** Copyright 1991-1995 by D. Richard Hipp. ** ** This library is free software; you can redistribute it and/or @@ -17,10 +19,10 @@ ** Boston, MA 02111-1307, USA. ** ** Modified 1997 to make it suitable for use with makeheaders. -* Updated to sqlite lemon version 1.22 +* Updated to sqlite lemon version 1.36 */ -/* First off, code is include which follows the "include" declaration -** in the input file. */ +/* First off, code is included that follows the "include" declaration +** in the input grammar file. */ %% #include <stdio.h> #include <string.h> @@ -79,7 +81,11 @@ #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) -/* Next are that tables used to determine what action to take based on the +/* The yyzerominor constant is used to initialize instances of +** YYMINORTYPE objects to zero. */ +static const YYMINORTYPE yyzerominor; + +/* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an ** action integer. @@ -134,7 +140,7 @@ ** ** %fallback ID X Y Z. ** -** appears in the grammer, then ID becomes a fallback token for X, Y, +** appears in the grammar, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. @@ -158,11 +164,11 @@ static const YYCODETYPE yyFallback[] = { ** It is sometimes called the "minor" token. */ struct yyStackEntry { - int stateno; /* The state-number */ - int 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 - ** is the value of the token */ + YYACTIONTYPE stateno; /* The state-number */ + 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 + ** is the value of the token */ }; typedef struct yyStackEntry yyStackEntry; @@ -170,6 +176,9 @@ typedef struct yyStackEntry yyStackEntry; ** the following structure */ struct yyParser { int yyidx; /* Index of top element in stack */ +#ifdef YYTRACKMAXSTACKDEPTH + int yyidxMax; /* Maximum value of yyidx */ +#endif int yyerrcnt; /* Shifts left before out of the error */ ParseARG_SDECL /* A place to hold %extra_argument */ #if YYSTACKDEPTH<=0 @@ -276,6 +285,9 @@ void *ParseAlloc(void *(*mallocProc)(gulong)){ #endif if( pParser ){ pParser->yyidx = -1; +#ifdef YYTRACKMAXSTACKDEPTH + pParser->yyidxMax = 0; +#endif #if YYSTACKDEPTH<=0 yyGrowStack(pParser); #endif @@ -357,6 +369,16 @@ void ParseFree( } /* +** Return the peak depth of the stack for a parser. +*/ +#ifdef YYTRACKMAXSTACKDEPTH +int ParseStackPeak(void *p){ + yyParser *pParser = (yyParser*)p; + return pParser->yyidxMax; +} +#endif + +/* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. ** @@ -425,13 +447,25 @@ static int yy_find_reduce_action( YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; +#ifdef YYERRORSYMBOL + if( stateno>YY_REDUCE_MAX ){ + return yy_default[stateno]; + } +#else assert( stateno<=YY_REDUCE_MAX ); +#endif i = yy_reduce_ofst[stateno]; assert( i!=YY_REDUCE_USE_DFLT ); assert( iLookAhead!=YYNOCODE ); i += iLookAhead; +#ifdef YYERRORSYMBOL + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ + return yy_default[stateno]; + } +#else assert( i>=0 && i<YY_SZ_ACTTAB ); assert( yy_lookahead[i]==iLookAhead ); +#endif return yy_action[i]; } @@ -460,10 +494,15 @@ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ int yyNewState, /* The new state to shift in */ int yyMajor, /* The major token to shift in */ - YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */ + YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */ ){ yyStackEntry *yytos; yypParser->yyidx++; +#ifdef YYTRACKMAXSTACKDEPTH + if( yypParser->yyidx>yypParser->yyidxMax ){ + yypParser->yyidxMax = yypParser->yyidx; + } +#endif #if YYSTACKDEPTH>0 if( yypParser->yyidx>=YYSTACKDEPTH ){ yyStackOverflow(yypParser, yypMinor); @@ -543,7 +582,8 @@ static void yy_reduce( ** from wireshark this week. Clearly they are stressing Lemon in ways ** that it has not been previously stressed... (SQLite ticket #2172) */ - memset(&yygotominor, 0, sizeof(yygotominor)); + /*memset(&yygotominor, 0, sizeof(yygotominor));*/ + yygotominor = yyzerominor; switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: @@ -672,8 +712,9 @@ void Parse( if( yypParser->yyidx<0 ){ #if YYSTACKDEPTH<=0 if( yypParser->yystksz <=0 ){ - memset(&yyminorunion, 0, sizeof(yyminorunion)); - yyStackOverflow(yypParser, &yyminorunion); + /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ + yyminorunion = yyzerominor; + yyStackOverflow(yypParser, &yyminorunion); return; } #endif |