ExpressionParser: Conditional operator. A binary op that evals the rhs if lhs > 0.5 else 0.0.

This commit is contained in:
Jordan Woyak 2018-12-30 16:29:48 -06:00
parent 718efce1dc
commit 58efc93ed4

View File

@ -28,9 +28,14 @@ enum TokenType
TOK_EOF, TOK_EOF,
TOK_LPAREN, TOK_LPAREN,
TOK_RPAREN, TOK_RPAREN,
TOK_AND,
TOK_OR,
TOK_UNARY, TOK_UNARY,
TOK_CONTROL,
TOK_LITERAL,
TOK_VARIABLE,
// Binary Ops:
TOK_BINARY_OPS_BEGIN,
TOK_AND = TOK_BINARY_OPS_BEGIN,
TOK_OR,
TOK_ADD, TOK_ADD,
TOK_MUL, TOK_MUL,
TOK_DIV, TOK_DIV,
@ -38,9 +43,8 @@ enum TokenType
TOK_ASSIGN, TOK_ASSIGN,
TOK_LTHAN, TOK_LTHAN,
TOK_GTHAN, TOK_GTHAN,
TOK_CONTROL, TOK_COND,
TOK_LITERAL, TOK_BINARY_OPS_END,
TOK_VARIABLE,
}; };
inline std::string OpName(TokenType op) inline std::string OpName(TokenType op)
@ -67,6 +71,8 @@ inline std::string OpName(TokenType op)
return "LThan"; return "LThan";
case TOK_GTHAN: case TOK_GTHAN:
return "GThan"; return "GThan";
case TOK_COND:
return "Cond";
case TOK_VARIABLE: case TOK_VARIABLE:
return "Var"; return "Var";
default: default:
@ -115,6 +121,8 @@ public:
return "<"; return "<";
case TOK_GTHAN: case TOK_GTHAN:
return ">"; return ">";
case TOK_COND:
return "?";
case TOK_CONTROL: case TOK_CONTROL:
return "Device(" + data + ")"; return "Device(" + data + ")";
case TOK_LITERAL: case TOK_LITERAL:
@ -240,6 +248,8 @@ public:
return Token(TOK_LTHAN); return Token(TOK_LTHAN);
case '>': case '>':
return Token(TOK_GTHAN); return Token(TOK_GTHAN);
case '?':
return Token(TOK_COND);
case '\'': case '\'':
return GetLiteral(); return GetLiteral();
case '$': case '$':
@ -334,38 +344,43 @@ public:
ControlState GetValue() const override ControlState GetValue() const override
{ {
ControlState lhsValue = lhs->GetValue();
ControlState rhsValue = rhs->GetValue();
switch (op) switch (op)
{ {
case TOK_AND: case TOK_AND:
return std::min(lhsValue, rhsValue); return std::min(lhs->GetValue(), rhs->GetValue());
case TOK_OR: case TOK_OR:
return std::max(lhsValue, rhsValue); return std::max(lhs->GetValue(), rhs->GetValue());
case TOK_ADD: case TOK_ADD:
return lhsValue + rhsValue; return lhs->GetValue() + rhs->GetValue();
case TOK_MUL: case TOK_MUL:
return lhsValue * rhsValue; return lhs->GetValue() * rhs->GetValue();
case TOK_DIV: case TOK_DIV:
{ {
const ControlState result = lhsValue / rhsValue; const ControlState result = lhs->GetValue() / rhs->GetValue();
return std::isinf(result) ? 0.0 : result; return std::isinf(result) ? 0.0 : result;
} }
case TOK_MOD: case TOK_MOD:
{ {
const ControlState result = std::fmod(lhsValue, rhsValue); const ControlState result = std::fmod(lhs->GetValue(), rhs->GetValue());
return std::isnan(result) ? 0.0 : result; return std::isnan(result) ? 0.0 : result;
} }
case TOK_ASSIGN: case TOK_ASSIGN:
{ {
lhs->SetValue(rhsValue); lhs->SetValue(rhs->GetValue());
// TODO: Should this instead GetValue(lhs) ? return lhs->GetValue();
return rhsValue;
} }
case TOK_LTHAN: case TOK_LTHAN:
return lhsValue < rhsValue; return lhs->GetValue() < rhs->GetValue();
case TOK_GTHAN: case TOK_GTHAN:
return lhsValue > rhsValue; return lhs->GetValue() > rhs->GetValue();
case TOK_COND:
{
constexpr ControlState COND_THRESHOLD = 0.5;
if (lhs->GetValue() > COND_THRESHOLD)
return rhs->GetValue();
else
return 0.0;
}
default: default:
assert(false); assert(false);
return 0; return 0;
@ -742,21 +757,7 @@ private:
bool IsBinaryToken(TokenType type) bool IsBinaryToken(TokenType type)
{ {
switch (type) return type >= TOK_BINARY_OPS_BEGIN && type < TOK_BINARY_OPS_END;
{
case TOK_AND:
case TOK_OR:
case TOK_ADD:
case TOK_MUL:
case TOK_DIV:
case TOK_MOD:
case TOK_ASSIGN:
case TOK_LTHAN:
case TOK_GTHAN:
return true;
default:
return false;
}
} }
ParseResult Binary() ParseResult Binary()