mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-22 05:40:01 -06:00
ExpressionParser: Add !while loop unary expression. Limited to 10000 reps to prevent infinite loops. Rhs is re-evaluated until it is < 0.5. Added comma operator, which behaves like it does in c++. Added subration operator.
This commit is contained in:
@ -37,6 +37,7 @@ enum TokenType
|
|||||||
TOK_AND = TOK_BINARY_OPS_BEGIN,
|
TOK_AND = TOK_BINARY_OPS_BEGIN,
|
||||||
TOK_OR,
|
TOK_OR,
|
||||||
TOK_ADD,
|
TOK_ADD,
|
||||||
|
TOK_SUB,
|
||||||
TOK_MUL,
|
TOK_MUL,
|
||||||
TOK_DIV,
|
TOK_DIV,
|
||||||
TOK_MOD,
|
TOK_MOD,
|
||||||
@ -44,6 +45,7 @@ enum TokenType
|
|||||||
TOK_LTHAN,
|
TOK_LTHAN,
|
||||||
TOK_GTHAN,
|
TOK_GTHAN,
|
||||||
TOK_COND,
|
TOK_COND,
|
||||||
|
TOK_COMMA,
|
||||||
TOK_BINARY_OPS_END,
|
TOK_BINARY_OPS_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,6 +61,8 @@ inline std::string OpName(TokenType op)
|
|||||||
return "Unary";
|
return "Unary";
|
||||||
case TOK_ADD:
|
case TOK_ADD:
|
||||||
return "Add";
|
return "Add";
|
||||||
|
case TOK_SUB:
|
||||||
|
return "Sub";
|
||||||
case TOK_MUL:
|
case TOK_MUL:
|
||||||
return "Mul";
|
return "Mul";
|
||||||
case TOK_DIV:
|
case TOK_DIV:
|
||||||
@ -73,6 +77,8 @@ inline std::string OpName(TokenType op)
|
|||||||
return "GThan";
|
return "GThan";
|
||||||
case TOK_COND:
|
case TOK_COND:
|
||||||
return "Cond";
|
return "Cond";
|
||||||
|
case TOK_COMMA:
|
||||||
|
return "Comma";
|
||||||
case TOK_VARIABLE:
|
case TOK_VARIABLE:
|
||||||
return "Var";
|
return "Var";
|
||||||
default:
|
default:
|
||||||
@ -109,6 +115,8 @@ public:
|
|||||||
return '!' + data;
|
return '!' + data;
|
||||||
case TOK_ADD:
|
case TOK_ADD:
|
||||||
return "+";
|
return "+";
|
||||||
|
case TOK_SUB:
|
||||||
|
return "-";
|
||||||
case TOK_MUL:
|
case TOK_MUL:
|
||||||
return "*";
|
return "*";
|
||||||
case TOK_DIV:
|
case TOK_DIV:
|
||||||
@ -123,6 +131,8 @@ public:
|
|||||||
return ">";
|
return ">";
|
||||||
case TOK_COND:
|
case TOK_COND:
|
||||||
return "?";
|
return "?";
|
||||||
|
case TOK_COMMA:
|
||||||
|
return ",";
|
||||||
case TOK_CONTROL:
|
case TOK_CONTROL:
|
||||||
return "Device(" + data + ')';
|
return "Device(" + data + ')';
|
||||||
case TOK_LITERAL:
|
case TOK_LITERAL:
|
||||||
@ -236,6 +246,8 @@ public:
|
|||||||
return GetUnaryFunction();
|
return GetUnaryFunction();
|
||||||
case '+':
|
case '+':
|
||||||
return Token(TOK_ADD);
|
return Token(TOK_ADD);
|
||||||
|
case '-':
|
||||||
|
return Token(TOK_SUB);
|
||||||
case '*':
|
case '*':
|
||||||
return Token(TOK_MUL);
|
return Token(TOK_MUL);
|
||||||
case '/':
|
case '/':
|
||||||
@ -250,6 +262,8 @@ public:
|
|||||||
return Token(TOK_GTHAN);
|
return Token(TOK_GTHAN);
|
||||||
case '?':
|
case '?':
|
||||||
return Token(TOK_COND);
|
return Token(TOK_COND);
|
||||||
|
case ',':
|
||||||
|
return Token(TOK_COMMA);
|
||||||
case '\'':
|
case '\'':
|
||||||
return GetLiteral();
|
return GetLiteral();
|
||||||
case '$':
|
case '$':
|
||||||
@ -352,6 +366,8 @@ public:
|
|||||||
return std::max(lhs->GetValue(), rhs->GetValue());
|
return std::max(lhs->GetValue(), rhs->GetValue());
|
||||||
case TOK_ADD:
|
case TOK_ADD:
|
||||||
return lhs->GetValue() + rhs->GetValue();
|
return lhs->GetValue() + rhs->GetValue();
|
||||||
|
case TOK_SUB:
|
||||||
|
return lhs->GetValue() - rhs->GetValue();
|
||||||
case TOK_MUL:
|
case TOK_MUL:
|
||||||
return lhs->GetValue() * rhs->GetValue();
|
return lhs->GetValue() * rhs->GetValue();
|
||||||
case TOK_DIV:
|
case TOK_DIV:
|
||||||
@ -381,6 +397,12 @@ public:
|
|||||||
else
|
else
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
case TOK_COMMA:
|
||||||
|
{
|
||||||
|
// Eval and discard lhs:
|
||||||
|
lhs->GetValue();
|
||||||
|
return rhs->GetValue();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
return 0;
|
return 0;
|
||||||
@ -498,6 +520,32 @@ public:
|
|||||||
std::string GetFuncName() const override { return "Sin"; }
|
std::string GetFuncName() const override { return "Sin"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UnaryWhileExpression : public UnaryExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnaryWhileExpression(std::unique_ptr<Expression>&& inner_) : UnaryExpression(std::move(inner_)) {}
|
||||||
|
|
||||||
|
ControlState GetValue() const override
|
||||||
|
{
|
||||||
|
constexpr int MAX_REPS = 10000;
|
||||||
|
constexpr int COND_THRESHOLD = 0.5;
|
||||||
|
|
||||||
|
// Returns 1.0 on successful loop, 0.0 on reps exceeded. Sensible?
|
||||||
|
|
||||||
|
for (int i = 0; i != MAX_REPS; ++i)
|
||||||
|
{
|
||||||
|
const ControlState val = inner->GetValue();
|
||||||
|
if (val < COND_THRESHOLD)
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exceeded max reps:
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
void SetValue(ControlState value) override {}
|
||||||
|
std::string GetFuncName() const override { return "Sin"; }
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<UnaryExpression> MakeUnaryExpression(std::string name,
|
std::unique_ptr<UnaryExpression> MakeUnaryExpression(std::string name,
|
||||||
std::unique_ptr<Expression>&& inner_)
|
std::unique_ptr<Expression>&& inner_)
|
||||||
{
|
{
|
||||||
@ -511,6 +559,8 @@ std::unique_ptr<UnaryExpression> MakeUnaryExpression(std::string name,
|
|||||||
return std::make_unique<UnaryToggleExpression>(std::move(inner_));
|
return std::make_unique<UnaryToggleExpression>(std::move(inner_));
|
||||||
else if ("sin" == name)
|
else if ("sin" == name)
|
||||||
return std::make_unique<UnarySinExpression>(std::move(inner_));
|
return std::make_unique<UnarySinExpression>(std::move(inner_));
|
||||||
|
else if ("while" == name)
|
||||||
|
return std::make_unique<UnaryWhileExpression>(std::move(inner_));
|
||||||
else
|
else
|
||||||
return std::make_unique<UnaryUnknownExpression>(std::move(inner_));
|
return std::make_unique<UnaryUnknownExpression>(std::move(inner_));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user