size : 6793
uploaded_on : Sat Jul 18 00:00:00 1998
modified_on : Wed Dec 8 14:03:07 1999
title : String parsing unit
org_filename : Parse.pas
author : Palfrader Peter
authoremail : Weasel@holidayinfo.com
description : Parsing strings
keywords :
tested : not tested yet
submitted_by : The CKB Crew
submitted_by_email : ckb@netalive.org
uploaded_by : nobody
modified_by : nobody
owner : nobody
lang : pas
file-type : text/plain
category : pascal-alg-maths
__END_OF_HEADER__
{
Written by Palfrader Peter (Weasel@holidayinfo.com) in 1998
for the Coder's Knowledge Base at http://www.netalive.org/ckb/
Released into Public Domain. Credits would be fine.
}
unit parse;
interface
type
TElementtype = (etOperator, etConst, etVar);
TOperatorType =(otPlus, otMinus, otMultiply, otDivide, otNegate);
TWhat = (wtLength, wtcode, wtElement);
PElement = ^TElement;
TElement = object {an element is either a operator, a value or a variable}
ElementType : TElementtype;
Operator : TOperatorType;
tree1, tree2 : PElement;
varName : string;
value : extended;
constructor init;
destructor done;
function calc : extended;
end;
TTree = object
top : PElement;
constructor init;
destructor done;
procedure FreeAll;
procedure Parse(parsestr : string);
function calc : extended;
end;
implementation
function GetVariableValue(varname : string) : extended;
begin end;
const
MaxLength=1024; {may be changed without any problems}
AllowedVarChars:set of char=['A'..'Z','a'..'z','_'];
type
TCharElement = record
what : TWhat;
case TWhat of
wtLength : ( Length : integer);
wtcode : ( code : char);
wtElement : ( Element : PElement);
end;
TItmStr = array[0..MaxLength-1] of TCharElement;
{**************** Element implementation ****************}
constructor TElement.init;
begin
tree1:=nil;
tree2:=nil;
varName:=' ';
ElementType:=etConst;
Operator:=otplus;
value:=0;
end;
destructor TElement.done;
begin
if tree1<>nil then dispose(tree1,done);
if tree2<>nil then dispose(tree2,done);
end;
function TElement.calc : extended;
begin
case ElementType of
etOperator :
case Operator of
otPlus : calc:=tree1^.calc+tree2^.calc;
otMinus : calc:=tree1^.calc-tree2^.calc;
otMultiply : calc:=tree1^.calc*tree2^.calc;
otDivide : calc:=tree1^.calc/tree2^.calc;
otNegate : calc:=-tree1^.calc;
end;
etconst : calc:=value;
etvar : calc:=GetVariableValue(varName);
end;
end;
{**************** Tree implementation ****************}
constructor TTree.init;
begin
Top:=nil;
end;
destructor TTree.done;
begin
FreeAll;
end;
procedure TTree.FreeAll;
begin
if Top<>nil then dispose(Top,done);
end;
function TTree.calc : extended;
begin
calc:=top^.calc;
end;
procedure TTree.Parse(parsestr : string);
function BaseConvert(str : string) : extended;
var
r:extended;
code:integer;
begin {if you want other bases than 10 be enabled
for example by adding a h at the end of the number,
do this yourself. The after a number will be in str}
val(str,r,code);
BaseConvert:=r;
end;
procedure Copyps(
var Dest : TItmStr;
Source : TItmStr;
fromi,toi : integer);
{Copy a part from to inclusive}
var
z : integer;
begin
fillchar(dest,sizeof(dest),0);
dest[0].what:=wtlength;
dest[0].length:=toi-fromi+1;
for z:=1 to dest[0].length do
dest[z]:=source[z+fromi-1];
end;
procedure Subststr(
VAR ItStr : TItmStr;
fromi,toi : integer;
Element : PElement);
{Substitute a part by a Item instead}
var
z : integer;
itstr2 : TItmStr;
begin
fillchar(itstr2,sizeof(itstr2),0);
itstr2[0].what:=wtlength;
itstr2[0].length:=itstr[0].length - toi + fromi;
for z:=1 to fromi-1 do itstr2[z]:=itstr[z];
itstr2[fromi].what :=wtelement;
itstr2[fromi].element:=element;
for z:=fromi+1 to itstr2[0].length do
itstr2[z]:=itstr[z-fromi+toi];
ItStr:=itstr2;
end;
procedure InsertElement(
VAR ItStr : TItmStr;
Pos : integer;
OpType : TOperatorType);
var
n { = new }: PElement;
begin
n:=nil;
new(n,init);
n^.ElementType := etoperator;
n^.Operator := OPType;
case OpType of
otPlus, otMinus, otMultiply, otDivide :
begin
n^.Tree1:=itstr[pos-1].element;
n^.Tree2:=itstr[pos+1].element;
subststr(itstr,pos-1,pos+1,n);
end;
otNegate :
begin
n^.Tree1:=itstr[pos+1].element;
subststr(itstr,pos,pos+1,n);
end;
end;
end;
function Parsblock(itstr : TItmStr) : PElement;
var
pos : integer;
z : integer;
s : integer;
itstr2 : TItmStr;
begin
pos:=1;
while pos<=itstr[0].length do
begin
if (itstr[pos].what=wtcode) and (itstr[pos].code='(') then
begin
z:=1;
s:=pos;
while z<>0 do
begin
inc(s);
if itstr[s].code='(' then
inc(z);
if itstr[s].code=')' then
dec(z);
end;
Copyps(itstr2,itstr,pos+1,s-1);
subststr(itstr,pos,s,Parsblock(itstr2));
end;
inc(pos);
end;
pos:=itstr[0].length; {this time from right to left so many - each after the other won't hurt}
while pos>=1 do
begin
if (itstr[pos].what=wtcode) and
(itstr[pos].code='-') and
( (pos=1) or (
(itstr[pos-1].what=wtcode) and
((itstr[pos-1].code='+') or (itstr[pos-1].code='-'))
)
)
then
InsertElement(itstr,pos,otnegate);
dec(pos);
end;
pos:=1;
while pos<=itstr[0].length do
begin
if (itstr(.pos.).what=wtcode) then
case itstr(.pos.).code of
'/' :
begin
InsertElement(itstr,pos,otdivide);
dec(pos);
end;
'*' :
begin
InsertElement(itstr,pos,otmultiply);
dec(pos);
end;
end;
inc(pos);
end;
pos:=1;
while pos<=itstr[0].length do
begin
if (itstr(.pos.).what=wtcode) and
(itstr(.pos.).code='-') then
begin
InsertElement(itstr,pos,otminus);
dec(pos);
end;
inc(pos);
end;
pos:=1;
while pos<=itstr[0].length do
begin
if (itstr(.pos.).what=wtcode) and
(itstr(.pos.).code='+') then
begin
InsertElement(itstr,pos,otplus);
dec(pos);
end;
inc(pos);
end;
Parsblock:=itstr[1].element;
end;
var
s : integer;
itstr : TItmStr;
newel : PElement;
tmp : string;
fromi : integer;
begin
FreeAll;
fillchar(itstr,sizeof(itstr),0);
itstr[0].what:=wtlength;
itstr[0].length:=length(parsestr);
for s:=1 to length(parsestr) do
begin
itstr[s].what:=wtcode;
itstr[s].code:=parsestr[s];
end;
s:=1;
while s<=itstr[0].length do {get constants}
begin
if (itstr[s].what=wtcode) and (itstr[s].code in ['0'..'9']) then
begin
fromi:=s;
tmp:='';
while (s<=itstr[0].length) and not (i