Add escape codes for string literals
parent
75d9f8573b
commit
c03dfc1284
|
@ -1770,6 +1770,24 @@ msgstr ""
|
|||
msgid "This parameter needs a default value"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing end quote"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Octal value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing hex digits after escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hex value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid universal character name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dividing by zero"
|
||||
msgstr ""
|
||||
|
||||
|
|
18
po/de.po
18
po/de.po
|
@ -680,6 +680,9 @@ msgstr "Anweisungen über das ausgewählte Objekt"
|
|||
msgid "Help balloons\\Explain the function of the buttons"
|
||||
msgstr "Hilfeblasen\\Hilfeblasen"
|
||||
|
||||
msgid "Hex value out of range"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Higher speed\\Doubles speed"
|
||||
msgstr "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell"
|
||||
|
@ -759,6 +762,9 @@ msgstr "Anweisungen\\Anweisungen für die Mission oder Übung"
|
|||
msgid "Internal error - tell the developers"
|
||||
msgstr "Interner Fehler - Benachrichtige bitte die Entwickler"
|
||||
|
||||
msgid "Invalid universal character name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invert\\Invert values on this axis"
|
||||
msgstr "Invertieren\\Die Werte dieser Achse invertieren"
|
||||
|
||||
|
@ -869,6 +875,12 @@ msgstr "Verkleinern"
|
|||
msgid "Mipmap level\\Mipmap level"
|
||||
msgstr "Mipmap-Level\\Mipmap-Level"
|
||||
|
||||
msgid "Missing end quote"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing hex digits after escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Mission name"
|
||||
msgstr "Name der Mission"
|
||||
|
||||
|
@ -1031,6 +1043,9 @@ msgstr "OK\\Programm kompilieren"
|
|||
msgid "Object too close"
|
||||
msgstr "Gegenstand zu nahe"
|
||||
|
||||
msgid "Octal value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "One step"
|
||||
msgstr "Ein Schritt"
|
||||
|
||||
|
@ -1632,6 +1647,9 @@ msgstr "Das Objekt existiert nicht"
|
|||
msgid "Unknown command"
|
||||
msgstr "Befehl unbekannt"
|
||||
|
||||
msgid "Unknown escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown function"
|
||||
msgstr "Unbekannte Funktion"
|
||||
|
||||
|
|
18
po/fr.po
18
po/fr.po
|
@ -677,6 +677,9 @@ msgstr "Instructions sur la sélection"
|
|||
msgid "Help balloons\\Explain the function of the buttons"
|
||||
msgstr "Bulles d'aide\\Bulles explicatives"
|
||||
|
||||
msgid "Hex value out of range"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Higher speed\\Doubles speed"
|
||||
msgstr "Vitesse 2.0x\\Deux fois plus rapide"
|
||||
|
@ -756,6 +759,9 @@ msgstr "Instructions mission\\Marche à suivre"
|
|||
msgid "Internal error - tell the developers"
|
||||
msgstr "Erreur interne - contacter les développeurs"
|
||||
|
||||
msgid "Invalid universal character name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invert\\Invert values on this axis"
|
||||
msgstr "Inversion\\Inverse les valeurs sur cet axe"
|
||||
|
||||
|
@ -866,6 +872,12 @@ msgstr "Taille réduite"
|
|||
msgid "Mipmap level\\Mipmap level"
|
||||
msgstr "Niveau de MIP mapping\\Niveau de MIP mapping"
|
||||
|
||||
msgid "Missing end quote"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing hex digits after escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Mission name"
|
||||
msgstr "Nom de la mission"
|
||||
|
||||
|
@ -1028,6 +1040,9 @@ msgstr "D'accord\\Compiler le programme"
|
|||
msgid "Object too close"
|
||||
msgstr "Objet trop proche"
|
||||
|
||||
msgid "Octal value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "One step"
|
||||
msgstr "Un pas"
|
||||
|
||||
|
@ -1629,6 +1644,9 @@ msgstr "Objet n'existe pas"
|
|||
msgid "Unknown command"
|
||||
msgstr "Commande inconnue"
|
||||
|
||||
msgid "Unknown escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown function"
|
||||
msgstr "Routine inconnue"
|
||||
|
||||
|
|
18
po/pl.po
18
po/pl.po
|
@ -678,6 +678,9 @@ msgstr "Pomoc na temat zaznaczonego obiektu"
|
|||
msgid "Help balloons\\Explain the function of the buttons"
|
||||
msgstr "Dymki pomocy\\Wyjaśnia funkcje przycisków"
|
||||
|
||||
msgid "Hex value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "Higher speed\\Doubles speed"
|
||||
msgstr "Zwiększ prędkość\\Podwaja prędkość"
|
||||
|
||||
|
@ -756,6 +759,9 @@ msgstr "Rozkazy\\Pokazuje rozkazy dotyczące bieżącej misji"
|
|||
msgid "Internal error - tell the developers"
|
||||
msgstr "Błąd wewnętrzny - powiadom twórców gry"
|
||||
|
||||
msgid "Invalid universal character name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invert\\Invert values on this axis"
|
||||
msgstr "Odwróć\\Odwróć wartości na tej osi"
|
||||
|
||||
|
@ -852,6 +858,12 @@ msgstr "Pomniejsz"
|
|||
msgid "Mipmap level\\Mipmap level"
|
||||
msgstr "Poziom mipmap\\Poziom mipmap"
|
||||
|
||||
msgid "Missing end quote"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing hex digits after escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Mission name"
|
||||
msgstr "Nazwa misji"
|
||||
|
||||
|
@ -1014,6 +1026,9 @@ msgstr "OK\\Zamyka edytor programu i powraca do gry"
|
|||
msgid "Object too close"
|
||||
msgstr "Obiekt za blisko"
|
||||
|
||||
msgid "Octal value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "One step"
|
||||
msgstr "Jeden krok"
|
||||
|
||||
|
@ -1614,6 +1629,9 @@ msgstr "Obiekt nieznany"
|
|||
msgid "Unknown command"
|
||||
msgstr "Nieznane polecenie"
|
||||
|
||||
msgid "Unknown escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown function"
|
||||
msgstr "Funkcja nieznana"
|
||||
|
||||
|
|
18
po/ru.po
18
po/ru.po
|
@ -686,6 +686,9 @@ msgstr "Справка о выбранном объекте"
|
|||
msgid "Help balloons\\Explain the function of the buttons"
|
||||
msgstr "Подсказки\\Объяснение функций кнопок"
|
||||
|
||||
msgid "Hex value out of range"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Higher speed\\Doubles speed"
|
||||
msgstr "Скорость 2.0х\\В два раза быстрее"
|
||||
|
@ -765,6 +768,9 @@ msgstr "Инструкции\\Показывает инструкции по т
|
|||
msgid "Internal error - tell the developers"
|
||||
msgstr "Внутренняя ошибка - сообщите разработчикам"
|
||||
|
||||
msgid "Invalid universal character name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invert\\Invert values on this axis"
|
||||
msgstr "Инвертир.\\Инвертировать значения по этой оси"
|
||||
|
||||
|
@ -875,6 +881,12 @@ msgstr "Свернуть"
|
|||
msgid "Mipmap level\\Mipmap level"
|
||||
msgstr "Уровень уменьшающей фильтрации\\Уровень уменьшающей фильтрации"
|
||||
|
||||
msgid "Missing end quote"
|
||||
msgstr ""
|
||||
|
||||
msgid "Missing hex digits after escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Mission name"
|
||||
msgstr "Название миссии"
|
||||
|
||||
|
@ -1039,6 +1051,9 @@ msgstr "ОК\\Закрыть редактор программ и вернуть
|
|||
msgid "Object too close"
|
||||
msgstr "Объект слишком близок"
|
||||
|
||||
msgid "Octal value out of range"
|
||||
msgstr ""
|
||||
|
||||
msgid "One step"
|
||||
msgstr "Один шаг"
|
||||
|
||||
|
@ -1645,6 +1660,9 @@ msgstr "Неизвестный объект"
|
|||
msgid "Unknown command"
|
||||
msgstr "Неизвестная команда"
|
||||
|
||||
msgid "Unknown escape sequence"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown function"
|
||||
msgstr "Неизвестная функция"
|
||||
|
||||
|
|
|
@ -241,6 +241,12 @@ enum CBotError : int
|
|||
CBotErrNoClassName = 5046, //!< class name expected
|
||||
CBotErrNoReturn = 5047, //!< non-void function needs "return;"
|
||||
CBotErrDefaultValue = 5048, //!< this parameter needs a default value
|
||||
CBotErrEndQuote = 5049, //!< missing end quote
|
||||
CBotErrBadEscape = 5050, //!< unknown escape sequence
|
||||
CBotErrOctalRange = 5051, //!< octal value out of range
|
||||
CBotErrHexDigits = 5052, //!< missing hex digits after escape sequence
|
||||
CBotErrHexRange = 5053, //!< hex value out of range
|
||||
CBotErrUnicodeName = 5054, //!< invalid universal character name
|
||||
|
||||
// Runtime errors
|
||||
CBotErrZeroDiv = 6000, //!< division by zero
|
||||
|
|
|
@ -42,15 +42,136 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
{
|
||||
CBotCStack* pStk = pStack->TokenStack();
|
||||
|
||||
CBotExprLitString* inst = new CBotExprLitString();
|
||||
std::string s = p->GetString();
|
||||
|
||||
inst->SetToken(p);
|
||||
p = p->GetNext();
|
||||
auto it = s.cbegin();
|
||||
if (++it != s.cend())
|
||||
{
|
||||
int pos = p->GetStart();
|
||||
std::string valstring = "";
|
||||
while (it != s.cend() && *it != '\"')
|
||||
{
|
||||
pStk->SetStartError(++pos);
|
||||
if (*it != '\\') // not escape sequence ?
|
||||
{
|
||||
valstring += *(it++);
|
||||
continue;
|
||||
}
|
||||
|
||||
CBotVar* var = CBotVar::Create("", CBotTypString);
|
||||
pStk->SetVar(var);
|
||||
if (++it == s.cend()) break;
|
||||
|
||||
return pStack->Return(inst, pStk);
|
||||
if (CharInList(*it, "01234567")) // octal
|
||||
{
|
||||
std::string octal = "";
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (!CharInList(*it, "01234567")) break;
|
||||
++pos;
|
||||
octal += *it;
|
||||
if (++it == s.cend()) break;
|
||||
}
|
||||
|
||||
unsigned int val = std::stoi(octal, nullptr, 8);
|
||||
if (val <= 255)
|
||||
{
|
||||
valstring.push_back(val);
|
||||
continue;
|
||||
}
|
||||
pStk->SetError(CBotErrOctalRange, pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
++pos;
|
||||
unsigned char c = *(it++);
|
||||
if (c == '\"' || c == '\'' || c == '\\') valstring += c;
|
||||
else if (c == 'a') valstring += '\a'; // alert bell
|
||||
else if (c == 'b') valstring += '\b'; // backspace
|
||||
else if (c == 'f') valstring += '\f'; // form feed
|
||||
else if (c == 'n') valstring += '\n'; // new line
|
||||
else if (c == 'r') valstring += '\r'; // carriage return
|
||||
else if (c == 't') valstring += '\t'; // horizontal tab
|
||||
else if (c == 'v') valstring += '\v'; // vertical tab
|
||||
else if (c == 'x' || c == 'u' || c == 'U') // hex or unicode
|
||||
{
|
||||
if (it != s.cend())
|
||||
{
|
||||
std::string hex = "";
|
||||
bool isHexCode = (c == 'x');
|
||||
size_t maxlen = (c == 'u') ? 4 : 8;
|
||||
|
||||
for (size_t i = 0; isHexCode || i < maxlen; i++)
|
||||
{
|
||||
if (!CharInList(*it, "0123456789ABCDEFabcdef")) break;
|
||||
++pos;
|
||||
hex += *it;
|
||||
if (++it == s.cend()) break;
|
||||
}
|
||||
|
||||
if (!hex.empty())
|
||||
{
|
||||
unsigned int val = 0;
|
||||
try
|
||||
{
|
||||
val = std::stoi(hex, nullptr, 16);
|
||||
}
|
||||
catch (const std::out_of_range& e)
|
||||
{
|
||||
pStk->SetError(CBotErrHexRange, pos + 1);
|
||||
}
|
||||
|
||||
if (pStk->IsOk())
|
||||
{
|
||||
if (isHexCode) // hexadecimal
|
||||
{
|
||||
if (val <= 255)
|
||||
{
|
||||
valstring.push_back(val);
|
||||
continue;
|
||||
}
|
||||
pStk->SetError(CBotErrHexRange, pos + 1);
|
||||
}
|
||||
else if (maxlen == hex.length()) // unicode character
|
||||
{
|
||||
if (val < 0xD800 || (0xDFFF < val && val < 0x110000))
|
||||
{
|
||||
valstring += CodePointToUTF8(val);
|
||||
continue;
|
||||
}
|
||||
pStk->SetError(CBotErrUnicodeName, pos + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pStk->SetError(CBotErrHexDigits, pos + 1);
|
||||
}
|
||||
else
|
||||
pStk->SetError(CBotErrBadEscape, pos + 1); // unknown escape code
|
||||
}
|
||||
|
||||
if (!pStk->IsOk()) break;
|
||||
}
|
||||
|
||||
if (it == s.cend() || *it != '\"')
|
||||
pStk->SetError(CBotErrEndQuote, p);
|
||||
|
||||
if (pStk->IsOk())
|
||||
{
|
||||
CBotExprLitString* inst = new CBotExprLitString();
|
||||
inst->m_valstring.swap(valstring);
|
||||
inst->SetToken(p);
|
||||
p = p->GetNext();
|
||||
|
||||
CBotVar* var = CBotVar::Create("", CBotTypString);
|
||||
pStk->SetVar(var);
|
||||
|
||||
return pStack->Return(inst, pStk);
|
||||
}
|
||||
}
|
||||
|
||||
pStk->SetError(CBotErrEndQuote, p);
|
||||
return pStack->Return(nullptr, pStk);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -62,10 +183,7 @@ bool CBotExprLitString::Execute(CBotStack* &pj)
|
|||
|
||||
CBotVar* var = CBotVar::Create("", CBotTypString);
|
||||
|
||||
std::string chaine = m_token.GetString();
|
||||
chaine = chaine.substr(1, chaine.length()-2); // removes the quotes
|
||||
|
||||
var->SetValString(chaine); // value of the number
|
||||
var->SetValString(m_valstring);
|
||||
|
||||
pile->SetVar(var); // put on the stack
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ public:
|
|||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotExprLitString"; }
|
||||
virtual std::string GetDebugData() override;
|
||||
|
||||
private:
|
||||
std::string m_valstring = "";
|
||||
};
|
||||
|
||||
} // namespace CBot
|
||||
|
|
|
@ -241,23 +241,13 @@ void CBotToken::SetPos(int start, int end)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CharInList(const char c, const char* list)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (c == list[i++]) return true;
|
||||
if (list[i] == 0) return false;
|
||||
}
|
||||
}
|
||||
|
||||
static char sep1[] = " \r\n\t,:()[]{}-+*/=;><!~^|&%.";
|
||||
static char sep1[] = " \r\n\t,:()[]{}-+*/=;><!~^|&%.\"\'?";
|
||||
static char sep2[] = " \r\n\t"; // only separators
|
||||
static char sep3[] = ",:()[]{}-+*/=;<>!~^|&%."; // operational separators
|
||||
static char sep3[] = ",:()[]{}-+*/=;<>!~^|&%.?"; // operational separators
|
||||
static char num[] = "0123456789"; // point (single) is tested separately
|
||||
static char hexnum[] = "0123456789ABCDEFabcdef";
|
||||
static char nch[] = "\"\r\n\t"; // forbidden in chains
|
||||
static char nch[] = "\r\n\t"; // forbidden in chains
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotToken* CBotToken::NextToken(const char*& program, bool first)
|
||||
|
@ -278,14 +268,13 @@ CBotToken* CBotToken::NextToken(const char*& program, bool first)
|
|||
// special case for strings
|
||||
if (token[0] == '\"' )
|
||||
{
|
||||
while (c != 0 && !CharInList(c, nch))
|
||||
while (c != 0 && c != '\"' && !CharInList(c, nch))
|
||||
{
|
||||
if ( c == '\\' )
|
||||
{
|
||||
c = *(program++); // next character
|
||||
if ( c == 'n' ) c = '\n';
|
||||
if ( c == 'r' ) c = '\r';
|
||||
if ( c == 't' ) c = '\t';
|
||||
token += c;
|
||||
c = *(program++);
|
||||
if (c == 0 || CharInList(c, nch)) break;
|
||||
}
|
||||
token += c;
|
||||
c = *(program++);
|
||||
|
|
|
@ -236,4 +236,49 @@ float GetNumFloat(const std::string& str)
|
|||
return static_cast<float>(num);
|
||||
}
|
||||
|
||||
bool CharInList(const char c, const char* list)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (list[i] != 0)
|
||||
{
|
||||
if (c == list[i++]) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string CodePointToUTF8(unsigned int val)
|
||||
{
|
||||
std::string s = "";
|
||||
|
||||
if (val < 0xD800 || (0xDFFF < val && val < 0x110000))
|
||||
{
|
||||
if (val < 0x80)
|
||||
{
|
||||
s.push_back(val);
|
||||
}
|
||||
else if (val < 0x800)
|
||||
{
|
||||
s.push_back(0xC0 + (val >> 6));
|
||||
s.push_back(0x80 + (val & 0x3F));
|
||||
}
|
||||
else if (val < 0x10000)
|
||||
{
|
||||
s.push_back(0xE0 + (val >> 12));
|
||||
s.push_back(0x80 + ((val >> 6) & 0x3F));
|
||||
s.push_back(0x80 + (val & 0x3F));
|
||||
}
|
||||
else
|
||||
{
|
||||
s.push_back(0xF0 + (val >> 18));
|
||||
s.push_back(0x80 + ((val >> 12) & 0x3F));
|
||||
s.push_back(0x80 + ((val >> 6) & 0x3F));
|
||||
s.push_back(0x80 + (val & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace CBot
|
||||
|
|
|
@ -96,6 +96,21 @@ long GetNumInt(const std::string& str);
|
|||
*/
|
||||
float GetNumFloat(const std::string& str);
|
||||
|
||||
/*!
|
||||
* \brief Search a null-terminated string for a char value.
|
||||
* \param c The char to find.
|
||||
* \param list The string to search.
|
||||
* \return true if the char is found.
|
||||
*/
|
||||
bool CharInList(const char c, const char* list);
|
||||
|
||||
/*!
|
||||
* \brief Converts a Unicode code point to UTF-8 encoded character.
|
||||
* \param val Code point value.
|
||||
* \return UTF-8 encoded string or empty string.
|
||||
*/
|
||||
std::string CodePointToUTF8(unsigned int val);
|
||||
|
||||
template<typename T> class CBotLinkedList
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -731,6 +731,12 @@ void InitializeRestext()
|
|||
stringsCbot[CBot::CBotErrNoClassName] = TR("Class name expected");
|
||||
stringsCbot[CBot::CBotErrNoReturn] = TR("Non-void function needs \"return;\"");
|
||||
stringsCbot[CBot::CBotErrDefaultValue] = TR("This parameter needs a default value");
|
||||
stringsCbot[CBot::CBotErrEndQuote] = TR("Missing end quote");
|
||||
stringsCbot[CBot::CBotErrBadEscape] = TR("Unknown escape sequence");
|
||||
stringsCbot[CBot::CBotErrOctalRange] = TR("Octal value out of range");
|
||||
stringsCbot[CBot::CBotErrHexDigits] = TR("Missing hex digits after escape sequence");
|
||||
stringsCbot[CBot::CBotErrHexRange] = TR("Hex value out of range");
|
||||
stringsCbot[CBot::CBotErrUnicodeName] = TR("Invalid universal character name");
|
||||
|
||||
stringsCbot[CBot::CBotErrZeroDiv] = TR("Dividing by zero");
|
||||
stringsCbot[CBot::CBotErrNotInit] = TR("Variable not initialized");
|
||||
|
|
|
@ -1533,6 +1533,120 @@ TEST_F(CBotUT, String)
|
|||
" ASSERT(c == \"Colobot!\");\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void MissingEndQuote()\n"
|
||||
"{\n"
|
||||
" \"Colobot...\n"
|
||||
"}\n",
|
||||
CBotErrEndQuote
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, StringEscapeCodes)
|
||||
{
|
||||
ExecuteTest(
|
||||
"extern void HexEscapeCodes()\n"
|
||||
"{\n"
|
||||
" ASSERT(\" \\x07 \" == \" \\a \");\n"
|
||||
" ASSERT(\" \\x08 \" == \" \\b \");\n"
|
||||
" ASSERT(\" \\x09 \" == \" \\t \");\n"
|
||||
" ASSERT(\" \\x0A \" == \" \\n \");\n"
|
||||
" ASSERT(\" \\x0B \" == \" \\v \");\n"
|
||||
" ASSERT(\" \\x0C \" == \" \\f \");\n"
|
||||
" ASSERT(\" \\x0D \" == \" \\r \");\n"
|
||||
" ASSERT(\" \\x22 \" == \" \\\" \");\n"
|
||||
" ASSERT(\" \\x27 \" == \" \\\' \");\n"
|
||||
" ASSERT(\" \\x5C \" == \" \\\\ \");\n"
|
||||
" string test = \"\\x31 \\x32 \\x33\";\n"
|
||||
" ASSERT(test == \"1 2 3\");\n"
|
||||
"}\n"
|
||||
"extern void OctalEscapeCodes()\n"
|
||||
"{\n"
|
||||
" ASSERT(\" \\000 \" == \" \\x00 \");\n"
|
||||
" ASSERT(\" \\007 \" == \" \\x07 \");\n"
|
||||
" ASSERT(\" \\010 \" == \" \\x08 \");\n"
|
||||
" ASSERT(\" \\011 \" == \" \\x09 \");\n"
|
||||
" ASSERT(\" \\012 \" == \" \\x0A \");\n"
|
||||
" ASSERT(\" \\013 \" == \" \\x0B \");\n"
|
||||
" ASSERT(\" \\014 \" == \" \\x0C \");\n"
|
||||
" ASSERT(\" \\015 \" == \" \\x0D \");\n"
|
||||
" ASSERT(\" \\042 \" == \" \\x22 \");\n"
|
||||
" ASSERT(\" \\047 \" == \" \\x27 \");\n"
|
||||
" ASSERT(\" \\134 \" == \" \\x5C \");\n"
|
||||
" string test = \"\\101 \\102 \\103\";\n"
|
||||
" ASSERT(test == \"A B C\");\n"
|
||||
"}\n"
|
||||
"extern void UnicodeEscapeCodesToUTF_8()\n"
|
||||
"{\n"
|
||||
" ASSERT(\" \\u0000 \" == \" \\0 \");\n"
|
||||
" ASSERT(\" \\u0007 \" == \" \\a \");\n"
|
||||
" ASSERT(\" \\u0008 \" == \" \\b \");\n"
|
||||
" ASSERT(\" \\u0009 \" == \" \\t \");\n"
|
||||
" ASSERT(\" \\u000A \" == \" \\n \");\n"
|
||||
" ASSERT(\" \\u000B \" == \" \\v \");\n"
|
||||
" ASSERT(\" \\u000C \" == \" \\f \");\n"
|
||||
" ASSERT(\" \\u000D \" == \" \\r \");\n"
|
||||
" ASSERT(\" \\u0022 \" == \" \\\" \");\n"
|
||||
" ASSERT(\" \\u0027 \" == \" \\\' \");\n"
|
||||
" ASSERT(\" \\u005C \" == \" \\\\ \");\n"
|
||||
"\n"
|
||||
" ASSERT(\"\\u00A9\" == \"\\xC2\\xA9\");\n"
|
||||
" ASSERT(\"\\u00AE\" == \"\\xC2\\xAE\");\n"
|
||||
" ASSERT(\"\\u262E\" == \"\\xE2\\x98\\xAE\");\n"
|
||||
" ASSERT(\"\\u262F\" == \"\\xE2\\x98\\xAF\");\n"
|
||||
" ASSERT(\"\\U0001F60E\" == \"\\xF0\\x9F\\x98\\x8E\");\n"
|
||||
" ASSERT(\"\\U0001F61C\" == \"\\xF0\\x9F\\x98\\x9C\");\n"
|
||||
" ASSERT(\"\\U0001F6E0\" == \"\\xF0\\x9F\\x9B\\xA0\");\n"
|
||||
"}\n"
|
||||
"extern void UnicodeMaxCharacterNameToUTF_8()\n"
|
||||
"{\n"
|
||||
" ASSERT(\"\\U0010FFFF\" == \"\\xF4\\x8F\\xBF\\xBF\");\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, StringEscapeCodeErrors)
|
||||
{
|
||||
ExecuteTest(
|
||||
"extern void UnknownEscapeSequence()\n"
|
||||
"{\n"
|
||||
" \"Unknown: \\p \";\n"
|
||||
"}\n",
|
||||
CBotErrBadEscape
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void MissingHexDigits()\n"
|
||||
"{\n"
|
||||
" \" \\x \";\n"
|
||||
"}\n",
|
||||
CBotErrHexDigits
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void HexValueOutOfRange()\n"
|
||||
"{\n"
|
||||
" \" \\x100 \";\n"
|
||||
"}\n",
|
||||
CBotErrHexRange
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void OctalValueOutOfRange()\n"
|
||||
"{\n"
|
||||
" \" \\400 \";\n"
|
||||
"}\n",
|
||||
CBotErrOctalRange
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void BadUnicodeCharacterName()\n"
|
||||
"{\n"
|
||||
" \" \\U00110000 \";\n"
|
||||
"}\n",
|
||||
CBotErrUnicodeName
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: not implemented, see issue #694
|
||||
|
|
Loading…
Reference in New Issue