183 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
| IMPLEMENTATION MODULE TableHandler;
 | |
| 
 | |
|   FROM InOut	IMPORT	Write, WriteLn, WriteInt;
 | |
|   FROM Storage	IMPORT	Allocate;
 | |
| 
 | |
|   CONST	TableLength = 3000;
 | |
| 
 | |
|   TYPE
 | |
| 	TreePtr = POINTER TO Word;
 | |
| 	ListPtr = POINTER TO Item;
 | |
| 	Item = RECORD
 | |
| 		num: INTEGER;
 | |
| 		next: ListPtr
 | |
| 	       END;
 | |
| 	Word = RECORD
 | |
| 		key: CARDINAL;	(* table index *)
 | |
| 		first: ListPtr;	(* list head *)
 | |
| 		left, right: TreePtr
 | |
| 	       END;
 | |
| 	Table = TreePtr;
 | |
| 
 | |
|   VAR
 | |
| 	id: ARRAY [0..WordLength] OF CHAR;
 | |
| 	ascinx: CARDINAL;
 | |
| 	asc: ARRAY [0..TableLength-1] OF CHAR;
 | |
| 
 | |
|   PROCEDURE InitTable(VAR t: Table);
 | |
|   BEGIN
 | |
| 	Allocate(t, SIZE(Word));
 | |
| 	t^.right := NIL
 | |
|   END InitTable;
 | |
| 
 | |
|   PROCEDURE Search(p: TreePtr): TreePtr;
 | |
|   (* search node with name equal to id
 | |
|   *)
 | |
|     TYPE	Relation = (less, equal, greater);
 | |
|     VAR		q: TreePtr;
 | |
| 		r: Relation;
 | |
| 		i: CARDINAL;
 | |
|     
 | |
|     PROCEDURE rel(k: CARDINAL): Relation;
 | |
|     (* compare id with asc[k]
 | |
|     *)
 | |
|       VAR	i: CARDINAL;
 | |
| 		R: Relation;
 | |
| 		x,y: CHAR;
 | |
|     BEGIN
 | |
| 	i := 0;
 | |
| 	R := equal;
 | |
| 	LOOP
 | |
| 	    x := id[i];
 | |
| 	    y := asc[k];
 | |
| 	    IF CAP(x) # CAP(y) THEN EXIT END;
 | |
| 	    IF x <= " " THEN RETURN R END;
 | |
| 	    IF x < y THEN R := less ELSIF x > y THEN R := greater END;
 | |
| 	    i := i+1;
 | |
| 	    k := k+1;
 | |
| 	END;
 | |
| 	IF CAP(x) > CAP(y) THEN RETURN greater ELSE RETURN less END
 | |
|     END rel;
 | |
| 
 | |
|   BEGIN	(* Search *)
 | |
| 	q := p^.right;
 | |
| 	r := greater;
 | |
| 	WHILE q # NIL DO
 | |
| 	    p := q;
 | |
| 	    r := rel(p^.key);
 | |
| 	    IF r = equal THEN RETURN p
 | |
| 	    ELSIF r = less THEN q := p^.left
 | |
| 	    ELSE q := p^.right
 | |
| 	    END
 | |
| 	END;
 | |
| 	Allocate(q, SIZE(Word));	(* not found, hence insert *)
 | |
| 	IF q # NIL THEN
 | |
| 	    WITH q^ DO
 | |
| 		key := ascinx;
 | |
| 		first := NIL;
 | |
| 		left := NIL;
 | |
| 		right := NIL
 | |
| 	    END;
 | |
| 	    IF r = less THEN p^.left := q ELSE p^.right := q END;
 | |
| 	    i := 0;	(* copy identifier into asc table *)
 | |
| 	    WHILE id[i] > " " DO
 | |
| 		IF ascinx = TableLength THEN
 | |
| 		    asc[ascinx] := " ";
 | |
| 		    id[i] := " ";
 | |
