Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/cm/util/subst.sml
ViewVC logotype

Annotation of /sml/trunk/src/cm/util/subst.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 873 - (view) (download)

1 : blume 873 (*
2 :     * A string substitution facility.
3 :     *
4 :     * (C) 2001 Lucent Technologies, Bell Labs
5 :     *
6 :     * author: Matthias Blume (blume@research.bell-labs.com)
7 :     *)
8 :     structure Subst :> sig
9 :    
10 :     type substitution = Substring.substring -> string option
11 :    
12 :     (* Given the spec (1st argument), scan the second argument for
13 :     * all occurences of prefixes and try the substitutions (left-to-right)
14 :     * associated with the matching prefix until one matches. *)
15 :     val substitute :
16 :     { prefix : string, substitutions: substitution list } list ->
17 :     string -> string
18 :    
19 :     (* a simple string replacement substitution *)
20 :     val subfor : string -> string -> substitution
21 :    
22 :     (* given prefix length and stop character, use a given substitution
23 :     * on the subslice without prefix and stop char *)
24 :     val submap : int * char -> substitution -> substitution
25 :    
26 :     (* a list selection substitution:
27 :     * The first argument is the general spec, the second argument is the
28 :     * list to select from. The general spec consists of:
29 :     * - the length of the prefix (the prefix will be ignored),
30 :     * - the stop character (which will also be ignored
31 :     * - a selector that extracts the substitution string from a list element
32 :     * - a separator string used when n = 0 or missing (the whole list gets
33 :     * inserted in this case, with the separator string separating elements)
34 :     *)
35 :     val subnsel : int * char * ('a -> string) * string -> 'a list -> substitution
36 :    
37 :     end = struct
38 :    
39 :     structure SS = Substring
40 :    
41 :     type substitution = SS.substring -> string option
42 :    
43 :     fun substitute rules = let
44 :     val rules =
45 :     map (fn { prefix, substitutions } => { prefix = SS.all prefix,
46 :     substitutions = substitutions })
47 :     rules
48 :     fun doit s = let
49 :     val len = size s
50 :     fun loop (i0, i, acc) = let
51 :     fun matchingrule { prefix, substitutions } = let
52 :     val plen = SS.size prefix
53 :     in
54 :     i + plen <= len andalso
55 :     SS.compare (prefix, SS.substring (s, i, plen)) = EQUAL
56 :     end
57 :     fun findrule () =
58 :     Option.map #substitutions (List.find matchingrule rules)
59 :     fun newacc k =
60 :     if k > i0 then SS.substring (s, i0, k - i0) :: acc else acc
61 :     in
62 :     if i >= len then SS.concat (rev (newacc len))
63 :     else case findrule () of
64 :     NONE => loop (i0, i + 1, acc)
65 :     | SOME substitutions => let
66 :     val acc = newacc i
67 :     fun dosubst j = let
68 :     fun finddosubst [] = dosubst (j + 1)
69 :     | finddosubst (replace :: sl) = let
70 :     val ss = SS.substring (s, i, j - i)
71 :     in
72 :     case replace ss of
73 :     NONE => finddosubst sl
74 :     | SOME r => loop (j, j, SS.all r :: acc)
75 :     end
76 :     in
77 :     if j > len then loop (i, len, acc)
78 :     else finddosubst substitutions
79 :     end
80 :     in
81 :     dosubst (i + 1)
82 :     end
83 :     end
84 :     in
85 :     loop (0, 0, [])
86 :     end
87 :     in
88 :     doit
89 :     end
90 :    
91 :     fun subfor p r ss = if Substring.compare (Substring.all p, ss) = EQUAL then SOME r
92 :     else NONE
93 :    
94 :     fun submap (plen, stopchar) m ss = let
95 :     val sslen = SS.size ss
96 :     in
97 :     if SS.sub (ss, sslen - 1) = stopchar then
98 :     m (SS.slice (ss, plen, SOME (sslen - plen - 1)))
99 :     else NONE
100 :     end
101 :    
102 :     fun subnsel (plen, stopchar, sel, sep) l ss = let
103 :     fun m numslice = let
104 :     val nums = SS.string numslice
105 :     fun concatWith sep l = (* String.concatWith sep l *)
106 :     let fun build [] = []
107 :     | build [x] = [x]
108 :     | build (x :: xs) = x :: sep :: build xs
109 :     in
110 :     concat (build l)
111 :     end
112 :     fun all () = SOME (concatWith sep (map sel l))
113 :     fun seli i =
114 :     SOME (sel (List.nth (l, i))
115 :     handle General.Subscript => SS.string ss)
116 :     in
117 :     if nums = "" then all ()
118 :     else case Int.fromString nums of
119 :     SOME 0 => all ()
120 :     | SOME i => seli (i - 1)
121 :     | NONE => SOME (SS.string ss)
122 :     end
123 :     in
124 :     submap (plen, stopchar) m ss
125 :     end
126 :    
127 :     end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0