summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2019-10-22 19:12:55 -0500
committerJordan Woyak <jordan.woyak@gmail.com>2020-09-25 20:29:18 -0500
commit52547379c99f290118641f29168cfae5cc94db51 (patch)
tree6ee909194aa20ca8cf76d528cc55846733acb449 /Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
parent57f14b260bf043b6c261ca284b6c45fa3a7932de (diff)
ExpressionParser: Add Hotkey syntax.
Diffstat (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp')
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
index 1b1a24753c..0533b88a16 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
@@ -112,6 +113,8 @@ Token Lexer::NextToken()
return Token(TOK_LPAREN);
case ')':
return Token(TOK_RPAREN);
+ case '@':
+ return Token(TOK_HOTKEY);
case '&':
return Token(TOK_AND);
case '|':
@@ -374,6 +377,63 @@ protected:
ControlState* m_value_ptr{};
};
+class HotkeyExpression : public Expression
+{
+public:
+ HotkeyExpression(std::vector<std::unique_ptr<ControlExpression>> inputs)
+ : m_inputs(std::move(inputs))
+ {
+ }
+
+ ControlState GetValue() const override
+ {
+ if (m_inputs.empty())
+ return 0;
+
+ const bool modifiers_pressed = std::all_of(m_inputs.begin(), std::prev(m_inputs.end()),
+ [](const std::unique_ptr<ControlExpression>& input) {
+ // TODO: kill magic number.
+ return input->GetValue() > 0.5;
+ });
+
+ if (modifiers_pressed)
+ {
+ // TODO: kill magic number.
+ const bool final_input_pressed = (**m_inputs.rbegin()).GetValue() > 0.5;
+
+ if (m_is_ready)
+ return final_input_pressed;
+
+ if (!final_input_pressed)
+ m_is_ready = true;
+ }
+ else
+ m_is_ready = false;
+
+ return 0;
+ }
+
+ void SetValue(ControlState) override {}
+
+ int CountNumControls() const override
+ {
+ int result = 0;
+ for (auto& input : m_inputs)
+ result += input->CountNumControls();
+ return result;
+ }
+
+ void UpdateReferences(ControlEnvironment& env) override
+ {
+ for (auto& input : m_inputs)
+ input->UpdateReferences(env);
+ }
+
+private:
+ std::vector<std::unique_ptr<ControlExpression>> m_inputs;
+ mutable bool m_is_ready = false;
+};
+
// 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
@@ -600,6 +660,10 @@ private:
{
return ParseParens();
}
+ case TOK_HOTKEY:
+ {
+ return ParseHotkeys();
+ }
case TOK_SUB:
{
// An atom was expected but we got a subtraction symbol.
@@ -684,6 +748,39 @@ private:
return result;
}
+ ParseResult ParseHotkeys()
+ {
+ Token tok = Chew();
+ if (tok.type != TOK_LPAREN)
+ return ParseResult::MakeErrorResult(tok, _trans("Expected opening paren."));
+
+ std::vector<std::unique_ptr<ControlExpression>> inputs;
+
+ while (true)
+ {
+ tok = Chew();
+
+ if (tok.type != TOK_CONTROL && tok.type != TOK_BAREWORD)
+ return ParseResult::MakeErrorResult(tok, _trans("Expected name of input."));
+
+ ControlQualifier cq;
+ cq.FromString(tok.data);
+ inputs.emplace_back(std::make_unique<ControlExpression>(std::move(cq)));
+
+ tok = Chew();
+
+ if (tok.type == TOK_ADD)
+ continue;
+
+ if (tok.type == TOK_RPAREN)
+ break;
+
+ return ParseResult::MakeErrorResult(tok, _trans("Expected + or closing paren."));
+ }
+
+ return ParseResult::MakeSuccessfulResult(std::make_unique<HotkeyExpression>(std::move(inputs)));
+ }
+
ParseResult ParseToplevel() { return ParseBinary(); }
}; // namespace ExpressionParser