#include <stdio.h>
#include <stdlib.h>

void Dump(int i);

static const unsigned char Clett[437 /*0:436*/] = {
/*  0*/    1,   40,  1,   41,  1,   42,  1,   44,  2,   201, 198, 6,   213, 206, 204,
/* 15*/    197, 211, 211, 5,   215, 200, 201, 204, 197, 5,   213, 206, 212, 201, 204,
/* 30*/    3,   198, 207, 210, 1,   61,  5,   193, 204, 201, 193, 211, 7,   201, 206,
/* 45*/    212, 197, 199, 197, 210, 4,   210, 197, 193, 204, 4,   204, 207, 206, 199,
/* 60*/    4,   194, 217, 212, 197, 6,   211, 212, 210, 201, 206, 199, 4,   200, 193,
/* 75*/    204, 198, 5,   211, 200, 207, 210, 212, 6,   210, 197, 195, 207, 210, 196,
/* 90*/    7,   210, 207, 213, 212, 201, 206, 197, 2,   198, 206, 3,   205, 193, 208,
/*105*/    8,   198, 213, 206, 195, 212, 201, 207, 206, 4,   206, 193, 205, 197, 9,
/*120*/    193, 210, 210, 193, 217, 206, 193, 205, 197, 9,   207, 198, 208, 210, 207,
/*135*/    199, 210, 193, 205, 6,   207, 198, 198, 201, 204, 197, 6,   207, 198, 204,
/*150*/    201, 211, 212, 6,   198, 207, 210, 205, 193, 212, 3,   206, 207, 212, 3,
/*165*/    193, 206, 196, 2,   207, 210, 1,   58,  4,   211, 208, 197, 195, 5,   193,
/*180*/    210, 210, 193, 217, 3,   207, 215, 206, 8,   197, 216, 212, 197, 210, 206,
/*195*/    193, 204, 9,   197, 216, 212, 210, 201, 206, 211, 201, 195, 8,   195, 207,
/*210*/    206, 211, 212, 193, 206, 212, 5,   195, 207, 206, 211, 212, 5,   197, 214,
/*225*/    197, 206, 212, 5,   211, 212, 193, 210, 212, 9,   212, 200, 197, 206, 211,
/*240*/    212, 193, 210, 212, 4,   212, 200, 197, 206, 9,   197, 204, 211, 197, 211,
/*255*/    212, 193, 210, 212, 4,   197, 204, 211, 197, 1,   95,  6,   211, 217, 211,
/*270*/    212, 197, 205, 7,   196, 217, 206, 193, 205, 201, 195, 4,   80,  85,  84,
/*285*/    95,  5,   67,  78,  79,  80,  95,  1,   43,  1,   45,  1,   64,  2,   45,
/*300*/    62,  6,   210, 197, 212, 213, 210, 206, 6,   210, 197, 211, 213, 204, 212,
/*315*/    7,   205, 207, 206, 201, 212, 207, 210, 4,   211, 212, 207, 208, 6,   211,
/*330*/    201, 199, 206, 193, 204, 4,   197, 216, 201, 212, 8,   195, 207, 206, 212,
/*345*/    201, 206, 213, 197, 6,   198, 201, 206, 201, 211, 200, 5,   195, 217, 195,
/*360*/    204, 197, 6,   210, 197, 208, 197, 193, 212, 3,   197, 206, 196, 7,   201,
/*375*/    206, 195, 204, 213, 196, 197, 5,   194, 197, 199, 201, 206, 2,   207, 206,
/*390*/    6,   211, 215, 201, 212, 195, 200, 4,   204, 201, 211, 212, 14,  212, 210,
/*405*/    213, 211, 212, 197, 196, 208, 210, 207, 199, 210, 193, 205, 6,   205, 193,
/*420*/    201, 206, 197, 208, 7,   195, 207, 206, 212, 210, 207, 204, 4,   40,  42,
/*435*/    41,  58};
/*
P(OPERAND)     =(NAME)(APP)(ENAME'),
                (CONST),
                '('(EXPR)')';
 */
