packages feed

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.