Previous Up Next

Print binary identifier tree
(printtree)

Introduction

This module contains a procedure that prints the complete contents of the binary identifier tree in alphabetic order of the identifiers.

1 Print binary identifier tree

The procedure print tree prints the complete binary tree. The global boolean variable with all names controls whether the Pascal identifiers are also printed.

2 Interface

This module uses declarations from the following modules:

2.1 Exported procedure

The following procedure is exported by this module:

3 The listing

[ENVIRONMENT ('printtree.pen'),
 INHERIT     ('definitions.pen',
              'perform.pen',
              'listing.pen',
              'bintree.pen')]MODULE printnodetree;

(*      MODULE: PRINTTREE                                                     *)

(*  This program contains the procedures that print the identifier tree and   *)
(*  related information on the listing. The greatest part concerns the        *)
(*  printing of attribute assignments.                                        *)


3.1 Elementary printing procedures

[HIDDEN] PROCEDURE print_node(p:pnode);
(* This procedure prints the name of node p, if p equals NIL "<*NIL*>" is     *)
(* printed.                                                                   *)
BEGIN
  IF   p = NIL
  THEN print_alfa('<*NIL*>')
  ELSE print_alfa(p^.name)
END;

[HIDDEN] PROCEDURE print_partnamenr(nr:integer);
(* This procedure prints the number of a partname, if the partname is an      *)
(* error partname, "<*>" is printed.                                          *)
VAR
  scale : integer;
BEGIN
  IF   nr = error_part_nr
  THEN print_alfa('<*>')
  ELSE BEGIN
         IF   nr < 10
         THEN print_alfa( chr(nr + ord('0')) )
         ELSE print_alfa( chr((nr DIV 10) MOD 10 + ord('0'))
                        + chr(nr MOD 10 + ord('0')) )
       END
END;

[HIDDEN] PROCEDURE print_type(type_ptr:ttype);
(* This procedure prints a formal type using type_ptr. A concluded formal     *)
(* type as a pair of brackets "<" and ">" around it. An error formal type is  *)
(* printed as "<<*>>", and an undefined formal type as "<*>".                 *)
BEGIN
 WITH type_ptr
 DO BEGIN
      IF   conc
      THEN print_char('<');
      print_node(type_name);
      IF   conc
      THEN print_char('>');
    END
END;

3.2 Printing expressions

(*  The following procedure is for printing of expressions                    *)

[HIDDEN] PROCEDURE print_expr(expr_ptr : pexpr);
(* This procedure prints the expression, pointed to by expr_ptr. If expr_ptr  *)
(* is NIL, "<NIL>" is printed, otherwise one of the tree kinds of expressions *)
(* is printed.                                                                *)

  PROCEDURE print_lexpr(lexpr_ptr : plexpr);
  (* This procedure prints a list of expressions pointed to by lexpr_ptr,     *)
  (* separated by commas. This procedure is used for printing the applied     *)
  (* argument expression within a function.                                   *)
  VAR
    walker : plexpr;
  BEGIN
    walker := lexpr_ptr;
    WHILE walker <> NIL
    DO BEGIN
         print_char('{');
         print_alfa(walker^.type_of_arg);
         print_char('}');
         print_expr(walker^.first);
         walker := walker^.rest;
         IF   walker <> NIL
         THEN print_alfa(', ');
       END
  END;

  PROCEDURE print_lalt_expr(alt_ptr : plalt_expr);
  (* This procedure prints a list of case alternatives pointed to by alt_ptr. *)
  (* The alternatives are separated by semi-colons, and every alternative     *)
  (* consists of a selector and an expression.                                *)
  VAR
    walker : plalt_expr;

    PROCEDURE print_selectors(other_sel : boolean; selector : elements);
    (* This procedure prints a list of element names pointed to by the pointer*)
    (* lnode_ptr, separated with commas or "OTHERS" if lnode_ptr is equal to  *)
    (* others_selector. It is used to print a selector.                       *)
    VAR
      elemnr : integer;
    BEGIN
      IF   other_sel
      THEN print_alfa('OTHERS')
      ELSE BEGIN
             elemnr := start_nr;
             WHILE selector <> []
             DO BEGIN
                  next_elem(elemnr, selector);
                  print_node(element[elemnr]);
                  IF   selector <> []
                  THEN print_char(',')
                END
           END
    END;

  BEGIN (* of print_lalt_expr *)
    walker := alt_ptr;
    WHILE walker <> NIL
    DO BEGIN
         WITH walker^
         DO BEGIN
              print_selectors(other_sel, selectors);
              print_alfa(' : ');
              print_expr(expr)
            END;
         walker := walker^.rest;
         IF   walker <> NIL
         THEN print_alfa('; ');
       END
  END;

