home *** CD-ROM | disk | FTP | other *** search
/ Vectronix 2 / VECTRONIX2.iso / FILES_01 / HISPEED2.LZH / MYCALC / RPN.PAS < prev   
Pascal/Delphi Source File  |  1991-07-02  |  5KB  |  192 lines

  1. {-------------------------------------------------------------------------
  2.                    HighSpeed Pascal GEM accessory demo
  3.  
  4.                     RPN (Reverse Polish Notation) UNIT
  5.  
  6.                       Copyright (c) 1990 by D-House I
  7.                             All rights reserved
  8.  
  9.                       Programmed by Martin Eskildsen
  10. -------------------------------------------------------------------------}
  11. {$R-,S-,D+,F-}
  12.  
  13. unit RPN;
  14.  
  15. INTERFACE
  16.  
  17. const
  18.   width         = 17;           { output field width:digits     }
  19.   digits        =  5;
  20.   CR            = #13;          { Carriage Return               }
  21.   BS            = #08;          { BackSpace                     }
  22.  
  23. type
  24.   real          = extended;     { define calculator precision   }
  25.  
  26. var
  27.   error         : integer;              { error code            }
  28.   inputstring   : string [width];       { input string          }
  29.  
  30. { Enter a char in the input string or react if the char is a command
  31.   such as '+', '-', CR etc. }
  32. procedure CharInput(ch : char);
  33.  
  34. { Return the value of the top of the stack (x register) }
  35. function TopOfStack : real;
  36.  
  37. IMPLEMENTATION
  38.  
  39. type
  40.   stacktype     = record                { this is our stack     }
  41.                     x, y, z, t : real   { structure : four regi-}
  42.                   end;                  { sters                 }
  43.  
  44. var
  45.   stack         : stacktype;            { the stack             }
  46.   lift          : boolean;              { allow pushes if true  }
  47.  
  48. function TopOfStack : real;
  49. begin
  50.   TopOfStack := stack.x
  51. end;
  52.  
  53. { Return the value of the x register, and move the y and z registers up :
  54.     x -> return value
  55.     y -> x
  56.     z -> y
  57.     t    is left alone
  58. }
  59. function Pop : real;
  60. begin
  61.   with stack do begin
  62.     Pop := x;
  63.     x   := y;
  64.     y   := z;
  65.     z   := t
  66.   end
  67. end;
  68.  
  69. { Push a value onto the stack :
  70.       z -> t
  71.       y -> z
  72.       x -> y
  73.   value -> x
  74. }
  75. procedure Push(n : real);
  76. begin
  77.   with stack do begin
  78.     t := z;
  79.     z := y;
  80.     y := x;
  81.     x := n
  82.   end
  83. end;
  84.  
  85. { Swap the x and y registers, and enable stack lift }
  86. procedure SwapXY;
  87. var temp : real;
  88. begin
  89.   lift    := TRUE;
  90.   temp    := stack.x;
  91.   stack.x := stack.y;
  92.   stack.y := temp
  93. end;
  94.  
  95. { Add the x and y register }
  96. procedure Add;
  97. begin
  98.   Push(Pop + Pop)  { first pop gets x reg, second pop gets y reg }
  99. end;
  100.  
  101. { Push(y - x) }
  102. procedure Sub;
  103. begin
  104.   Push(-Pop + Pop)
  105. end;
  106.  
  107. { Push(x * y) }
  108. procedure Mult;
  109. begin
  110.   Push(Pop * Pop)
  111. end;
  112.  
  113. { Push(y / x) if x <> 0.0. Otherwise return error 1 }
  114. procedure Divide;
  115. var n : real;
  116. begin
  117.   n := Pop;
  118.   if n = 0.0 then begin
  119.     Push(n);
  120.     Error := 0
  121.   end
  122.   else Push(Pop / n)
  123. end;
  124.  
  125. { Insert a character in the input string, or execute command }
  126. procedure CharInput(ch : char);
  127.  
  128.   { Add the char to the input string, provided it's not full }
  129.   procedure AddCh;
  130.   begin
  131.     if length(InputString) < width then InputString := InputString + ch
  132.   end;
  133.  
  134.   { If the input string is empty, the x register is duplicated (pushed),
  135.     otherwise the value formed by the string is evaluated and put on the
  136.     stack
  137.   }
  138.   procedure MakeValue;
  139.   var
  140.     value  : real;
  141.     errpos : integer;
  142.   begin
  143.     if InputString = '' then Push(stack.x)      { duplicate }
  144.     else begin
  145.       val(InputString, value, errpos);
  146.       if errpos <> 0 then error := 1    { error 1 should never occur }
  147.       else begin
  148.         if lift then Push(value) else stack.x := value;
  149.         lift := ch <> CR;
  150.         if not lift then Push(value)
  151.       end;
  152.       InputString := ''
  153.     end
  154.   end;
  155.  
  156. begin { CharInput }
  157.   error := -1;
  158.   case ch of
  159.     '0'..'9' : AddCh;
  160.     '.'      : if pos('.', inputString) = 0 then AddCh;
  161.     CR       : MakeValue;
  162.     BS       : if length(inputString) > 0
  163.                then delete(inputString, Length(InputString), 1)
  164.                else begin
  165.                  stack.x := 0.0;        { clear x reg if input string }
  166.                  lift := FALSE          { was empty, else delete char }
  167.                end
  168.   else
  169.     if InputString <> '' then MakeValue;
  170.     case ch of
  171.       '('      : push(-Pop);    { sign inversion }
  172.       ')'      : SwapXY;
  173.       '+'      : Add;
  174.       '-'      : Sub;
  175.       '*'      : Mult;
  176.       '/'      : Divide
  177.     end
  178.   end
  179. end;
  180.  
  181. begin { of unit }
  182.   InputString := '';
  183.   error := -1;
  184.   lift  := FALSE;
  185.   with stack do begin
  186.     x := 0.0;
  187.     y := 0.0;
  188.     z := 0.0;
  189.     t := 0.0
  190.   end
  191. end.
  192.