home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / setl2 / calc.stl < prev    next >
Text File  |  1991-11-16  |  5KB  |  227 lines

  1. --
  2. --  CALCULATOR
  3. --  ==========
  4. --
  5. --  This is a simple five function calculator.  It handles valid SETL2
  6. --  expressions made up of +, -, *, /, and **.  The error handling is
  7. --  rather crude.
  8. --
  9.  
  10. program Calculator;
  11.  
  12.    var Operator_Info;
  13.  
  14.    --
  15.    -- Operator information map.  The general form is
  16.    --
  17.    --     [operator, [in-stack-priority,in-coming-priority,handler]]
  18.    --
  19.  
  20.    Operator_Info := {["(",[0,4,om]],
  21.                      [")",[om,om,om]],
  22.                      ["+",[1,1,Binop_Plus]],
  23.                      ["-",[1,1,Binop_Minus]],
  24.                      ["*",[2,2,Binop_Times]],
  25.                      ["/",[2,2,Binop_Divide]],
  26.                      ["**",[3,4,Binop_Power]]};
  27.  
  28.    --
  29.    --  main loop -- get a line, find the result, print it
  30.    --
  31.  
  32.    while true loop
  33.  
  34.       get(Input_Line);
  35.  
  36.       if eof() then 
  37.          exit;
  38.       end if;
  39.  
  40.       print(Input_Line," = ",Solve(Input_Line));
  41.  
  42.    end loop;
  43.  
  44.    --
  45.    --  Solve
  46.    --  -----
  47.    --
  48.    --  This procedure accepts a character string containing an
  49.    --  expression, evaluates it, and returns the result.
  50.    --
  51.  
  52.    procedure Solve(Input_Line);
  53.  
  54.       Work_Line := Input_Line;
  55.       Operand_Stack := [];
  56.       Operator_Stack := [];
  57.  
  58.       while #Work_Line > 0 loop
  59.  
  60.          -- skip white space
  61.  
  62.          span(Work_Line,""+/[char(i) : i in [0 .. abs(" ")]]);
  63.  
  64.          -- pick off the next operand
  65.  
  66.          if Work_Line(1) in {str(i) : i in [0 .. 9]}+{"{","[","\""} then
  67.  
  68.             reads(Work_Line,Token);
  69.             Operand_Stack with:= Token;
  70.             continue;
  71.  
  72.          end if;
  73.          
  74.          -- we didn't find an operand, we had better find an operator
  75.  
  76.          Token := "";
  77.          
  78.          while #Work_Line > 0 and
  79.                Operator_Info(Token+Work_Line(1)) /= om loop
  80.             Token +:= throwaway fromb Work_Line;
  81.          end loop;
  82.  
  83.          if Operator_Info(Token) = om then
  84.             print("Invalid operator => ",Token);
  85.             stop;
  86.          end if;
  87.        
  88.          --
  89.          --  when we find a closing parenthesis, we evaluate until we
  90.          --  find the corresponding opening parentheses
  91.          --
  92.  
  93.          if Token = ")" then
  94.  
  95.             while #Operator_Stack > 0 and
  96.                   Operator_Stack(#Operator_Stack) /= "(" loop
  97.  
  98.                Operator frome Operator_Stack;
  99.  
  100.                if #Operand_Stack < 2 then
  101.                   print("Invalid expression");  
  102.                   stop;
  103.                end if;
  104.  
  105.                right frome Operand_Stack;
  106.                left frome Operand_Stack;
  107.  
  108.                Operand_Stack with :=
  109.                   Operator_Info(Operator)(3)(left,right);
  110.  
  111.             end loop;
  112.  
  113.             if #Operator_Stack = 0 then
  114.                print("Invalid expression");  
  115.                stop;
  116.             end if;
  117.  
  118.             Operator frome Operator_Stack;
  119.             continue;
  120.  
  121.          end if;
  122.           
  123.          --
  124.          --  we evaluate while the stack priority of the top operator is
  125.          --  greater than the incoming operator
  126.          --
  127.  
  128.          while #Operator_Stack > 0 loop
  129.  
  130.             Operator frome Operator_Stack;
  131.  
  132.             if Operator_Info(Operator)(1) >= Operator_Info(Token)(2) then
  133.  
  134.                if #Operand_Stack < 2 then
  135.                   print("Invalid expression");  
  136.                   stop;
  137.                end if;
  138.  
  139.                right frome Operand_Stack;
  140.                left frome Operand_Stack;
  141.  
  142.                Operand_Stack with :=
  143.                   Operator_Info(Operator)(3)(left,right);
  144.  
  145.             else
  146.  
  147.                Operator_Stack with:= Operator;
  148.                exit;
  149.  
  150.             end if;
  151.  
  152.          end loop;
  153.  
  154.          Operator_Stack with:= Token;
  155.  
  156.       end loop;
  157.  
  158.       --
  159.       --  we've exhausted the input string, evaluate any remaining
  160.       --  operators
  161.       --
  162.  
  163.       while #Operator_Stack > 0 loop
  164.  
  165.          Operator frome Operator_Stack;
  166.  
  167.          if Operator = "(" then
  168.             print("Invalid expression");  
  169.             stop;
  170.          end if;
  171.  
  172.          if #Operand_Stack < 2 then
  173.             print("Invalid expression");  
  174.             stop;
  175.          end if;
  176.  
  177.          right frome Operand_Stack;
  178.          left frome Operand_Stack;
  179.  
  180.          Operand_Stack with :=
  181.             Operator_Info(Operator)(3)(left,right);
  182.  
  183.       end loop;
  184.  
  185.       if #Operand_Stack /= 1 then
  186.          print("Invalid expression");  
  187.          stop;
  188.       end if;
  189.  
  190.       --
  191.       --  the result is on the top of the operand stack
  192.       --
  193.  
  194.       return Operand_Stack(1);
  195.  
  196.    end Solve;
  197.    
  198.    --
  199.    --  Operator Procedures
  200.    --  -------------------
  201.    --
  202.    --  The following simple procedures just implement the primitive
  203.    --  functions of the calculator.
  204.    --
  205.  
  206.    procedure Binop_Plus(left,right);
  207.       return left + right;
  208.    end Binop_Plus;
  209.  
  210.    procedure Binop_Minus(left,right);
  211.       return left - right;
  212.    end Binop_Minus;
  213.  
  214.    procedure Binop_Times(left,right);
  215.       return left * right;
  216.    end Binop_Times;
  217.  
  218.    procedure Binop_Divide(left,right);
  219.       return left / right;
  220.    end Binop_Divide;
  221.  
  222.    procedure Binop_Power(left,right);
  223.       return left ** right;
  224.    end Binop_Power;
  225.  
  226. end Calculator;
  227.