mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Bug fixes from Oleg Oleinick (CVS 195)
FossilOrigin-Name: 1f0197d504fa2bde15b287ac6c0102cacdb1e482
This commit is contained in:
57
tool/lemon.c
57
tool/lemon.c
@ -3,8 +3,8 @@
|
||||
**
|
||||
** This file contains all sources (including headers) to the LEMON
|
||||
** LALR(1) parser generator. The sources have been combined into a
|
||||
** single file to make it easy to include LEMON as part of another
|
||||
** program.
|
||||
** single file to make it easy to include LEMON in the source tree
|
||||
** and Makefile of another program.
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU General Public
|
||||
@ -263,6 +263,7 @@ struct lemon {
|
||||
char *name; /* Name of the generated parser */
|
||||
char *arg; /* Declaration of the 3th argument to parser */
|
||||
char *tokentype; /* Type of terminal symbols in the parser stack */
|
||||
char *vartype; /* The default type of non-terminal symbols */
|
||||
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 */
|
||||
@ -279,6 +280,8 @@ struct lemon {
|
||||
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 *outname; /* Name of the current output file */
|
||||
char *tokenprefix; /* A prefix added to token names in the .h file */
|
||||
@ -1216,9 +1219,11 @@ char **argv;
|
||||
lem.basisflag = basisflag;
|
||||
lem.nconflict = 0;
|
||||
lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
|
||||
lem.vartype = 0;
|
||||
lem.stacksize = 0;
|
||||
lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
|
||||
lem.tokenprefix = lem.outname = lem.extracode = 0;
|
||||
lem.vardest = 0;
|
||||
lem.tablesize = 0;
|
||||
Symbol_new("$");
|
||||
lem.errsym = Symbol_new("error");
|
||||
@ -1967,6 +1972,9 @@ to follow the previous rule.");
|
||||
}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;
|
||||
}else if( strcmp(x,"syntax_error")==0 ){
|
||||
@ -1985,6 +1993,8 @@ to follow the previous rule.");
|
||||
psp->declargslot = &(psp->gp->arg);
|
||||
}else if( strcmp(x,"token_type")==0 ){
|
||||
psp->declargslot = &(psp->gp->tokentype);
|
||||
}else if( strcmp(x,"default_type")==0 ){
|
||||
psp->declargslot = &(psp->gp->vartype);
|
||||
}else if( strcmp(x,"stack_size")==0 ){
|
||||
psp->declargslot = &(psp->gp->stacksize);
|
||||
}else if( strcmp(x,"start_symbol")==0 ){
|
||||
@ -2210,7 +2220,7 @@ struct lemon *gp;
|
||||
}
|
||||
}
|
||||
if( c==0 ){
|
||||
ErrorMsg(ps.filename,startline,
|
||||
ErrorMsg(ps.filename,ps.tokenlineno,
|
||||
"C code starting on this line is not terminated before the end of the file.");
|
||||
ps.errorcnt++;
|
||||
nextcp = cp;
|
||||
@ -2643,6 +2653,8 @@ struct lemon *lemp;
|
||||
}
|
||||
if( access(buf,004)==0 ){
|
||||
tpltname = buf;
|
||||
}else if( access(templatename,004)==0 ){
|
||||
tpltname = templatename;
|
||||
}else{
|
||||
tpltname = pathsearch(lemp->argv0,templatename,0);
|
||||
}
|
||||
@ -2697,10 +2709,13 @@ int *lineno;
|
||||
cp = lemp->tokendest;
|
||||
if( cp==0 ) return;
|
||||
fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
|
||||
}else{
|
||||
}else if( sp->destructor ){
|
||||
cp = sp->destructor;
|
||||
if( cp==0 ) return;
|
||||
fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
|
||||
}else if( lemp->vardest ){
|
||||
cp = lemp->vardest;
|
||||
if( cp==0 ) return;
|
||||
fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
|
||||
}
|
||||
for(; *cp; cp++){
|
||||
if( *cp=='$' && cp[1]=='$' ){
|
||||
@ -2717,7 +2732,7 @@ int *lineno;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE (non-zero) if the given symbol has a distructor.
|
||||
** Return TRUE (non-zero) if the given symbol has a destructor.
|
||||
*/
|
||||
int has_destructor(sp, lemp)
|
||||
struct symbol *sp;
|
||||
@ -2727,7 +2742,7 @@ struct lemon *lemp;
|
||||
if( sp->type==TERMINAL ){
|
||||
ret = lemp->tokendest!=0;
|
||||
}else{
|
||||
ret = sp->destructor!=0;
|
||||
ret = lemp->vardest!=0 || sp->destructor!=0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -2796,7 +2811,7 @@ int *lineno;
|
||||
for(i=0; i<rp->nrhs; i++){
|
||||
if( rp->rhsalias[i] && !used[i] ){
|
||||
ErrorMsg(lemp->filename,rp->ruleline,
|
||||
"Label $%s$ for \"%s(%s)\" is never used.",
|
||||
"Label %s for \"%s(%s)\" is never used.",
|
||||
rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
|
||||
lemp->errorcnt++;
|
||||
}else if( rp->rhsalias[i]==0 ){
|
||||
@ -2840,6 +2855,9 @@ int mhflag; /* True if generating makeheaders output */
|
||||
types = (char**)malloc( arraysize * sizeof(char*) );
|
||||
for(i=0; i<arraysize; i++) types[i] = 0;
|
||||
maxdtlength = 0;
|
||||
if( lemp->vartype ){
|
||||
maxdtlength = strlen(lemp->vartype);
|
||||
}
|
||||
for(i=0; i<lemp->nsymbol; i++){
|
||||
int len;
|
||||
struct symbol *sp = lemp->symbols[i];
|
||||
@ -2855,8 +2873,10 @@ int mhflag; /* True if generating makeheaders output */
|
||||
|
||||
/* Build a hash table of datatypes. The ".dtnum" field of each symbol
|
||||
** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
|
||||
** used for terminal symbols and for nonterminals which don't specify
|
||||
** a datatype using the %type directive. */
|
||||
** used for terminal symbols. If there is no %default_type defined then
|
||||
** 0 is also used as the .dtnum value for nonterminals which do not specify
|
||||
** a datatype using the %type directive.
|
||||
*/
|
||||
for(i=0; i<lemp->nsymbol; i++){
|
||||
struct symbol *sp = lemp->symbols[i];
|
||||
char *cp;
|
||||
@ -2864,11 +2884,12 @@ int mhflag; /* True if generating makeheaders output */
|
||||
sp->dtnum = arraysize+1;
|
||||
continue;
|
||||
}
|
||||
if( sp->type!=NONTERMINAL || sp->datatype==0 ){
|
||||
if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
|
||||
sp->dtnum = 0;
|
||||
continue;
|
||||
}
|
||||
cp = sp->datatype;
|
||||
if( cp==0 ) cp = lemp->vartype;
|
||||
j = 0;
|
||||
while( isspace(*cp) ) cp++;
|
||||
while( *cp ) stddt[j++] = *cp++;
|
||||
@ -3159,6 +3180,20 @@ int mhflag; /* Output in makeheaders format if true */
|
||||
emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
}
|
||||
if( lemp->vardest ){
|
||||
struct symbol *dflt_sp = 0;
|
||||
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;
|
||||
fprintf(out," case %d:\n",sp->index); lineno++;
|
||||
dflt_sp = sp;
|
||||
}
|
||||
if( dflt_sp!=0 ){
|
||||
emit_destructor_code(out,dflt_sp,lemp,&lineno);
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
}
|
||||
}
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes whenever the parser stack overflows */
|
||||
|
Reference in New Issue
Block a user