static const int Symbol[797 /*1300:2096*/] = {
#define Symbol(n) Symbol[(n)-1300]
    1311, 1305, 1001, 1358, 1783, 1307, 1003, 1311, 0,    1337, 2,    1321,
    1315, 1001, 1014, 1317, 1003, 1321, 0,    1321, 2,    1328, 1328, 1010,
    1028, 1311, 1011, 1351, 1337, 1335, 1010, 1028, 1311, 1011, 1351, 1337,
    4,    1344, 1344, 1010, 1028, 1300, 1011, 1344, 1351, 1349, 1026, 1300,
    999,  1351, 1000, 1358, 1356, 1026, 1311, 999,  1358, 1000, 1366, 1364,
    0,    1337, 1366, 2,    1366, 1000, 1373, 1371, 6,    1337, 999,  1373,
    1000, 1378, 1376, 8,    1378, 11,   1402, 1385, 18,   1010, 1530, 1552,
    1011, 1391, 24,   1010, 1530, 1552, 1011, 1402, 30,   1010, 1001, 34,
    1337, 6,    1337, 6,    1337, 1011, 1408, 1406, 36,   1013, 1408, 1000,
    1415, 1413, 6,    1001, 999,  1415, 1000, 1420, 1418, 42,   1420, 1000,
    1428, 1423, 42,   1425, 50,   1428, 55,   50,   1453, 1431, 42,   1433,
    50,   1436, 55,   1420, 1439, 60,   1415, 1442, 65,   1689, 1445, 72,
    1415, 1448, 77,   1415, 1453, 83,   0,    1845, 2,    1460, 1456, 90,
    1460, 1031, 1428, 1460, 1467, 1463, 98,   1465, 101,  1467, 105,  1483,
    1473, 1428, 1488, 1001, 1408, 1479, 1453, 1483, 1001, 1408, 1495, 1483,
    114,  1001, 1408, 1488, 1486, 114,  1488, 1000, 1495, 1491, 119,  1493,
    114,  1495, 1000, 1505, 1503, 0,    1010, 1467, 1011, 1505, 2,    1505,
    1000, 1514, 1512, 1030, 1010, 1467, 1011, 999,  1514, 1000, 1525, 1518,
    129,  1016, 1520, 139,  1523, 146,  1018, 1525, 1016, 1530, 1528, 153,
    1530, 1000, 1546, 1536, 1337, 1032, 1337, 1546, 1541, 0,    1530, 1552,
    2,    1544, 160,  1530, 1546, 1337, 1552, 1550, 1037, 1337, 1552, 1000,
    1563, 1557, 164,  1530, 1563, 1561, 168,  1530, 1570, 1563, 1000, 1570,
    1568, 164,  1530, 999,  1570, 1000, 1577, 1575, 168,  1530, 999,  1577,
    1000, 1585, 1581, 1033, 1337, 1583, 171,  1585, 1000, 1592, 1589, 173,
    1010, 1592, 1015, 1010, 1596, 1595, 173,  1596, 1605, 1603, 6,    1337,
    171,  1337, 1596, 1605, 1000, 1614, 1610, 1488, 1001, 1408, 1614, 178,
    1525, 1614, 1620, 1620, 1001, 1408, 1791, 1620, 1626, 1624, 6,    1614,
    1626, 1000, 1645, 1637, 1488, 1592, 1010, 1001, 1402, 1799, 1011, 1645,
    1006, 1645, 178,  1525, 1592, 1001, 1402, 1791, 1667, 1656, 1654, 6,
    1010, 1001, 1402, 1799, 1011, 1645, 1656, 1000, 1667, 1659, 184,  1661,
    188,  1663, 197,  1665, 207,  1667, 216,  1678, 1676, 34,   1012, 1028,
    1300, 1344, 1689, 1678, 1678, 1000, 1689, 1687, 6,    1012, 1028, 1300,
    1344, 1689, 999,  1689, 1000, 1696, 1694, 0,    1328, 2,    1696, 1000,
    1703, 1701, 6,    1321, 999,  1703, 1000, 1708, 1706, 222,  1708, 1000,
    1714, 1712, 6,    1337, 1714, 1000, 1727, 1725, 6,    1001, 1408, 0,
    1337, 171,  1337, 2,    999,  1727, 1000, 1734, 1732, 24,   1530, 1552,
    1734, 1000, 1747, 1737, 1019, 1739, 1006, 1744, 1373, 1530, 1552, 1006,
    1747, 1378, 1006, 1760, 1751, 228,  1034, 1754, 234,  1034, 1760, 244,
    1010, 1939, 1011, 1766, 1766, 1764, 164,  1939, 1766, 1000, 1783, 1770,
    249,  1034, 1778, 259,  1373, 1010, 1530, 1552, 1011, 1747, 1781, 259,
    1939, 1783, 1000, 1791, 1789, 264,  1001, 1358, 1783, 1791, 1000, 1799,
    1799, 0,    1337, 171,  1337, 1596, 2,    1807, 1805, 34,   1028, 1300,
    1344, 1807, 1000, 1816, 1810, 266,  1812, 188,  1814, 273,  1816, 1000,
    1827, 1825, 1001, 34,   1337, 6,    1337, 6,    1337, 1827, 1000, 1834,
    1832, 6,    1852, 999,  1834, 1000, 1845, 1838, 173,  1001, 1845, 1001,
    0,    1852, 1827, 1870, 2,    1852, 1848, 1001, 1852, 1852, 1827, 1870,
    1862, 1856, 1428, 1862, 1862, 0,    1852, 1827, 1870, 2,    1870, 1867,
    1488, 1001, 1408, 1870, 178,  1614, 1878, 1876, 168,  1852, 1827, 999,
    1878, 1000, 1901, 1885, 4,    1910, 1001, 1901, 1006, 1889, 281,  1002,
    1006, 1893, 1022, 1917, 1006, 1899, 286,  1009, 6,    1009, 1006, 1901,
    1043, 1910, 1905, 292,  1005, 1908, 294,  1005, 1910, 1000, 1917, 1913,
    296,  1915, 34,   1917, 1000, 1939, 1920, 1023, 1923, 1024, 1321, 1926,
    1025, 1321, 1929, 1039, 1321, 1934, 1040, 1321, 6,    1321, 1939, 1041,
    1321, 6,    1321, 1972, 1948, 1010, 1001, 1358, 1783, 1011, 1577, 1760,
    1952, 298,  1001, 1358, 1954, 301,  1958, 308,  1033, 1337, 1961, 315,
    1760, 1963, 323,  1968, 328,  1703, 1321, 1708, 1970, 335,  1972, 340,
    2097, 1979, 1027, 1010, 1939, 1011, 1734, 1981, 1007, 1989, 1373, 1010,
    1530, 1552, 1011, 1747, 1006, 1994, 349,  1035, 1766, 1006, 1999, 356,
    1029, 1816, 1006, 2004, 362,  1036, 1727, 1006, 2009, 1378, 356,  1029,
    1006, 2016, 1031, 1010, 1428, 1011, 1605, 1006, 2020, 369,  1514, 1006,
    2025, 83,   153,  1834, 1006, 2035, 1010, 1807, 1453, 1011, 1585, 1001,
    1402, 1495, 1006, 2039, 1656, 1428, 1626, 2043, 373,  1003, 1038, 2048,
    381,  1015, 1010, 1006, 2057, 387,  1021, 1703, 1321, 1696, 228,  1034,
    1006, 2068, 390,  1001, 1408, 0,    1337, 171,  1337, 2,    1714, 1006,
    2072, 397,  1006, 1017, 2078, 259,  1035, 1004, 1034, 1006, 2081, 4,
    1878, 2084, 402,  1006, 2088, 417,  1001, 1006, 2092, 424,  1003, 1006,
    2095, 1001, 432,  2097, 1006};
