|
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"式の解釈と計算(2/2)"
300行を超えたので分割しました。
--------------------------------------------------------------------------
// 式のコンパイル
procedure Expression;
var k: String;
begin
k := token;
if (k = '+') or (k = '-') or
(k = 'NOT') or (k = 'LOW') or (k = 'HIGH') then
begin
token := NextToken;
Term;
if k = '-' then WorkList.Add('NEG_')
else
if k = 'NOT' then WorkList.Add('NOT_')
else
if k = 'LOW' then WorkList.Add('LOW_')
else
if k = 'HIGH' then WorkList.Add('HIGH');
end
else Term;
k := token;
while (k = '+') or (k = '-') do
begin
token := NextToken;
Term;
if k = '-' then WorkList.Add('SUB_')
else
if k = '+' then WorkList.Add('ADD_');
k := token;
end;
end;
// トークンの取得
// 文字列を空白又はタブをデリミタとして分解しトークンリストに入れる
procedure GetToken(s: String; str: TStringList);
var tmp, strbuf: String;
begin
tmp := '';
s := AnsiUpperCase(s);
repeat
s := Trim(s);
strbuf := s[1]; tmp := tmp+strbuf; Delete(s, 1, 1);
if (strbuf = '+') or (strbuf = '-') or (strbuf = '*') or
(strbuf = '/') or (strbuf = '(') or (strbuf = ')') then
begin
if Length(tmp) > 1 then str.Add(Copy(tmp, 1, Length(tmp)-1));
str.Add(strbuf);
tmp := '';
end
else
if (s <> '') and
((s[1] = ' ') or (s[1] = #9)) then
begin
str.Add(tmp);
tmp := '';
end;
until s = '';
if tmp <> '' then str.Add(tmp);
end;
// 式の計算
function Calculation: Boolean;
var i, temp: Integer; Key: String;
begin
Result := True;
for i := 0 to WorkList.Count-1 do
begin
Key := WorkList[i];
if IsNumber('$'+Key) then Push(Key)
else
if Key = 'ADD_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(temp+HexToInt(Pop), 4));
end
else
if Key = 'SUB_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop)-temp, 4));
end
else
if Key = 'MUL_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(temp*HexToInt(Pop), 4));
end
else
if Key = 'DIV_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) div temp, 4));
end
else
if Key = 'NEG_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(-temp, 4));
end
else
if Key = 'NOT_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(not temp, 4));
end
else
if Key = 'LOW_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(temp mod 256, 4));
end
else
if Key = 'HIGH' then
begin
temp := HexToInt(Pop);
Push(IntToHex(temp div 256, 4));
end
else
if Key = 'MOD_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) mod temp, 4));
end
else
if Key = 'SHR_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) shr temp, 4));
end
else
if Key = 'SHL_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) shl temp, 4));
end
else
if Key = 'AND_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) and temp, 4));
end
else
if Key = 'OR__' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) or temp, 4));
end
else
if Key = 'XOR_' then
begin
temp := HexToInt(Pop);
Push(IntToHex(HexToInt(Pop) xor temp, 4));
end
else
begin
Result := False;
Break;
end;
end;
end;
// 式の解釈と実行
function Calc(s: String): String;
begin
Index := 0;
StackPtr := 0;
TokenList.Clear;
WorkList.Clear;
GetToken(s, TokenList);
token := NextToken;
Expression;
if Calculation then Result := Pop
else Result := calcFault;
end;
end.
Original document by TAK8 氏 ID:(QYR01421)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|