home *** CD-ROM | disk | FTP | other *** search
- (* HASH.PAS
- Erlaeuterung zur lexikalischen Analyse. Implementierung der Symbol-
- tabelle des Scanners durch Hashing mit Kollisionsaufloesung mit Ver-
- kettung. Es werden Symbole von der Tastatur eingelesen und in der
- Reihenfolge ihres Auftretens in eine Hashtabelle eingetragen.
- Config.: ATARI ST & Pascal ST Plus, MS-DOS & Turbo Pascal *)
- PROGRAM hash;
- CONST
- maxidlength=8; zeilenmax=23; tablestart=4; maxentries=18; hashmax=9;
- TYPE
- Str80 = STRING[80];
- kollision = ^kliste;
- kliste = RECORD na : Str80; next : kollision; END;
- hashvektor = ARRAY[0..hashmax] OF kollision;
- VAR
- i, j, hashindex: INTEGER; na: Str80; hash: hashvektor;
-
- PROCEDURE DrawLine;
- VAR i: INTEGER;
- BEGIN FOR i := 1 TO 80 DO Write('-'); END;
-
- PROCEDURE DrawColumn (x, y: INTEGER);
- BEGIN
- WHILE y <= zeilenmax DO BEGIN GotoXY(x,y); Write('!'); y := y+1; END;
- END;
-
- (* Operationen auf Hashtabelle: *)
- PROCEDURE Init;
- VAR i: INTEGER;
- BEGIN FOR i := 0 TO hashmax DO hash[i] := NIL END;
-
- (* 'pos' gibt den Hashindex h(na) zurueck: *)
- FUNCTION Insert (VAR na: Str80; VAR Pos: INTEGER): BOOLEAN;
- FUNCTION h (na: Str80): INTEGER; (* Hashfunktion *)
- BEGIN h := (Ord(na[1])+Ord(na[Length(na)])) MOD (hashmax+1); END;
-
- (* fuegt n in die Kollisionsliste l ein, falls n noch nicht in l ent-
- halten ist. Insertlist = true wenn in l eingefuegt wurde: *)
- FUNCTION InsertList (VAR n: Str80; VAR l: kollision): BOOLEAN;
- VAR l1: kollision;
- BEGIN
- IF l = NIL THEN BEGIN (* n wird in die Liste eingefuegt *)
- New(l1); l1^.na := n; l1^.next := NIL; l := l1; InsertList := TRUE;
- END
- ELSE IF l^.na = n THEN
- InsertList := FALSE (* n ist in l bereits enthalten *)
- ELSE
- InsertList := InsertList(n,l^.next) (* suche Rest der Liste nach n *)
- END;
-
- BEGIN (* Insert *)
- Pos := h(na); Insert := InsertList(na,hash[Pos]); (* klar ! *)
- END;
-
- (* gibt die Laenge der Kollisionsliste l zurueck: *)
- FUNCTION ListLen (l: kollision): INTEGER;
- BEGIN
- IF l = NIL THEN ListLen := 0 ELSE ListLen := ListLen(l^.next)+1;
- END;
-
- PROCEDURE Menue; (* zeichnet die Symboltabelle auf den Bildschirm: *)
- VAR i: INTEGER; f: TEXT; c: CHAR; s: Str80;
- BEGIN
- ClrScr; WriteLn('Hashing mit Kollisionsaufloesung durch Verkettung');
- GotoXY(1,25); Write('Ende mit Bezeichner "ende", Eingabe max. 7 Zeichen');
- GotoXY(1,tablestart); DrawLine;
- FOR i := 1 TO 10 DO DrawColumn(i*maxidlength,tablestart+1);
- GotoXY(1,zeilenmax); DrawLine; GotoXY(1,tablestart-1);
- FOR i := 0 TO 8 DO Write(' ':4,i,' ':3);
- Write(' ':4,'9'); (* <-- sonst wandert der Cursor automatisch in die
- naechste Zeile und scrollt die Tabelle um 1 nach oben *)
- END;
-
- (* traegt den Bezeichner n in der Bildschirmtabelle bei Hashindex 'index'
- ein. n ist dabei der 'ith_entry'-Eintrag in der Kollisionsliste mit dem
- zugehoerigen Index 'index': *)
- PROCEDURE ShowId (VAR n: Str80; index, ith_entry: INTEGER);
- VAR i: INTEGER; c: CHAR;
- PROCEDURE Wait (l: INTEGER); BEGIN WHILE l > 0 DO l := l-1 END;
- BEGIN
- IF ith_entry > maxentries THEN BEGIN
- GotoXY(0,25); Write('Symboltabellen-Ueberlauf, breche ab... ');
- n := 'ende';
- END
- ELSE
- FOR i := 1 TO 5 DO BEGIN
- IF Odd(i) THEN NormVideo ELSE LowVideo;
- GotoXY(index*maxidlength+1,tablestart+ith_entry);
- IF Length(n) >= maxidlength THEN n[0] := Chr(maxidlength-1);
- Write(n); Wait(30000);
- END;
- END;
-
- BEGIN
- Menue; Init; na := '';
- WHILE na <> 'ende' DO BEGIN
- GotoXY(1,zeilenmax+1); ClrEol; Write('Bezeichner : '); ReadLn(na);
- IF Insert(na,hashindex) THEN
- ShowId(na,hashindex,ListLen(hash[hashindex]));
- END;
- END.