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:
Jordan Woyak
2018-12-30 17:32:32 -06:00
parent 2c89b60298
commit 46c0ae7d1f

View File

@ -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_));
} }