PROGRAM rm;

{ Rechen-Meister : Erweiterte Bruch-Arithmetik mit Fakultaet,
                   Binomial-Koeffizienten und Potenz.                }

CONST einaus   : ARRAY [boolean] OF STRING [3] = ('aus', 'ein');
      rzeichen : SET OF char = ['0'..'9', '/', '+', '-', '*',
                                ':', '.', '!', '^', '(', ')'];
      cr       = #13#10;
      invon    = ^['G4'; { inverse Darstellungsweise an  }
      invoff   = ^['G0'; { inverse Darstellungsweise aus }

TYPE  zeile    = STRING [255];
      bruch    = RECORD
                   zaehler, nenner : real
                 END;
      formel   = RECORD
                   name    : STRING [20];
                   eintrag : STRING [127]
                 END;
      flags    = (argum, print, teile, float, gebro);
 zeichenvorrat = SET OF char;

CONST flagname : ARRAY [flags] OF STRING [12] = ('Argument    ',
                                 'Printer     ', 'Teilergebnis',
                                 'Fliesskomma ', 'Bruch       ');

VAR   eingabe, temp  : zeile;
      erg            : bruch;
      error, fa, fb  : boolean;
      fehlermeldung  : STRING [30];
      fc, m          : integer;
      formelsammlung : FILE OF formel;
      arbeitsformel  : formel;
      status         : ARRAY [flags] OF boolean;
      druckaus,
      bildaus        : text;
      testset        : SET OF char;
      a, b           : real;

{$I RM1.PAS}

{====================================================================}

{                            Hauptprogramm                           }

BEGIN { rm }
  clrscr;
  temp := '';
  anfangstatus;
  assign (druckaus, 'LST:');
  rewrite (druckaus);
  assign (bildaus, 'CON:');
  rewrite (bildaus);
  assign (formelsammlung, 'RM.FML');
  writeln ('Rechenmeister   Version 1.0');
  writeln;
  REPEAT
    REPEAT
      write (': ');
      readln (eingabe)
    UNTIL eingabe <> '';
    gross (eingabe);
    IF status [print]
      THEN
        writeln (druckaus, ': ', eingabe);
    replace (' ', '', eingabe);
    CASE eingabe [1] OF
      'D'           : BEGIN
                        temp := copy (eingabe, 2, length (eingabe)-1);
                        arbeitsformel.eintrag := temp
                      END;
      '?'           : writeln (temp);
      'L', 'S', 'X' : IF length (eingabe) > 1
                        THEN
                          IF syntaxok (rzeichen+[eingabe [2]], temp)
                            THEN
                              BEGIN
                                machzahlen (eingabe, '..',a,b,fa,fb);
                                IF NOT error AND NOT fa AND NOT fb
                                  THEN
                                    liste (temp, eingabe [2],
                                           trunc (a), trunc (b))
                                  ELSE
                                    meldung ('???')
                              END;
      'R'           : BEGIN
                        m := pos ('=', eingabe);
                        error := m = 0;
                        IF NOT error
                          THEN
                            BEGIN
                              replace (copy (eingabe, 2, m-2),
                            copy(eingabe,m+1,length(eingabe)-m),temp);
                              writeln (bildaus, temp);
                              IF status [print]
                                THEN
                                  writeln (druckaus, temp)
                            END
                          ELSE
                            meldung ('???')
                      END;
      'F'           : status [float] := NOT status [float];
      'B'           : status [gebro] := NOT status [gebro];
      'P'           : status [print] := NOT status [print];
      'A'           : status [argum] := NOT status [argum];
      'T'           : status [teile] := NOT status [teile];
      '#'           : schreibstatus;
      'O'           : temp := arbeitsformel.eintrag;
      'K', 'G'      : BEGIN
                        machzahlen (eingabe, ',',a,b,fa,fb);
                        IF NOT error AND NOT fa AND NOT fb
                          THEN
                            BEGIN
                              erg.nenner := 1;
                              IF eingabe [1] = 'K'
                                THEN
                                  erg.zaehler := kgv (a, b)
                                ELSE
                                  erg.zaehler := ggt (a, b);
                              schreibergebnis (bildaus, erg, 0);
                              IF status [print]
                                THEN
                                  schreibergebnis (druckaus, erg, 0)
                            END
                      END;
       '$'          : dirformel;
       '>'          :schreibformel(copy(eingabe,2,length(eingabe)-1));
       '<'          : BEGIN
                        liesformel(copy(eingabe,2,length(eingabe)-1));
                        temp := arbeitsformel.eintrag;
                        IF error
                          THEN
                            meldung ('Formel nicht gefunden.')
                      END;
      'H'           : hilfe;
      ';'           : BEGIN
                      END;
      'Q'           : BEGIN
                      END;
    ELSE
      BEGIN
        replace ('@', bruchstring (erg), eingabe);
        zerlege (eingabe, erg, error);
        schreibergebnis (bildaus, erg, 0);
        IF status [print]
          THEN
            schreibergebnis (druckaus, erg, 0)
      END
    END;
    writeln;
    IF status [print]
      THEN
        writeln (druckaus)
  UNTIL eingabe [1] = 'Q'
END.  { rm }