3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 19:27:06 +00:00

escape characters in theory_str

This commit is contained in:
Murphy Berzish 2016-11-22 18:21:40 -05:00
parent 5e37a21802
commit 11d8ffc4d4
3 changed files with 72 additions and 1 deletions

View file

@ -339,6 +339,70 @@ str_util::str_util(ast_manager &m) :
m_fid = m_plugin->get_family_id();
}
/*
* Scan through the string 'val' and interpret each instance of "backslash followed by a character"
* as a possible escape sequence. Emit all other characters as-is.
* This exists because the SMT-LIB 2.5 standard does not recognize escape sequences other than "" -> " .
* The escape sequences recognized are as follows:
* \a \b \e \f \n \r \t \v : as specified by the C++ standard
* \ooo : produces the ASCII character corresponding to the octal value "ooo", where each "o" is a
* single octal digit and between 1 and 3 valid digits are given
* \xhh : produces the ASCII character corresponding to the hexadecimal value "hh", where each "h" is a
* single case-insensitive hex digit (0-9A-F) and exactly 2 digits are given
* \C, for any character C that does not start a legal escape sequence : the backslash is ignored and "C" is produced.
*/
app * str_util::mk_string_with_escape_characters(std::string & val) {
std::string parsedStr;
parsedStr.reserve(val.length());
for (unsigned i = 0; i < val.length(); ++i) {
char nextChar = val.at(i);
if (nextChar == '\\') {
// check escape sequence
i++;
if (i >= val.length()) {
// TODO illegal escape sequence
NOT_IMPLEMENTED_YET();
}
char escapeChar1 = val.at(i);
if (escapeChar1 == 'a') {
parsedStr.push_back('\a');
} else if (escapeChar1 == 'b') {
parsedStr.push_back('\b');
} else if (escapeChar1 == 'e') {
parsedStr.push_back('\e');
} else if (escapeChar1 == 'f') {
parsedStr.push_back('\f');
} else if (escapeChar1 == 'n') {
parsedStr.push_back('\n');
} else if (escapeChar1 == 'r') {
parsedStr.push_back('\r');
} else if (escapeChar1 == 't') {
parsedStr.push_back('\t');
} else if (escapeChar1 == 'v') {
parsedStr.push_back('\v');
} else if (escapeChar1 == 'x') {
// TODO hex escape
NOT_IMPLEMENTED_YET();
} else if (escapeChar1 == '0' || escapeChar1 == '1' || escapeChar1 == '2' || escapeChar1 == '3' ||
escapeChar1 == '4' || escapeChar1 == '5' || escapeChar1 == '6' || escapeChar1 == '7') {
// TODO octal escape
NOT_IMPLEMENTED_YET();
} else {
// unrecognized escape sequence -- just emit that character
parsedStr.push_back(escapeChar1);
}
} else {
parsedStr.push_back(nextChar);
}
// i is incremented at the end of this loop.
// If it is modified, ensure that it points to the index before
// the next character.
}
return mk_string(parsedStr);
}
static std::string str2RegexStr(std::string str) {
std::string res = "";
int len = str.size();

View file

@ -156,10 +156,17 @@ public:
app * mk_string(std::string & val) {
return m_plugin->mk_string(val);
}
app * mk_fresh_string() {
return m_plugin->mk_fresh_string();
}
app * mk_string_with_escape_characters(const char * val) {
std::string str(val);
return mk_string_with_escape_characters(str);
}
app * mk_string_with_escape_characters(std::string & val);
app * mk_re_Str2Reg(expr * s) {
expr * es[1] = {s};
return m_manager.mk_app(get_fid(), OP_RE_STR2REGEX, 1, es);

View file

@ -1104,7 +1104,7 @@ namespace smt2 {
strncpy(buf, original_token, bufsize);
buf[bufsize] = '\0';
TRACE("parse_string", tout << "new string constant: " << buf << " length=" << bufsize << "\n";);
expr_stack().push_back(strutil().mk_string(buf));
expr_stack().push_back(strutil().mk_string_with_escape_characters(buf));
next();
}