Blame | Last modification | View Log | Download
{.PA}{*******************************************************************}{* SOURCE CODE MODULE: MC-MOD04 *}{* PURPOSE: Evaluate formulas. *}{* Recalculate spread sheet. *}{* *}{* NOTE: This module contains recursive procedures *}{* and is for computer scientists only. *}{*******************************************************************}varForm: Boolean;{$A-}procedure Evaluate(var IsFormula: Boolean; { True if formula}var Formula: AnyString; { Fomula to evaluate}var Value: Real; { Result of formula }var ErrPos: Integer);{ Position of error }constNumbers: set of Char = ['0'..'9'];EofLine = ^M;varPos: Integer; { Current position in formula }Ch: Char; { Current character being scanned }EXY: string[3]; { Intermidiate string for conversion }{ Procedure NextCh returns the next character in the formula }{ The variable Pos contains the position ann Ch the character }procedure NextCh;beginrepeatPos:=Pos+1;if Pos<=Length(Formula) thenCh:=Formula[Pos] else Ch:=eofline;until Ch<>' ';end { NextCh };function Expression: Real;varE: Real;Opr: Char;function SimpleExpression: Real;varS: Real;Opr: Char;function Term: Real;varT: Real;function SignedFactor: Real;function Factor: Real;typeStandardFunction = (fabs,fsqrt,fsqr,fsin,fcos,farctan,fln,flog,fexp,ffact);StandardFunctionList = array[StandardFunction] of string[6];constStandardFunctionNames: StandardFunctionList =('ABS','SQRT','SQR','SIN','COS','ARCTAN','LN','LOG','EXP','FACT');varE,EE,L: Integer; { intermidiate variables }Found:Boolean;F: Real;Sf:StandardFunction;OldEFY, { Current cell }EFY,SumFY,Start:Integer;OldEFX,EFX,SumFX:ScreenIndex;CellSum: Real;function Fact(I: Integer): Real;beginif I > 0 then begin Fact:=I*Fact(I-1); endelse Fact:=1;end { Fact };{.PA}begin { Function Factor }if Ch in Numbers thenbeginStart:=Pos;repeat NextCh until not (Ch in Numbers);if Ch='.' then repeat NextCh until not (Ch in Numbers);if Ch='E' thenbeginNextCh;repeat NextCh until not (Ch in Numbers);end;Val(Copy(Formula,Start,Pos-Start),F,ErrPos);end elseif Ch='(' thenbeginNextCh;F:=Expression;if Ch=')' then NextCh else ErrPos:=Pos;end elseif Ch in ['A'..'G'] then { Maybe a cell reference }beginEFX:=Ch;NextCh;if Ch in Numbers thenbeginF:=0;EXY:=Ch; NextCh;if Ch in Numbers thenbeginEXY:=EXY+Ch;NextCh;end;Val(EXY,EFY,ErrPos);IsFormula:=true;if (Constant in Screen[EFX,EFY].CellStatus) andnot (Calculated in Screen[EFX,EFY].CellStatus) thenbeginEvaluate(Form,screen[EFX,EFY].contents,f,ErrPos);Screen[EFX,EFY].CellStatus:=Screen[EFX,EFY].CellStatus+[Calculated]end else if not (Txt in Screen[EFX,EFY].CellStatus) thenF:=Screen[EFX,EFY].Value;if Ch='>' thenbeginOldEFX:=EFX; OldEFY:=EFY;NextCh;EFX:=Ch;NextCh;if Ch in Numbers thenbeginEXY:=Ch;NextCh;if Ch in Numbers thenbeginEXY:=EXY+Ch;NextCh;end;val(EXY,EFY,ErrPos);Cellsum:=0;for SumFY:=OldEFY to EFY dobeginfor SumFX:=OldEFX to EFX dobeginF:=0;if (Constant in Screen[SumFX,SumFY].CellStatus) andnot (Calculated in Screen[SumFX,SumFY].CellStatus) thenbeginEvaluate(Form,Screen[SumFX,SumFY].contents,f,errPos);Screen[SumFX,SumFY].CellStatus:=Screen[SumFX,SumFY].CellStatus+[Calculated];end else if not (Txt in Screen[SumFX,SumFY].CellStatus) thenF:=ScrEEn[SumFX,SumFY].Value;Cellsum:=Cellsum+f;f:=Cellsum;end;end;end;end;end;end elsebeginfound:=false;for sf:=fabs to ffact doif not found thenbeginl:=Length(StandardFunctionNames[sf]);if copy(Formula,Pos,l)=StandardFunctionNames[sf] thenbeginPos:=Pos+l-1; NextCh;F:=Factor;case sf offabs: f:=abs(f);fsqrt: f:=sqrt(f);fsqr: f:=sqr(f);fsin: f:=sin(f);fcos: f:=cos(f);farctan: f:=arctan(f);fln : f:=ln(f);flog: f:=ln(f)/ln(10);fexp: f:=exp(f);ffact: f:=fact(trunc(f));end;Found:=true;end;end;if not Found then ErrPos:=Pos;end;Factor:=F;end { function Factor};