| 		    overflow := 1
 | |
| 		ELSE
 | |
| 		    asc[ascinx] := id[i];
 | |
| 		    ascinx := ascinx + 1;
 | |
| 		    i := i + 1
 | |
| 		END
 | |
| 	    END;
 | |
| 	    asc[ascinx] := " ";
 | |
| 	    ascinx := ascinx + 1;
 | |
| 	END;
 | |
| 	RETURN q;
 | |
|   END Search;
 | |
| 
 | |
|   PROCEDURE Record(t: Table; VAR x: ARRAY OF CHAR; n: INTEGER);
 | |
|     VAR	p: TreePtr;
 | |
| 	q: ListPtr;
 | |
| 	i: CARDINAL;
 | |
|   BEGIN
 | |
| 	i := 0;
 | |
| 	REPEAT
 | |
| 	    id[i] := x[i];
 | |
| 	    i := i + 1
 | |
| 	UNTIL (id[i-1] = " ") OR (i = WordLength);
 | |
| 	p := Search(t);
 | |
| 	IF p = NIL THEN
 | |
| 	    overflow := 2
 | |
| 	ELSE
 | |
| 	    Allocate(q, SIZE(Item));
 | |
| 	    IF q = NIL THEN
 | |
| 		overflow := 3;
 | |
| 	    ELSE
 | |
| 		q^.num := n;
 | |
| 		q^.next := p^.first;
 | |
| 		p^.first := q
 | |
| 	    END
 | |
| 	END
 | |
|   END Record;
 | |
| 
 | |
|   PROCEDURE Tabulate(t: Table);
 | |
| 
 | |
|     PROCEDURE PrintItem(p: TreePtr);
 | |
|       CONST	L = 6;
 | |
| 		N = (LineWidth - WordLength) DIV L;
 | |
|       VAR	ch: CHAR;
 | |
| 		i, k: CARDINAL;
 | |
| 		q: ListPtr;
 | |
|     BEGIN
 | |
| 	i := WordLength + 1;
 | |
| 	k := p^.key;
 | |
| 	REPEAT
 | |
| 	    ch := asc[k];
 | |
| 	    i := i - 1;
 | |
| 	    k := k + 1;
 | |
| 	    Write(ch)
 | |
| 	UNTIL ch <= " ";
 | |
| 	WHILE i > 0 DO
 | |
| 	    Write(" ");
 | |
| 	    i := i-1
 | |
| 	END;
 | |
| 	q := p^.first;
 | |
| 	i := N;
 | |
| 	WHILE q # NIL DO
 | |
| 	    IF i = 0 THEN
 | |
| 		WriteLn;
 | |
| 		i := WordLength+1;
 | |
| 		REPEAT
 | |
| 		    Write(" ");
 | |
| 		    i := i-1
 | |
| 		UNTIL i = 0;
 | |
| 		i := N
 | |
| 	    END;
 | |
| 	    WriteInt(q^.num, L);
 | |
| 	    q := q^.next;
 | |
| 	    i := i - 1
 | |
| 	END;
 | |
| 	WriteLn
 | |
|     END PrintItem;
 | |
| 
 | |
|     PROCEDURE TraverseTree(p: TreePtr);
 | |
|     BEGIN
 | |
| 	IF p # NIL THEN
 | |
| 	    TraverseTree(p^.left);
 | |
| 	    PrintItem(p);
 | |
| 	    TraverseTree(p^.right)
 | |
| 	END
 | |
|     END TraverseTree;
 | |
| 
 | |
|   BEGIN (* Tabulate *)
 | |
| 	WriteLn;
 | |
| 	TraverseTree(t^.right)
 | |
|   END Tabulate;
 | |
| 
 | |
| BEGIN
 | |
| 	ascinx := 0;
 | |
| 	id[WordLength] := " ";
 | |
| 	overflow := 0
 | |
| END TableHandler.
 |