BEGIN (* of print_expr *)
  IF  expr_ptr = NIL
  THEN print_alfa('<NIL>')
  ELSE WITH expr_ptr^
       DO CASE kind OF
           e_atoc : BEGIN
                      print_node(attr);
                      print_alfa(' OF ');
                      print_partnamenr(partnamenr)
                    END;
           e_func : BEGIN
                      print_node(func);
                      print_char('(');
                      print_lexpr(args);
                      print_char(')')
                    END;
           e_case : BEGIN
                      print_alfa('CASE ');
                      print_partnamenr(headpnnr);
                      print_alfa(' OF ');
                      print_lalt_expr(alter);
                      print_alfa(' ESAC')
                    END
          END
END;

3.3 Printing lists of attribute assignments

(*  The following procedure is for printing a list of attribute assignments   *)

[HIDDEN] PROCEDURE print_lattr_ass(aas_ptr : plattr_ass);
(* This procedure prints a list of attribute assignments, separated by        *)
(* commas and starting on a new line.                                         *)
VAR
  walker : plattr_ass;

  PROCEDURE print_lalt_ass(alt_ptr : plalt_ass);
  (* This procedure prints a list of selective assignment alternatives,       *)
  (* pointed to by alt_ptr, separated by semi-colons and all starting on a    *)
  (* new line.                                                                *)
  VAR
    walker : plalt_ass;

    PROCEDURE print_selectors(other_sel : boolean; selector : elements);
    (* This procedure prints a selector of a selective assignment. If it is a *)
    (* others selector, when list is equal others_selector, "OTHERS" is       *)
    (* printed. Otherwise all the elements represented by the list list are   *)
    (* printed under each other separated by commas.                          *)

    VAR
      elemnr : integer;
    BEGIN
      IF   other_sel
      THEN print_fixed('OTHERS',15)
      ELSE BEGIN
             elemnr := start_nr;
             WHILE selector <> []
             DO BEGIN
                  next_elem(elemnr, selector);
                  print_fixed(element[elemnr]^.name,15);
                  IF   selector <> []
                  THEN BEGIN
                         print_char(',');
                         print_newline(1)
                      END
                END
           END
    END;

  BEGIN (* of print_lalt_ass *)
    walker := alt_ptr;
    WHILE walker <> NIL
    DO BEGIN
         print_newline(1);
         WITH walker^
         DO BEGIN
              print_selectors(other_sel, selectors);
              print_alfa(': ');
              shift_right(17);
              print_lattr_ass(attr_ass);
            END;
         walker := walker^.rest;
         IF   walker <> NIL
         THEN print_char(';');
         shift_left(17);
       END
  END;

BEGIN (* of print_lattr_ass *)
  walker := aas_ptr;
  WHILE walker <> NIL
  DO BEGIN
       shift_right(1);
       WITH walker^
       DO CASE kind OF
           a_simp : BEGIN
                      print_node(attr);
                      print_alfa(' OF ');
                      print_partnamenr(partnamenr);
                      print_alfa(' = ');
                      print_expr(expr)
                    END;
           a_sele : BEGIN
                      print_alfa('CASE ');
                      print_partnamenr(headpnnr);
                      print_alfa(' OF');
                      shift_right(2);
                      print_lalt_ass(alter);
                      shift_left(2);
                      print_newline(1);
                      print_alfa('ESAC')
                    END
          END;
          shift_left(1);
          print_newline(1);
          walker := walker^.rest;
          IF   walker <> NIL
          THEN print_char(',')
      END
END;

3.4 Printing element identifier

(*  The procedures on this page print the information with the different      *)
(*  kinds of names.                                                           *)

