In lemon, add "%if" and "%else" and allow boolean expressions as the
argument to "%if", "%ifdef", and "%ifndef". FossilOrigin-Name: 951d22b72f80de9e23df645abcc3d88ca1a275b46ea23b84152ef48716922b37
This commit is contained in:
parent
4b849b0b09
commit
0a34cf551c
11
manifest
11
manifest
@ -1,6 +1,6 @@
|
||||
B 7a876209a678a34c198b54ceef9e3c041f128a14dc73357f6a57cadadaa6cf7b
|
||||
C Fix\sthe\spragma_foreign_key_check\svirtual\stable\sso\sthat\sit\saccepts\sarguments.
|
||||
D 2020-07-03T12:32:04.573
|
||||
C In\slemon,\sadd\s"%if"\sand\s"%else"\sand\sallow\sboolean\sexpressions\sas\sthe\nargument\sto\s"%if",\s"%ifdef",\sand\s"%ifndef".
|
||||
D 2020-07-03T15:41:08.646
|
||||
F Makefile.in 19374a5db06c3199ec1bab71ab74a103d8abf21053c05e9389255dc58083f806
|
||||
F Makefile.msc 48f5a3fc32672c09ad73795749f6253e406a31526935fbbffd8f021108d54574
|
||||
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
|
||||
@ -34,13 +34,14 @@ F test/fuzzdata8.db 0ae860b36b79fd41cafddc9e6602358b2d5c331cf200283221e659f86e19
|
||||
F test/gencol1.test b05e6c5edb9b10d48efb634ed07342441bddc89d225043e17095c36e567521a0
|
||||
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
|
||||
F test/speedtest1.c a8b5afe72d78ff365012aba48d3f0c579e957facb7630f765f58a6ae4656d20d
|
||||
F tool/lemon.c 600a58b9d1b8ec5419373982428e927ca208826edacb91ca42ab94514d006039
|
||||
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
|
||||
F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
|
||||
F tool/mksqlite3c.tcl f4ef476510eca4124c874a72029f1e01bc54a896b1724e8f9eef0d8bfae0e84c
|
||||
F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf
|
||||
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
|
||||
F tool/speed-check.sh 615cbdf50f1409ef3bbf9f682e396df80f49d97ed93ed3e61c8e91fae6afde58
|
||||
P 81bc4b65ae2a68128b0be75a7a3d4f47f05cc588ff130ba56366ab9b16289228
|
||||
R 959518f214ac8fa04f9479823db88ae3
|
||||
P 07f849dee3d245ecf80ba3c3ce8dfc630e71ddb1e9c0bcc1f08cee22001fcb07
|
||||
R ab4092566c985aba1362a3a393cab635
|
||||
U drh
|
||||
Z df6c0f239cac29280d3b9659da8bad1e
|
||||
Z abad44d232bcc4ccdddfa3cd71995651
|
||||
|
@ -1 +1 @@
|
||||
07f849dee3d245ecf80ba3c3ce8dfc630e71ddb1e9c0bcc1f08cee22001fcb07
|
||||
951d22b72f80de9e23df645abcc3d88ca1a275b46ea23b84152ef48716922b37
|
143
tool/lemon.c
143
tool/lemon.c
@ -423,6 +423,7 @@ struct lemon {
|
||||
int nlookaheadtab; /* Number of entries in yy_lookahead[] */
|
||||
int tablesize; /* Total table size of all tables in bytes */
|
||||
int basisflag; /* Print only basis configurations */
|
||||
int printPreprocessed; /* Show preprocessor output on stdout */
|
||||
int has_fallback; /* True if any %fallback is seen in the grammar */
|
||||
int nolinenosflag; /* True if #line statements should not be printed */
|
||||
char *argv0; /* Name of the program */
|
||||
@ -1636,12 +1637,14 @@ int main(int argc, char **argv)
|
||||
static int nolinenosflag = 0;
|
||||
static int noResort = 0;
|
||||
static int sqlFlag = 0;
|
||||
static int printPP = 0;
|
||||
|
||||
static struct s_options options[] = {
|
||||
{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, "Output directory. Default '.'"},
|
||||
{OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
|
||||
{OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."},
|
||||
{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.)"},
|
||||
@ -1686,11 +1689,12 @@ int main(int argc, char **argv)
|
||||
lem.filename = OptArg(0);
|
||||
lem.basisflag = basisflag;
|
||||
lem.nolinenosflag = nolinenosflag;
|
||||
lem.printPreprocessed = printPP;
|
||||
Symbol_new("$");
|
||||
|
||||
/* Parse the input file */
|
||||
Parse(&lem);
|
||||
if( lem.errorcnt ) exit(lem.errorcnt);
|
||||
if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
|
||||
if( lem.nrule==0 ){
|
||||
fprintf(stderr,"Empty grammar.\n");
|
||||
exit(1);
|
||||
@ -2779,13 +2783,108 @@ static void parseonetoken(struct pstate *psp)
|
||||
}
|
||||
}
|
||||
|
||||
/* The text in the input is part of the argument to an %ifdef or %ifndef.
|
||||
** Evaluate the text as a boolean expression. Return true or false.
|
||||
*/
|
||||
static int eval_preprocessor_boolean(char *z, int lineno){
|
||||
int neg = 0;
|
||||
int res = 0;
|
||||
int okTerm = 1;
|
||||
int i;
|
||||
for(i=0; z[i]!=0; i++){
|
||||
if( ISSPACE(z[i]) ) continue;
|
||||
if( z[i]=='!' ){
|
||||
if( !okTerm ) goto pp_syntax_error;
|
||||
neg = !neg;
|
||||
continue;
|
||||
}
|
||||
if( z[i]=='|' && z[i+1]=='|' ){
|
||||
if( okTerm ) goto pp_syntax_error;
|
||||
if( res ) return 1;
|
||||
i++;
|
||||
okTerm = 1;
|
||||
continue;
|
||||
}
|
||||
if( z[i]=='&' && z[i+1]=='&' ){
|
||||
if( okTerm ) goto pp_syntax_error;
|
||||
if( !res ) return 0;
|
||||
i++;
|
||||
okTerm = 1;
|
||||
continue;
|
||||
}
|
||||
if( z[i]=='(' ){
|
||||
int k;
|
||||
int n = 1;
|
||||
if( !okTerm ) goto pp_syntax_error;
|
||||
for(k=i+1; z[k]; k++){
|
||||
if( z[k]==')' ){
|
||||
n--;
|
||||
if( n==0 ){
|
||||
z[k] = 0;
|
||||
res = eval_preprocessor_boolean(&z[i+1], -1);
|
||||
z[k] = ')';
|
||||
if( res<0 ){
|
||||
i = i-res;
|
||||
goto pp_syntax_error;
|
||||
}
|
||||
i = k;
|
||||
break;
|
||||
}
|
||||
}else if( z[k]=='(' ){
|
||||
n++;
|
||||
}else if( z[k]==0 ){
|
||||
i = k;
|
||||
goto pp_syntax_error;
|
||||
}
|
||||
}
|
||||
if( neg ){
|
||||
res = !res;
|
||||
neg = 0;
|
||||
}
|
||||
okTerm = 0;
|
||||
continue;
|
||||
}
|
||||
if( ISALPHA(z[i]) ){
|
||||
int j, k, n;
|
||||
if( !okTerm ) goto pp_syntax_error;
|
||||
for(k=i+1; ISALNUM(z[k]) || z[k]=='_'; k++){}
|
||||
n = k - i;
|
||||
res = 0;
|
||||
for(j=0; j<nDefine; j++){
|
||||
if( strncmp(azDefine[j],&z[i],n)==0 && azDefine[j][n]==0 ){
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = k-1;
|
||||
if( neg ){
|
||||
res = !res;
|
||||
neg = 0;
|
||||
}
|
||||
okTerm = 0;
|
||||
continue;
|
||||
}
|
||||
goto pp_syntax_error;
|
||||
}
|
||||
return res;
|
||||
|
||||
pp_syntax_error:
|
||||
if( lineno>0 ){
|
||||
fprintf(stderr, "%%if syntax error on line %d.\n", lineno);
|
||||
fprintf(stderr, " %.*s <-- syntax error here\n", i+1, z);
|
||||
exit(1);
|
||||
}else{
|
||||
return -(i+1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
static void preprocess_input(char *z){
|
||||
int i, j, k, n;
|
||||
int i, j, k;
|
||||
int exclude = 0;
|
||||
int start = 0;
|
||||
int lineno = 1;
|
||||
@ -2801,21 +2900,33 @@ 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],"%else",5)==0 && ISSPACE(z[i+5]) ){
|
||||
if( exclude==1){
|
||||
exclude = 0;
|
||||
for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
|
||||
}else if( exclude==0 ){
|
||||
exclude = 1;
|
||||
start = i;
|
||||
start_lineno = lineno;
|
||||
}
|
||||
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
|
||||
}else if( strncmp(&z[i],"%ifdef ",7)==0
|
||||
|| strncmp(&z[i],"%if ",4)==0
|
||||
|| strncmp(&z[i],"%ifndef ",8)==0 ){
|
||||
if( exclude ){
|
||||
exclude++;
|
||||
}else{
|
||||
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 ){
|
||||
exclude = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( z[i+3]=='n' ) exclude = !exclude;
|
||||
int isNot;
|
||||
int iBool;
|
||||
for(j=i; z[j] && !ISSPACE(z[j]); j++){}
|
||||
iBool = j;
|
||||
isNot = (j==i+7);
|
||||
while( z[j] && z[j]!='\n' ){ j++; }
|
||||
k = z[j];
|
||||
z[j] = 0;
|
||||
exclude = eval_preprocessor_boolean(&z[iBool], lineno);
|
||||
z[j] = k;
|
||||
if( !isNot ) exclude = !exclude;
|
||||
if( exclude ){
|
||||
start = i;
|
||||
start_lineno = lineno;
|
||||
@ -2883,6 +2994,10 @@ void Parse(struct lemon *gp)
|
||||
|
||||
/* Make an initial pass through the file to handle %ifdef and %ifndef */
|
||||
preprocess_input(filebuf);
|
||||
if( gp->printPreprocessed ){
|
||||
printf("%s\n", filebuf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now scan the text of the input file */
|
||||
lineno = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user