diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2018-12-30 16:06:29 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2019-10-11 17:14:32 -0500 |
| commit | e896835f86e52051b1998a344549dfa8ba79847a (patch) | |
| tree | 3dd3d8523f1804400dc70550188cf6a932a0af3b /Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | |
| parent | 1efcf861ead76bbffb4ac22726d799975146707c (diff) | |
ExpressionParser: Renamed ControlFinder to ControlEnvironment. Added support for variables and assignment operator. ControlExpression objects now reference a matching input and output so the two can me mixed in any expression. (you can set rumble directly from inputs)
Diffstat (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp')
| -rw-r--r-- | Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 124 |
1 files changed, 96 insertions, 28 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 2de2650699..f375c465d7 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -35,8 +35,10 @@ enum TokenType TOK_MUL, TOK_DIV, TOK_MOD, + TOK_ASSIGN, TOK_CONTROL, TOK_LITERAL, + TOK_VARIABLE, }; inline std::string OpName(TokenType op) @@ -57,6 +59,10 @@ inline std::string OpName(TokenType op) return "Div"; case TOK_MOD: return "Mod"; + case TOK_ASSIGN: + return "Assign"; + case TOK_VARIABLE: + return "Var"; default: assert(false); return ""; @@ -97,10 +103,14 @@ public: return "/"; case TOK_MOD: return "%"; + case TOK_ASSIGN: + return "="; case TOK_CONTROL: return "Device(" + data + ")"; case TOK_LITERAL: return '\'' + data + '\''; + case TOK_VARIABLE: + return '$' + data; case TOK_INVALID: break; } @@ -131,21 +141,23 @@ public: return false; } - Token GetUnaryFunction() + std::string FetchWordChars() { - std::string name; + std::string word; std::regex valid_name_char("[a-z0-9_]", std::regex_constants::icase); while (it != expr.end() && std::regex_match(std::string(1, *it), valid_name_char)) { - name += *it; + word += *it; ++it; } - return Token(TOK_UNARY, name); + return word; } + Token GetUnaryFunction() { return Token(TOK_UNARY, FetchWordChars()); } + Token GetLiteral() { std::string value; @@ -153,6 +165,8 @@ public: return Token(TOK_LITERAL, value); } + Token GetVariable() { return Token(TOK_VARIABLE, FetchWordChars()); } + Token GetFullyQualifiedControl() { std::string value; @@ -210,8 +224,12 @@ public: return Token(TOK_DIV); case '%': return Token(TOK_MOD); + case '=': + return Token(TOK_ASSIGN); case '\'': return GetLiteral(); + case '$': + return GetVariable(); case '`': return GetFullyQualifiedControl(); default: @@ -249,15 +267,14 @@ public: class ControlExpression : public Expression { public: - ControlQualifier qualifier; - Device::Control* control = nullptr; // Keep a shared_ptr to the device so the control pointer doesn't become invalid + // TODO: This is causing devices to be destructed after backends are shutdown: std::shared_ptr<Device> m_device; explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} ControlState GetValue() const override { - if (!control) + if (!input) return 0.0; // Note: Inputs may return negative values in situations where opposing directions are @@ -266,20 +283,26 @@ public: // FYI: Clamping values greater than 1.0 is purposely not done to support unbounded values in // the future. (e.g. raw accelerometer/gyro data) - return std::max(0.0, control->ToInput()->GetState()); + return std::max(0.0, input->GetState()); } void SetValue(ControlState value) override { - if (control) - control->ToOutput()->SetState(value); + if (output) + output->SetState(value); } - int CountNumControls() const override { return control ? 1 : 0; } - void UpdateReferences(ControlFinder& finder) override + int CountNumControls() const override { return (input || output) ? 1 : 0; } + void UpdateReferences(ControlEnvironment& env) override { - m_device = finder.FindDevice(qualifier); - control = finder.FindControl(qualifier); + m_device = env.FindDevice(qualifier); + input = env.FindInput(qualifier); + output = env.FindOutput(qualifier); } operator std::string() const override { return "`" + static_cast<std::string>(qualifier) + "`"; } + +private: + ControlQualifier qualifier; + Device::Input* input = nullptr; + Device::Output* output = nullptr; }; class BinaryExpression : public Expression @@ -319,6 +342,12 @@ public: const ControlState result = std::fmod(lhsValue, rhsValue); return std::isnan(result) ? 0.0 : result; } + case TOK_ASSIGN: + { + lhs->SetValue(rhsValue); + // TODO: Should this instead GetValue(lhs) ? + return rhsValue; + } default: assert(false); return 0; @@ -338,10 +367,10 @@ public: return lhs->CountNumControls() + rhs->CountNumControls(); } - void UpdateReferences(ControlFinder& finder) override + void UpdateReferences(ControlEnvironment& env) override { - lhs->UpdateReferences(finder); - rhs->UpdateReferences(finder); + lhs->UpdateReferences(env); + rhs->UpdateReferences(env); } operator std::string() const override @@ -356,7 +385,7 @@ public: UnaryExpression(std::unique_ptr<Expression>&& inner_) : inner(std::move(inner_)) {} int CountNumControls() const override { return inner->CountNumControls(); } - void UpdateReferences(ControlFinder& finder) override { inner->UpdateReferences(finder); } + void UpdateReferences(ControlEnvironment& env) override { inner->UpdateReferences(env); } operator std::string() const override { @@ -462,7 +491,7 @@ public: int CountNumControls() const override { return 1; } - void UpdateReferences(ControlFinder&) override + void UpdateReferences(ControlEnvironment&) override { // Nothing needed. } @@ -523,6 +552,29 @@ std::unique_ptr<LiteralExpression> MakeLiteralExpression(std::string name) } } +class VariableExpression : public Expression +{ +public: + VariableExpression(std::string name) : m_name(name) {} + + ControlState GetValue() const override { return *m_value_ptr; } + + void SetValue(ControlState value) override { *m_value_ptr = value; } + + int CountNumControls() const override { return 1; } + + void UpdateReferences(ControlEnvironment& env) override + { + m_value_ptr = env.GetVariablePtr(m_name); + } + + operator std::string() const override { return '$' + m_name; } + +protected: + const std::string m_name; + ControlState* m_value_ptr{}; +}; + // This class proxies all methods to its either left-hand child if it has bound controls, or its // right-hand child. Its intended use is for supporting old-style barewords expressions. class CoalesceExpression : public Expression @@ -543,10 +595,10 @@ public: static_cast<std::string>(*m_rhs) + ')'; } - void UpdateReferences(ControlFinder& finder) override + void UpdateReferences(ControlEnvironment& env) override { - m_lhs->UpdateReferences(finder); - m_rhs->UpdateReferences(finder); + m_lhs->UpdateReferences(env); + m_rhs->UpdateReferences(env); } private: @@ -559,7 +611,7 @@ private: std::unique_ptr<Expression> m_rhs; }; -std::shared_ptr<Device> ControlFinder::FindDevice(ControlQualifier qualifier) const +std::shared_ptr<Device> ControlEnvironment::FindDevice(ControlQualifier qualifier) const { if (qualifier.has_device) return container.FindDevice(qualifier.device_qualifier); @@ -567,16 +619,27 @@ std::shared_ptr<Device> ControlFinder::FindDevice(ControlQualifier qualifier) co return container.FindDevice(default_device); } -Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const +Device::Input* ControlEnvironment::FindInput(ControlQualifier qualifier) const { const std::shared_ptr<Device> device = FindDevice(qualifier); if (!device) return nullptr; - if (is_input) - return device->FindInput(qualifier.control_name); - else - return device->FindOutput(qualifier.control_name); + return device->FindInput(qualifier.control_name); +} + +Device::Output* ControlEnvironment::FindOutput(ControlQualifier qualifier) const +{ + const std::shared_ptr<Device> device = FindDevice(qualifier); + if (!device) + return nullptr; + + return device->FindOutput(qualifier.control_name); +} + +ControlState* ControlEnvironment::GetVariablePtr(const std::string& name) +{ + return &m_variables[name]; } struct ParseResult @@ -623,6 +686,10 @@ private: { return {ParseStatus::Successful, MakeLiteralExpression(tok.data)}; } + case TOK_VARIABLE: + { + return {ParseStatus::Successful, std::make_unique<VariableExpression>(tok.data)}; + } case TOK_LPAREN: return Paren(); default: @@ -665,6 +732,7 @@ private: case TOK_MUL: case TOK_DIV: case TOK_MOD: + case TOK_ASSIGN: return true; default: return false; |
