1 |
commit: 8838cef4a07903791881cc64c8c5de02370eb38b |
2 |
Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org> |
3 |
AuthorDate: Tue Apr 19 13:35:06 2011 +0000 |
4 |
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org> |
5 |
CommitDate: Wed Apr 20 13:44:30 2011 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=8838cef4 |
7 |
|
8 |
Walker: implement replacement expansion for raw string |
9 |
|
10 |
${parameter/pattern/string} is supported for raw string. We haven't |
11 |
provided any advanced pattern matching yet. Array and positional |
12 |
parameter expansion like ${var[@]/foo/bar} and ${*/foo/bar} are not |
13 |
supported for now. |
14 |
|
15 |
--- |
16 |
bashast/libbashWalker.g | 34 +++++++++++++++++++++++++- |
17 |
scripts/var_expansion.ebuild | 15 +++++++++++ |
18 |
scripts/var_expansion.ebuild.result | 15 +++++++++++ |
19 |
src/core/interpreter.cpp | 36 +++++++++++++++++++++++++++ |
20 |
src/core/interpreter.h | 46 +++++++++++++++++++++++++++++++++++ |
21 |
5 files changed, 145 insertions(+), 1 deletions(-) |
22 |
|
23 |
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g |
24 |
index b6c9a7f..752e470 100644 |
25 |
--- a/bashast/libbashWalker.g |
26 |
+++ b/bashast/libbashWalker.g |
27 |
@@ -194,7 +194,39 @@ var_expansion returns[std::string libbash_value] |
28 |
|^(libbash_name=name_base ARRAY_SIZE) { |
29 |
libbash_value = boost::lexical_cast<std::string>(walker->get_array_length(libbash_name)); |
30 |
} |
31 |
- )); |
32 |
+ )) |
33 |
+ |^(REPLACE_ALL var_name pattern=string_expr (replacement=string_expr)?) { |
34 |
+ libbash_value = walker->do_replace_expansion($var_name.libbash_value, |
35 |
+ std::bind(&interpreter::replace_all, |
36 |
+ std::placeholders::_1, |
37 |
+ pattern.libbash_value, |
38 |
+ replacement.libbash_value), |
39 |
+ $var_name.index); |
40 |
+ } |
41 |
+ |^(REPLACE_AT_END var_name pattern=string_expr (replacement=string_expr)?) { |
42 |
+ libbash_value = walker->do_replace_expansion($var_name.libbash_value, |
43 |
+ std::bind(&interpreter::replace_at_end, |
44 |
+ std::placeholders::_1, |
45 |
+ pattern.libbash_value, |
46 |
+ replacement.libbash_value), |
47 |
+ $var_name.index); |
48 |
+ } |
49 |
+ |^(REPLACE_AT_START var_name pattern=string_expr (replacement=string_expr)?) { |
50 |
+ libbash_value = walker->do_replace_expansion($var_name.libbash_value, |
51 |
+ std::bind(&interpreter::replace_at_start, |
52 |
+ std::placeholders::_1, |
53 |
+ pattern.libbash_value, |
54 |
+ replacement.libbash_value), |
55 |
+ $var_name.index); |
56 |
+ } |
57 |
+ |^(REPLACE_FIRST var_name pattern=string_expr (replacement=string_expr)?) { |
58 |
+ libbash_value = walker->do_replace_expansion($var_name.libbash_value, |
59 |
+ std::bind(&interpreter::replace_first, |
60 |
+ std::placeholders::_1, |
61 |
+ pattern.libbash_value, |
62 |
+ replacement.libbash_value), |
63 |
+ $var_name.index); |
64 |
+ }; |
65 |
|
66 |
word returns[std::string libbash_value] |
67 |
:(num) => libbash_string=num { $libbash_value = libbash_string; } |
68 |
|
69 |
diff --git a/scripts/var_expansion.ebuild b/scripts/var_expansion.ebuild |
70 |
index c45ad1e..9a46277 100644 |
71 |
--- a/scripts/var_expansion.ebuild |
72 |
+++ b/scripts/var_expansion.ebuild |
73 |
@@ -37,3 +37,18 @@ FOO035="${#ARRAY[0]}" |
74 |
FOO036="${#ARRAY[@]}" |
75 |
FOO037="${#ARRAY[*]}" |
76 |
FOO038="${#ARRAY}" |
77 |
+FOO039="Hello World" |
78 |
+FOO040=${FOO039/nothing/nothing} |
79 |
+FOO041=${FOO039/o W/ow} |
80 |
+FOO042=${FOO039//o/e} |
81 |
+FOO043=${FOO039/#He/he} |
82 |
+FOO044=${FOO039/#he/he} |
83 |
+FOO045=${FOO039/%rld/rlD} |
84 |
+FOO046=${FOO039/%rlD/rlD} |
85 |
+FOO047=${FOO039/o W} |
86 |
+FOO048=${FOO039//o} |
87 |
+FOO049=${FOO039/#He} |
88 |
+FOO050=${FOO039/#he} |
89 |
+FOO051=${FOO039/%rld} |
90 |
+FOO052=${FOO039/%rlD} |
91 |
+FOO053=${FOO039/aaaaaaaaaaaa} |
92 |
|
93 |
diff --git a/scripts/var_expansion.ebuild.result b/scripts/var_expansion.ebuild.result |
94 |
index 8bea3b8..ed5fea3 100644 |
95 |
--- a/scripts/var_expansion.ebuild.result |
96 |
+++ b/scripts/var_expansion.ebuild.result |
97 |
@@ -39,3 +39,18 @@ FOO035=2 |
98 |
FOO036=5 |
99 |
FOO037=5 |
100 |
FOO038=2 |
101 |
+FOO039=Hello World |
102 |
+FOO040=Hello World |
103 |
+FOO041=Helloworld |
104 |
+FOO042=Helle Werld |
105 |
+FOO043=hello World |
106 |
+FOO044=Hello World |
107 |
+FOO045=Hello WorlD |
108 |
+FOO046=Hello World |
109 |
+FOO047=Hellorld |
110 |
+FOO048=Hell Wrld |
111 |
+FOO049=llo World |
112 |
+FOO050=Hello World |
113 |
+FOO051=Hello Wo |
114 |
+FOO052=Hello World |
115 |
+FOO053=Hello World |
116 |
|
117 |
diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp |
118 |
index c683315..0ac5699 100644 |
119 |
--- a/src/core/interpreter.cpp |
120 |
+++ b/src/core/interpreter.cpp |
121 |
@@ -24,8 +24,11 @@ |
122 |
|
123 |
#include "core/interpreter.h" |
124 |
|
125 |
+#include <functional> |
126 |
+ |
127 |
#include <boost/algorithm/string/classification.hpp> |
128 |
#include <boost/algorithm/string/join.hpp> |
129 |
+#include <boost/algorithm/string/replace.hpp> |
130 |
#include <boost/algorithm/string/split.hpp> |
131 |
|
132 |
#include "libbashWalker.h" |
133 |
@@ -109,3 +112,36 @@ bool interpreter::call(const std::string& name, |
134 |
|
135 |
return true; |
136 |
} |
137 |
+ |
138 |
+void interpreter::replace_all(std::string& value, |
139 |
+ const std::string& pattern, |
140 |
+ const std::string& replacement) |
141 |
+{ |
142 |
+ boost::replace_all(value, pattern, replacement); |
143 |
+} |
144 |
+ |
145 |
+void interpreter::replace_at_end(std::string& value, |
146 |
+ const std::string& pattern, |
147 |
+ const std::string& replacement) |
148 |
+{ |
149 |
+ if(value.size() >= pattern.size() && |
150 |
+ value.substr(value.size() - pattern.size()) == pattern) |
151 |
+ value.replace(value.size() - pattern.size(), |
152 |
+ pattern.size(), |
153 |
+ replacement); |
154 |
+} |
155 |
+ |
156 |
+void interpreter::replace_at_start(std::string& value, |
157 |
+ const std::string& pattern, |
158 |
+ const std::string& replacement) |
159 |
+{ |
160 |
+ if(value.substr(0, pattern.size()) == pattern) |
161 |
+ value.replace(0, pattern.size(), replacement); |
162 |
+} |
163 |
+ |
164 |
+void interpreter::replace_first(std::string& value, |
165 |
+ const std::string& pattern, |
166 |
+ const std::string& replacement) |
167 |
+{ |
168 |
+ boost::replace_first(value, pattern, replacement); |
169 |
+} |
170 |
|
171 |
diff --git a/src/core/interpreter.h b/src/core/interpreter.h |
172 |
index 22a083e..72b8e3b 100644 |
173 |
--- a/src/core/interpreter.h |
174 |
+++ b/src/core/interpreter.h |
175 |
@@ -563,6 +563,20 @@ public: |
176 |
return value.substr(offset, length); |
177 |
} |
178 |
|
179 |
+ /// \brief perform replacement expansion |
180 |
+ /// \param the name of the varaible that needs to be expanded |
181 |
+ /// \param the function object used to perform expansion |
182 |
+ /// \param array index, use index=0 if it's not an array |
183 |
+ /// \return the expanded value |
184 |
+ std::string do_replace_expansion(const std::string& name, |
185 |
+ std::function<void(std::string&)> replacer, |
186 |
+ const unsigned index) const |
187 |
+ { |
188 |
+ std::string value = resolve<std::string>(name, index); |
189 |
+ replacer(value); |
190 |
+ return value; |
191 |
+ } |
192 |
+ |
193 |
/// \brief get the length of a string variable |
194 |
/// \param the name of the variable |
195 |
/// \return the length |
196 |
@@ -600,5 +614,37 @@ public: |
197 |
/// \param the value of the word |
198 |
//. \param[out] the splitted result |
199 |
void split_word(const std::string& word, std::vector<std::string>& output); |
200 |
+ |
201 |
+ /// \brief perform expansion like ${var//foo/bar} |
202 |
+ /// \param the value to be expanded |
203 |
+ /// \param the pattern used to match the value |
204 |
+ /// \param the replacement string |
205 |
+ static void replace_all(std::string& value, |
206 |
+ const std::string& pattern, |
207 |
+ const std::string& replacement); |
208 |
+ |
209 |
+ /// \brief perform expansion like ${var/%foo/bar} |
210 |
+ /// \param the value to be expanded |
211 |
+ /// \param the pattern used to match the value |
212 |
+ /// \param the replacement string |
213 |
+ static void replace_at_end(std::string& value, |
214 |
+ const std::string& pattern, |
215 |
+ const std::string& replacement); |
216 |
+ |
217 |
+ /// \brief perform expansion like ${var/#foo/bar} |
218 |
+ /// \param the value to be expanded |
219 |
+ /// \param the pattern used to match the value |
220 |
+ /// \param the replacement string |
221 |
+ static void replace_at_start(std::string& value, |
222 |
+ const std::string& pattern, |
223 |
+ const std::string& replacement); |
224 |
+ |
225 |
+ /// \brief perform expansion like ${var/foo/bar} |
226 |
+ /// \param the value to be expanded |
227 |
+ /// \param the pattern used to match the value |
228 |
+ /// \param the replacement string |
229 |
+ static void replace_first(std::string& value, |
230 |
+ const std::string& pattern, |
231 |
+ const std::string& replacement); |
232 |
}; |
233 |
#endif |