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 1148 - (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 : blume 1148 map (fn { prefix, substitutions } =>
46 :     { prefix = SS.all prefix, substitutions = substitutions })
47 : blume 873 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 : blume 1148 | SOME r =>
75 :     loop (j, j, SS.all r :: acc)
76 : blume 873 end
77 :     in
78 :     if j > len then loop (i, len, acc)
79 :     else finddosubst substitutions
80 :     end
81 :     in
82 :     dosubst (i + 1)
83 :     end
84 :     end
85 :     in
86 :     loop (0, 0, [])
87 :     end
88 :     in
89 :     doit
90 :     end
91 :    
92 : blume 1148 fun subfor p r ss =
93 :     if Substring.compare (Substring.all p, ss) = EQUAL then SOME r
94 :     else NONE
95 : blume 873
96 :     fun submap (plen, stopchar) m ss = let
97 :     val sslen = SS.size ss
98 :     in
99 :     if SS.sub (ss, sslen - 1) = stopchar then
100 :     m (SS.slice (ss, plen, SOME (sslen - plen - 1)))
101 :     else NONE
102 :     end
103 :    
104 :     fun subnsel (plen, stopchar, sel, sep) l ss = let
105 :     fun m numslice = let
106 :     val nums = SS.string numslice
107 : blume 1148 fun all () = SOME (String.concatWith sep (map sel l))
108 : blume 873 fun seli i =
109 :     SOME (sel (List.nth (l, i))
110 :     handle General.Subscript => SS.string ss)
111 :     in
112 :     if nums = "" then all ()
113 :     else case Int.fromString nums of
114 :     SOME 0 => all ()
115 :     | SOME i => seli (i - 1)
116 :     | NONE => SOME (SS.string ss)
117 :     end
118 :     in
119 :     submap (plen, stopchar) m ss
120 :     end
121 :    
122 :     end

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