| 1 | # Copyright 2001, 2002 Dave Abrahams |
|---|
| 2 | # Copyright 2003 Douglas Gregor |
|---|
| 3 | # Copyright 2003 Rene Rivera |
|---|
| 4 | # Copyright 2002, 2003, 2004, 2005 Vladimir Prus |
|---|
| 5 | # Distributed under the Boost Software License, Version 1.0. |
|---|
| 6 | # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
|---|
| 7 | |
|---|
| 8 | # |
|---|
| 9 | # Returns a list of the following substrings: |
|---|
| 10 | # 1) from beginning till the first occurence of 'separator' or till the end, |
|---|
| 11 | # 2) between each occurence of 'separator' and the next occurence, |
|---|
| 12 | # 3) from the last occurence of 'separator' till the end. |
|---|
| 13 | # If no separator is present, the result will contain only one element. |
|---|
| 14 | # |
|---|
| 15 | rule split ( string separator ) |
|---|
| 16 | { |
|---|
| 17 | local result ; |
|---|
| 18 | local s = $(string) ; |
|---|
| 19 | |
|---|
| 20 | # Break pieaces off 's' until it has no separators left. |
|---|
| 21 | local match = 1 ; |
|---|
| 22 | while $(match) |
|---|
| 23 | { |
|---|
| 24 | match = [ MATCH ^(.*)($(separator))(.*) : $(s) ] ; |
|---|
| 25 | if $(match) { |
|---|
| 26 | match += "" ; # in case 3rd item was empty - works around MATCH bug |
|---|
| 27 | result = $(match[3]) $(result) ; |
|---|
| 28 | s = $(match[1]) ; |
|---|
| 29 | } |
|---|
| 30 | } |
|---|
| 31 | # Combine the remaining part at the beginning, which does not have |
|---|
| 32 | # separators, with the pieces broken off. |
|---|
| 33 | # Note that rule's signature does not allow initial s to be empty. |
|---|
| 34 | return $(s) $(result) ; |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | # Returns the concatenated results of Applying regex.split to every |
|---|
| 38 | # element of list using the separator pattern. |
|---|
| 39 | rule split-list ( list * : separator ) |
|---|
| 40 | { |
|---|
| 41 | local result ; |
|---|
| 42 | for s in $(list) |
|---|
| 43 | { |
|---|
| 44 | result += [ split $(s) $(separator) ] ; |
|---|
| 45 | } |
|---|
| 46 | return $(result) ; |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | # Match string against pattern, and return the elements indicated by |
|---|
| 50 | # indices. |
|---|
| 51 | rule match ( pattern : string : indices * ) |
|---|
| 52 | { |
|---|
| 53 | indices ?= 1 2 3 4 5 6 7 8 9 ; |
|---|
| 54 | local x = [ MATCH $(pattern) : $(string) ] ; |
|---|
| 55 | return $(x[$(indices)]) ; |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | # Matches all elements of 'list' agains the 'pattern' |
|---|
| 59 | # and returns a list of the elements indicated by indices of |
|---|
| 60 | # all successfull matches. If 'indices' is omitted returns |
|---|
| 61 | # a list of first paranthethised groups of all successfull |
|---|
| 62 | # matches. |
|---|
| 63 | # |
|---|
| 64 | rule transform ( list * : pattern : indices * ) |
|---|
| 65 | { |
|---|
| 66 | indices ?= 1 ; |
|---|
| 67 | local result ; |
|---|
| 68 | for local e in $(list) |
|---|
| 69 | { |
|---|
| 70 | local m = [ MATCH $(pattern) : $(e) ] ; |
|---|
| 71 | if $(m) |
|---|
| 72 | { |
|---|
| 73 | result += $(m[$(indices)]) ; |
|---|
| 74 | } |
|---|
| 75 | } |
|---|
| 76 | return $(result) ; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | NATIVE_RULE regex : transform ; |
|---|
| 80 | |
|---|
| 81 | # Escapes all of the characters in symbols using the escape symbol |
|---|
| 82 | # escape-symbol for the given string, and returns the escaped string |
|---|
| 83 | rule escape ( string : symbols : escape-symbol ) |
|---|
| 84 | { |
|---|
| 85 | local result = "" ; |
|---|
| 86 | local m = 1 ; |
|---|
| 87 | while $(m) |
|---|
| 88 | { |
|---|
| 89 | m = [ MATCH ^([^$(symbols)]*)([$(symbols)])(.*) : $(string) ] ; |
|---|
| 90 | if $(m) |
|---|
| 91 | { |
|---|
| 92 | m += "" ; # Supposedly a bug fix; borrowed from regex.split |
|---|
| 93 | result = "$(result)$(m[1])$(escape-symbol)$(m[2])" ; |
|---|
| 94 | string = $(m[3]) ; |
|---|
| 95 | } |
|---|
| 96 | } |
|---|
| 97 | string ?= "" ; |
|---|
| 98 | result = "$(result)$(string)" ; |
|---|
| 99 | return $(result) ; |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | # Replaces occurances of a match string in a given string. Returns the |
|---|
| 103 | # new string. The match string can be a regex expression. |
|---|
| 104 | # |
|---|
| 105 | rule replace ( |
|---|
| 106 | string # The string to modify. |
|---|
| 107 | match # The characters to replace. |
|---|
| 108 | replacement # The string to replace with. |
|---|
| 109 | ) |
|---|
| 110 | { |
|---|
| 111 | local result = "" ; |
|---|
| 112 | local parts = 1 ; |
|---|
| 113 | while $(parts) |
|---|
| 114 | { |
|---|
| 115 | parts = [ MATCH ^(.*)($(match))(.*) : $(string) ] ; |
|---|
| 116 | if $(parts) |
|---|
| 117 | { |
|---|
| 118 | parts += "" ; |
|---|
| 119 | result = "$(replacement)$(parts[3])$(result)" ; |
|---|
| 120 | string = $(parts[1]) ; |
|---|
| 121 | } |
|---|
| 122 | } |
|---|
| 123 | string ?= "" ; |
|---|
| 124 | result = "$(string)$(result)" ; |
|---|
| 125 | return $(result) ; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | # Replaces occurances of a match string in a given list of strings. |
|---|
| 129 | # Returns the list of new strings. The match string can be a regex |
|---|
| 130 | # expression. |
|---|
| 131 | # |
|---|
| 132 | # list - the list of strings to modify. |
|---|
| 133 | # match - the search expression. |
|---|
| 134 | # replacement - the string to replace with. |
|---|
| 135 | # |
|---|
| 136 | rule replace-list ( list * : match : replacement ) |
|---|
| 137 | { |
|---|
| 138 | local result ; |
|---|
| 139 | for local e in $(list) |
|---|
| 140 | { |
|---|
| 141 | result += [ replace $(e) $(match) $(replacement) ] ; |
|---|
| 142 | } |
|---|
| 143 | return $(result) ; |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | rule __test__ ( ) |
|---|
| 147 | { |
|---|
| 148 | import assert ; |
|---|
| 149 | |
|---|
| 150 | assert.result a b c : split "a/b/c" / ; |
|---|
| 151 | assert.result "" a b c : split "/a/b/c" / ; |
|---|
| 152 | assert.result "" "" a b c : split "//a/b/c" / ; |
|---|
| 153 | assert.result "" a "" b c : split "/a//b/c" / ; |
|---|
| 154 | assert.result "" a "" b c "" : split "/a//b/c/" / ; |
|---|
| 155 | assert.result "" a "" b c "" "" : split "/a//b/c//" / ; |
|---|
| 156 | |
|---|
| 157 | assert.result a c b d |
|---|
| 158 | : match (.)(.)(.)(.) : abcd : 1 3 2 4 ; |
|---|
| 159 | |
|---|
| 160 | assert.result a b c d |
|---|
| 161 | : match (.)(.)(.)(.) : abcd ; |
|---|
| 162 | |
|---|
| 163 | assert.result ababab cddc |
|---|
| 164 | : match ((ab)*)([cd]+) : abababcddc : 1 3 ; |
|---|
| 165 | |
|---|
| 166 | assert.result a.h c.h |
|---|
| 167 | : transform <a.h> \"b.h\" <c.h> : <(.*)> ; |
|---|
| 168 | |
|---|
| 169 | assert.result a.h b.h c.h |
|---|
| 170 | : transform <a.h> \"b.h\" <c.h> : <([^>]*)>|\"([^\"]*)\" : 1 2 ; |
|---|
| 171 | |
|---|
| 172 | assert.result "^<?xml version=\"1.0\"^>" |
|---|
| 173 | : escape "<?xml version=\"1.0\">" : "&|()<>^" : "^" ; |
|---|
| 174 | |
|---|
| 175 | assert.result "<?xml version=\\\"1.0\\\">" |
|---|
| 176 | : escape "<?xml version=\"1.0\">" : "\\\"" : "\\" ; |
|---|
| 177 | |
|---|
| 178 | assert.result "string string " : replace "string string " " " " " ; |
|---|
| 179 | assert.result " string string" : replace " string string" " " " " ; |
|---|
| 180 | assert.result "string string" : replace "string string" " " " " ; |
|---|
| 181 | assert.result "-" : replace "&" "&" "-" ; |
|---|
| 182 | |
|---|
| 183 | assert.result "-" "a-b" : replace-list "&" "a&b" : "&" : "-" ; |
|---|
| 184 | } |
|---|