1 /********************* */
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Andres Noetzli
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8 ** in the top-level source directory and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief Implementation of utility functions for words.
15 #include "theory/strings/word.h"
17 #include "expr/sequence.h"
18 #include "util/string.h"
20 using namespace cvc5::kind
;
26 Node
Word::mkEmptyWord(TypeNode tn
)
30 std::vector
<unsigned> vec
;
31 return NodeManager::currentNM()->mkConst(String(vec
));
33 else if (tn
.isSequence())
35 std::vector
<Node
> seq
;
36 return NodeManager::currentNM()->mkConst(
37 Sequence(tn
.getSequenceElementType(), seq
));
43 Node
Word::mkWordFlatten(const std::vector
<Node
>& xs
)
46 NodeManager
* nm
= NodeManager::currentNM();
47 Kind k
= xs
[0].getKind();
48 if (k
== CONST_STRING
)
50 std::vector
<unsigned> vec
;
53 Assert(x
.getKind() == CONST_STRING
);
54 String sx
= x
.getConst
<String
>();
55 const std::vector
<unsigned>& vecc
= sx
.getVec();
56 vec
.insert(vec
.end(), vecc
.begin(), vecc
.end());
58 return nm
->mkConst(String(vec
));
60 else if (k
== CONST_SEQUENCE
)
62 std::vector
<Node
> seq
;
63 TypeNode tn
= xs
[0].getType();
66 Assert(x
.getType() == tn
);
67 const Sequence
& sx
= x
.getConst
<Sequence
>();
68 const std::vector
<Node
>& vecc
= sx
.getVec();
69 seq
.insert(seq
.end(), vecc
.begin(), vecc
.end());
71 return NodeManager::currentNM()->mkConst(
72 Sequence(tn
.getSequenceElementType(), seq
));
78 size_t Word::getLength(TNode x
)
81 if (k
== CONST_STRING
)
83 return x
.getConst
<String
>().size();
85 else if (k
== CONST_SEQUENCE
)
87 return x
.getConst
<Sequence
>().size();
89 Unimplemented() << "Word::getLength on " << x
;
93 std::vector
<Node
> Word::getChars(TNode x
)
96 std::vector
<Node
> ret
;
97 NodeManager
* nm
= NodeManager::currentNM();
98 if (k
== CONST_STRING
)
100 std::vector
<unsigned> ccVec
;
101 const std::vector
<unsigned>& cvec
= x
.getConst
<String
>().getVec();
102 for (unsigned chVal
: cvec
)
105 ccVec
.push_back(chVal
);
106 Node ch
= nm
->mkConst(String(ccVec
));
111 else if (k
== CONST_SEQUENCE
)
113 TypeNode t
= x
.getConst
<Sequence
>().getType();
114 const Sequence
& sx
= x
.getConst
<Sequence
>();
115 const std::vector
<Node
>& vec
= sx
.getVec();
116 for (const Node
& v
: vec
)
118 ret
.push_back(nm
->mkConst(Sequence(t
, {v
})));
126 bool Word::isEmpty(TNode x
) { return x
.isConst() && getLength(x
) == 0; }
128 bool Word::strncmp(TNode x
, TNode y
, std::size_t n
)
130 Kind k
= x
.getKind();
131 if (k
== CONST_STRING
)
133 Assert(y
.getKind() == CONST_STRING
);
134 String sx
= x
.getConst
<String
>();
135 String sy
= y
.getConst
<String
>();
136 return sx
.strncmp(sy
, n
);
138 else if (k
== CONST_SEQUENCE
)
140 Assert(y
.getKind() == CONST_SEQUENCE
);
141 const Sequence
& sx
= x
.getConst
<Sequence
>();
142 const Sequence
& sy
= y
.getConst
<Sequence
>();
143 return sx
.strncmp(sy
, n
);
149 bool Word::rstrncmp(TNode x
, TNode y
, std::size_t n
)
151 Kind k
= x
.getKind();
152 if (k
== CONST_STRING
)
154 Assert(y
.getKind() == CONST_STRING
);
155 String sx
= x
.getConst
<String
>();
156 String sy
= y
.getConst
<String
>();
157 return sx
.rstrncmp(sy
, n
);
159 else if (k
== CONST_SEQUENCE
)
161 Assert(y
.getKind() == CONST_SEQUENCE
);
162 const Sequence
& sx
= x
.getConst
<Sequence
>();
163 const Sequence
& sy
= y
.getConst
<Sequence
>();
164 return sx
.rstrncmp(sy
, n
);
170 std::size_t Word::find(TNode x
, TNode y
, std::size_t start
)
172 Kind k
= x
.getKind();
173 if (k
== CONST_STRING
)
175 Assert(y
.getKind() == CONST_STRING
);
176 String sx
= x
.getConst
<String
>();
177 String sy
= y
.getConst
<String
>();
178 return sx
.find(sy
, start
);
180 else if (k
== CONST_SEQUENCE
)
182 Assert(y
.getKind() == CONST_SEQUENCE
);
183 const Sequence
& sx
= x
.getConst
<Sequence
>();
184 const Sequence
& sy
= y
.getConst
<Sequence
>();
185 return sx
.find(sy
, start
);
191 std::size_t Word::rfind(TNode x
, TNode y
, std::size_t start
)
193 Kind k
= x
.getKind();
194 if (k
== CONST_STRING
)
196 Assert(y
.getKind() == CONST_STRING
);
197 String sx
= x
.getConst
<String
>();
198 String sy
= y
.getConst
<String
>();
199 return sx
.rfind(sy
, start
);
201 else if (k
== CONST_SEQUENCE
)
203 Assert(y
.getKind() == CONST_SEQUENCE
);
204 const Sequence
& sx
= x
.getConst
<Sequence
>();
205 const Sequence
& sy
= y
.getConst
<Sequence
>();
206 return sx
.rfind(sy
, start
);
212 bool Word::hasPrefix(TNode x
, TNode y
)
214 Kind k
= x
.getKind();
215 if (k
== CONST_STRING
)
217 Assert(y
.getKind() == CONST_STRING
);
218 String sx
= x
.getConst
<String
>();
219 String sy
= y
.getConst
<String
>();
220 return sx
.hasPrefix(sy
);
222 else if (k
== CONST_SEQUENCE
)
224 Assert(y
.getKind() == CONST_SEQUENCE
);
225 const Sequence
& sx
= x
.getConst
<Sequence
>();
226 const Sequence
& sy
= y
.getConst
<Sequence
>();
227 return sx
.hasPrefix(sy
);
233 bool Word::hasSuffix(TNode x
, TNode y
)
235 Kind k
= x
.getKind();
236 if (k
== CONST_STRING
)
238 Assert(y
.getKind() == CONST_STRING
);
239 String sx
= x
.getConst
<String
>();
240 String sy
= y
.getConst
<String
>();
241 return sx
.hasSuffix(sy
);
243 else if (k
== CONST_SEQUENCE
)
245 Assert(y
.getKind() == CONST_SEQUENCE
);
246 const Sequence
& sx
= x
.getConst
<Sequence
>();
247 const Sequence
& sy
= y
.getConst
<Sequence
>();
248 return sx
.hasSuffix(sy
);
254 Node
Word::update(TNode x
, std::size_t i
, TNode t
)
256 NodeManager
* nm
= NodeManager::currentNM();
257 Kind k
= x
.getKind();
258 if (k
== CONST_STRING
)
260 Assert(t
.getKind() == CONST_STRING
);
261 String sx
= x
.getConst
<String
>();
262 String st
= t
.getConst
<String
>();
263 return nm
->mkConst(String(sx
.update(i
, st
)));
265 else if (k
== CONST_SEQUENCE
)
267 Assert(t
.getKind() == CONST_SEQUENCE
);
268 const Sequence
& sx
= x
.getConst
<Sequence
>();
269 const Sequence
& st
= t
.getConst
<Sequence
>();
270 Sequence res
= sx
.update(i
, st
);
271 return nm
->mkConst(res
);
276 Node
Word::replace(TNode x
, TNode y
, TNode t
)
278 NodeManager
* nm
= NodeManager::currentNM();
279 Kind k
= x
.getKind();
280 if (k
== CONST_STRING
)
282 Assert(y
.getKind() == CONST_STRING
);
283 Assert(t
.getKind() == CONST_STRING
);
284 String sx
= x
.getConst
<String
>();
285 String sy
= y
.getConst
<String
>();
286 String st
= t
.getConst
<String
>();
287 return nm
->mkConst(String(sx
.replace(sy
, st
)));
289 else if (k
== CONST_SEQUENCE
)
291 Assert(y
.getKind() == CONST_SEQUENCE
);
292 Assert(t
.getKind() == CONST_SEQUENCE
);
293 const Sequence
& sx
= x
.getConst
<Sequence
>();
294 const Sequence
& sy
= y
.getConst
<Sequence
>();
295 const Sequence
& st
= t
.getConst
<Sequence
>();
296 Sequence res
= sx
.replace(sy
, st
);
297 return nm
->mkConst(res
);
302 Node
Word::substr(TNode x
, std::size_t i
)
304 NodeManager
* nm
= NodeManager::currentNM();
305 Kind k
= x
.getKind();
306 if (k
== CONST_STRING
)
308 String sx
= x
.getConst
<String
>();
309 return nm
->mkConst(String(sx
.substr(i
)));
311 else if (k
== CONST_SEQUENCE
)
313 const Sequence
& sx
= x
.getConst
<Sequence
>();
314 Sequence res
= sx
.substr(i
);
315 return nm
->mkConst(res
);
320 Node
Word::substr(TNode x
, std::size_t i
, std::size_t j
)
322 NodeManager
* nm
= NodeManager::currentNM();
323 Kind k
= x
.getKind();
324 if (k
== CONST_STRING
)
326 String sx
= x
.getConst
<String
>();
327 return nm
->mkConst(String(sx
.substr(i
, j
)));
329 else if (k
== CONST_SEQUENCE
)
331 const Sequence
& sx
= x
.getConst
<Sequence
>();
332 Sequence res
= sx
.substr(i
, j
);
333 return nm
->mkConst(res
);
339 Node
Word::prefix(TNode x
, std::size_t i
) { return substr(x
, 0, i
); }
341 Node
Word::suffix(TNode x
, std::size_t i
)
343 NodeManager
* nm
= NodeManager::currentNM();
344 Kind k
= x
.getKind();
345 if (k
== CONST_STRING
)
347 String sx
= x
.getConst
<String
>();
348 return nm
->mkConst(String(sx
.suffix(i
)));
350 else if (k
== CONST_SEQUENCE
)
352 const Sequence
& sx
= x
.getConst
<Sequence
>();
353 Sequence res
= sx
.suffix(i
);
354 return nm
->mkConst(res
);
360 bool Word::noOverlapWith(TNode x
, TNode y
)
362 Kind k
= x
.getKind();
363 if (k
== CONST_STRING
)
365 Assert(y
.getKind() == CONST_STRING
);
366 String sx
= x
.getConst
<String
>();
367 String sy
= y
.getConst
<String
>();
368 return sx
.noOverlapWith(sy
);
370 else if (k
== CONST_SEQUENCE
)
372 Assert(y
.getKind() == CONST_SEQUENCE
);
373 const Sequence
& sx
= x
.getConst
<Sequence
>();
374 const Sequence
& sy
= y
.getConst
<Sequence
>();
375 return sx
.noOverlapWith(sy
);
381 std::size_t Word::overlap(TNode x
, TNode y
)
383 Kind k
= x
.getKind();
384 if (k
== CONST_STRING
)
386 Assert(y
.getKind() == CONST_STRING
);
387 String sx
= x
.getConst
<String
>();
388 String sy
= y
.getConst
<String
>();
389 return sx
.overlap(sy
);
391 else if (k
== CONST_SEQUENCE
)
393 Assert(y
.getKind() == CONST_SEQUENCE
);
394 const Sequence
& sx
= x
.getConst
<Sequence
>();
395 const Sequence
& sy
= y
.getConst
<Sequence
>();
396 return sx
.overlap(sy
);
402 std::size_t Word::roverlap(TNode x
, TNode y
)
404 Kind k
= x
.getKind();
405 if (k
== CONST_STRING
)
407 Assert(y
.getKind() == CONST_STRING
);
408 String sx
= x
.getConst
<String
>();
409 String sy
= y
.getConst
<String
>();
410 return sx
.roverlap(sy
);
412 else if (k
== CONST_SEQUENCE
)
414 Assert(y
.getKind() == CONST_SEQUENCE
);
415 const Sequence
& sx
= x
.getConst
<Sequence
>();
416 const Sequence
& sy
= y
.getConst
<Sequence
>();
417 return sx
.roverlap(sy
);
423 bool Word::isRepeated(TNode x
)
425 Kind k
= x
.getKind();
426 if (k
== CONST_STRING
)
428 return x
.getConst
<String
>().isRepeated();
430 else if (k
== CONST_SEQUENCE
)
432 return x
.getConst
<Sequence
>().isRepeated();
438 Node
Word::splitConstant(TNode x
, TNode y
, size_t& index
, bool isRev
)
440 Assert(x
.isConst() && y
.isConst());
441 size_t lenA
= getLength(x
);
442 size_t lenB
= getLength(y
);
443 index
= lenA
<= lenB
? 1 : 0;
444 size_t lenShort
= index
== 1 ? lenA
: lenB
;
445 bool cmp
= isRev
? rstrncmp(x
, y
, lenShort
) : strncmp(x
, y
, lenShort
);
448 Node l
= index
== 0 ? x
: y
;
451 size_t new_len
= getLength(l
) - lenShort
;
452 return substr(l
, 0, new_len
);
456 return substr(l
, lenShort
);
459 // not the same prefix/suffix
463 Node
Word::reverse(TNode x
)
465 NodeManager
* nm
= NodeManager::currentNM();
466 Kind k
= x
.getKind();
467 if (k
== CONST_STRING
)
469 String sx
= x
.getConst
<String
>();
470 std::vector
<unsigned> nvec
= sx
.getVec();
471 std::reverse(nvec
.begin(), nvec
.end());
472 return nm
->mkConst(String(nvec
));
474 else if (k
== CONST_SEQUENCE
)
476 const Sequence
& sx
= x
.getConst
<Sequence
>();
477 const std::vector
<Node
>& vecc
= sx
.getVec();
478 std::vector
<Node
> vecr(vecc
.begin(), vecc
.end());
479 std::reverse(vecr
.begin(), vecr
.end());
480 Sequence
res(sx
.getType(), vecr
);
481 return nm
->mkConst(res
);
487 } // namespace strings
488 } // namespace theory