home *** CD-ROM | disk | FTP | other *** search
- Program MiniCalc;
- {$I-
- Calculator by Christen Fihl 1990,
- Example of use: * P=22/7 ; 2+3 ; p*5 ; sin(pi*45/180)
- * 22/7 ; P ; 2+3
- }
- {------ Type Real=Double; {Choose your own precision (Single/Double/Extended}
-
- Const NextIsError=#1; NextIsValue=#2; NextIsName=#3; NextIsEOF=#4;
-
- Type TStr = String[80];
- TSaved = Array['A'..'Z'] of Real;
-
- Var xx: real;
- Saved: TSaved; {26 Memory cells}
- InputLine: TStr;
- Position,n: Integer; {Position on InputLine}
- ErrPos: Integer;
- LastPos: Integer;
- CmdLine: TStr;
- NextName: TStr; {Returned by Next when Ch=NextIsName}
- NextVal,R: Real; {Value returned by Next when Ch=NextIsVal}
- Ch,LastCh: Char;
-
- procedure Next; {Return Ch:=Last}
- var p,e: integer;
- procedure NextCh;
- begin
- if Position<=Length(InputLine) then inc(Position);
- if Position>Length(InputLine) then Ch:=NextIsEOF
- else Ch:=UpCase(InputLine[Position]);
- end;
- procedure PrevCh;
- begin
- dec(Position)
- end;
-
- begin {procedure Next}
- LastCh:=Ch; LastPos:=Position;
- repeat NextCh until Ch<>' ';
- ErrPos:=Position;
- case Ch of
- '0'..'9','.': {Number}
- begin
- p:=Position;
- repeat NextCh until not (Ch in ['0'..'9','.']);
- if UpCase(Ch)='E' then begin {look for E}
- NextCh;
- if Ch in ['+','-'] then NextCh;
- while Ch in ['0'..'9'] do NextCh;
- end;
- Val(Copy(InputLine,p,Position-p),NextVal,e);
- if e<>0 then begin Position:=p+e-1; Ch:=NextIsError end;
- PrevCh; Ch:=NextIsValue;
- end;
- 'A'..'Z': {Name}
- begin
- NextName:='';
- while (Ch in ['A'..'Z']) do begin NextName:=NextName+Ch; NextCh end;
- PrevCh; Ch:=NextIsName;
- end;
- end;
- end;
-
- function AddExpr: Real; FORWARD;
-
- function Factor: Real;
- function FindAndSkip(What: TStr): Boolean;
- begin
- if NextName=What then begin
- Next; FindAndSkip:=True;
- end else FindAndSkip:=False;
- end;
-
- begin
- case Ch of
- NextIsValue:
- begin
- Factor:=NextVal;
- Next;
- end;
- NextIsName: {SIN(10) or SIN 10}
- begin
- {Add your own here}
- if FindAndSkip('PI') then Factor:=PI else
- if FindAndSkip('SQR') then Factor:=sqr(Factor) else
- if FindAndSkip('SQRT') then Factor:=sqrt(Factor) else
- if FindAndSkip('ABS') then Factor:=abs(Factor) else
- if FindAndSkip('SIN') then Factor:=sin(Factor) else
- if FindAndSkip('COS') then Factor:=cos(Factor) else
- if FindAndSkip('ARCTAN') then Factor:=arctan(Factor) else
- if FindAndSkip('LOG') then Factor:=ln(Factor)/ln(10) else
- if FindAndSkip('LN') then Factor:=ln(Factor) else
- if FindAndSkip('EXP') then Factor:=exp(Factor) else
- if FindAndSkip('MIN') then begin {User defined routine}
- if Saved['X']<Saved['Y'] then Factor:=Saved['X'] {Min(x,y)}
- else Factor:=Saved['Y']
- end else
- if Length(NextName)=1 then begin
- Factor:=Saved[NextName[1]];
- Next;
- end else Ch:=NextIsError
- end;
- '(': {fx X=3+(4*5)}
- begin
- Next;
- Factor:=AddExpr; {recursive call!}
- if Ch<>')' then Ch:=NextIsError
- else Next;
- end;
- else {Error}
- Ch:=NextIsError; Factor:=0;
- end;
- end;
-
- function SignedFactor: Real; {SignedFactor ::= (+|-| ) SignedFactor}
- begin
- case Ch of
- '-': begin Next; SignedFactor:=-SignedFactor; end;
- '+': begin Next; SignedFactor:=+SignedFactor; end;
- else
- SignedFactor:=Factor;
- end;
- end;
-
- function Term: Real; {Term ::= (^| ) SignedFactor}
- var R: Real;
- begin
- R:=SignedFactor;
- while Ch='^' do begin
- Next; R:=exp(ln(R)*SignedFactor);
- end;
- Term:=R;
- end;
-
- function MulExpr: Real; {MulExpr ::= Term (*|/| ) Term}
- var R: Real;
- begin
- R:=Term;
- while Ch in ['*','/'] do begin
- Next;
- case LastCh of
- '*': R:=R*Term;
- '/': R:=R/Term;
- end;
- end;
- MulExpr:=R;
- end;
-
- function AddExpr: Real; {AddExpr ::= MulExpr (+|-| ) MulExpr}
- var R: Real;
- begin
- R:=MulExpr;
- while Ch in ['+','-'] do begin
- Next;
- case LastCh of
- '+': R:=R+MulExpr;
- '-': R:=R-MulExpr;
- end;
- end;
- AddExpr:=R;
- end;
-
- function AssignStmt: Boolean; {AssignStmt ::= ID=AddExpr}
- var ID: Char; Pos2: Integer;
- begin
- AssignStmt:=False;
- if Ch=NextIsName then begin
- Pos2:=LastPos; ID:=NextName[1];
- Next; if Ch='=' then begin
- Next;
- Saved[ID]:=AddExpr;
- AssignStmt:=True;
- end else begin
- Position:=Pos2; Next;
- end;
- end;
- end;
-
- Label Exit;
- begin {Main program}
- FillChar(Saved,SizeOf(Saved),0);
- writeln('MiniCalc');
- repeat
- write('* '); readln(CmdLine); if CmdLine='' then goto Exit;
- repeat
- Position:=Pos(';',CmdLine+';');
- InputLine:=Copy(CmdLine,1,Position-1);
- Delete(CmdLine,1,Position);
- Position:=0; Next;
- if (Ch<>NextIsEOF) then begin
- if not AssignStmt then begin
- R:=AddExpr;
- if Ch=NextIsEOF then begin
- write('= ');
- if abs(R)>1 then {Chose your own format}
- writeln(R:10:5)
- else
- if R=0 then writeln(0) else writeln(R);
- end;
- end;
- if Ch<>NextIsEOF then begin
- writeln(InputLine);
- writeln('^ Error':ErrPos+8);
- end;
- end;
- until (CmdLine='');
- until false;
- Exit:
- end.
-
-