diff --git a/manifest b/manifest
index 516ef5ea88..d68e12f7d7 100644
--- a/manifest
+++ b/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
diff --git a/manifest.uuid b/manifest.uuid
index c0880373ff..11c6988207 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-07f849dee3d245ecf80ba3c3ce8dfc630e71ddb1e9c0bcc1f08cee22001fcb07
\ No newline at end of file
+951d22b72f80de9e23df645abcc3d88ca1a275b46ea23b84152ef48716922b37
\ No newline at end of file
diff --git a/tool/lemon.c b/tool/lemon.c
index 8dcf65179f..40e4e2894f 100644
--- a/tool/lemon.c
+++ b/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;