[HIDDEN] PROCEDURE print_element(ptr : pnode);
(* This procedure prints the information of an element name. These are: The   *)
(* names of the attributes defined with attribute rules. The words "ROOT      *)
(* ELEMENT", if this is the root element. The class rule if it is not empty.  *)
(* The kind of tree rule, and the tree rule if it is not empty. The attribute *)
(* assignments, if they are defined.                                          *)

  PROCEDURE print_attrs(attr : tattr);
  (* This procedure prints the attributes, represented by attr_ptr. Every     *)
  (* attribute is printed on a new line. It is preceded by "-", and behind it *)
  (* are the words "INPUT" and "OUTPUT" printed, if there has been an         *)
  (* interface rule with this kind and with this element.                     *)

  VAR
    attrnr : integer;
  BEGIN
    attrnr := start_nr;
    WHILE attr[nor_gen] <> []
    DO BEGIN
         next_attr(attrnr, attr[nor_gen]);
         print_alfa('- ');
         print_fixed(attribute[attrnr]^.name, 35);
         IF   attrnr IN (attr[nor_in] + g_input_attr)
         THEN print_alfa('  INPUT ');
         IF   attrnr IN (attr[nor_out] + g_output_attr)
         THEN print_alfa('  OUTPUT');
         print_newline(1)
       END
  END;

  PROCEDURE print_elem_list(list : elements);
  (* This procedure prints a list of elements with list. The names of the     *)
  (* elements are printed with their full names and separated by commas.      *)
  VAR
    elemnr : integer;
  BEGIN
    elemnr := start_nr;
    WHILE list <> []
    DO BEGIN
         next_elem(elemnr, list);
         print_node(element[elemnr]);
         IF list <> []
         THEN print_alfa(', ');
       END
  END;

  PROCEDURE print_kind_of_rule(kind : trule_kind);
  (* This procedure prints the kind of the tree rule, using kind.             *)
  BEGIN
    CASE kind OF
      r_empt : print_alfa('EMPTY      ');
      r_dire : print_alfa('DIRECT     ');
      r_indi : print_alfa('INDIRECT   ');
      r_undf : print_alfa('UNDEFINED  ')
    END;
    print_alfa('TREE RULE ')
  END;


  PROCEDURE print_tree_def(tree_rule_ptr : ptree_rule);
  (* This procedure prints the tree rule, represented by tree_rule_ptr. It is *)
  (* preceded with the symbol "=>". All the parts are printed on a new line,  *)
  (* separated with a comma.                                                  *)
  VAR
    walker : ptree_rule;
  BEGIN
    print_alfa('=> ');
    shift_right(1);
    walker := tree_rule_ptr;
    WHILE walker <> NIL
    DO BEGIN
         WITH walker^
         DO BEGIN
              print_fixed(partname, 15);
              print_alfa(': ');
              print_node(element)
            END;
         print_newline(1);
         walker := walker^.rest;
         IF walker <> NIL
         THEN print_alfa(', ');
       END;
    print_alfa('. ');
    shift_left(1);
    print_newline(1)
  END;

BEGIN (* of print_element *)
  WITH ptr^
  DO BEGIN
       reset_left_margin(2);
       print_newline(1);
       print_attrs(attr);
       IF  ptr = root
       THEN BEGIN
              write(listing,'ROOT ELEMENT');
              print_newline(1)
            END;
       IF   parent <> []
       THEN BEGIN
              print_alfa('IN CLASSES : ');
              shift_right(13);
              print_elem_list(parent);
              shift_left(13);
              print_newline(1)
            END;
       IF   class_rule <> []
       THEN BEGIN
              print_alfa('= {');
              shift_right(3);
              print_elem_list(class_rule);
              print_char('}');
              shift_left(3);
              print_newline(1)
            END;
       print_kind_of_rule(kind_of_rule);
       print_newline(1);
       IF   tree_rule <> NIL
       THEN print_tree_def(tree_rule);
       IF   attr_ass <> NIL
       THEN BEGIN
              print_char('[');
              print_lattr_ass(attr_ass);
              print_char(']');
            END
     END
END;

3.5 Print attribute identifier

[HIDDEN] PROCEDURE print_attribute(ptr : pnode);
(* This procedure prints the information with an attribute, represented by    *)
(* ptr. The formal type is printed, followed by information about the kind of *)
(* attribute, and indications whether an interface rule (without "at")        *)
(* occurred with this attribute.                                              *)
BEGIN
  WITH ptr^
  DO BEGIN
       reset_left_margin(2);
       print_newline(1);
       print_alfa(': ');
       print_type(type_of_attr);
       print_alfa('  ');
       IF   attr_nr <> error_nr
       THEN BEGIN
              IF   attr_nr IN g_inh_attr
              THEN write(listing,'INHERITED  ')
              ELSE IF   attr_nr IN g_syn_attr
                   THEN write(listing,'SYNTHESIZED')
                   ELSE write(listing,'UNDEFINED  ');
              IF   attr_nr IN g_input_attr
              THEN write(listing,'  INPUT');
              IF   attr_nr IN g_output_attr
              THEN write(listing,'  OUTPUT');
            END
     END
END;

3.6 Print function identifier

[HIDDEN] PROCEDURE print_function(ptr : pnode);
(* This procedure print information about a function represented by ptr.      *)
(* Which is the formal parameter list, preceded by an "=" symbol.             *)
VAR
  walker : pltype;
BEGIN
  WITH ptr^
  DO BEGIN
       reset_left_margin(2);
       print_newline(1);
       print_alfa('= ');
       print_char('(');
       shift_right(3);
       walker := args;
       WHILE walker <> NIL
       DO BEGIN
            print_type(walker^.first);
            walker := walker^.rest;
            IF   walker <> NIL
            THEN print_alfa(', ')
          END;
       print_alfa(') ');
       print_alfa(': ');
       print_type(type_of_func)
     END
END;

3.7 Main printing procedure

(* The procedures on this pages print the identifier tree in alphabetical     *)
(* order.                                                                     *)

[HIDDEN] PROCEDURE print_name_tree(ptr : pnode; depth : integer);
(* This procedure prints the sub-tree below the pointer ptr, with all its     *)
(* information.                                                               *)

  PROCEDURE print_info;
  (* This procedure prints the information with a name. Information about     *)
  (* the error status is also printed.                                        *)

    PROCEDURE print_n_kind(kind : tnode_kind);
    (* This procedure prints the kind of a name.                              *)
    BEGIN
      CASE kind OF
        n_class  : write(listing,'CLASS    ');
        n_node   : write(listing,'NODE TYPE');
        n_elem   : write(listing,'ELEMENT  ');
        n_type   : write(listing,'TYPE     ');
        n_func   : write(listing,'FUNCTION ');
        n_attr   : write(listing,'ATTRIBUTE');
        n_system : write(listing,'SYSTEM   ');
        n_pascal : write(listing,'PASCAL   ');
        n_undef  : write(listing,'UNDEFINED');
      END
    END;

    PROCEDURE print_error_status(status : terror_sts);
    (* This procedure prints an error status, if it is unequal the correct    *)
    (* error status.                                                          *)
    VAR
      kind : tnode_kind;
    BEGIN
      WITH status
      DO BEGIN
           IF   conc
           THEN write(listing,'  CONCLUDED');
           IF   defined <> []
           THEN BEGIN
                  write(listing,'  {');
                  kind := n_class;
                  REPEAT
                    WHILE NOT(kind IN defined)
                    DO kind := succ(kind);
                    print_n_kind(kind);
                    defined := defined - [kind];
                    IF   defined <> []
                    THEN write(listing,',');
                  UNTIL defined = [];
                  write(listing,'}')
                END
         END
    END;

  BEGIN (* of print_info *)
    WITH ptr^
    DO BEGIN
         reset_left_margin(0);
         print_newline(1);
         write(listing,name,'  ');
         print_n_kind(kind);
         write(listing,'[',depth:2,']');
         print_error_status(status);
         CASE kind OF
           n_class ,
           n_node  ,
           n_elem  : print_element(ptr);
           n_attr  : print_attribute(ptr);
           n_func  : print_function(ptr);
         OTHERWISE
         END
       END
  END;

BEGIN (* begin of print_name_tree *)
  IF   ptr <> NIL
  THEN WITH ptr^
       DO BEGIN
            print_name_tree(left,depth+1);
            IF   with_all_names OR (kind < n_system)
            THEN print_info;
            print_name_tree(right,depth+1)
          END
END;

PROCEDURE print_tree;
(* This procedure prints the entire identifier tree.                          *)
BEGIN
  perf_start_time(perf_print_id);
  print_newline(2);
  write(listing,'Information of the defined identifiers :');
  IF   with_all_names
  THEN write(listing,' (including predefined identifiers)');
  print_newline(1);
  print_name_tree(nametree,0);
  perf_end_time  (perf_print_id);
END;

END.


My life as a hacker | My home page