cvc5-cvc5-1.2.0.src.theory.strings.word.cpp Maven / Gradle / Ivy
The newest version!
/******************************************************************************
* Top contributors (to current version):
* Andrew Reynolds, Aina Niemetz, Andres Noetzli
*
* This file is part of the cvc5 project.
*
* Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
* in the top-level source directory and their institutional affiliations.
* All rights reserved. See the file COPYING in the top-level source
* directory for licensing information.
* ****************************************************************************
*
* Implementation of utility functions for words.
*/
#include "theory/strings/word.h"
#include "expr/sequence.h"
#include "util/string.h"
using namespace cvc5::internal::kind;
namespace cvc5::internal {
namespace theory {
namespace strings {
Node Word::mkEmptyWord(TypeNode tn)
{
if (tn.isString())
{
std::vector vec;
return NodeManager::currentNM()->mkConst(String(vec));
}
else if (tn.isSequence())
{
std::vector seq;
return NodeManager::currentNM()->mkConst(
Sequence(tn.getSequenceElementType(), seq));
}
Unimplemented();
return Node::null();
}
Node Word::mkWordFlatten(const std::vector& xs)
{
Assert(!xs.empty());
NodeManager* nm = NodeManager::currentNM();
Kind k = xs[0].getKind();
if (k == Kind::CONST_STRING)
{
std::vector vec;
for (TNode x : xs)
{
Assert(x.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
const std::vector& vecc = sx.getVec();
vec.insert(vec.end(), vecc.begin(), vecc.end());
}
return nm->mkConst(String(vec));
}
else if (k == Kind::CONST_SEQUENCE)
{
std::vector seq;
TypeNode tn = xs[0].getType();
for (TNode x : xs)
{
Assert(x.getType() == tn);
const Sequence& sx = x.getConst();
const std::vector& vecc = sx.getVec();
seq.insert(seq.end(), vecc.begin(), vecc.end());
}
return NodeManager::currentNM()->mkConst(
Sequence(tn.getSequenceElementType(), seq));
}
Unimplemented();
return Node::null();
}
size_t Word::getLength(TNode x)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
return x.getConst().size();
}
else if (k == Kind::CONST_SEQUENCE)
{
return x.getConst().size();
}
Unimplemented() << "Word::getLength on " << x;
return 0;
}
std::vector Word::getChars(TNode x)
{
Kind k = x.getKind();
std::vector ret;
NodeManager* nm = NodeManager::currentNM();
if (k == Kind::CONST_STRING)
{
std::vector ccVec;
const std::vector& cvec = x.getConst().getVec();
for (unsigned chVal : cvec)
{
ccVec.clear();
ccVec.push_back(chVal);
Node ch = nm->mkConst(String(ccVec));
ret.push_back(ch);
}
return ret;
}
else if (k == Kind::CONST_SEQUENCE)
{
TypeNode t = x.getConst().getType();
const Sequence& sx = x.getConst();
const std::vector& vec = sx.getVec();
for (const Node& v : vec)
{
ret.push_back(nm->mkConst(Sequence(t, {v})));
}
return ret;
}
Unimplemented();
return ret;
}
Node Word::getNth(TNode x, size_t n)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
const std::vector& vec = x.getConst().getVec();
Assert(n < vec.size());
return NodeManager::currentNM()->mkConstInt(vec[n]);
}
else if (k == Kind::CONST_SEQUENCE)
{
const std::vector& vec = x.getConst().getVec();
Assert(n < vec.size());
return vec[n];
}
Unimplemented();
return Node::null();
}
bool Word::isEmpty(TNode x) { return x.isConst() && getLength(x) == 0; }
bool Word::strncmp(TNode x, TNode y, std::size_t n)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.strncmp(sy, n);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.strncmp(sy, n);
}
Unimplemented();
return false;
}
bool Word::rstrncmp(TNode x, TNode y, std::size_t n)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.rstrncmp(sy, n);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.rstrncmp(sy, n);
}
Unimplemented();
return false;
}
std::size_t Word::find(TNode x, TNode y, std::size_t start)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.find(sy, start);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.find(sy, start);
}
Unimplemented();
return 0;
}
std::size_t Word::rfind(TNode x, TNode y, std::size_t start)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.rfind(sy, start);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.rfind(sy, start);
}
Unimplemented();
return 0;
}
bool Word::hasPrefix(TNode x, TNode y)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.hasPrefix(sy);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.hasPrefix(sy);
}
Unimplemented();
return false;
}
bool Word::hasSuffix(TNode x, TNode y)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.hasSuffix(sy);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.hasSuffix(sy);
}
Unimplemented();
return false;
}
Node Word::update(TNode x, std::size_t i, TNode t)
{
NodeManager* nm = NodeManager::currentNM();
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(t.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String st = t.getConst();
return nm->mkConst(String(sx.update(i, st)));
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(t.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& st = t.getConst();
Sequence res = sx.update(i, st);
return nm->mkConst(res);
}
Unimplemented();
return Node::null();
}
Node Word::replace(TNode x, TNode y, TNode t)
{
NodeManager* nm = NodeManager::currentNM();
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
Assert(t.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
String st = t.getConst();
return nm->mkConst(String(sx.replace(sy, st)));
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
Assert(t.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
const Sequence& st = t.getConst();
Sequence res = sx.replace(sy, st);
return nm->mkConst(res);
}
Unimplemented();
return Node::null();
}
Node Word::substr(TNode x, std::size_t i)
{
NodeManager* nm = NodeManager::currentNM();
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
String sx = x.getConst();
return nm->mkConst(String(sx.substr(i)));
}
else if (k == Kind::CONST_SEQUENCE)
{
const Sequence& sx = x.getConst();
Sequence res = sx.substr(i);
return nm->mkConst(res);
}
Unimplemented();
return Node::null();
}
Node Word::substr(TNode x, std::size_t i, std::size_t j)
{
NodeManager* nm = NodeManager::currentNM();
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
String sx = x.getConst();
return nm->mkConst(String(sx.substr(i, j)));
}
else if (k == Kind::CONST_SEQUENCE)
{
const Sequence& sx = x.getConst();
Sequence res = sx.substr(i, j);
return nm->mkConst(res);
}
Unimplemented();
return Node::null();
}
Node Word::prefix(TNode x, std::size_t i) { return substr(x, 0, i); }
Node Word::suffix(TNode x, std::size_t i)
{
NodeManager* nm = NodeManager::currentNM();
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
String sx = x.getConst();
return nm->mkConst(String(sx.suffix(i)));
}
else if (k == Kind::CONST_SEQUENCE)
{
const Sequence& sx = x.getConst();
Sequence res = sx.suffix(i);
return nm->mkConst(res);
}
Unimplemented();
return Node::null();
}
bool Word::noOverlapWith(TNode x, TNode y)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.noOverlapWith(sy);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.noOverlapWith(sy);
}
Unimplemented();
return false;
}
std::size_t Word::overlap(TNode x, TNode y)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.overlap(sy);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.overlap(sy);
}
Unimplemented();
return 0;
}
std::size_t Word::roverlap(TNode x, TNode y)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
Assert(y.getKind() == Kind::CONST_STRING);
String sx = x.getConst();
String sy = y.getConst();
return sx.roverlap(sy);
}
else if (k == Kind::CONST_SEQUENCE)
{
Assert(y.getKind() == Kind::CONST_SEQUENCE);
const Sequence& sx = x.getConst();
const Sequence& sy = y.getConst();
return sx.roverlap(sy);
}
Unimplemented();
return 0;
}
bool Word::isRepeated(TNode x)
{
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
return x.getConst().isRepeated();
}
else if (k == Kind::CONST_SEQUENCE)
{
return x.getConst().isRepeated();
}
Unimplemented();
return false;
}
Node Word::splitConstant(TNode x, TNode y, size_t& index, bool isRev)
{
Assert(x.isConst() && y.isConst());
size_t lenA = getLength(x);
size_t lenB = getLength(y);
index = lenA <= lenB ? 1 : 0;
size_t lenShort = index == 1 ? lenA : lenB;
bool cmp = isRev ? rstrncmp(x, y, lenShort) : strncmp(x, y, lenShort);
if (cmp)
{
Node l = index == 0 ? x : y;
if (isRev)
{
size_t new_len = getLength(l) - lenShort;
return substr(l, 0, new_len);
}
else
{
return substr(l, lenShort);
}
}
// not the same prefix/suffix
return Node::null();
}
Node Word::reverse(TNode x)
{
NodeManager* nm = NodeManager::currentNM();
Kind k = x.getKind();
if (k == Kind::CONST_STRING)
{
String sx = x.getConst();
std::vector nvec = sx.getVec();
std::reverse(nvec.begin(), nvec.end());
return nm->mkConst(String(nvec));
}
else if (k == Kind::CONST_SEQUENCE)
{
const Sequence& sx = x.getConst();
const std::vector& vecc = sx.getVec();
std::vector vecr(vecc.begin(), vecc.end());
std::reverse(vecr.begin(), vecr.end());
Sequence res(sx.getType(), vecr);
return nm->mkConst(res);
}
Unimplemented();
return Node::null();
}
} // namespace strings
} // namespace theory
} // namespace cvc5::internal