#include <perms.h>
int _imp_mainep(int _imp_argc, char **_imp_argv) {
  static const int Grammar = 1;
  static const int Oldfile = 2;
  static const int Report = 0;
  static const int Newfile = 1;
  static const int Glist = 2;
  static const int Dlist = 3;
  static const int Ident = 70;
  static const int Lastbit = 512;
  static const int Exit = 0;
  static int Charmax = 0;
  static int Nmax = -1;
  static int Inits = 0;
  static int Newname = 0;
  int Sym;
  int Gmin;
  int Gmax;
  int Kmax;
  unsigned char Char[600 /*1:600*/];
  int Index[128 /*0:127*/];
  int Item[256 /*0:255*/];
  int Next[256 /*0:255*/];
  int Initial[79 /*1:79*/];
  int Keydict[480 /*32:511*/];
  static const int Phrasemin = 112;
  static const int Atommax = 111;
  int Phrase[144 /*112:255*/];
  int Atomic[32 /*80:111*/];
  void Readsym(void) {
    for (;;) {
      do
        Readsymbol(Sym);
      while (Sym == ' ');
      if (Sym != '-' || Nextsymbol() != Nl) return;
      Skipsymbol();
    }
  }
  void Printchars(int P) {
    while (Char[P]) {
      Printsymbol(Char[P]);
      P++;
    }
  }
  void Printname(int N) {
    Printchars(Index[N & 127]);
    while (N & 384) {
      Printsymbol('<');
      N -= 128;
    }
  }
  void Readname(int *N) {
    int I;
    int J;
    int K;
    int M;
    I = Charmax;
    for (;;) {
      I++;
      Char[I] = Sym;
      Readsymbol(Sym);
      if (('A' > Sym || Sym > 'Z') && ('0' > Sym || Sym > '9') && Sym != '\'')
        break;
    }
    I++;
    Char[I] = 0;
    if (Sym == ' ') Readsym();
    M = Nmax;
    while (M >= 0) {
      J = Index[M];
      K = Charmax + 1;
      while (J != 0 && Char[J] == Char[K]) {
        if (!Char[J]) goto Ok;
        J++;
        K++;
      }
      M--;
    }
  Ok:
    if (Newname) {
      if (M >= 0) {
        printstring("DUPLICATE: ");
        Printchars(Charmax + 1);
        Newline();
      }
      Index[*N] = Charmax + 1;
      Charmax = I;
      if (Nmax < *N) Nmax = *N;
    } else {
      if (M < 0) {
        printstring("UNKNOWN: ");
        Printchars(Charmax + 1);
        Newline();
        M = 0;
      }
      *N = M;
    }
  }
  void Readgrammar(void) {
    static int Minmin = 0;
    static int Maxmax = 0;
    int I;
    int J;
    int K;
    int L;
    int P;
    int Min;
    int Max;
    int Exp;
    int End;
    int Converted[251 /*-100:150*/];
    int Head[100 /*-100:-1*/];
    int Tail[100 /*-100:-1*/];
    int Token[150 /*1:150*/];
    int Link[150 /*1:150*/];
    int Map[256 /*0:255*/];
    int Cell(int H, int T) {
      int I;
      I = T;
      if (I > 0) I = 0;
      while (I != Min) {
        I--;
        if (Head[I] == H && Tail[I] == T) return (I);
      }
      Min--;
      Head[Min] = H;
      Tail[Min] = T;
      Converted[Min] = 0;
      return (Min);
    }
    int Union(int X, int Y) {
      int Hx;
      int Hy;
      if (X == Y) return (X);
      if (X < Y) {
        Hx = X;
        X = Y;
        Y = Hx;
      }
      if (X >= 0) {
        if (Y >= 0) return (Cell(X, Y));
        Hy = Head[Y];
        if (X > Hy) return (Cell(X, Y));
        if (X != Hy) return (Cell(Hy, Union(X, Tail[Y])));
        return (Y);
      }
      Hx = Head[X];
      Hy = Head[Y];
      if (Hx > Hy) return (Cell(Hx, Union(Tail[X], Y)));
      if (Hx != Hy) return (Cell(Hy, Union(X, Tail[Y])));
      return (Cell(Hx, Union(Tail[X], Tail[Y])));
    }
    void Concatenate(int X, int Y) {
      int I;
      int J;
      I = X;
      do {
        J = Link[I];
        Link[I] = Y;
        I = J;
      } while (I != X);
    }
    void Acceptexp(int *Exp, int *Expend) {
      int I;
      int String;
      int Stringend;
      int Unit;
      int Unitend;
      *Exp = 0;
    S:
      String = 0;
    U:
      if (Sym == '(') {
        Readsym();
        Acceptexp(Unit, Unitend);
        if (Unit == 0 || Sym != ')') goto Err;
        Readsym();
      } else {
        if ('A' <= Sym && Sym <= 'Z') {
          Readname(I);
          while (Sym == '<') {
            I += 128;
            Readsym();
          }
        } else {
          if (Sym != '+') goto Err;
          I = 0;
          while (Sym == '+') {
            I += 128;
            Readsym();
          }
        }
        Max++;
        Token[Max] = I;
        Link[Max] = Max;
        Unit = Max;
        Unitend = Max;
      }
      if (Sym == '*' || Sym == '!') {
        Max++;
        Token[Max] = -1;
        Link[Max] = Max;
        Min--;
        Head[Min] = Max;
        Tail[Min] = Unit;
        Concatenate(Unitend, Min);
        Unitend = Max;
        if (Sym == '*') Unit = Min;
        Readsym();
      }
      if (Sym == '?') {
        Max++;
        Token[Max] = -1;
        Link[Max] = Link[Unitend];
        Link[Unitend] = Max;
        Min--;
        Head[Min] = Max;
        Tail[Min] = Unit;
        Unit = Min;
        Readsym();
      }
      if (!String)
        String = Unit;
      else
        Concatenate(Stringend, Unit);
      Stringend = Unitend;
      if (Sym != ',' && Sym != ')' && Sym != Nl) goto U;
      if (!*Exp) {
        *Exp = String;
        *Expend = Stringend;
      } else {
        *Exp = Union(String, *Exp);
        I = Link[*Expend];
        Link[*Expend] = Link[Stringend];
        Link[Stringend] = I;
      }
      if (Sym != ',') return;
      do
        Readsym();
      while (Sym == Nl);
      goto S;
    Err:
      *Exp = 0;
    }
    void Convert(void) {
      int I;
      int J;
      int Count;
      int M;
      int N;
      int Gmax1;
      int Loopstop;
      void Tcount(int X) {
        int T;
        for (;;) {
          if (!X) return;
          if (X < 0) {
            Tcount(Tail[X]);
            X = Head[X];
          }
          T = Token[X];
          if (T >= 0) break;
          if (T == Loopstop) return;
          Token[X] = Loopstop;
          X = Link[X];
        }
        Count--;
      }
      void Addcomponents(int X) {
        static int I;
        static int T;
        static int Tc;
        static int U;
        static int Uc;
        while (X) {
          if (X < 0) {
            Addcomponents(Tail[X]);
            X = Head[X];
          }
          T = Token[X];
          if (T >= 0) break;
          if (T == Loopstop) return;
          Token[X] = Loopstop;
          X = Link[X];
        }
        if (X)
          X = Link[X];
        else
          T = Exit;
        Tc = T & 127;
        I = Gmax1;
        for (;;) {
          I++;
          if (I > Gmax) break;
          U = Item[I];
          if (U == T) {
            Next[I] = Union(Next[I], X);
            return;
          }
          Uc = U & 127;
          if (Uc == Tc || (Uc > Atommax && Tc > Atommax)) {
            printstring("CLASH: ");
            Printname(U);
            Space();
            Printname(T);
            Newline();
          }
          if (Tc == Ident || (Tc < Uc && Uc >= Phrasemin) || Uc == 0) {
            for (I = Gmax; I >= I; I--) {
              Item[I + 1] = Item[I];
              Next[I + 1] = Next[I];
            }
            break;
          }
        }
        Gmax++;
        Item[I] = T;
        Next[I] = X;
      }
      Loopstop = -1;
      Gmin = Gmax + 1;
      for (I = Min; I <= Max; I++) Converted[I] = 0;
      N = Next[0];
    L__1:
      Gmax1 = Gmax;
      Loopstop--;
      Addcomponents(N);
      Item[Gmax] = Item[Gmax] + Lastbit;
      if (!Gmax1) {
        Inits = Gmax;
        while (Inits != 0 && (Item[Inits] & 127) >= Phrasemin) Inits--;
      }
      Converted[N] = Gmax + 1;
      M = 0;
      for (I = Gmin; I <= Gmax; I++) {
        J = Next[I];
        if (J) {
          Count = Converted[J];
          if (!Count) {
            Loopstop--;
            Tcount(J);
            Converted[J] = Count;
          }
          if (Count < M) {
            M = Count;
            N = J;
          }
        }
      }
      if (M) goto L__1;
      for (I = Gmin; I <= Gmax; I++) {
        J = Next[I];
        if (J) J = Converted[J];
        Next[I] = J;
      }
    }
    void Minimize(void) {
      int I;
      int J;
      int K;
      int M;
      int N;
      int Stack[150 /*1:150*/];
      int Ultmap(int I) {
        int J;
        do {
          J = I;
          I = Map[I];
        } while (I != J && I != 0);
        return (J);
      }
      int Equivalent(int Nn, int Mm) {
        int I;
        int J;
        int K;
        int Pos1;
        int Pos2;
        Pos1 = 0;
        Pos2 = 0;
      L__1:
        for (;;) {
          K = Item[Mm];
          if (Item[Nn] != K) goto L__9;
          I = Next[Nn];
          J = Next[Mm];
          if ((I == 0 && J != 0) || (I != 0 && J == 0)) goto L__9;
          Pos1++;
          Stack[Pos1] = Nn;
          Map[Nn] = Mm;
          Nn++;
          Mm++;
          if (K & Lastbit) break;
        }
      L__2:
        if (Pos2 == Pos1) return (1);
        Pos2++;
        I = Stack[Pos2];
        Nn = Ultmap(Next[I]);
        Mm = Ultmap(Next[Map[I]]);
        if (Nn == Mm) goto L__2;
        if (Nn < Mm) {
          I = Nn;
          Nn = Mm;
          Mm = I;
        }
        if (Nn > N) goto L__1;
      L__9:
        while (Pos1) {
          I = Stack[Pos1];
          Map[I] = I;
          Pos1--;
        }
        return (0);
      }
      for (I = 0; I <= Gmax; I++) Map[I] = I;
      for (N = Gmin; N <= Gmax; N++)
        if (Map[N] == N) {
          if (N == Gmin || (Item[N - 1] & Lastbit) != 0) {
            M = 1;
            while (M != N) {
              if (Map[M] == M && Equivalent(N, M) != 0) break;
              M++;
            }
          }
        } else
          Map[N] = Ultmap(N);
      J = Gmin - 1;
      for (I = Gmin; I <= Gmax; I++) {
        K = Map[I];
        if (K == I) {
          J++;
          Map[I] = J;
          Item[J] = Item[I];
          Next[J] = Next[I];
        } else
          Map[I] = Map[K];
      }
      Gmax = J;
      for (I = Gmin; I <= Gmax; I++) {
        K = Next[I];
        if (K) Next[I] = Map[K];
      }
    }
    Gmax = 0;
  L__1:
    do
      Readsym();
    while (Sym == Nl);
    if (Sym == '/') goto L__10;
    if (Sym == 'S' && Nextsymbol() == 'S') {
      Skipsymbol();
      P = 0;
    } else {
      Readname(P);
      if (Phrasemin > P || P > 127) goto L__9;
    }
    Min = 0;
    Max = 0;
    do
      Readsym();
    while (Sym == Nl || Sym == '-' || Sym == '>');
    Acceptexp(Exp, End);
    if (Exp == 0 || Sym != Nl) goto L__9;
    Concatenate(End, 0);
    Item[0] = 1023;
    Next[0] = Exp;
    Convert();
    if (Min < Minmin) Minmin = Min;
    if (Max > Maxmax) Maxmax = Max;
    I = Gmin;
    if (P != 112) {
      Minimize();
      I = Map[Gmin];
    }
    Selectoutput(Glist);
    if (!P) {
      for (I = 1; I <= Gmax; I++) {
        J = Item[I];
        K = Next[I];
        if (K) {
          K -= Inits;
          if (K <= 0) exit(0);
        }
        if (I <= Inits) {
          L = J & 127;
          if (L >= Phrasemin) goto L__99;
          if (L >= 80) L = Atomic[L];
          if (Initial[L]) _imp_monitor(25);
          Initial[L] = (J << 8) + K;
        } else {
          Item[I - Inits] = J;
          Next[I - Inits] = K;
        }
      L__99:;
      }
      Gmax -= Inits;
    } else {
      Phrase[P] = I;
      Printname(P);
      printstring(" =>");
      Write(I, 1);
    }
    K = Lastbit;
    for (I = Gmin; I <= Gmax; I++) {
      if (K & Lastbit) {
        Newline();
        Write(I, 3);
        J = 0;
      }
      J++;
      if (J > 5) {
        Newline();
        Spaces(4);
        J = 1;
      }
      Spaces(3);
      K = Item[I];
      if (K & 127)
        Printname(K);
      else {
        printstring("*E");
        while (K & 384) {
          Printsymbol('+');
          K -= 128;
        }
      }
      Write(Next[I], 1);
    }
    Newline();
    Selectoutput(Report);
    goto L__1;
  L__9:
    if (P) {
      Printname(P);
      Newline();
    }
    printstring("WRONG FORMAT AT: ");
    K = 0;
    while (Sym != Nl || K == ',' || K == '-') {
      Printsymbol(Sym);
      K = Sym;
      Readsymbol(Sym);
    }
    Newline();
    goto L__1;
  L__10:
    printstring("MIN =");
    Write(Minmin, 1);
    printstring("  MAX =");
    Write(Maxmax, 1);
    Newline();
    P = Phrase[Item[1] & 127];
    if (!P) _imp_monitor(26);
    for (;;) {
      J = Item[P];
      K = J & 127;
      if (K >= Phrasemin) _imp_monitor(27);
      if (K >= 80) K = Atomic[K];
      if (Initial[K]) _imp_monitor(28);
      Initial[K] = (((J & 127) + Lastbit) << 8) + Next[P];
      if (J & Lastbit) break;
      P++;
    }
    Selectoutput(Glist);
    Newlines(2);
    for (I = 1; I <= 79; I++) {
      K = Initial[I];
      if (K) {
        Write(I, 2);
        printstring(":  ");
        Printname((unsigned)K >> 8);
        Write(K & 255, 3);
        Newline();
      }
    }
    Selectoutput(Report);
  }
  void Readatoms(void) {
    int I;
    int J;
    int K;
    int Dict;
    int Dmax;
    int Code;
    int Class;
    int Sub;
    int Char[451 /*0:450*/];
    int Cont[451 /*0:450*/];
    int Alt[451 /*0:450*/];
    void Readcode(void) {
      Code = Nextsymbol();
      Sub = 0;
      if (Code != ',' && Code != Nl) {
        Skipsymbol();
        if (Code != '(') return;
        Read(Sub);
        Skipsymbol();
      }
      Code = Class + 128;
    }
    void Insertword(int *X) {
      for (;;) {
        if (Code == '$') Code = Nl;
        while (Char[*X] < Code) {
          if (!Cont[*X]) Cont[*X] = Sub;
          X = &Alt[*X];
        }
        if (Char[*X] != Code) {
          Dmax++;
          Char[Dmax] = Code;
          Cont[Dmax] = 0;
          Alt[Dmax] = *X;
          *X = Dmax;
        }
        if (Code & 128) break;
        Readcode();
        X = &Cont[*X];
      }
      Cont[*X] = Sub;
    }
    void Store(int X) {
      int M;
      int N;
      int V;
      for (;;) {
        Kmax++;
        N = Kmax;
        M = Alt[X];
        if (M) {
          Store(M);
          M = -131072;
        }
        V = Char[X];
        X = Cont[X];
        if (V & 128) break;
        if (!M) {
          if (Alt[X] == 0 && (Char[X] & 128) == 0) {
            V += Char[X] << 7;
            X = Cont[X];
          }
        } else
          V = ((Kmax + 1) << 7) + V - 131072;
        Keydict[N] = V;
      }
      Keydict[N] = M + 65536 + (X << 6) + (V & 63);
    }
    Dict = 0;
    Dmax = 0;
    Char[0] = 999;
  L__1:
    for (;;) {
      Sym = Nextsymbol();
      if (Sym != '[' && Sym != Nl) break;
      do
        Readsymbol(Sym);
      while (Sym != Nl);
    }
    if (Sym == '/') goto L__10;
    Read(Class);
    Newname = 1;
    Readsym();
    Readname(Class);
    Newname = 0;
    if (Class < 80) {
      if (Sym != '[')
        for (;;) {
          Code = Sym;
          Insertword(Dict);
          Readsymbol(Sym);
          if (Sym != ',') break;
          do
            Readsymbol(Sym);
          while (Sym == ' ' || Sym == Nl);
        }
    } else if (Class < Phrasemin && Sym == '=') {
      Readsym();
      Readname(Atomic[Class]);
    }
    while (Sym != Nl) Readsymbol(Sym);
    goto L__1;
    void Display(int I, int S) {
      int J;
    L__1:
      J = Keydict[I];
      if (!(J & 65536)) {
        Printsymbol(J & 127);
        if (J > 0) {
          J = (unsigned)J >> 7;
          if (J) {
            Printsymbol(J);
            S++;
          }
          Space();
          I++;
          S += 2;
          goto L__1;
        }
        Space();
        Display((unsigned)J >> 7 & 511, S + 2);
      } else {
        Printsymbol(':');
        Printname(J & 63);
        Write((unsigned)J >> 6 & 1023, 1);
        Newline();
      }
      if (J >= 0) return;
      Spaces(S);
      I++;
      goto L__1;
    }
  L__10:
    Selectoutput(Dlist);
    Newlines(2);
    Kmax = 95;
    Keydict[32] = 0;
    for (I = 33; I <= 95; I++) {
      Printsymbol(I);
      Space();
      if (Char[Dict] == I) {
        J = (Kmax + 1) << 2;
        Store(Cont[Dict]);
        Dict = Alt[Dict];
        Display((unsigned)J >> 2, 2);
      } else {
        Printsymbol('?');
        Newline();
        J = 32 << 2;
      }
      if ('A' > I || I > 'Z') J += 3;
      if ('0' <= I && I <= '9') J -= 2;
      if (I == ';') J--;
      Keydict[I] = J;
    }
    Newlines(2);
    Selectoutput(Report);
  }
  int I;
  int J;
  int K;
  Charmax = 0;
  for (I = 1; I <= 127; I++) Index[I] = 0;
  for (I = 1; I <= 79; I++) Initial[I] = 0;
  Selectoutput(Report);
  do
    Readsymbol(I);
  while (I != '/');
  do
    Readsymbol(I);
  while (I != Nl);
  Readatoms();
  do
    Readsymbol(I);
  while (I != Nl);
  Readgrammar();
  Selectoutput(Newfile);
  Selectinput(Oldfile);
  if (_imp_on_event(9)) goto Eof;
  I = 0;
  for (;;) {
    Readsymbol(K);
    Printsymbol(K);
    if (K == '!' && Nextsymbol() == '*') I = 1;
    if (I == 1 && K == Nl) break;
  }
Eof:
  printstring("%OWNINTEGER GMAX1=");
  Write(Gmax, 0);
  Newline();
  printstring("%OWNINTEGER GMAX=");
  Write(Gmax, 0);
  Newlines(2);
  printstring("%OWNINTEGERARRAY PHRASE(112:127) = %C");
  for (I = 112; I <= 127; I++) {
    if (!(I & 7)) Newline();
    Write(Phrase[I], 3);
    if (I != 127) Printsymbol(',');
  }
  Newlines(2);
  printstring("%OWNINTEGERARRAY ATOMIC(80:111) = %C");
  for (I = 80; I <= 111; I++) {
    if (!(I & 7)) Newline();
    Write(Atomic[I], 3);
    if (I != 111) Printsymbol(',');
  }
  Newlines(2);
  int Packed(int J, int K) {
    K += (J & 896) << 1;
    J = J & 127;
    return ((K << 7) + J);
  }
  printstring("%OWNINTEGERARRAY INITIAL(1:79) = %C");
  Newline();
  Spaces(9);
  for (I = 1; I <= 79; I++) {
    if (!(I & 7)) Newline();
    Write(Packed((unsigned)Initial[I] >> 8, Initial[I] & 255), 7);
    if (I != 79) Printsymbol(',');
  }
  Newlines(2);
  printstring("%OWNINTEGERARRAY GRAM(0:255) = %C");
  for (I = 0; I <= 255; I++) {
    if (!(I & 7)) Newline();
    K = 0;
    if (I != 0 && I <= Gmax) K = Packed(Item[I] ^ 512, Next[I]);
    Write(K, 7);
    if (I != 255) Printsymbol(',');
  }
  Newlines(2);
  printstring("%OWNINTEGERARRAY KDICT(32:");
  Write(Kmax, 0);
  printstring(") = %C");
  for (I = 32; I <= Kmax; I++) {
    if (!(I & 7)) Newline();
    Write(Keydict[I], 7);
    if (I != Kmax) Printsymbol(',');
  }
  Newlines(2);
  if (_imp_on_event(9)) goto L__99;
  for (;;) {
    if (Nextsymbol() == '!') break;
    do
      Readsymbol(K);
    while (K != Nl);
  }
  for (;;) {
    Readsymbol(K);
    Printsymbol(K);
  }
L__99:;
  exit(0);
  return (1);
}