static const int Ss = 1972;

char *pn[2097] = { [ 0 ... 2096 ] = "" };
#define pn(x) pn[x]

#define TO_BE_DUMPED 1
#define DUMPED 2
static int state[2097] = { [ 0 ... 2096 ] = 0 };

int main(int argc, char **argv) {
  int i,d;

  pn(Ss) = "SS";      // build this list by matching the initial output against similar grammars

  pn(1027) = "CHUI";
  pn(1010) = "HOLE";
  pn(1939) = "UI";
  pn(1011) = "MARK";
  pn(1734) = "RESTOFSS1";
  pn(1007) = "TEXT";
  pn(1373) = "IU";
  pn(1530) = "SC";
  pn(1552) = "RESTOFCOND";
  pn(1747) = "RESTOFIU";
  pn(1006) = "S";
  pn(1035) = "NOTEFINISH";
  pn(1766) = "ELSE'";
  pn(1029) = "NOTECYCLE";
  pn(1816) = "CYCPARM";
  pn(1036) = "NOTEREPEAT";
  pn(1727) = "RESTOFREPEAT";
  pn(1378) = "%WU";
  pn(1031) = "CHTYPE";
  pn(1428) = "TYPE";
  pn(1605) = "DECLN";
  pn(1514) = "ENDLIST";
  pn(1834) = "RFSTMNT";
  pn(1807) = "%SEX";
  pn(1453) = "RT";
  pn(1585) = "%SPEC'";
  pn(1001) = "NAME";
  pn(1402) = "ALIAS'";
  pn(1495) = "FPP";
  pn(1656) = "XOWN";
  pn(1626) = "OWNDEC";
  pn(1003) = "CONST";
  pn(1038) = "INCLUDE";
  pn(1015) = "DOWN";
  pn(1021) = "TRACE";
  pn(1703) = "%EVENT'";
  pn(1321) = "CEXPR";
  pn(1696) = "RESTOFELIST";
  pn(1034) = "NOTESTART";
  pn(1408) = "NLIST'";
  pn(1337) = "EXPR";
  pn(1714) = "RESTOFSWLIST";
  pn(1017) = "LISTON";
  pn(1035) = "NOTEFINISH";
  pn(1004) = "DUMMYSTART";
  pn(1878) = "UCI";
  pn(1002) = "ICONST";
  pn(1005) = "N";
  pn(1009) = "N255";
  pn(1012) = "READLINE?";
  pn(1013) = "TEXTTEXT";
  pn(1016) = "UP";
  pn(1018) = "LISTOFF";
  pn(1022) = "SETNEM";
  pn(1023) = "UCNOPS";
  pn(1024) = "UCUB";
  pn(1025) = "UCSB";
  pn(1028) = "+'";
  pn(1033) = "ASSOP";
  pn(1037) = "COMP2";
  pn(1039) = "UCW";
  pn(1040) = "UCUBUB";
  pn(1041) = "UCUBW";
  pn(1043) = "UCWRONG";
  pn(1300) = "COPERAND";
  pn(1300) = "OPERAND";
  pn(1311) = "COPERAND";
  pn(1344) = "RESTOFCEXPR";
  pn(1344) = "RESTOFEXPR";
  pn(1351) = "RESTOFCEXPR";
  pn(1358) = "APP";
  pn(1415) = "FULLTYPE";
  pn(1420) = "BTYPE";
  pn(1460) = "FM";
  pn(1483) = "%NAME'";
  pn(1488) = "%QNAME'";
  pn(1505) = "RESTOFFPLIST";
  pn(1525) = "%FORMAT'";
  pn(1563) = "RESTOFANDC";
  pn(1570) = "RESTOFORC";
  pn(1577) = "RESTOFUI";
  pn(1596) = "RESTOFBPLIST";
  pn(1614) = "ADECLN";
  pn(1678) = "ROCL";
  pn(1689) = "REPFACT";
  pn(1708) = "OPEXPR";
  pn(1760) = "AUI";
  pn(1783) = "ENAME'";
  pn(1827) = "RESTOFRFDEC";
  pn(1845) = "RFREF";
  pn(1852) = "RFDEC";
  pn(1862) = "RFELMNT";
  pn(1870) = "ALTRFDEC";
  pn(1901) = "OPTINC";
  pn(1910) = "AT'";
  pn(1917) = "RESTOFUCI";
  pn(1026) = "OP";
  pn(1467) = "FPDEL";
  pn(1030) = ",'";
  pn(1032) = "COMP1";
  pn(1546) = "RESTOFSC";
  pn(1791) = "BPAIR";
  pn(1620) = "RESTOFARLIST";
  pn(1592) = "VSPEC'";
  pn(1799) = "CONST'";
  pn(1645) = "RESTOFOWNDEC";
  pn(1667) = "CONSTLIST";
  pn(1328) = "STAROREXPR";
  pn(1019) = "COLON";
  pn(1366) = "DUMMYAPP";  
  // recursively dump grammar from Phrase <SS>

  state[Ss] = TO_BE_DUMPED;
  for (;;) {
    int found = 0;
    // Keep doing passes until none found
    for (i = 0; i < 2097; i++) {
      if (state[i]&TO_BE_DUMPED) {
        //fprintf(stderr, "Target: %d  state=%d\n", i, state[i]);
        if ((state[i]&DUMPED) == 0) {
          found++;
          //fprintf(stderr, "Dumping...\n");
          Dump(i);
          state[i] |= DUMPED;
        }
      }
    }
    if (!found) break;
  }

  d = 0;
  for (i = 0; i < 2097; i++) {
    if (state[i]) {
      d += 1;
    }
  }
  fprintf(stdout, "%0d\n", d);
  for (i = 0; i < 2097; i++) {
    if (state[i]) {
      fprintf(stdout, "D(%s)\n", pn(i));
    }
  }

  
  return 0;
}

                                                               
void Dump(int i) {
    int next = Symbol(i);
    if (*pn(i) == '\0') {
      fprintf(stdout, "P(#%d) = \n   ", i);
    } else {
      fprintf(stdout, "P(%s) = \n   ", pn(i));
    }
    i += 1;
    while (i < next) {
      // Extract phrase definition.
      int lim = Symbol(i);
      fprintf(stdout, "        ");
      i += 1;
      while (i < lim) {
        int q = Symbol(i);
        // Now we extract subphrases.
        if (q < 437) {
          int n, len = Clett[q];
          if (Clett[q+1]&128) fprintf(stdout, "'%%"); else fprintf(stdout, "'");
          for (n = q+1; n <= q+len; n++) {
            fprintf(stdout, "%c", Clett[n]&127);
          }
          if (Clett[q+1]&128) fprintf(stdout, "' "); else fprintf(stdout, "' ");
        } else if (q >= 1300) {
          state[q] |= TO_BE_DUMPED;
          if (q == 999) {
            fprintf(stdout, "*");
          } else if (q == 1000) {
            fprintf(stdout, "0");
          } else {
            if (*pn(q) == '\0') {
              fprintf(stdout, "(#%d) ", q);
            } else {
              fprintf(stdout, "(%s) ", pn(q));
            }
          }
        } else {
          if (q == 999) {
            fprintf(stdout, "*");
          } else if (q == 1000) {
            fprintf(stdout, "0");
          } else {
            if (*pn(q) == '\0') {
              fprintf(stdout, "(#%d) ", q);
            } else {
              fprintf(stdout, "(%s) ", pn(q));
            }
          }
        }
        i++;
      }
      if (i == next) fprintf(stdout, ";\n   "); else fprintf(stdout, ",\n   ");
    }
    fprintf(stdout, "\n");
}

