PreviousUpNext

15.4.152  src/app/yacc/src/print-package-g.pkg

#  Mythryl-Yacc Parser Generator (c) 1989 Andrew W. Appel, David R. Tarditi 

# Compiled by:
#     src/app/yacc/src/mythryl-yacc.lib

###                "Laughter without a tinge of philosophy
###                 is but a sneeze of humor.
###
###                "Genuine humor is replete with wisdom."
###
###                                 -- Mark Twain,
###                                    quoted in Mark Twain and I,
###                                    Opie Read



generic package print_package_g (

    package lr_table:         Lr_Table;                 # Lr_Table              is from   src/app/yacc/lib/base.api
    package shrink_lr_table:  Shrink_Lr_Table;          # Shrink_Lr_Table       is from   src/app/yacc/src/shrink-lr-table.api

    sharing lr_table == shrink_lr_table::lr_table;
)
: (weak) Print_Package          # Print_Package is from   src/app/yacc/src/print-package.api
{
    include package   rw_vector;
    include package   list;

    infix my 9 sub;

    package lr_table = lr_table;

    include package   shrink_lr_table;
    include package   lr_table;


    # line_length = approximately the largest number of characters to allow
    # on a line when printing out an encode string

    line_length = 72;

    # max_length = length of a table entry.  All table entries are encoded
    # using two 16-bit integers, one for the terminal number and the other
    # for the entry.  Each integer is printed as two characters (low byte,
    # high byte), using the ML ascii escape sequence.  We need 4
    #    characters for each escape sequence and 16 characters for each entry

    max_length =  16;

    #  number of entries we can fit on a row 

    entry_count = line_length / max_length;

    # convert integer between 0 and 255 to the three character ascii
    # decimal escape sequence for it

    stipulate
        lookup = rw_vector::make_rw_vector (256, "\x00");

#       fun int_to_string i
#            =
#           if   (i >= 100) "\\"   + (int::to_string i);
#           elif (i >=  10) "\\0"  + (int::to_string i);
#           else            "\\00" + (int::to_string i);
#            fi;

        fun int_to_string i
            =
            sprintf "\\x%02x" i;

        fun loop n
            =
            if (n !=256)
                  rw_vector::set (lookup, n, int_to_string n);
                  loop (n+1);
            fi;

        my _ = loop 0;

    herein

        fun chr i
            =
            lookup[ i ];
    end;

    fun make_package { table, name, print, verbose }
        =
        entries
        where 

            states =   state_count table;
            rules  =   rule_count  table;

            fun print_pair_list (print_start:  (X, Y) -> Void) l
                =
                f (l, 0)
                where
                    fun f (EMPTY, _) => ();

                         f (PAIR (a, b, r), count)
                              =>
                              if (count >= entry_count)
                                  #  
                                  print "\\\n\\"; print_start (a, b); f (r, 1);
                              else
                                  print_start (a, b); f (r, (count+1));
                              fi;
                    end;
                end;

            fun print_list print_start l
                =
                f (l, 0)
                where 
                    fun f (NIL, _)
                            =>
                            ();

                        f (a ! r, count)
                           =>
                           if (count >= entry_count)
                               #  
                               print "\\\n\\";
                               print_start a;
                               f (r, 1);
                           else
                               print_start a;
                               f (r, count+1);
                           fi;
                    end;
                end;

            fun print_finish _
                =
                print "\\x00\\x00\\\n\\";

            fun print_pair_row print_start
                =
                \\ entrylist
                    =
                    {   print_entries entrylist;
                        print_finish();
                    }
                    where 
                        print_entries
                            =
                            print_pair_list   print_start;
            end;

            fun print_pair_row_with_default (print_start, pr_default)
                =
                {  f = print_pair_row print_start;

                   \\ (l, default)
                       =
                       {   pr_default default;
                           f l;
                       };
                };

            fun print_table (print_row, count)
                =
                {   print "\"\\\n\\";

                    f 0
                    where
                        fun f i
                            =
                            if   (i != count)
                                
                                 print_row i;
                                 f (i+1);
                            fi;
                    end;

                    print "\";\n";
                };

            print_char
                =
                print o chr;


            # Print an integer between 0 and 2^16-1 as a
            # 2-byte character, with the low byte first:
            #
            fun print_int i
                =
                {   print_char (i % 256);
                    print_char (i / 256);
                };

            # encode actions as integers:
            #
            #   ACCEPT => 0
            #   ERROR => 1
            #   SHIFT i => 2 + i
            #   REDUCE rulenum => numstates+2+rulenum


            fun print_action (REDUCE rulenum)  =>   print_int (rulenum+states+2);
                print_action (SHIFT (STATE i)) =>   print_int (i+2);
                print_action ACCEPT            =>   print_int 0;
                print_action ERROR             =>   print_int 1;
            end;

            fun print_terminal_action (TERM t, action)
                =
                {   print_int (t+1);
                    print_action action;
                };

            fun print_goto (NONTERM n, STATE s)
                =
                {   print_int (n+1);
                    print_int s;
                };

            my ((row_count, row_numbers, action_rows), entries)
                = 
                shrink_action_list (table, verbose);

            stipulate
                a =   rw_vector::from_list   action_rows;
            herein
                fun get_action_row i
                    =
                    a[ i ];
            end;

            fun print_goto_row i
               = 
               f (g (STATE i))
               where 

                   f =   print_pair_row print_goto;
                   g =   describe_goto table;
               end;

           fun print_action_row i
              =
              f (get_action_row i)
              where 

                  f =   print_pair_row_with_default
                           (   print_terminal_action,
                               print_action
                           );
              end;

           print "my ";
           print name;
           print "=";
           print "{   action_rows =\n";
           print_table (print_action_row, row_count);
           print "    action_row_numbers =\n\"";
           print_list (\\ i => print_int i; end ) row_numbers;
           print "\";\n";
           print "   goto_table =\n"; 
           print_table (print_goto_row, states);
           print "   numstates = ";
           print (int::to_string states);
           print ";\n   numrules = ";
           print (int::to_string rules);
           print ";\n\
                  \ s = REF \"\";  index = REF 0;\n\
                  \    string_to_int = \\\\ () = \n\
                  \    {    i = *index;\n\
                  \         index := i+2;\n\
                  \         string::get_byte(*s, i) + string::get_byte(*s, i+1) * 256;\n\
                  \    };\n\
                  \\n\
                  \    string_to_list = \\\\ s' =\n\
                  \    {   len = string::length_in_bytes s';\n\
                  \        fun f () =\n\
                  \           if (*index < len)\n\
                  \           string_to_int() ! f();\n\
                  \           else NIL; fi;\n\
                  \        index := 0;\n\
                  \        s := s';\n\
                  \        f ();\n\
                  \   };\n\
                  \\n\
                  \   string_to_pairlist =   \\\\ (conv_key, conv_entry) =   f\n\
                  \   where \n\
                  \         fun f ()\n\
                  \             =\n\
                  \             case (string_to_int ())\n\
                  \                 0 => EMPTY;\n\
                  \                 n => PAIR (conv_key (n - 1), conv_entry (string_to_int()), f());\n\
                  \             esac;\n\
                  \   end;\n\
                  \\n\
                  \   string_to_pairlist_default =   \\\\ (conv_key, conv_entry) =\n\
                  \    {   conv_row = string_to_pairlist (conv_key, conv_entry);\n\
                  \       \\\\ () =\n\
                  \       {   default = conv_entry (string_to_int());\n\
                  \           row = conv_row();\n\
                  \          (row, default);\n\
                  \       };\n\
                  \   };\n\
                  \\n\
                  \    string_to_table = \\\\ (convert_row, s') =\n\
                  \    {   len = string::length_in_bytes s';\n\
                  \        fun f ()\n\
                  \            =\n\
                  \           if (*index < len)\n\
                  \              convert_row() ! f();\n\
                  \           else NIL; fi;\n\
                  \        s := s';\n\
                  \        index := 0;\n\
                  \        f ();\n\
                  \     };\n\
                  \\n\
                  \stipulate\n\
                  \  memo = rw_vector::make_rw_vector (numstates+numrules, ERROR);\n\
                  \  my _ ={   fun g i\n\
                  \                =\n\
                  \                {   rw_vector::set (memo, i, REDUCE (i-numstates));\n\
                  \                    g (i+1);\n\
                  \                };\n\
                  \\n\
                  \            fun f i\n\
                  \                =\n\
                  \                if   (i == numstates)\n\
                  \                     g i;\n\
                  \                else    rw_vector::set (memo, i, SHIFT (STATE i));\n\
                  \                         f (i+1);\n\
                  \                fi;\n\
                  \\n\
                  \            f 0\n\
                  \            except\n\
                  \                INDEX_OUT_OF_BOUNDS =  ();\n\
                  \        };\n\
                  \herein\n\
                  \    entry_to_action\n\
                  \        =\n\
                  \        \\\\ 0 =>  ACCEPT;\n\
                  \           1 =>  ERROR;\n\
                  \           j =>  rw_vector::get (memo, (j - 2));\n\
                  \        end;\n\
                  \end;\n\
                  \\n\
                  \   goto_table = rw_vector::from_list (string_to_table (string_to_pairlist (NONTERM, STATE), goto_table));\n\
                  \   action_rows = string_to_table (string_to_pairlist_default (TERM, entry_to_action), action_rows);\n\
                  \   action_row_numbers = string_to_list action_row_numbers;\n\
                  \   action_table\n\
                  \    =\n\
                  \    {   action_row_lookup\n\
                  \            =\n\
                  \            {   a=rw_vector::from_list (action_rows);\n\
                  \\n\
                  \                \\\\ i =   rw_vector::get (a, i);\n\
                  \            };\n\
                  \\n\
                  \        rw_vector::from_list (map action_row_lookup action_row_numbers);\n\
                  \    };\n\
                  \\n\
                  \    lr_table::make_lr_table {\n\
                  \        actions => action_table,\n\
                  \        gotos   => goto_table,\n\
                  \        rule_count   => numrules,\n\
                  \        state_count  => numstates,\n\
                  \        initial_state => STATE ";

           print (int::to_string ((\\ (STATE i) = i) (initial_state table)));

           print "   };\n\
                 \};\n";
       end;                     # fun make_package
};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext