mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
Allow comparison operators of arbitrary length
This commit is contained in:
parent
31ae1cd339
commit
868a398b86
3 changed files with 81 additions and 101 deletions
|
@ -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,53 +453,69 @@ 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
special = S_cmpEQ;
|
||||
putback(c);
|
||||
// return false;
|
||||
/// Allow = as synonym for ==. \todo optionally disable for post-1.0 scripting improvements.
|
||||
}
|
||||
}
|
||||
if (validComparisonOperatorCharacter(c))
|
||||
c.appendTo(op);
|
||||
else
|
||||
{
|
||||
putback(c);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (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])
|
||||
{
|
||||
if (get(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] == '=')
|
||||
{
|
||||
/// \todo hack to allow a space in comparison operators (add option to disable)
|
||||
if (c == ' ' && !get(c))
|
||||
return false;
|
||||
|
||||
if (c == '=')
|
||||
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())
|
||||
{
|
||||
MultiChar next;
|
||||
|
@ -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…
Reference in a new issue