home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug120.arc
/
PASCAL.LBR
/
CALC.PQS
/
CALC.PAS
Wrap
Pascal/Delphi Source File
|
1979-12-31
|
7KB
|
226 lines
program Calc;
(* - A non-recursive parser, using the method of assigning a numerical
- value to each operator,
- based on a program by Scott Magruder, published in Computer Language,
- June 1987.
- revised by Jim Friend, Sydney Microbee Users Group *)
const
STORESIZE = 100;
HOLDSIZE = 80;
DigitWidth: Integer = 18;
Decimals: Integer = 2;
var
Code, LoopCount: Integer;
Format: string[2];
StoredVars: Integer;
FormulaLine: string[80];
VOP: array[1..HOLDSIZE] of Integer;
TEO: array[1..HOLDSIZE] of Char;
StoreName: array[1..STORESIZE] of string[15];
StoreValue: array[1..STORESIZE] of real;
HoldName: array[1..HOLDSIZE] of string[15];
HoldValue: array[1..HOLDSIZE] of real;
Blunder: Boolean;
procedure CheckVar(K: Integer);
var
Found: Boolean;
begin
Found := False;
for LoopCount := 1 to StoredVars do
begin
if HoldName[K] = StoreName[LoopCount] then
begin
Found := True;
if K <> 1 then HoldValue[K] := StoreValue[LoopCount];
end;
end;
if (K = 1) and (not Found) then
begin
Found := True;
StoredVars := StoredVars + 1;
StoreName[StoredVars] := HoldName[K];
StoreValue[StoredVars] := 0.0;
end;
if not Found then
begin
Writeln('Error - Variable ',HoldName[K],' not found.');
Blunder := True;
end;
end;
procedure Assignment;
begin
for LoopCount := 1 to StoredVars do
begin
if HoldName[1] = StoreName[LoopCount] then
StoreValue[LoopCount] := HoldValue[1];
end;
end;
procedure EvaluateTable(var K, L: Integer);
begin
while (TEO[1] <> '<') and (VOP[L] <= VOP[K]) do
begin
case TEO[K] of
'+': HoldValue[K - 1] := HoldValue[K - 1] + HoldValue[K];
'-': HoldValue[K - 1] := HoldValue[K - 1] - HoldValue[K];
'*': HoldValue[K - 1] := HoldValue[K - 1] * HoldValue[K];
'/': begin
if HoldValue[K] <> 0 then
HoldValue[K - 1] := HoldValue[K - 1] / HoldValue[K]
else
begin
Writeln('Division by zero error.');
Blunder := True;
end;
end;
'^': HoldValue[K - 1] := Exp(HoldValue[K] * Ln(HoldValue[K - 1]));
'=': HoldValue[K - 1] := HoldValue[K];
'E': HoldValue[K - 1] := Exp(HoldValue[K]);
'~': HoldValue[K - 1] := -1 * HoldValue[K];
end;
VOP[K] := VOP[K + 1];
TEO[K] := TEO[K + 1];
K := K - 1;
L := K + 1;
if L <> 1 then HoldName[L] := '';
if L <> 1 then HoldValue[L] := 0.0;
end;
end;
function Unary(J, K: Integer): Boolean;
begin
repeat
J := J - 1
until FormulaLine[J] in ['A'..'Z', 'a'..'z', '0'..'9', '+', '-',
'*', '/', '^', '~', '='];
Unary := (FormulaLine[J] in ['+', '-', '*', '/', '^', '~', '=']) or
(TEO[K] = 'E');
end;
procedure ScanLine;
var
Found: Boolean;
TempName: string[15];
K, L, IncPar, I, Code: Integer;
begin
for K := 1 to HOLDSIZE do HoldName[K] := '';
for K := 1 to HOLDSIZE do VOP[K] := 0;
K := 1;
IncPar := 0;
for I := 1 to Length(FormulaLine) do
begin
L := K + 1;
if FormulaLine[I] = '<' then
VOP[L] := IncPar;
if FormulaLine[I] = '-' then
if Unary(I, K) then
FormulaLine[I] := '~';
if (FormulaLine[I] = '+') or (FormulaLine[I] = '-') then
VOP[L] := 2 + IncPar;
if FormulaLine[I] = '=' then
VOP[L] := 1 + IncPar;
if FormulaLine[I] = '^' then
VOP[L] := 5 + IncPar;
if FormulaLine[I] = '~' then
VOP[L] := 200 + IncPar;
if (FormulaLine[I] = '*') or (FormulaLine[I] = '/') then
VOP[L] := 3 + IncPar;
if FormulaLine[I] = '(' then
begin
IncPar := IncPar + 10;
Found := False;
if HoldName[K] = 'EXP' then Found := True;
if Found then
begin
VOP[L] := 100 + IncPar;
TEO[L] := 'E';
K := K + 1;
L := K + 1;
end;
end;
if FormulaLine[I] = ')' then
IncPar := IncPar - 10;
if FormulaLine[I] in ['A'..'Z', 'a'..'z', '0'..'9', '.', '~'] then
HoldName[K] := HoldName[K] + UpCase(FormulaLine[I]);
if FormulaLine[I] in ['+', '-', '=', '*', '/', '^', '<', '~'] then
begin
TEO[L] := FormulaLine[I];
TempName := HoldName[K];
if TempName[1] in ['0'..'9'] then
begin
if HoldValue[K] = 0 then
Val(HoldName[K], HoldValue[K], Code);
if Code <> 0 then
begin
Writeln('Error in converting string to number.');
Blunder := True;
end;
end;
if TempName[1] in ['A'..'Z', 'a'..'z'] then CheckVar(K);
EvaluateTable(K, L);
K := K + 1;
end;
if FormulaLine[I] = '<' then
begin
VOP[L] := IncPar;
if VOP[L] > 0 then Writeln('Error - expected ) not found.');
if VOP[L] < 0 then Writeln('Error - too many )s.');
if VOP[L] <> 0 then Blunder := True;
end;
end;
end;
begin
ClrScr;
Writeln('CALCULATOR': 45);
Writeln;
Writeln('Usage: enter name of formula result, then =, then formula.');
Writeln('Terminate program by entering "\".');
Writeln;
Writeln('Default output is fixed point with 2 digits after decimal point.');
Writeln('Enter RETURN for default, S for scientific format, number of');
Write('digits for fixed point: ');
Readln(Format);
if Format = '' then
Decimals := 2
else
if UpCase(Format[1]) = 'S' then
Decimals := -1
else
begin
Val(Format, Decimals, Code);
if Code <> 0 then Decimals := 2;
end;
Writeln;
Writeln;
StoredVars := 0;
repeat
Blunder := False;
for LoopCount := 1 to HOLDSIZE do
begin
HoldName[LoopCount] := '';
HoldValue[LoopCount] := 0.0;
end;
TEO[1] := '>';
Write('Enter formula: ');
FormulaLine := '';
Readln(FormulaLine);
FormulaLine := FormulaLine + '<';
ScanLine;
if not Blunder then
begin
Assignment;
for LoopCount := 1 to StoredVars do
Writeln(StoreName[LoopCount]: 15,
': Value ', StoreValue[LoopCount]: DigitWidth: Decimals);
end;
until FormulaLine[1] = '\';
end.