From 7e59cdc766d922b72f74f6c8625d7c9cdafa4752 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Wed, 26 Aug 2015 20:35:02 -0400 Subject: Add functions which operate on strings instead of counted slices --- src/lib.urp | 1 + src/regex.ur | 58 ++++++++++++++++++++++++++++++++++++++++++---------------- src/regex.urs | 25 ++++++++++++++++++------- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/lib.urp b/src/lib.urp index 1339a60..7fcdc82 100644 --- a/src/lib.urp +++ b/src/lib.urp @@ -10,5 +10,6 @@ file /cgGvSqBi.js regex__FFI.js script /cgGvSqBi.js $/list +$/option $/string regex diff --git a/src/regex.ur b/src/regex.ur index 0024561..b379646 100644 --- a/src/regex.ur +++ b/src/regex.ur @@ -20,33 +20,41 @@ fun concat (strings : list string) : string = (* Substrings and matches *) -type substring = {Start : int, Len : int} -type match = {Whole : substring, Groups : list substring} +type counted_substring = {Start : int, Len : int} +type match a = {Whole : a, Groups : list a} -fun substring_offset (delta : int) (substring : substring) : substring = +fun substring_offset (delta : int) (substring : counted_substring) + : counted_substring = {Start = substring.Start + delta, Len = substring.Len} -fun match_offset (delta : int) (match : match) : match = - {Whole = substring_offset delta match.Whole, - Groups = List.mp (substring_offset delta) match.Groups} +fun mp [a ::: Type] [b ::: Type] (f : a -> b) (match : match a) : match b = + {Whole = f match.Whole, Groups = List.mp f match.Groups} + +fun match_offset (delta : int) + : match counted_substring -> match counted_substring = + mp (substring_offset delta) (* Returns the index of the character just _after_ a match. *) -fun after_match (match : match) : int = +fun after_match (match : match counted_substring) : int = match.Whole.Start + match.Whole.Len +fun get_substrings (haystack : string) + : match counted_substring -> match string = + mp (String.substring haystack) + (* Unmarshaling FFI types *) structure FFI = Regex__FFI (* Unmarshals an 'FFI.substring_t' from C into Ur. *) -fun unmarshal_substring (substring : FFI.substring_t) : substring = +fun unmarshal_substring (substring : FFI.substring_t) : counted_substring = {Start = FFI.substring_start substring, Len = FFI.substring_length substring} (* Unmarshals an 'FFI.substring_list_t' from C into Ur. *) fun unmarshal_substring_list (substrings : FFI.substring_list_t) - : option match = + : option (match counted_substring) = case FFI.substring_list_length substrings of 0 => None | n_groups => @@ -70,11 +78,14 @@ fun validate (regex : string) : string = then regex else error regex: Empty regex -fun match needle haystack = +fun match' needle haystack = unmarshal_substring_list (FFI.do_match (validate needle) haystack) -fun all_matches needle haystack = - case match needle haystack of +fun match needle haystack = + Option.mp (get_substrings haystack) (match' needle haystack) + +fun all_matches' needle haystack = + case match' needle haystack of None => [] | Some match => let @@ -82,14 +93,17 @@ fun all_matches needle haystack = in match :: List.mp (match_offset remaining_start) - (all_matches needle + (all_matches' needle (String.suffix haystack remaining_start)) end -fun transform needle f_nomatch f_match haystack = +fun all_matches needle haystack = + List.mp (get_substrings haystack) (all_matches' needle haystack) + +fun transform' needle f_nomatch f_match haystack = let val haystack_length = String.length haystack - val matches = all_matches needle haystack + val matches = all_matches' needle haystack in (* Handle the first nonmatching region. *) f_nomatch {Start = 0, @@ -122,8 +136,20 @@ fun transform needle f_nomatch f_match haystack = matches) end +fun transform needle f_nomatch f_match haystack = + transform' needle + (fn s => f_nomatch (String.substring haystack s)) + (fn m => f_match (get_substrings haystack m)) + haystack + +fun transform_matches' needle f_match haystack = + transform' needle (String.substring haystack) f_match haystack + fun transform_matches needle f_match haystack = - transform needle (String.substring haystack) f_match haystack + transform' needle + (String.substring haystack) + (fn m => f_match (get_substrings haystack m)) + haystack fun replace needle haystack replacement = transform_matches needle (fn _ => replacement) haystack diff --git a/src/regex.urs b/src/regex.urs index 6e7bdcc..d3b0815 100644 --- a/src/regex.urs +++ b/src/regex.urs @@ -16,8 +16,8 @@ specific language governing permissions and limitations under the License. *) This library implements ECMAScript regular expressions. *) -type substring = {Start : int, Len : int} -type match = {Whole : substring, Groups : list substring} +type match a = {Whole : a, Groups : list a} +type counted_substring = {Start : int, Len : int} (* Searching *) @@ -25,12 +25,14 @@ type match = {Whole : substring, Groups : list substring} 'Some match' if a match succeeds and 'None' otherwise. *) val match : string (* needle *) -> string (* haystack *) - -> option match + -> option (match string) +val match' : string -> string -> option (match counted_substring) (* Finds _all_ matches for a regular expression in a string. *) val all_matches : string (* needle *) -> string (* haystack *) - -> list match + -> list (match string) +val all_matches' : string -> string -> list (match counted_substring) (* Replacement *) @@ -44,9 +46,13 @@ val replace : string (* needle *) (* Transforms a string by applying a function to replace every match in the string. *) val transform_matches : string (* needle *) - -> (match -> string) (* transformation *) + -> (match string -> string) (* transformation *) -> string (* haystack *) -> string +val transform_matches' : string + -> (match counted_substring -> string) + -> string + -> string (* Executes a general regex-guided transformation over a string. Matches 'needle' against any part of 'haystack', splitting 'haystack' into matching and @@ -74,7 +80,12 @@ evaluates to "_a_*x*_b_*x*__" *) val transform : string (* needle *) - -> (substring -> string) (* non-matching transformation *) - -> (match -> string) (* matching transformation *) + -> (string -> string) (* non-matching transformation *) + -> (match string -> string) (* matching transformation *) -> string (* haystack *) -> string +val transform' : string + -> (counted_substring -> string) + -> (match counted_substring -> string) + -> string + -> string -- cgit v1.2.3