language-Modula2-0.1: examples/Modula-2_Libraries/C.-Lins_Modula-2_Software_Component_Library/Vol3/EBNF/EBNFTABL.MOD
IMPLEMENTATION MODULE EBNFTable;
(*====================================================================
Version : 1.0d2 06 Feb 1989 C. Lins
Compiler : JPI's TopSpeed Modula-2 Compiler
Component: EBNFTable
INTRODUCTION
This module defines a symbol table for identifiers and line numbers
for the EBNF tool.
The act of tabulating a symbol table causes the table to be destroyed.
REVISION HISTORY
v1.0d1 04 Feb 1989 C. Lins:
Initial implementation derived from Wirth's Programming in
Modula-2, 4th edition, pp 96-100.
v1.0d2 06 Feb 1989 C. Lins:
Changed to use k-balanced tree where k = 3.
v1.1 01 Dec 1989 I. S. C. Houston
Changed to use JPI Compiler and library.
====================================================================*)
FROM JPIStorage IMPORT
(*--proc*) Allocate, Deallocate;
FROM StrCSUMI IMPORT
(*--type*) String;
FROM Relations IMPORT
(*--type*) Relation;
IMPORT StrCSUMI;
IMPORT TreeTypes;
IMPORT IPBSUMI;
IMPORT TypeManager;
IMPORT CharItems;
FROM IO IMPORT
(*--proc*) WrChar, WrCharRep, WrInt, WrLn;
TYPE SymbolTable = IPBSUMI.Tree;
VAR listOverflow : BOOLEAN;
PROCEDURE StringAssign ( theKey : TreeTypes.Key) : TreeTypes.Key;
VAR newString : String;
BEGIN
(* Ensure that target string doesn't contain garbage that Assign might
interpret as a legal string and try and deallocate it. *)
newString := StrCSUMI.NullString;
(* Assign the string value from source to target *)
StrCSUMI.Assign( String(theKey), newString);
(* Return the new string copy *)
RETURN TreeTypes.Key(newString);
END StringAssign;
(*--------------------*)
PROCEDURE StringCompare ( left, right : TreeTypes.Key) : Relation;
BEGIN
RETURN StrCSUMI.Compare(String(left), String(right));
END StringCompare;
(*--------------------*)
PROCEDURE StringDispose (VAR theKey : TreeTypes.Key);
VAR s : String;
BEGIN
(* Coerce into proper type for use as VAR parameter *)
s := String(theKey);
(* Deallocate the dynamic string. "s" is changed to NIL *)
StrCSUMI.Destroy(s);
(* Store NIL back into the key *)
theKey := TreeTypes.Key(s);
END StringDispose;
(*--------------------*)
TYPE List = POINTER TO ListNode;
TYPE ListNode = RECORD
lineNo : INTEGER;
next : List;
END (*--ListNode*);
(* We must provide an assignment routine but know that it won't be used. *)
PROCEDURE ListAssign (list : TreeTypes.Data) : TreeTypes.Data;
BEGIN
RETURN list
END ListAssign;
(*--------------------*)
PROCEDURE ListDispose (VAR list : TreeTypes.Data);
VAR l : List;
BEGIN
l := List(list);
Deallocate(l,SIZE(ListNode)); (* returns NIL *)
list := TreeTypes.Data(l); (* output null list of coerced type *)
END ListDispose;
(*--------------------*)
PROCEDURE NewListNode ( theLineNo : INTEGER) : List;
VAR l : List;
BEGIN
Allocate(l, SIZE(ListNode));
IF (l = NIL) THEN
listOverflow := TRUE;
ELSE
l^.lineNo := theLineNo;
l^.next := NIL;
END (*--if*);
RETURN l;
END NewListNode;
PROCEDURE Create () : SymbolTable (*--out *);
VAR theTable : SymbolTable;
stringKeyTypeID : TypeManager.TypeID;
listDataTypeID : TypeManager.TypeID;
BEGIN
stringKeyTypeID := TypeManager.Create("string",
StringAssign,
StringCompare,
StringDispose);
listDataTypeID := TypeManager.Create("list",
ListAssign,
TypeManager.NoCompareProc,
ListDispose);
theTable := SymbolTable(
IPBSUMI.Create(stringKeyTypeID,
listDataTypeID, 3));
RETURN theTable;
END Create;
(*--------------------*)
PROCEDURE Found ( theKey : TreeTypes.Key;
VAR theList : TreeTypes.Data;
newData : TreeTypes.Data);
VAR newList : List;
BEGIN
newList := List(newData);
newList^.next := List(theList);
theList := TreeTypes.Data(newList);
END Found;
(*--------------------*)
PROCEDURE Record ( inTable : SymbolTable (*--inout*);
theID : String (*--in *);
lineNo : INTEGER (*--in *));
VAR t : IPBSUMI.Tree;
newList : List;
BEGIN
newList := NewListNode(lineNo);
IF NOT listOverflow THEN
t := IPBSUMI.Tree(inTable);
IPBSUMI.Insert(t,
TreeTypes.Key(theID),
TreeTypes.Data(newList),
Found);
END (*--if*);
(* CursorControl.SpinCursor(8); *)
END Record;
(*--------------------*)
PROCEDURE OutputString (c : CharItems.Item);
BEGIN
WrChar(c);
END OutputString;
(*--------------------*)
PROCEDURE WriteTable ( theKey : TreeTypes.Key (*--in *);
VAR theData: TreeTypes.Data (*--in *));
CONST width = 6;
lineWidth = 120;
wordWidth = 30;
N = (lineWidth - wordWidth) DIV width;
VAR q : List;
i : INTEGER;
keyLength : INTEGER;
BEGIN
(* CursorControl.SpinCursor(-8); *)
StrCSUMI.Traverse( String(theKey), OutputString);
keyLength := StrCSUMI.LengthOf( String(theKey) );
IF (keyLength < wordWidth) THEN
WrCharRep(" ",wordWidth-keyLength);
END (*--if*);
WrChar(" ");
q := List(theData);
i := N;
WHILE (q # NIL) DO
IF (i = 0) THEN
WrLn;
WrCharRep(" ",wordWidth+1);
i := N;
END (*--if*);
WrInt(q^.lineNo, width);
q := q^.next;
DEC(i);
(* CursorControl.SpinCursor(-4); *)
END (*--while*);
WrLn;
END WriteTable;
(*--------------------*)
PROCEDURE Tabulate ( theTable: SymbolTable (*--in *));
VAR t : IPBSUMI.Tree;
BEGIN
IPBSUMI.Inorder( IPBSUMI.Tree(theTable), WriteTable);
t := IPBSUMI.Tree(theTable);
IPBSUMI.Destroy(t);
END Tabulate;
(*--------------------*)
PROCEDURE Overflow () : BOOLEAN (*--out *);
BEGIN
RETURN (IPBSUMI.TreeError() # TreeTypes.noerr) OR listOverflow;
END Overflow;
(*--------------------*)
BEGIN
listOverflow := FALSE;
END EBNFTable.