Allow comparison operators of arbitrary length

depth-refraction
unknown 1 year ago
parent 31ae1cd339
commit 868a398b86

@ -23,6 +23,7 @@
Bug #6645: Enemy block sounds align with animation instead of blocked hits
Bug #6657: Distant terrain tiles become black when using FWIW mod
Bug #6661: Saved games that have no preview screenshot cause issues or crashes
Bug #6716: mwscript comparison operator handling is too restrictive
Bug #6807: Ultimate Galleon is not working properly
Bug #6893: Lua: Inconsistent behavior with actors affected by Disable and SetDelete commands
Bug #6939: OpenMW-CS: ID columns are too short

@ -10,6 +10,19 @@
#include <components/misc/strings/lower.hpp>
namespace
{
bool startsComparisonOperator(const Compiler::MultiChar& c)
{
return c == '=' || c == '<' || c == '>' || c == '!';
}
bool validComparisonOperatorCharacter(const Compiler::MultiChar& c)
{
return startsComparisonOperator(c) || c == ' ' || c == '\t';
}
}
namespace Compiler
{
bool Scanner::get(MultiChar& c)
@ -440,52 +453,68 @@ namespace Compiler
special = S_member;
}
else if (c == '=')
else if (startsComparisonOperator(c))
{
if (get(c))
TokenLoc loc = mLoc;
std::string op;
c.appendTo(op);
while (get(c))
{
/// \todo hack to allow a space in comparison operators (add option to disable)
if (c == ' ' && !get(c))
special = S_cmpEQ;
else if (c == '=')
special = S_cmpEQ;
else if (c == '>' || c == '<') // Treat => and =< as ==
{
special = S_cmpEQ;
mErrorHandler.warning(std::string("invalid operator =") + c.data() + ", treating it as ==", mLoc);
}
if (validComparisonOperatorCharacter(c))
c.appendTo(op);
else
{
special = S_cmpEQ;
putback(c);
// return false;
/// Allow = as synonym for ==. \todo optionally disable for post-1.0 scripting improvements.
break;
}
}
else
{
putback(c);
return false;
}
}
else if (c == '!')
{
if (get(c))
size_t end = op.size();
while (end > 0 && (op[end - 1] == '\t' || op[end - 1] == ' '))
--end;
std::string_view trimmedOperator = std::string_view{ op }.substr(0, end);
switch (trimmedOperator[0])
{
/// \todo hack to allow a space in comparison operators (add option to disable)
if (c == ' ' && !get(c))
return false;
if (c == '=')
case '=':
special = S_cmpEQ;
if (trimmedOperator.size() != 2 || trimmedOperator[1] != '=')
mErrorHandler.warning(
"invalid operator " + std::string(trimmedOperator) + ", treating it as ==", loc);
break;
case '<':
special = S_cmpLT;
if (trimmedOperator[1] == '=')
{
special = S_cmpLE;
if (trimmedOperator.size() != 2)
mErrorHandler.warning(
"invalid operator " + std::string(trimmedOperator) + ", treating it as <=", loc);
}
else if (trimmedOperator.size() != 1)
mErrorHandler.warning(
"invalid operator " + std::string(trimmedOperator) + ", treating it as <", loc);
break;
case '>':
special = S_cmpGT;
if (trimmedOperator[1] == '=')
{
special = S_cmpGE;
if (trimmedOperator.size() != 2)
mErrorHandler.warning(
"invalid operator " + std::string(trimmedOperator) + ", treating it as >=", loc);
}
else if (trimmedOperator.size() != 1)
mErrorHandler.warning(
"invalid operator " + std::string(trimmedOperator) + ", treating it as >", loc);
break;
case '!':
special = S_cmpNE;
else
{
putback(c);
if (trimmedOperator.size() != 2 || trimmedOperator[1] != '=')
mErrorHandler.warning(
"invalid operator " + std::string(trimmedOperator) + ", treating it as !=", loc);
break;
default:
return false;
}
}
else
return false;
}
else if (c.isMinusSign())
{
@ -503,62 +532,6 @@ namespace Compiler
else
special = S_minus;
}
else if (c == '<')
{
if (get(c))
{
/// \todo hack to allow a space in comparison operators (add option to disable)
if (c == ' ' && !get(c))
special = S_cmpLT;
else if (c == '=')
{
special = S_cmpLE;
if (get(c) && c != '=') // <== is a allowed as an alternative to <= :(
putback(c);
}
else if (c == '<' || c == '>') // Treat <> and << as <
{
special = S_cmpLT;
mErrorHandler.warning("Invalid operator, treating it as <", mLoc);
}
else
{
putback(c);
special = S_cmpLT;
}
}
else
special = S_cmpLT;
}
else if (c == '>')
{
if (get(c))
{
/// \todo hack to allow a space in comparison operators (add option to disable)
if (c == ' ' && !get(c))
special = S_cmpGT;
else if (c == '=')
{
special = S_cmpGE;
if (get(c) && c != '=') // >== is a allowed as an alternative to >= :(
putback(c);
}
else if (c == '<' || c == '>') // Treat >< and >> as >
{
special = S_cmpGT;
mErrorHandler.warning("Invalid operator, treating it as >", mLoc);
}
else
{
putback(c);
special = S_cmpGT;
}
}
else
special = S_cmpGT;
}
else if (c == '+')
special = S_plus;
else if (c == '*')

