PreviousUpNext

15.4.173  src/lib/c-glue/ml-grinder/regexp-lib.pkg

# 2007-09-27 CrT:  I've merged this into  src/lib/regex/glue/regular-expression-matcher-g.pkg
#                  so this code is mostly historical at this point.
#                  I've left it here for now as a forwarding pointer
#                  for when I get around to studying the ml-grinder
#                  code generally. 

# A lazy man's interface to the regexp library.

package reg_exp_lib :> Regexp_Lib {

   package re
       =
       regular_expression_matcher_g (
           package p = perl_regex_parser;
           package e = perl_regex_engine;
       );

   package m  = regex_match_result;

   # For caching compiled regexp 
   #
   package h
       =
       typelocked_hashtable_g (
           type Hash_Key = String
           hash_value = hash_string::hash_string
           same_key = op= : String * String -> Bool
       );

   type regexp = String and text = String


   cache
      =
      h::makeTable (16, Match) : h::Hashtable( re::regexp )

   fun compile regexp
       =
       case h::find cache regexp

         of  THE re => re

          | NULL
                =>
                {   re =   re::compile_string regexp
                in  h::set cache (regexp, re);
                    re
                end

   fun search regexp text
       =
       number_string::scan_string (re::find (compile regexp)) text

   fun getArgs text children
       = 
       {   fun walk (m::Match (THE { pos, len }, children))
               = 
               {   s =   string::substring (text, pos, len);
                   s . list::cat (map walk children);
               ?

             | walk (m::Match (NULL, children))
                   =
                   "" . list::cat (map walk children);

          list::cat (map walk children);
       }

   fun grep regexp text
       = 
       case search regexp text

         of NULL => NULL

          | THE (m::Match(_, children)) => THE (getArgs text children)

   fun extractGroup regexp i text
       =
       case search regexp text

         of  NULL => ""

          | THE m => (    case m::nth (m, i)
                            of NULL => ""
                             | THE { pos, len } => string::substring (text, pos, len)
                     )
                     except _ => ""

   fun extract regexp
       =
       extractGroup regexp 0

   fun look regexp text
       = 
       {   n =   size text;

           fun getc i
               =
               if i >= n   then NULL
                           else THE (string::get_byte_as_char (text, i), i+1);

           re::find (compile regexp) getc;
       }

   fun findAllGroup regexp g text
       = 
       {   look =   look regexp text;

           fun loop s
               = 
               case look s

                 of THE (m, s)
                        => 
                       (case m::nth (m, g) of
                         THE { pos, len } => string::substring (text, pos, len) . loop s
                       | NULL => loop s
                       )

               | NULL => []; 

           loop 0;
       }

   fun findAll regexp
       =
       findAllGroup regexp 0 

   fun matches regexp text
       =
       null_or::not_null (search regexp text) 

   fun match text { cases, default }
       = 
       {   fun loop []
                   =
                   default ()

             | loop((regexp, action) . rest)
                   = 
                   case grep regexp text

                     of NULL     =>   loop rest
                      | THE args =>   action args;

           loop cases;
       }

   fun subst regexp f text
       = 
       case search regexp text

         of NULL => text

          | THE (m::Match (THE { pos, len }, children))
                =>
                {   prefix =   string::extract (text, 0, THE pos);
                    suffix =   string::extract (text, pos+len, NULL);
                    prefix + f (getArgs text children) + suffix;
                }
          | THE _ => raise exception INDEX_OUT_OF_BOUNDS

   fun substAll regexp f text
       = 
       {   look =   look regexp text;

           fun loop s
               =
               case look s

                 of NULL => [if s == 0 then text else string::extract (text, s, NULL)]

                  | THE (m::Match (THE { pos, len }, children), s')
                    =>
                    {   prefix =   string::substring (text, s, pos-s);

                        prefix . f (getArgs text children) . loop s';
                    }

                  | THE _ => raise exception INDEX_OUT_OF_BOUNDS;

           string::cat (loop 0);
       }

   fun replace    regexp s =   subst    regexp (\\ _ => s) 
   fun replaceAll regexp s =   substAll regexp (\\ _ => s) 

};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext