parser tree
This tree structure stores strings together with a number. It can be used
as parser tree.
{
ParsTree - parser tree structure
---------------------------------------------------------------
This stucture can learn words ( sequence of any characters )
together with a code. The codeformat may be choosen before
compilation, see TYPE CodeTyp.
If a word is already known, the LEARN returns false.
At any time a word may be SEARCHed, if found it returns true
and the returned code is valid.
---------------------------------------------------------------
PRPtr --> PRec:
Term:BOOLEAN; true if terminal
Ch :CHAR; character
Sub:PRPtr; PRPtr --> PRec
Code:CodeTyp; longint
Next:PRPtr; PRPtr --> PRec
Alt:PRPtr; PRPtr --> PRec
---------------------------------------------------------------
Important Note : The whole tree is to be hanged on a to be
supplied pointer( type PRPtr ), which has to be initialized
to NIL before use.
---------------------------------------------------------------
Changes:
6/mar/95 :added size function
PEntries: number of strings
PText: text bytes found in strings
PDelta: suppressed number of text bytes
PTotal: includes code, excludes PDelta
:added readentry function
not yet complete
---------------------------------------------------------------
TestProg is PTTEST.PAS
Upper Unit is PARSERTREE.PAS
---------------------------------------------------------------
Created :8.aug.93
Last Update :6/mar/95
---------------------------------------------------------------
Is updated version of : -
---------------------------------------------------------------
}
UNIT ParsTree;
INTERFACE
TYPE
CodeTyp =WORD; { can be BYTE WORD LONGINT }
PPtr=^PRPtr;
PRPtr=^PRec;
PRec=RECORD { size is 8byte+CodeTyp }
Term:BOOLEAN; { true if terminal, false if there is more }
Ch :CHAR; { character }
Sub:PRPtr;
Code:CodeTyp;
Next:PRPtr;
Alt:PRPtr;
END;
{ TRUE if successful - else known }
FUNCTION Learn(VAR K:PRPtr;S:STRING;Z:CodeTyp):BOOLEAN;
{ TRUE if successful }
FUNCTION Search(VAR K:PRPtr;S:STRING;VAR Z:CodeTyp):BOOLEAN;
PROCEDURE List(VAR K:PRPtr);
PROCEDURE Kill(VAR K:PRPtr);
PROCEDURE Size(VAR K:PRPtr;VAR PEntries,PText,PDelta,PTotal:LONGINT);
FUNCTION ReadEntry(VAR K:PRPtr;E:LONGINT;VAR S:STRING;VAR Z:CodeTyp):BOOLEAN;
IMPLEMENTATION
{ append rest of string at AT with code Z
Note AT is a POINTER
}
PROCEDURE AppendH(s:STRING;From:BYTE;At:PPtr;Z:CodeTyp);
VAR T:PRPtr;
V:PPtr;
i:BYTE;
BEGIN
V:=At;
FOR i:=From TO Length(s) DO
BEGIN
T:=New(PRPtr);
V^:=T;
T^.Term:=FALSE;
T^.Code:=0;
T^.Ch:=s[i];
T^.Sub:=NIL;
T^.Next:=NIL;
T^.Alt:=NIL;
V:=@T^.next;
END;
T^.Code:=Z;
T^.Term:=TRUE;
END;
FUNCTION FindI(S:STRING;pos:BYTE;p:PPtr;Z:CodeTyp):BOOLEAN;
{ p is truely a ptr to ptr }
VAR t:PRPtr;
v,l:PPtr;
found :BOOLEAN;
BEGIN
IF (p^=NIL) THEN { branch empty - insert there }
BEGIN
AppendH(s,1,p,Z); { append at entry ptr }
FindI:=TRUE;
END
ELSE { there is a nextptr }
BEGIN
v:=p;l:=v;
found:=FALSE;
REPEAT
IF (ord(v^^.ch)NIL) THEN
BEGIN
L:=V;V:=@V^^.Alt;
END
ELSE { no altptr - insert after }
BEGIN
AppendH(s,pos,@v^^.alt,Z);
Found:=TRUE;
FindI:=TRUE;
END;
END { pos not reached }
ELSE
BEGIN
IF (ord(v^^.ch)=ord(s[pos])) THEN { pos found }
BEGIN
IF (posNIL) THEN
BEGIN
L:=V;V:=@V^^.Alt;
END
ELSE { no altptr - insert after }
BEGIN
Found:=TRUE;
FindS:=FALSE;
END;
END { pos not reached }
ELSE
BEGIN
IF (ord(v^^.ch)=ord(s[pos])) THEN { pos found }
BEGIN
IF (posNIL) THEN ListI(j^.next,pos+1)
ELSE BEGIN Write(' ',j^.code); Writeln; END;
IF (j^.alt<>NIL) THEN
BEGIN
FOR i:=1 to pos DO Write(' ');
ListI(j^.alt,pos);
END;
END;
PROCEDURE KillI(j:PRPtr;pos:BYTE);
VAR p,t,v:PRPtr;
VAR i :BYTE;
BEGIN
{ Write(j^.ch); debug }
IF (j^.alt<>NIL) THEN
BEGIN
KillI(j^.alt,pos);
END;
IF (j^.next<>NIL) THEN KillI(j^.next,pos+1);
Dispose(J);
END;
PROCEDURE SizeI(j:PRPtr;pos:Byte;VAR PEntries,PText,PDelta,PTotal:LONGINT);
VAR p,t,v:PRPtr;
VAR i :BYTE;
BEGIN
inc(PText);inc(PTotal);
IF (j^.next<>NIL) THEN SizeI(j^.next,pos+1,PEntries,PText,PDelta,PTotal)
ELSE BEGIN inc(PEntries);inc(PTotal,SizeOf(CodeTyp)); END;
IF (j^.alt<>NIL) THEN
BEGIN
FOR i:=1 to pos DO inc(PDelta);
SizeI(j^.alt,pos,PEntries,PText,PDelta,PTotal);
END;
END;
{-------------------------------------------------------------}
FUNCTION Search(VAR K:PRPtr;S:STRING;VAR Z:CodeTyp):BOOLEAN;
BEGIN
Search:=FindS(S,1,@K,Z);
END;
FUNCTION Learn(VAR K:PRPtr;S:STRING;Z:CodeTyp):BOOLEAN;
BEGIN
Learn:=FindI(S,1,@K,Z);
END;
PROCEDURE List(VAR K:PRPtr);
BEGIN
IF (K<>NIL) THEN ListI(K,0);
END;
PROCEDURE Kill(VAR K:PRPtr);
BEGIN
IF (K<>NIL) THEN KillI(K,0);
END;
PROCEDURE Size(VAR K:PRPtr;VAR PEntries,PText,PDelta,PTotal:LONGINT);
BEGIN
PEntries:=0;PText:=0;PTotal:=0;
IF (K<>NIL) THEN SizeI(K,0,PEntries,PText,PDelta,PTotal);
END;
FUNCTION ReadEntry(VAR K:PRPtr;E:LONGINT;VAR S:STRING;VAR Z:CodeTyp):BOOLEAN;
VAR p:PRPtr;
BEGIN
S:='';
IF (K<>NIL) THEN
BEGIN
p:=K;
END
ELSE ReadEntry:=FALSE;
END;
{---------------------------------------------------------------}
{BEGIN} { autoinit of this unit}
END. { unit }
The encapsulation
{
Parser -
Created :
Last Update :
Is updated version of :
}
UNIT ParserTree;
INTERFACE
USES ParsTree;
TYPE
ParserPtr=^ParserType;
ParserType=OBJECT
Head:PRPtr;
CONSTRUCTOR Init;
DESTRUCTOR Done;
FUNCTION Learn(S:STRING;Z:CodeTyp):BOOLEAN;
FUNCTION Search(S:STRING;VAR Z:CodeTyp):BOOLEAN;
PROCEDURE List;
PROCEDURE Size(VAR A,B,C,D:LONGINT);
{ PROCEDURE Store(VAR K:PRPtr);}
{ PROCEDURE Load(VAR K:PRPtr);}
END;
IMPLEMENTATION
CONSTRUCTOR ParserType.Init;
BEGIN
Head:=NIL;
END;
DESTRUCTOR ParserType.Done;
BEGIN
ParsTree.Kill(Head);
END;
FUNCTION ParserType.Learn(S:STRING;Z:CodeTyp):BOOLEAN;
BEGIN
Learn:=ParsTree.Learn(Head,S,Z);
END;
FUNCTION ParserType.Search(S:STRING;VAR Z:CodeTyp):BOOLEAN;
BEGIN
Search:=ParsTree.Search(Head,S,Z);
END;
PROCEDURE ParserType.List;
BEGIN
ParsTree.List(Head);
END;
PROCEDURE ParserType.Size(VAR A,B,C,D:LONGINT);
BEGIN
ParsTree.Size(Head,a,b,c,d);
END;
BEGIN { autoinit of this unit}
END. { unit }
Sample App
PROGRAM ParserTreeTest;
USES OPCrt,ParsTree;
VAR Q:PRPtr;
Z:CodeTyp;
Y:LONGINT;
BEGIN
clrscr;
Q:=NIL;
Y:=MemAvail;
IF not (Learn(Q,'BAAB',5)) THEN Writeln('!');
IF not (Learn(Q,'AAAC',3)) THEN Writeln('!');
IF not (Learn(Q,'BAAC',6)) THEN Writeln('!');
IF not (Learn(Q,'CAAD',8)) THEN Writeln('!');
IF not (Learn(Q,'AAAB',2)) THEN Writeln('!');
IF not (Learn(Q,'AAAA',1)) THEN Writeln('!');
IF not (Learn(Q,'BAAD',7)) THEN Writeln('!');
IF not (Learn(Q,'ABAA',4)) THEN Writeln('!');
IF not (Learn(Q,'XAAB',13)) THEN Writeln('!');
IF not (Learn(Q,'XAAC',11)) THEN Writeln('!');
IF not (Learn(Q,'XAAC',14)) THEN Writeln('!');
IF not (Learn(Q,'XAAD',16)) THEN Writeln('!');
IF not (Learn(Q,'XAAB',10)) THEN Writeln('!');
IF not (Learn(Q,'XAAA',9)) THEN Writeln('!');
IF not (Learn(Q,'XAAD',15)) THEN Writeln('!');
IF not (Learn(Q,'XBAA',12)) THEN Writeln('!');
list(Q);
IF Search(Q,'ABAA',Z) THEN Writeln('Found ',Z);
Kill(Q);
Writeln('deltaheap :',Y-MemAvail);
END.
Another sample App
program parsertest;
USES OPCrt,ParsTree,ParserTree;
VAR U:ParserType;
Z:CodeTyp;
Y:LONGINT;
A,B,C,D:LONGINT;
BEGIN
ClrScr;
Y:=Memavail;
U.Init;
IF Not U.Learn('PROGRAM',1) THEN Writeln('!');
IF Not U.Learn('PROCEDURE',1) THEN Writeln('!');
IF Not U.Learn('FUNCTION',1) THEN Writeln('!');
IF Not U.Learn('BEGIN',1) THEN Writeln('!');
IF Not U.Learn('END',1) THEN Writeln('!');
IF Not U.Learn('FOR',1) THEN Writeln('!');
IF Not U.Learn('WHILE',1) THEN Writeln('!');
IF Not U.Learn('REPEAT',1) THEN Writeln('!');
IF Not U.Learn('IF',1) THEN Writeln('!');
IF Not U.Learn('TYPE',1) THEN Writeln('!');
IF Not U.Learn('CONST',1) THEN Writeln('!');
IF Not U.Learn('VAR',1) THEN Writeln('!');
IF Not U.Learn('UNTIL',1) THEN Writeln('!');
U.List;
U.Size(A,B,C,D);
IF U.Search('ZETA',Z) THEN Writeln('Found ',Z);
U.Done;
Writeln('DeltaHeap :',Y-Memavail);
END.
home
last updated: 29.nov.99
Copyright (99,2000) Ing.Büro R.Tschaggelar