@ -48,25 +48,31 @@ namespace Compiler
return -1;
}
bool operator==(const char ch) { return mData[0] == ch && mData[1] == 0 && mData[2] == 0 && mData[3] == 0; }
bool operator==(const char ch) const
{
return mData[0] == ch && mData[1] == 0 && mData[2] == 0 && mData[3] == 0;
}
bool operator==(const MultiChar& ch)
bool operator==(const MultiChar& ch) const
{
return mData[0] == ch.mData[0] && mData[1] == ch.mData[1] && mData[2] == ch.mData[2]
&& mData[3] == ch.mData[3];
}
bool operator!=(const char ch) { return mData[0] != ch || mData[1] != 0 || mData[2] != 0 || mData[3] != 0; }
bool operator!=(const char ch) const
{
return mData[0] != ch || mData[1] != 0 || mData[2] != 0 || mData[3] != 0;
}
bool isWhitespace()
bool isWhitespace() const
{
return (mData[0] == ' ' || mData[0] == '\t' || mData[0] == ',') && mData[1] == 0 && mData[2] == 0
&& mData[3] == 0;
}
bool isDigit() { return std::isdigit(mData[0]) && mData[1] == 0 && mData[2] == 0 && mData[3] == 0; }
bool isDigit() const { return std::isdigit(mData[0]) && mData[1] == 0 && mData[2] == 0 && mData[3] == 0; }
bool isMinusSign()
bool isMinusSign() const
{
if (mData[0] == '-' && mData[1] == 0 && mData[2] == 0 && mData[3] == 0)
return true;
@ -74,7 +80,7 @@ namespace Compiler
return mData[0] == '\xe2' && mData[1] == '\x80' && mData[2] == '\x93' && mData[3] == 0;
}
bool isAlpha()
bool isAlpha() const
{
if (isMinusSign())
return false;
@ -82,13 +88,13 @@ namespace Compiler
return std::isalpha(mData[0]) || mData[1] != 0 || mData[2] != 0 || mData[3] != 0;
}
void appendTo(std::string& str)
void appendTo(std::string& str) const
{
for (int i = 0; i <= mLength; i++)
str += mData[i];
}
void putback(std::istream& in)
void putback(std::istream& in) const
{
for (int i = mLength; i >= 0; i--)
in.putback(mData[i]);
@ -157,7 +163,7 @@ namespace Compiler
mLength = -1;
}
std::string data()
std::string data() const
{
// NB: mLength is the number of the last element in the array
return std::string(mData, mLength + 1);

Loading…
Cancel
Save