home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 04 / calc.pas next >
Encoding:
Pascal/Delphi Source File  |  1989-04-26  |  21.0 KB  |  513 lines

  1. (***************************************************************************)
  2. (*                                                                         *)
  3. (*                            CALC.PAS                                     *)
  4. (*    Berechnung von arithmetischen Ausdruecken in Pascal zur Laufzeit     *)
  5. (*                                                                         *)
  6. (***************************************************************************)
  7.  
  8. (* ----------------------------------------------------------------------- *)
  9. (*            Uebersetzen eines Ausdrucks von AOS nach UPN:                *)
  10. (* 'Expr' enthaelt den zu uebersetzenden Ausdruck                          *)
  11. (* 'VarTable' ist ein Zeiger auf die fuer den zu uebersetzenden Ausdruck   *)
  12. (* zu verwendente Variablen-Tabelle. Ist dieser '= nil', wird von 'Calc-   *)
  13. (* Expression implizit eine solche Tabelle erzeugt und fuer den Ausdruck   *)
  14. (* verwendet. Man beachte in diesem Zusammenhang auch 'CalcDecMod'!        *)
  15. (* 'ExprPtr' gibt den Zeiger auf die von 'CompileExpression' erzeugte UPN- *)
  16. (* Queue zurueck. Dieser ist '= nil', wenn ein fehlerhafter Ausdruck vor-  *)
  17. (* liegt (kein Calc-Prog. erzeugt!).                                       *)
  18. (* 'CalcResult' ist TRUE, wenn kein Problem auftrat - sonst FALSE!         *)
  19. (* ----------------------------------------------------------------------- *)
  20. UNIT Calc;
  21.  
  22. INTERFACE
  23.  
  24. USES Crt, Turbo3, Graph, Graph3;
  25.  
  26. CONST
  27.   Calc_IdLen  = 10;
  28.   Calc_MaxVar = 10;
  29.   Calc_OpSize =  6;
  30.  
  31. TYPE
  32.   ErrString  = STRING[80];
  33.   Calc_IdStr = STRING[Calc_IdLen];
  34.   Calc_String = STRING[255];
  35.   Calc_Operand = REAL;
  36.   Calc_VarType = RECORD
  37.                    VarId : Calc_IdStr;
  38.                    Value : Calc_Operand;
  39.                  END;
  40.   Calc_VarTab = ^Calc_VarTable;
  41.   Calc_VarTable = ARRAY[0..Calc_MaxVar] OF Calc_VarType;
  42.   Calc_Symbols =
  43.     (Calc_Err, Calc_EOE,
  44.      Calc_Const, Calc_Var,
  45.      Calc_Pi, Calc_E,
  46.      Calc_lp, Calc_rp,
  47.      Calc_Neg,
  48.      CAlc_Add, Calc_Sub,
  49.      CAlc_Mul, Calc_Dvd, Calc_Div,
  50.      Calc_Mod, Calc_ggT, Calc_kgV,
  51.      Calc_Pow,
  52.      Calc_sqr, Calc_Sqrt, Calc_Exp,
  53.      Calc_Ln, CAlc_Lg, Calc_Ld,
  54.      CAlc_Sin, Calc_Cos, Calc_Tan, Calc_Cot,
  55.      Calc_ArcSin, CAlc_ArcCos, Calc_ArcTan, Calc_ArcCot,
  56.      Calc_Sinh, Calc_Cosh, Calc_Tanh, CAlc_Coth,
  57.      Calc_ArcSinh, Calc_ArcCosh, Calc_ArcTanh, Calc_ArcCoth,
  58.      Calc_Abs, Calc_Deg, CAlc_Rad, Calc_Rez, CAlc_Fak, Calc_Sign, Calc_Int,
  59.      Calc_End);
  60.   Calc_Prog = ^Calc_Instruct;
  61.   Calc_Instruct = RECORD
  62.                     NextInst : Calc_Prog;
  63.                     Instruct : Calc_Symbols;
  64.                     CASE Calc_Symbols OF
  65.                       Calc_Var  : (VarIndex : INTEGER);
  66.                       Calc_Const: (Operand : CAlc_Operand);
  67.                   END;
  68.  
  69. VAR CalcDecMod : BOOLEAN;
  70.     CalcResult : BOOLEAN;
  71.  
  72.  
  73. PROCEDURE CompileExpression (Expr: Calc_String;
  74.                              VAR VarTable: Calc_VarTab;
  75.                              VAR ExprPtr : Calc_Prog);
  76.  
  77. FUNCTION CalcExpression (ExprPtr : Calc_Prog;
  78.                          VarTable: Calc_VarTab): Calc_Operand;
  79.  
  80. IMPLEMENTATION
  81.  
  82. CONST Calc_Ids : ARRAY [Calc_Symbols] OF Calc_IdStr =
  83.                    ('ERR', ';', 'CONST', 'VAR', 'PI', 'E', '(', ')', 'NEG',
  84.                     '+', '-', '*', '/', 'DIV', 'MOD', 'GGT', 'KGV', '^',
  85.                     'SQR', 'SQRT', 'EXP', 'LN', 'LG', 'LD',
  86.                     'SIN', 'COS', 'TAN', 'COT',
  87.                     'ARCSIN', 'ARCCOS', 'ARCTAN', 'ARCCOT',
  88.                     'SINH', 'COSH', 'TANH', 'COTH',
  89.                     'ARCSINH', 'ARCCOSH', 'ARCTANH', 'ARCCOTH',
  90.                     'ABS', 'DEG', 'RAD', 'REZ', 'FAK', 'SGN', 'INT', 'END');
  91.  
  92. {$I CALCUTIL.PAS}
  93. {$I MATHFUNC.PAS}
  94. {$I CALCGLOB.PAS}
  95. {$I CALCSIMP.PAS}
  96. {$I CALCSIM2.PAS}
  97. {$I CALCDERI.PAS}
  98.  
  99. PROCEDURE CompileExpression (Expr: Calc_String;
  100.                              VAR VarTable: Calc_VarTab;
  101.                              VAR ExprPtr : Calc_Prog);
  102.  
  103. VAR VarTabFlag,
  104.     ParsError,
  105.     EndOfExpr  : BOOLEAN;
  106.     ch         : STRING[1];                (* akt. Zeichen aus String      *)
  107.     LastPos,
  108.     StrPos     : INTEGER;                  (* zaehlt String-Position mit   *)
  109.     TempIdent,
  110.     Ident      : Calc_String;              (* enth. aktuellen Bezeichner   *)
  111.     Symbol,                                (* akt. Symbol des Bezeichners  *)
  112.     LastSymbol : Calc_Symbols;             (* vorheriges Symbol            *)
  113.     Number     : Calc_Operand;             (* akt. Zahl/Index aus String   *)
  114.     ProgPtr    : Calc_Prog;
  115.  
  116.    (* -------------------------------------------------------------------- *)
  117.    (* Fehlerbehandlung! Die Anweisungen des IF-Zweiges koennen nach        *)
  118.    (* eigenen Beduerfnissen (z.B. der Programm-Umgebung) angepasst werden. *)
  119.  
  120.    PROCEDURE Error (ErrPos: INTEGER; ErrMsg: Calc_String);
  121.  
  122.    BEGIN
  123.       IF NOT ParsError THEN
  124.       BEGIN
  125.          WriteLn; Write('*** Fehler in CompileExpression:');
  126.          ClrEol; WriteLn;
  127.          Write (' ',Expr);ClrEol; Writeln;
  128.          Write (' ':ErrPos, '^'); ClrEol; Writeln;
  129.          Write (ErrMsg, '!'); Clreol; Writeln; ClrEol;
  130.          WriteLn; ClrEol
  131.       END;
  132.       ParsError := TRUE;  Symbol := Calc_Err
  133.    END;
  134.  
  135.    (* -------------------------------------------------------------------- *)
  136.    (*           naechsten Befehl an die UPN-Queue anhaengen:               *)
  137.    (* Dabei wird mittels 'HeapAvail' der noch freie Heap geprueft. Wegen   *)
  138.    (* des eventuellen Aufrufs der Error-Prozedur wird nicht nur Platz fuer *)
  139.    (* ein Queue-Element benoetigt - deshalb ein paar Bytes mehr, um eine   *)
  140.    (* Heap-Stack-Kollision zu vermeiden !                                  *)
  141.  
  142.    PROCEDURE Add_To_Queue (op: Calc_Symbols; x: Calc_Operand);
  143.  
  144.    VAR UPN_Entry: Calc_Prog;
  145.  
  146.    BEGIN
  147.       IF HeapAvail > 160.0 THEN     (* hier: noch 160 Bytes im Heap frei ? *)
  148.          BEGIN
  149.             New (UPN_Entry);
  150.             WITH UPN_Entry^ DO
  151.             BEGIN
  152.                NextInst := NIL;
  153.                Instruct := op;
  154.                CASE op OF
  155.                   Calc_Var  : VarIndex := Trunc(x);
  156.                   Calc_Const: Operand  := x
  157.                END
  158.             END;
  159.             ProgPtr^.NextInst := UPN_Entry;
  160.             ProgPtr           := ProgPtr^.NextInst
  161.          END
  162.       ELSE Error(1, 'nicht genuegend freier Speicher fuer den Ausdruck')
  163.    END;
  164.  
  165.    (* -------------------------------------------------------------------- *)
  166.    (*           naechstes Symbol aus der Zeichenkette holen:               *)
  167.  
  168.    PROCEDURE GetSymbol;
  169.  
  170.       (* ----------------------------------------------------------------- *)
  171.       (*           holt naechstes Zeichen aus der Zeichenkette:            *)
  172.  
  173.       PROCEDURE GetChar;
  174.  
  175.       BEGIN
  176.          ch := ' ';  StrPos := Succ(StrPos);
  177.          EndOfExpr := (StrPos > Length(Expr));
  178.          IF NOT EndOfExpr THEN ch := UpCase (Expr[StrPos])
  179.       END;
  180.  
  181.       (* ----------------------------------------------------------------- *)
  182.       (*        holt und wandelt Ziffernfolge aus der Zeichenkette:        *)
  183.       (* die Val-Prozedur von Turbo Pascal moechte in der Zeichenkette nur *)
  184.       (* gueltige Zeichen einer Real-Zahl haben, NumberEnd zeigt auf das   *)
  185.       (* erste ungueltige Zeichen! Deshalb folgendes:                      *)
  186.  
  187.       PROCEDURE GetNumber;
  188.  
  189.       VAR NumberStr: Calc_String;
  190.           NumberEnd,posi: INTEGER;
  191.  
  192.       BEGIN
  193.          NumberStr := Copy (Expr, StrPos, 255); (* nimm alles ab 1. Ziffer *)
  194.          NumberStr := NumberStr + '     ';
  195.          posi := 1;
  196.          while (not (numberstr[posi] in ['e','E']))
  197.            and (posi < length(numberstr))
  198.          do posi := succ(posi);
  199.          if numberstr[posi] in ['e','E'] THEN
  200.          BEGIN
  201.            if numberstr[posi+1] in ['+','-'] THEN posi := succ(posi);
  202.            if not (numberstr[posi+1] in ['0'..'9'])
  203.              THEN error(StrPos+posi,'unvollstaendiger Ausdruck')
  204.              else if
  205.               ((numberstr[posi+1] = '3') and (numberstr[posi+2] in ['7'..'9']))
  206.            or ((numberstr[posi+1] > '3') and (numberstr[posi+2] in ['0'..'9']))
  207.                 THEN error(StrPos+posi,'ausserhalb des Real-Bereichs');
  208.          END;
  209.          Val (NumberStr, Number, NumberEnd);
  210.          IF NumberEnd > 0 THEN        (* ungueltiges Zeichen in NumberStr! *)
  211.             BEGIN                     (* Zahl nicht am Ende von Expr.      *)
  212.                StrPos := StrPos + NumberEnd - 2;
  213.                NumberStr := Copy (NumberStr, 1, Pred(NumberEnd));
  214.                Val (NumberStr, Number, NumberEnd)
  215.             END
  216.          ELSE                     (* hat geklappt, weil am Ende von Expr ! *)
  217.             StrPos := Length(Expr)
  218.       END;
  219.  
  220.       (* ----------------------------------------------------------------- *)
  221.       (*           Symbolbezeichner in der Symbol-Tabelle suchen:          *)
  222.  
  223. PROCEDURE searchsymtab;
  224.  
  225. VAR symok: BOOLEAN;
  226.  
  227. BEGIN
  228.   symok := FALSE;
  229.   symbol := calc_err;
  230.   WHILE (symbol < calc_end) AND NOT symok DO
  231.     BEGIN
  232.       symbol := Succ(symbol);
  233.       symok := (ident = calc_ids[symbol]);
  234.     END;
  235.   IF NOT symok
  236.     THEN
  237.       symbol := calc_err
  238. END;
  239.  
  240.  
  241.       (* ----------------------------------------------------------------- *)
  242.  
  243.    BEGIN  (* GetSymbol *)
  244.       LastPos := StrPos;  LastSymbol := Symbol;  Ident := '';
  245.       WHILE (ch = ' ') AND NOT EndOfExpr DO GetChar;
  246.       CASE ch[1] OF
  247.          'A'..'Z': REPEAT      (* Bezeichner f. Operator, Funktion o. Var. *)
  248.                       Ident := Concat (Ident, ch);  GetChar
  249.                    UNTIL NOT (ch[1] IN ['A'..'Z', '0'..'9']);
  250.          '0'..'9','.': BEGIN  GetNumber;  Ident := 'CONST';  GetChar  END
  251.          ELSE      BEGIN  Ident := ch;  GetChar  END       (* + - * / usw. *)
  252.       END;
  253.       SearchSymtab;
  254.       IF Symbol = Calc_Err THEN      (* Zeichenfolge nicht identifiziert ! *)
  255.          IF Ident[1] IN ['A'..'Z'] THEN    (* nehmen wir sie als Variable! *)
  256.             Symbol := Calc_Var
  257.          ELSE IF Ident <> ' ' THEN Error(LastPos, 'unbekanntes Symbol');
  258.       IF Symbol = Calc_Var THEN
  259.          IF LastSymbol <> Calc_Var THEN
  260.             BEGIN
  261.                Number := SearchVarTab(VarTable, Ident);
  262.                (* entspr. 'CalcDecMod' eine nicht identifizierte Zeichen-
  263.                   folge abweisen oder als neue Variable interpretierten.   *)
  264.                IF CalcDecMod AND (Number = 0.0) THEN
  265.                   Error(LastPos, 'unbekanntes Symbol')
  266.                ELSE IF Number = 0.0 THEN
  267.                BEGIN
  268.                   Number := AddToVarTab(VarTable, Ident);
  269.                   IF Number < 0.0 THEN
  270.                      Error(LastPos, 'Zu viel Variable im Ausdruck')
  271.                END
  272.             END
  273.          ELSE IF NOT EndOfExpr THEN Error(LastPos, 'Operator erwartet')
  274.    END;
  275.  
  276.    (* -------------------------------------------------------------------- *)
  277.    (* Ausdruck kann aus mehreren mit + u. - verknuepften Termen bestehen.  *)
  278.    (* Das ist die Aufgabe von:                                             *)
  279.  
  280.  
  281.    PROCEDURE Expression;
  282.  
  283.    VAR ExprOp: Calc_Symbols;
  284.  
  285.       (* ----------------------------------------------------------------- *)
  286.       (* Term kann aus mehreren mit den entspr. Operatoren verknuepften    *)
  287.       (* Faktoren bestehen (z.B. Faktor*Faktor). Also:                     *)
  288.  
  289.       PROCEDURE Term;
  290.  
  291.       VAR TermOp: Calc_Symbols;
  292.  
  293.          (* -------------------------------------------------------------- *)
  294.          (* Faktor kann eine Variable, eine Konstante, eine Funktion oder  *)
  295.          (* wieder ein geklammerter Ausdruck sein, die alle noch           *)
  296.          (* potenziert werden koennen! Der Parameter 'fparen' gibt an, ob  *)
  297.          (* es sich bei einer Klammerung um Ausdrucks- oder Funktions-     *)
  298.          (* klammern handelt. Bei letzterem muss vor der Potenzierung noch *)
  299.          (* die Funktion ausgewertet werden! Deshalb:                      *)
  300.  
  301.          PROCEDURE Factor (fparen: BOOLEAN);
  302.  
  303.          VAR FacOp: Calc_Symbols;
  304.  
  305.          BEGIN
  306.             IF Symbol <> Calc_Err THEN
  307.             BEGIN
  308.                CASE Symbol OF
  309.                   Calc_Var: BEGIN
  310.                                Add_To_Queue (Calc_Var, Number);  GetSymbol
  311.                             END;
  312.                 Calc_Const: BEGIN
  313.                                Add_To_Queue (Calc_Const, Number);  GetSymbol
  314.                             END;
  315.                    Calc_Pi: BEGIN
  316.                                Add_To_Queue (Calc_Const, Pi);  GetSymbol
  317.                             END;
  318.                     Calc_E: BEGIN
  319.                                Add_To_Queue (Calc_Const, E);  GetSymbol
  320.                             END;
  321.                    Calc_lp: BEGIN                 (* geklammerter Ausdruck *)
  322.                                GetSymbol;
  323.                                Expression;
  324.                                IF (Symbol <> Calc_rp) THEN
  325.                                   Error (StrPos - Ord(ch[1] > ' '),
  326.                                          Concat(Calc_Ids[Calc_rp],
  327.                                                 ' erwartet'));
  328.                                GetSymbol
  329.                             END;
  330.                   Calc_Pow: ;      (* Potenzieren, wird spaeter erledigt ! *)
  331.                 Calc_Sqr..
  332.                   Calc_Fak: BEGIN                            (* Funktionen *)
  333.                                FacOp := Symbol;
  334.                                GetSymbol;
  335.                                IF (Symbol = Calc_lp) THEN
  336.                                   Factor(TRUE)
  337.                                ELSE
  338.                                   Error (LastPos, Concat(Calc_Ids[Calc_lp],
  339.                                                          ' erwartet'));
  340.                                Add_To_Queue (FacOp, 0)
  341.                             END
  342.                   ELSE              (* Symbol an dieser Stelle unerwartet! *)
  343.                      Error(LastPos, 'hier unerwartet')
  344.                END; (* CASE *)
  345.                IF NOT fparen THEN          (* keine Funktionsklammer, also *)
  346.                   IF Symbol = Calc_Pow THEN               (* potenzieren ! *)
  347.                      IF LastSymbol IN [Calc_Const,Calc_Var,Calc_rp,
  348.                                        Calc_PI,Calc_e] THEN
  349.                      BEGIN  (* wenn LastSym. ok, Potenzausdruck auswerten: *)
  350.                         GetSymbol;   Factor(FALSE);
  351.                         Add_To_Queue (Calc_Pow, 0);
  352.                      END
  353.                   ELSE                 (* Potenzierung hier nicht moeglich *)
  354.                      Error (Pred(StrPos), 'hier unerwartet');
  355.             END (* IF Symbol <> Calc_Err *)
  356.             ELSE
  357.                Error(StrPos-Ord(EndOfExpr), 'unvollstaendiger Ausdruck');
  358.          END; (* Faktor *)
  359.  
  360.       (* ----------------------------------------------------------------- *)
  361.  
  362.       BEGIN  (* Term *)
  363.          Factor(FALSE);
  364.          IF Symbol IN [Calc_Mul..Calc_kgV] THEN
  365.          BEGIN                      (* mehrere Faktoren im Term enthalten! *)
  366.             TermOp := Symbol;  GetSymbol;
  367.             Term;  Add_To_Queue (TermOp,0)
  368.          END;
  369.       END; (* Term *)
  370.  
  371.    (* -------------------------------------------------------------------- *)
  372.  
  373.    BEGIN  (* Expression *)
  374.       IF Symbol IN [Calc_Add..Calc_Sub] THEN
  375.          BEGIN                              (* Ausdruck beginnt mit + o. - *)
  376.             ExprOp := Symbol;  GetSymbol;  Term;
  377.             IF ExprOp = Calc_Sub THEN             (* 1. Symbol war -, also *)
  378.                Add_To_Queue (Calc_Neg, 0);        (* alles negieren !      *)
  379.          END
  380.       ELSE
  381.          Term;
  382.       WHILE (Symbol IN [Calc_Add..Calc_Sub]) DO
  383.       BEGIN                                   (* es folgen weitere Terme ! *)
  384.          ExprOp := Symbol;  GetSymbol;  Term;
  385.          Add_To_Queue (ExprOp, 0);
  386.       END;
  387.    END; (* Expression *)
  388.  
  389.    (* -------------------------------------------------------------------- *)
  390.  
  391. BEGIN  (* CompileExpression *)
  392.    Symbol := Calc_Err;   ParsError := FALSE;  EndOfExpr := FALSE;
  393.    StrPos := 0;          ch := ' ';           VarTabFlag := (VarTable = NIL);
  394.    IF VarTabFlag THEN VarTable := NewVarTab;
  395.    New (ExprPtr);   ExprPtr^.NextInst := NIL;  ProgPtr := ExprPtr;
  396.    GetSymbol;       Expression;
  397.    IF Symbol <> Calc_EOE THEN Error(LastPos, '";" erwartet');
  398.    CalcResult := NOT ParsError;
  399.    IF ParsError THEN
  400.    BEGIN
  401.       KillExpression(ExprPtr);
  402.       IF VarTabFlag THEN KillVarTab(VarTable)
  403.    END;
  404. END;
  405.  
  406. (* ----------------------------------------------------------------------- *)
  407. (*             Auswertung des in UPN uebersetzten Ausdrucks                *)
  408. (* ----------------------------------------------------------------------- *)
  409.  
  410. FUNCTION CalcExpression (ExprPtr : Calc_Prog;
  411.                          VarTable: Calc_VarTab): Calc_Operand;
  412.  
  413. CONST StackSize = 50;
  414.  
  415. VAR x       : Calc_Operand;
  416.     StackPtr: INTEGER;
  417.     Stack   : ARRAY[1..StackSize] OF Calc_Operand;         (* Rechenstapel *)
  418.  
  419.  
  420.    PROCEDURE Push;                        (* schiebt Zahl auf Rechenstapel *)
  421.  
  422.    BEGIN
  423.       Stack[StackPtr] := x;  StackPtr := Succ(StackPtr)
  424.    END;
  425.  
  426.  
  427.    FUNCTION Pop: Calc_Operand;               (* holt Zahl vom Rechenstapel *)
  428.  
  429.    BEGIN
  430.       StackPtr := Pred(StackPtr);  Pop := Stack[StackPtr]
  431.    END;
  432.  
  433.  
  434. BEGIN  (* CalcExpression *)
  435.    CalcResult := TRUE;
  436.    IF (ExprPtr <> NIL) AND (VarTable <> NIL) THEN
  437.    BEGIN
  438.       ExprPtr := ExprPtr^.NextInst;     (* 1. Eintrag der Queue ist leer ! *)
  439.       StackPtr := 1;  x := 0.0;                (* Laufzeit-Stapel ist leer *)
  440.       WHILE ExprPtr <> NIL DO
  441.       BEGIN
  442.          WITH ExprPtr^ DO
  443.             CASE Instruct OF
  444.                Calc_Const: BEGIN Push;  x := Operand  END;
  445.                Calc_Var  : BEGIN
  446.                               Push;  x := VarTable^[VarIndex].Value
  447.                            END;
  448.             ELSE
  449.                BEGIN
  450.                   CASE Instruct OF
  451.                      Calc_Neg    : x := -x;
  452.                      Calc_Add    : x := Pop+x;
  453.                      Calc_Sub    : x := Pop-x;
  454.                      Calc_Mul    : x := Pop*x;
  455.                      Calc_Dvd    : IF x <> 0.0 THEN x := Pop/x
  456.                                    ELSE CalcError(2, '');
  457.                      Calc_Div    : IF Trunc(x) <> 0 THEN
  458.                                      x := Trunc(Pop) DIV Trunc(x)
  459.                                    ELSE CalcError(2, '');
  460.                      Calc_Mod    : IF Trunc(x) <> 0 THEN
  461.                                      x := Trunc(Pop) MOD Trunc(x)
  462.                                    ELSE CalcError(2, '');
  463.                      Calc_ggT    : x := ggT(Trunc(Pop),Trunc(x));
  464.                      Calc_kgV    : x := kgV(Trunc(Pop),Trunc(x));
  465.                      Calc_Pow    : x := x_hoch_y(Pop,x);
  466.                      Calc_Sqr    : x := Sqr(x);
  467.                      Calc_Sqrt   : IF x >= 0.0 THEN x := Sqrt(x)
  468.                                    ELSE CalcError(3, 'Sqrt(x): x <= 0');
  469.                      Calc_Exp    : x := Exp(x);
  470.                      Calc_Ln     : IF x > 0.0 THEN x := Ln(x)
  471.                                    ELSE CalcError(3, 'ln(x): x <= 0');
  472.                      Calc_Lg     : x := lg(x);
  473.                      Calc_Ld     : x := ld(x);
  474.                      Calc_Sin    : x := Sin(x);
  475.                      Calc_Cos    : x := Cos(x);
  476.                      Calc_Tan    : x := tan(x);
  477.                      Calc_Cot    : x := cot(x);
  478.                      Calc_ArcSin : x := arcsin(x);
  479.                      Calc_ArcCos : x := arccos(x);
  480.                      Calc_ArcTan : x := ArcTan(x);
  481.                      Calc_ArcCot : x := arccot(x);
  482.                      Calc_Sinh   : x := sinh(x);
  483.                      Calc_Cosh   : x := cosh(x);
  484.                      Calc_Tanh   : x := tanh(x);
  485.                      Calc_Coth   : x := coth(x);
  486.                      Calc_ArcSinh: x := arsinh(x);
  487.                      Calc_ArcCosh: x := arcosh(x);
  488.                      Calc_ArcTanh: x := artanh(x);
  489.                      Calc_ArcCoth: x := arcoth(x);
  490.                      Calc_Abs    : x := abs(x);
  491.                      Calc_Deg    : x := altgrad(x);
  492.                      Calc_Rad    : x := radiant(x);
  493.                      Calc_Rez    : x := kehrwert(x);
  494.                      Calc_Fak    : x := fakultaet(Round(x));
  495.                      Calc_Int    : x := Int(x);
  496.                      Calc_Sign   : x := Sign(x);
  497.                      ELSE CalcError(0, 'Funktion nicht verfuegbar')
  498.                   END (* CASE *)
  499.                END (* ELSE *)
  500.             END (* CASE *);
  501.          ExprPtr := ExprPtr^.NextInst;
  502.          IF StackPtr > StackSize THEN CalcError(0, 'Stackueberlauf');
  503.          IF NOT CalcResult THEN ExprPtr := NIL
  504.       END; (* WHILE *)
  505.       CalcExpression := x
  506.    END (* THEN *)
  507.    ELSE CalcError(0, 'ungueltiger Ausdruck')
  508.  END;
  509.  
  510. END.
  511. (* ----------------------------------------------------------------------- *)
  512. (*                         Ende von CALC.PAS                               *)
  513.