home *** CD-ROM | disk | FTP | other *** search
/ norge.freeshell.org (192.94.73.8) / 192.94.73.8.tar / 192.94.73.8 / pub / computers / cpm / alphatronic / TP_301A.ZIP / mc-mod04.inc < prev    next >
Text File  |  1985-01-01  |  9KB  |  294 lines

  1. {.PA}
  2. {*******************************************************************}
  3. {*  SOURCE CODE MODULE: MC-MOD04                                   *}
  4. {*  PURPOSE:            Evaluate formulas.                         *}
  5. {*                      Recalculate spread sheet.                  *}
  6. {*                                                                 *}
  7. {*  NOTE:               This module contains recursive procedures  *}
  8. {*                      and is for computer scientists only.       *}
  9. {*******************************************************************}
  10.  
  11. var
  12.   Form: Boolean;
  13.  
  14. {$A-}
  15. procedure Evaluate(var IsFormula: Boolean; { True if formula}
  16.                    var Formula: AnyString; { Fomula to evaluate}
  17.                    var Value: Real;  { Result of formula }
  18.                    var ErrPos: Integer);{ Position of error }
  19. const
  20.   Numbers: set of Char = ['0'..'9'];
  21.   EofLine  = ^M;
  22.  
  23. var
  24.   Pos: Integer;    { Current position in formula                     }
  25.   Ch: Char;        { Current character being scanned                 }
  26.   EXY: string[3];  { Intermidiate string for conversion              }
  27.  
  28. { Procedure NextCh returns the next character in the formula         }
  29. { The variable Pos contains the position ann Ch the character        }
  30.  
  31.   procedure NextCh;
  32.   begin
  33.     repeat
  34.       Pos:=Pos+1;
  35.       if Pos<=Length(Formula) then
  36.       Ch:=Formula[Pos] else Ch:=eofline;
  37.     until Ch<>' ';
  38.   end  { NextCh };
  39.  
  40.  
  41.   function Expression: Real;
  42.   var
  43.     E: Real;
  44.     Opr: Char;
  45.  
  46.     function SimpleExpression: Real;
  47.     var
  48.       S: Real;
  49.       Opr: Char;
  50.  
  51.       function Term: Real;
  52.       var
  53.         T: Real;
  54.  
  55.         function SignedFactor: Real;
  56.  
  57.           function Factor: Real;
  58.           type
  59.             StandardFunction = (fabs,fsqrt,fsqr,fsin,fcos,
  60.             farctan,fln,flog,fexp,ffact);
  61.             StandardFunctionList = array[StandardFunction] of string[6];
  62.  
  63.           const
  64.             StandardFunctionNames: StandardFunctionList =('ABS','SQRT','SQR','SIN','COS',
  65.                                                           'ARCTAN','LN','LOG','EXP','FACT');
  66.           var
  67.             E,EE,L:  Integer;       { intermidiate variables }
  68.             Found:Boolean;
  69.             F: Real;
  70.             Sf:StandardFunction;
  71.             OldEFY,                 { Current cell  }
  72.             EFY,
  73.             SumFY,
  74.             Start:Integer;
  75.             OldEFX,
  76.             EFX,
  77.             SumFX:ScreenIndex;
  78.             CellSum: Real;
  79.  
  80.               function Fact(I: Integer): Real;
  81.               begin
  82.                 if I > 0 then begin Fact:=I*Fact(I-1); end
  83.                 else Fact:=1;
  84.               end  { Fact };
  85.  
  86. {.PA}
  87.           begin { Function Factor }
  88.             if Ch in Numbers then
  89.             begin
  90.               Start:=Pos;
  91.               repeat NextCh until not (Ch in Numbers);
  92.               if Ch='.' then repeat NextCh until not (Ch in Numbers);
  93.               if Ch='E' then
  94.               begin
  95.                 NextCh;
  96.                 repeat NextCh until not (Ch in Numbers);
  97.               end;
  98.               Val(Copy(Formula,Start,Pos-Start),F,ErrPos);
  99.             end else
  100.             if Ch='(' then
  101.             begin
  102.               NextCh;
  103.               F:=Expression;
  104.               if Ch=')' then NextCh else ErrPos:=Pos;
  105.             end else
  106.             if Ch in ['A'..'G'] then { Maybe a cell reference }
  107.             begin
  108.               EFX:=Ch;
  109.               NextCh;
  110.               if Ch in Numbers then
  111.               begin
  112.                 F:=0;
  113.                 EXY:=Ch; NextCh;
  114.                 if Ch in Numbers then
  115.                 begin
  116.                   EXY:=EXY+Ch;
  117.                   NextCh;
  118.                 end;
  119.                 Val(EXY,EFY,ErrPos);
  120.                 IsFormula:=true;
  121.                 if (Constant in Screen[EFX,EFY].CellStatus) and
  122.                 not (Calculated in Screen[EFX,EFY].CellStatus) then
  123.                 begin
  124.                   Evaluate(Form,screen[EFX,EFY].contents,f,ErrPos);
  125.                   Screen[EFX,EFY].CellStatus:=Screen[EFX,EFY].CellStatus+[Calculated]
  126.                 end else if not (Txt in Screen[EFX,EFY].CellStatus) then
  127.                 F:=Screen[EFX,EFY].Value;
  128.                 if Ch='>' then
  129.                 begin
  130.                   OldEFX:=EFX; OldEFY:=EFY;
  131.                   NextCh;
  132.                   EFX:=Ch;
  133.                   NextCh;
  134.                   if Ch in Numbers then
  135.                   begin
  136.                     EXY:=Ch;
  137.                     NextCh;
  138.                     if Ch in Numbers then
  139.                     begin
  140.                       EXY:=EXY+Ch;
  141.                       NextCh;
  142.                     end;
  143.                     val(EXY,EFY,ErrPos);
  144.                     Cellsum:=0;
  145.                     for SumFY:=OldEFY to EFY do
  146.                     begin
  147.                       for SumFX:=OldEFX to EFX do
  148.                       begin
  149.                         F:=0;
  150.                         if (Constant in Screen[SumFX,SumFY].CellStatus) and
  151.                         not (Calculated in Screen[SumFX,SumFY].CellStatus) then
  152.                         begin
  153.                           Evaluate(Form,Screen[SumFX,SumFY].contents,f,errPos);
  154.                           Screen[SumFX,SumFY].CellStatus:=
  155.                           Screen[SumFX,SumFY].CellStatus+[Calculated];
  156.                         end else if not (Txt in Screen[SumFX,SumFY].CellStatus) then
  157.                         F:=ScrEEn[SumFX,SumFY].Value;
  158.                         Cellsum:=Cellsum+f;
  159.                         f:=Cellsum;
  160.                       end;
  161.                     end;
  162.                   end;
  163.                 end;
  164.               end;
  165.             end else
  166.             begin
  167.               found:=false;
  168.               for sf:=fabs to ffact do
  169.               if not found then
  170.               begin
  171.                 l:=Length(StandardFunctionNames[sf]);
  172.                 if copy(Formula,Pos,l)=StandardFunctionNames[sf] then
  173.                 begin
  174.                   Pos:=Pos+l-1; NextCh;
  175.                   F:=Factor;
  176.                   case sf of
  177.                     fabs:     f:=abs(f);
  178.                     fsqrt:    f:=sqrt(f);
  179.                     fsqr:     f:=sqr(f);
  180.                     fsin:     f:=sin(f);
  181.                     fcos:     f:=cos(f);
  182.                     farctan:  f:=arctan(f);
  183.                     fln :     f:=ln(f);
  184.                     flog:     f:=ln(f)/ln(10);
  185.                     fexp:     f:=exp(f);
  186.                     ffact:    f:=fact(trunc(f));
  187.                   end;
  188.                   Found:=true;
  189.                 end;
  190.               end;
  191.               if not Found then ErrPos:=Pos;
  192.             end;
  193.             Factor:=F;
  194.           end { function Factor};
  195. {.PA}
  196.  
  197.         begin { SignedFactor }
  198.           if Ch='-' then
  199.           begin
  200.             NextCh; SignedFactor:=-Factor;
  201.           end else SignedFactor:=Factor;
  202.         end { SignedFactor };
  203.  
  204.       begin { Term }
  205.         T:=SignedFactor;
  206.         while Ch='^' do
  207.         begin
  208.           NextCh; t:=exp(ln(t)*SignedFactor);
  209.         end;
  210.         Term:=t;
  211.       end { Term };
  212.  
  213.  
  214.     begin { SimpleExpression }
  215.       s:=term;
  216.       while Ch in ['*','/'] do
  217.       begin
  218.         Opr:=Ch; NextCh;
  219.         case Opr of
  220.           '*': s:=s*term;
  221.           '/': s:=s/term;
  222.         end;
  223.       end;
  224.       SimpleExpression:=s;
  225.     end { SimpleExpression };
  226.  
  227.   begin { Expression }
  228.     E:=SimpleExpression;
  229.     while Ch in ['+','-'] do
  230.     begin
  231.       Opr:=Ch; NextCh;
  232.       case Opr of
  233.         '+': e:=e+SimpleExpression;
  234.         '-': e:=e-SimpleExpression;
  235.       end;
  236.     end;
  237.     Expression:=E;
  238.   end { Expression };
  239.  
  240.  
  241. begin { procedure Evaluate }
  242.   if Formula[1]='.' then Formula:='0'+Formula;
  243.   if Formula[1]='+' then delete(Formula,1,1);
  244.   IsFormula:=false;
  245.   Pos:=0; NextCh;
  246.   Value:=Expression;
  247.   if Ch=EofLine then ErrPos:=0 else ErrPos:=Pos;
  248. end { Evaluate };
  249.  
  250. {.PA}
  251.  
  252. procedure Recalculate;
  253. var
  254.   RFX: ScreenIndex;
  255.   RFY:integer;
  256.   OldValue: real;
  257.   Err: integer;
  258.  
  259. begin
  260.   LowVideo;
  261.   GotoXY(1,24); ClrEol;
  262.   Write('Calculating..');
  263.   for RFY:=1 to FYMax do
  264.   begin
  265.     for RFX:='A' to FXMax do
  266.     begin
  267.       with Screen[RFX,RFY] do
  268.       begin
  269.         if (Formula in CellStatus) then
  270.         begin
  271.           CellStatus:=CellStatus+[Calculated];
  272.           OldValue:=Value;
  273.           Evaluate(Form,Contents,Value,Err);
  274.           if OldValue<>Value then
  275.           begin
  276.             GotoXY(XPos[RFX],RFY+1);
  277.             if (DEC>=0) then Write(Value:FW:DEC)
  278.             else Write(Value:FW);
  279.           end;
  280.         end;
  281.       end;
  282.     end;
  283.   end;
  284.   GotoCell(FX,FY);
  285. end;
  286. FW);
  287.           end;
  288.         end;
  289.       end;
  290.     end;
  291.   end;
  292.   GotoCell(FX,FY);
  293. end;
  294.