235 lines
4.6 KiB
ObjectPascal
235 lines
4.6 KiB
ObjectPascal
program TruthTables;
|
|
const
|
|
StackSize = 80;
|
|
|
|
type
|
|
TVariable = record
|
|
Name: Char;
|
|
Value: Boolean;
|
|
end;
|
|
|
|
TStackOfBool = record
|
|
Top: Integer;
|
|
Elements: array [0 .. StackSize - 1] of Boolean;
|
|
end;
|
|
|
|
var
|
|
Expression: string;
|
|
Variables: array [0 .. 23] of TVariable;
|
|
VariablesLength: Integer;
|
|
i: Integer;
|
|
e: Char;
|
|
|
|
// Stack manipulation functions
|
|
function IsFull(var s: TStackOfBool): Boolean;
|
|
begin
|
|
IsFull := s.Top = StackSize - 1;
|
|
end;
|
|
|
|
function IsEmpty(var s: TStackOfBool): Boolean;
|
|
begin
|
|
IsEmpty := s.Top = -1;
|
|
end;
|
|
|
|
function Peek(var s: TStackOfBool): Boolean;
|
|
begin
|
|
if not IsEmpty(s) then
|
|
Peek := s.Elements[s.Top]
|
|
else
|
|
begin
|
|
Writeln('Stack is empty.');
|
|
Halt;
|
|
end;
|
|
end;
|
|
|
|
procedure Push(var s: TStackOfBool; val: Boolean);
|
|
begin
|
|
if not IsFull(s) then
|
|
begin
|
|
Inc(s.Top);
|
|
s.Elements[s.Top] := val;
|
|
end
|
|
else
|
|
begin
|
|
Writeln('Stack is full.');
|
|
Halt;
|
|
end
|
|
end;
|
|
|
|
function Pop(var s: TStackOfBool): Boolean;
|
|
begin
|
|
if not IsEmpty(s) then
|
|
begin
|
|
Result := s.Elements[s.Top];
|
|
Dec(s.Top);
|
|
end
|
|
else
|
|
begin
|
|
Writeln;
|
|
Writeln('Stack is empty.');
|
|
Halt;
|
|
end
|
|
end;
|
|
|
|
procedure MakeEmpty(var s: TStackOfBool);
|
|
begin
|
|
s.Top := -1;
|
|
end;
|
|
|
|
function ElementsCount(var s: TStackOfBool): Integer;
|
|
begin
|
|
ElementsCount := s.Top + 1;
|
|
end;
|
|
|
|
function IsOperator(const c: Char): Boolean;
|
|
begin
|
|
IsOperator := (c = '&') or (c = '|') or (c = '!') or (c = '^');
|
|
end;
|
|
|
|
function VariableIndex(const c: Char): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to VariablesLength - 1 do
|
|
if Variables[i].Name = c then
|
|
begin
|
|
VariableIndex := i;
|
|
Exit;
|
|
end;
|
|
VariableIndex := -1;
|
|
end;
|
|
|
|
function EvaluateExpression: Boolean;
|
|
var
|
|
i, vi: Integer;
|
|
e: Char;
|
|
s: TStackOfBool;
|
|
begin
|
|
MakeEmpty(s);
|
|
for i := 1 to Length(Expression) do
|
|
begin
|
|
e := Expression[i];
|
|
vi := VariableIndex(e);
|
|
if e = 'T' then
|
|
Push(s, True)
|
|
else if e = 'F' then
|
|
Push(s, False)
|
|
else if vi >= 0 then
|
|
Push(s, Variables[vi].Value)
|
|
else
|
|
begin
|
|
{$B+}
|
|
case e of
|
|
'&':
|
|
Push(s, Pop(s) and Pop(s));
|
|
'|':
|
|
Push(s, Pop(s) or Pop(s));
|
|
'!':
|
|
Push(s, not Pop(s));
|
|
'^':
|
|
Push(s, Pop(s) xor Pop(s));
|
|
else
|
|
Writeln;
|
|
Writeln('Non-conformant character ', e, ' in expression.');
|
|
Halt;
|
|
end;
|
|
{$B-}
|
|
end;
|
|
end;
|
|
if ElementsCount(s) <> 1 then
|
|
begin
|
|
Writeln;
|
|
Writeln('Stack should contain exactly one element.');
|
|
Halt;
|
|
end;
|
|
EvaluateExpression := Peek(s);
|
|
end;
|
|
|
|
procedure SetVariables(pos: Integer);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if pos > VariablesLength then
|
|
begin
|
|
Writeln;
|
|
Writeln('Argument to SetVariables cannot be greater than the number of variables.');
|
|
Halt;
|
|
end
|
|
else if pos = VariablesLength then
|
|
begin
|
|
for i := 0 to VariablesLength - 1 do
|
|
begin
|
|
if Variables[i].Value then
|
|
Write('T ')
|
|
else
|
|
Write('F ');
|
|
end;
|
|
if EvaluateExpression then
|
|
Writeln('T')
|
|
else
|
|
Writeln('F');
|
|
end
|
|
else
|
|
begin
|
|
Variables[pos].Value := False;
|
|
SetVariables(pos + 1);
|
|
Variables[pos].Value := True;
|
|
SetVariables(pos + 1);
|
|
end
|
|
end;
|
|
|
|
// removes space and converts to upper case
|
|
procedure ProcessExpression;
|
|
var
|
|
i: Integer;
|
|
exprTmp: string;
|
|
begin
|
|
exprTmp := '';
|
|
for i := 1 to Length(Expression) do
|
|
begin
|
|
if Expression[i] <> ' ' then
|
|
exprTmp := Concat(exprTmp, UpCase(Expression[i]));
|
|
end;
|
|
Expression := exprTmp
|
|
end;
|
|
|
|
begin
|
|
Writeln('Accepts single-character variables (except for ''T'' and ''F'',');
|
|
Writeln('which specify explicit true or false values), postfix, with');
|
|
Writeln('&|!^ for and, or, not, xor, respectively; optionally');
|
|
Writeln('seperated by space. Just enter nothing to quit.');
|
|
|
|
while (True) do
|
|
begin
|
|
Writeln;
|
|
Write('Boolean expression: ');
|
|
ReadLn(Expression);
|
|
ProcessExpression;
|
|
if Length(Expression) = 0 then
|
|
Break;
|
|
VariablesLength := 0;
|
|
for i := 1 to Length(Expression) do
|
|
begin
|
|
e := Expression[i];
|
|
if (not IsOperator(e)) and (e <> 'T') and (e <> 'F') and
|
|
(VariableIndex(e) = -1) then
|
|
begin
|
|
Variables[VariablesLength].Name := e;
|
|
Variables[VariablesLength].Value := False;
|
|
Inc(VariablesLength);
|
|
end;
|
|
end;
|
|
WriteLn;
|
|
if VariablesLength = 0 then
|
|
Writeln('No variables were entered.')
|
|
else
|
|
begin
|
|
for i := 0 to VariablesLength - 1 do
|
|
Write(Variables[i].Name, ' ');
|
|
Writeln(Expression);
|
|
Writeln(StringOfChar('=', VariablesLength * 3 + Length(Expression)));
|
|
SetVariables(0);
|
|
end;
|
|
end;
|
|
end.
|