summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2019-04-04 17:35:49 -0500
committerJordan Woyak <jordan.woyak@gmail.com>2019-10-11 18:12:18 -0500
commitb57178d246640270779d791b00d3a5b8fd7c13f2 (patch)
tree5948b2e8349695b2c5f52aa1d32506f6f8bd513c /Source/Core/InputCommon/ControlReference
parent7912dc57ddccc3868dea9f915b1f6d9d4416165d (diff)
ExpressionParser: Remove ! character from function syntax. Remove unused serialization functions.
Diffstat (limited to 'Source/Core/InputCommon/ControlReference')
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp240
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.h8
-rw-r--r--Source/Core/InputCommon/ControlReference/FunctionExpression.cpp78
-rw-r--r--Source/Core/InputCommon/ControlReference/FunctionExpression.h4
4 files changed, 84 insertions, 246 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
index a686e8fcc4..f7937a19bd 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -21,42 +21,6 @@ namespace ciface::ExpressionParser
{
using namespace ciface::Core;
-inline std::string OpName(TokenType op)
-{
- switch (op)
- {
- case TOK_AND:
- return "And";
- case TOK_OR:
- return "Or";
- case TOK_FUNCTION:
- return "Function";
- case TOK_ADD:
- return "Add";
- case TOK_SUB:
- return "Sub";
- case TOK_MUL:
- return "Mul";
- case TOK_DIV:
- return "Div";
- case TOK_MOD:
- return "Mod";
- case TOK_ASSIGN:
- return "Assign";
- case TOK_LTHAN:
- return "LThan";
- case TOK_GTHAN:
- return "GThan";
- case TOK_COMMA:
- return "Comma";
- case TOK_VARIABLE:
- return "Var";
- default:
- assert(false);
- return "";
- }
-}
-
Token::Token(TokenType type_) : type(type_)
{
}
@@ -70,55 +34,6 @@ bool Token::IsBinaryOperator() const
return type >= TOK_BINARY_OPS_BEGIN && type < TOK_BINARY_OPS_END;
}
-Token::operator std::string() const
-{
- switch (type)
- {
- case TOK_DISCARD:
- return "Discard";
- case TOK_EOF:
- return "EOF";
- case TOK_LPAREN:
- return "(";
- case TOK_RPAREN:
- return ")";
- case TOK_AND:
- return "&";
- case TOK_OR:
- return "|";
- case TOK_FUNCTION:
- return '!' + data;
- case TOK_ADD:
- return "+";
- case TOK_SUB:
- return "-";
- case TOK_MUL:
- return "*";
- case TOK_DIV:
- return "/";
- case TOK_MOD:
- return "%";
- case TOK_ASSIGN:
- return "=";
- case TOK_LTHAN:
- return "<";
- case TOK_GTHAN:
- return ">";
- case TOK_COMMA:
- return ",";
- case TOK_CONTROL:
- return "Device(" + data + ')';
- case TOK_LITERAL:
- return '\'' + data + '\'';
- case TOK_VARIABLE:
- return '$' + data;
- default:
- break;
- }
-
- return "Invalid";
-}
-
Lexer::Lexer(const std::string& expr_) : expr(expr_)
{
it = expr.begin();
@@ -134,21 +49,12 @@ std::string Lexer::FetchDelimString(char delim)
std::string Lexer::FetchWordChars()
{
- // Words must start with a letter or underscore.
- if (expr.end() == it || (!std::isalpha(*it, std::locale::classic()) && ('_' != *it)))
- return "";
-
// Valid word characters:
std::regex rx(R"([a-z\d_])", std::regex_constants::icase);
return FetchCharsWhile([&rx](char c) { return std::regex_match(std::string(1, c), rx); });
}
-Token Lexer::GetFunction()
-{
- return Token(TOK_FUNCTION, FetchWordChars());
-}
-
Token Lexer::GetDelimitedLiteral()
{
return Token(TOK_LITERAL, FetchDelimString('\''));
@@ -164,21 +70,15 @@ Token Lexer::GetFullyQualifiedControl()
return Token(TOK_CONTROL, FetchDelimString('`'));
}
-Token Lexer::GetBarewordsControl(char c)
+Token Lexer::GetBareword(char first_char)
{
- std::string name;
- name += c;
- name += FetchCharsWhile([](char c) { return std::isalpha(c, std::locale::classic()); });
-
- ControlQualifier qualifier;
- qualifier.control_name = name;
- return Token(TOK_CONTROL, qualifier);
+ return Token(TOK_BAREWORD, first_char + FetchWordChars());
}
-Token Lexer::GetRealLiteral(char c)
+Token Lexer::GetRealLiteral(char first_char)
{
std::string value;
- value += c;
+ value += first_char;
value += FetchCharsWhile([](char c) { return isdigit(c, std::locale::classic()) || ('.' == c); });
if (std::regex_match(value, std::regex(R"(\d+(\.\d+)?)")))
@@ -209,7 +109,7 @@ Token Lexer::NextToken()
case '|':
return Token(TOK_OR);
case '!':
- return GetFunction();
+ return Token(TOK_NOT);
case '+':
return Token(TOK_ADD);
case '-':
@@ -236,7 +136,7 @@ Token Lexer::NextToken()
return GetFullyQualifiedControl();
default:
if (isalpha(c, std::locale::classic()))
- return GetBarewordsControl(c);
+ return GetBareword(c);
else if (isdigit(c, std::locale::classic()))
return GetRealLiteral(c);
else
@@ -300,7 +200,6 @@ public:
input = env.FindInput(qualifier);
output = env.FindOutput(qualifier);
}
- operator std::string() const override { return "`" + static_cast<std::string>(qualifier) + "`"; }
private:
ControlQualifier qualifier;
@@ -384,11 +283,6 @@ public:
lhs->UpdateReferences(env);
rhs->UpdateReferences(env);
}
-
- operator std::string() const override
- {
- return OpName(op) + "(" + std::string(*lhs) + ", " + std::string(*rhs) + ")";
- }
};
class LiteralExpression : public Expression
@@ -406,8 +300,6 @@ public:
// Nothing needed.
}
- operator std::string() const override { return '\'' + GetName() + '\''; }
-
protected:
virtual std::string GetName() const = 0;
};
@@ -450,8 +342,6 @@ public:
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{};
@@ -471,12 +361,6 @@ public:
void SetValue(ControlState value) override { GetActiveChild()->SetValue(value); }
int CountNumControls() const override { return GetActiveChild()->CountNumControls(); }
- operator std::string() const override
- {
- return "Coalesce(" + static_cast<std::string>(*m_lhs) + ", " +
- static_cast<std::string>(*m_rhs) + ')';
- }
-
void UpdateReferences(ControlEnvironment& env) override
{
m_lhs->UpdateReferences(env);
@@ -566,19 +450,6 @@ public:
}
private:
- struct FunctionArguments
- {
- FunctionArguments(ParseResult&& result_, std::vector<std::unique_ptr<Expression>>&& args_ = {})
- : result(std::move(result_)), args(std::move(args_))
- {
- }
-
- // Note: expression member isn't being used.
- ParseResult result;
-
- std::vector<std::unique_ptr<Expression>> args;
- };
-
const std::vector<Token>& tokens;
std::vector<Token>::const_iterator m_it;
@@ -598,75 +469,81 @@ private:
return tok.type == type;
}
- FunctionArguments ParseFunctionArguments()
+ ParseResult ParseFunctionArguments(std::unique_ptr<FunctionExpression>&& func,
+ const Token& func_tok)
{
std::vector<std::unique_ptr<Expression>> args;
if (TOK_LPAREN != Peek().type)
{
// Single argument with no parens (useful for unary ! function)
- auto arg = ParseAtom(Chew());
+ const auto tok = Chew();
+ auto arg = ParseAtom(tok);
if (ParseStatus::Successful != arg.status)
- return {std::move(arg)};
+ return arg;
args.emplace_back(std::move(arg.expr));
- return {ParseResult::MakeSuccessfulResult({}), std::move(args)};
}
-
- // Chew the L-Paren
- Chew();
-
- // Check for empty argument list:
- if (TOK_RPAREN == Peek().type)
+ else
{
+ // Chew the L-Paren
Chew();
- return {ParseResult::MakeSuccessfulResult({})};
+
+ // Check for empty argument list:
+ if (TOK_RPAREN == Peek().type)
+ {
+ Chew();
+ }
+ else
+ {
+ while (true)
+ {
+ // Read one argument.
+ // Grab an expression, but stop at comma.
+ auto arg = ParseBinary(BinaryOperatorPrecedence(TOK_COMMA));
+ if (ParseStatus::Successful != arg.status)
+ return arg;
+
+ args.emplace_back(std::move(arg.expr));
+
+ // Right paren is the end of our arguments.
+ const Token tok = Chew();
+ if (TOK_RPAREN == tok.type)
+ break;
+
+ // Comma before the next argument.
+ if (TOK_COMMA != tok.type)
+ return ParseResult::MakeErrorResult(tok, _trans("Expected comma."));
+ };
+ }
}
- while (true)
+ if (!func->SetArguments(std::move(args)))
{
- // Read one argument.
- // Grab an expression, but stop at comma.
- auto arg = ParseBinary(BinaryOperatorPrecedence(TOK_COMMA));
- if (ParseStatus::Successful != arg.status)
- return {std::move(arg)};
-
- args.emplace_back(std::move(arg.expr));
-
- // Right paren is the end of our arguments.
- const Token tok = Chew();
- if (TOK_RPAREN == tok.type)
- return {ParseResult::MakeSuccessfulResult({}), std::move(args)};
-
- // Comma before the next argument.
- if (TOK_COMMA != tok.type)
- return {ParseResult::MakeErrorResult(tok, _trans("Expected comma."))};
+ // TODO: It would be nice to output how many arguments are expected.
+ return ParseResult::MakeErrorResult(func_tok, _trans("Wrong number of arguments."));
}
+
+ return ParseResult::MakeSuccessfulResult(std::move(func));
}
ParseResult ParseAtom(const Token& tok)
{
switch (tok.type)
{
- case TOK_FUNCTION:
+ case TOK_BAREWORD:
{
auto func = MakeFunctionExpression(tok.data);
if (!func)
- return ParseResult::MakeErrorResult(tok, _trans("Unknown function."));
-
- auto args = ParseFunctionArguments();
-
- if (ParseStatus::Successful != args.result.status)
- return std::move(args.result);
-
- if (!func->SetArguments(std::move(args.args)))
{
- // TODO: It would be nice to output how many arguments are expected.
- return ParseResult::MakeErrorResult(tok, _trans("Wrong number of arguments."));
+ // Invalid function, interpret this as a bareword control.
+ Token control_tok(tok);
+ control_tok.type = TOK_CONTROL;
+ return ParseAtom(control_tok);
}
- return ParseResult::MakeSuccessfulResult(std::move(func));
+ return ParseFunctionArguments(std::move(func), tok);
}
case TOK_CONTROL:
{
@@ -674,6 +551,10 @@ private:
cq.FromString(tok.data);
return ParseResult::MakeSuccessfulResult(std::make_unique<ControlExpression>(cq));
}
+ case TOK_NOT:
+ {
+ return ParseFunctionArguments(MakeFunctionExpression("not"), tok);
+ }
case TOK_LITERAL:
{
return MakeLiteralExpression(tok);
@@ -690,16 +571,13 @@ private:
{
// An atom was expected but we got a subtraction symbol.
// Interpret it as a unary minus function.
-
- // Make sure to copy the existing string position values for proper error results.
- Token func = tok;
- func.type = TOK_FUNCTION;
- func.data = "minus";
- return ParseAtom(std::move(func));
+ return ParseFunctionArguments(MakeFunctionExpression("minus"), tok);
}
default:
+ {
return ParseResult::MakeErrorResult(tok, _trans("Expected start of expression."));
}
+ }
}
static int BinaryOperatorPrecedence(TokenType type)
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h
index 3dac67e9db..2f41d2fde7 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h
@@ -20,10 +20,11 @@ enum TokenType
TOK_EOF,
TOK_LPAREN,
TOK_RPAREN,
- TOK_FUNCTION,
+ TOK_NOT,
TOK_CONTROL,
TOK_LITERAL,
TOK_VARIABLE,
+ TOK_BAREWORD,
// Binary Ops:
TOK_BINARY_OPS_BEGIN,
TOK_AND = TOK_BINARY_OPS_BEGIN,
@@ -54,7 +55,6 @@ public:
Token(TokenType type_, std::string data_);
bool IsBinaryOperator() const;
- operator std::string() const;
};
enum class ParseStatus
@@ -89,11 +89,10 @@ private:
std::string FetchDelimString(char delim);
std::string FetchWordChars();
- Token GetFunction();
Token GetDelimitedLiteral();
Token GetVariable();
Token GetFullyQualifiedControl();
- Token GetBarewordsControl(char c);
+ Token GetBareword(char c);
Token GetRealLiteral(char c);
Token NextToken();
@@ -164,7 +163,6 @@ public:
virtual void SetValue(ControlState state) = 0;
virtual int CountNumControls() const = 0;
virtual void UpdateReferences(ControlEnvironment& finder) = 0;
- virtual operator std::string() const = 0;
};
class ParseResult
diff --git a/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp b/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp
index 6c3f10ad74..daf36c0fa1 100644
--- a/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp
+++ b/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp
@@ -17,7 +17,7 @@ constexpr ControlState CONDITION_THRESHOLD = 0.5;
using Clock = std::chrono::steady_clock;
using FSec = std::chrono::duration<ControlState>;
-// usage: !toggle(toggle_state_input, [clear_state_input])
+// usage: toggle(toggle_state_input, [clear_state_input])
class ToggleExpression : public FunctionExpression
{
private:
@@ -49,14 +49,11 @@ private:
return m_state;
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "toggle"; }
-
mutable bool m_released{};
mutable bool m_state{};
};
-// usage: !not(expression)
+// usage: not(expression)
class NotExpression : public FunctionExpression
{
private:
@@ -67,10 +64,9 @@ private:
ControlState GetValue() const override { return 1.0 - GetArg(0).GetValue(); }
void SetValue(ControlState value) override { GetArg(0).SetValue(1.0 - value); }
- std::string GetFuncName() const override { return ""; }
};
-// usage: !sin(expression)
+// usage: sin(expression)
class SinExpression : public FunctionExpression
{
private:
@@ -80,11 +76,9 @@ private:
}
ControlState GetValue() const override { return std::sin(GetArg(0).GetValue()); }
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "sin"; }
};
-// usage: !timer(seconds)
+// usage: timer(seconds)
class TimerExpression : public FunctionExpression
{
private:
@@ -118,14 +112,12 @@ private:
return progress;
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "timer"; }
private:
mutable Clock::time_point m_start_time = Clock::now();
};
-// usage: !if(condition, true_expression, false_expression)
+// usage: if(condition, true_expression, false_expression)
class IfExpression : public FunctionExpression
{
private:
@@ -139,12 +131,9 @@ private:
return (GetArg(0).GetValue() > CONDITION_THRESHOLD) ? GetArg(1).GetValue() :
GetArg(2).GetValue();
}
-
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "if"; }
};
-// usage: !minus(expression)
+// usage: minus(expression)
class UnaryMinusExpression : public FunctionExpression
{
private:
@@ -158,12 +147,9 @@ private:
// Subtraction for clarity:
return 0.0 - GetArg(0).GetValue();
}
-
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "minus"; }
};
-// usage: !deadzone(input, amount)
+// usage: deadzone(input, amount)
class DeadzoneExpression : public FunctionExpression
{
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
@@ -177,12 +163,9 @@ class DeadzoneExpression : public FunctionExpression
const ControlState deadzone = GetArg(1).GetValue();
return std::copysign(std::max(0.0, std::abs(val) - deadzone) / (1.0 - deadzone), val);
}
-
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "deadzone"; }
};
-// usage: !smooth(input, seconds_up, seconds_down = seconds_up)
+// usage: smooth(input, seconds_up, seconds_down = seconds_up)
// seconds is seconds to change from 0.0 to 1.0
class SmoothExpression : public FunctionExpression
{
@@ -218,15 +201,12 @@ class SmoothExpression : public FunctionExpression
return m_value;
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "smooth"; }
-
private:
mutable ControlState m_value = 0.0;
mutable Clock::time_point m_last_update = Clock::now();
};
-// usage: !hold(input, seconds)
+// usage: hold(input, seconds)
class HoldExpression : public FunctionExpression
{
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
@@ -256,15 +236,12 @@ class HoldExpression : public FunctionExpression
return m_state;
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "smooth"; }
-
private:
mutable bool m_state = false;
mutable Clock::time_point m_start_time = Clock::now();
};
-// usage: !tap(input, seconds, taps=2)
+// usage: tap(input, seconds, taps=2)
class TapExpression : public FunctionExpression
{
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
@@ -313,16 +290,13 @@ class TapExpression : public FunctionExpression
return 0.0;
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "tap"; }
-
private:
mutable bool m_released = true;
mutable u32 m_taps = 0;
mutable Clock::time_point m_start_time = Clock::now();
};
-// usage: !relative(input, speed, [max_abs_value, [shared_state]])
+// usage: relative(input, speed, [max_abs_value, [shared_state]])
// speed is max movement per second
class RelativeExpression : public FunctionExpression
{
@@ -337,15 +311,15 @@ class RelativeExpression : public FunctionExpression
//
// e.g. A single mapping with a relatively adjusted value between 0.0 and 1.0
// Potentially useful for a trigger input
- // !relative(`Up` - `Down`, 2.0)
+ // relative(`Up` - `Down`, 2.0)
//
// e.g. A value with two mappings (such as analog stick Up/Down)
// The shared state allows the two mappings to work together.
// This mapping (for up) returns a value clamped between 0.0 and 1.0
- // !relative(`Up`, 2.0, 1.0, $y)
+ // relative(`Up`, 2.0, 1.0, $y)
// This mapping (for down) returns the negative value clamped between 0.0 and 1.0
// (Adjustments created by `Down` are applied negatively to the shared state)
- // !relative(`Down`, 2.0, -1.0, $y)
+ // relative(`Down`, 2.0, -1.0, $y)
const auto now = Clock::now();
@@ -373,15 +347,12 @@ class RelativeExpression : public FunctionExpression
return std::max(0.0, m_state * std::copysign(1.0, max_abs_value));
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "relative"; }
-
private:
mutable ControlState m_state = 0.0;
mutable Clock::time_point m_last_update = Clock::now();
};
-// usage: !pulse(input, seconds)
+// usage: pulse(input, seconds)
class PulseExpression : public FunctionExpression
{
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
@@ -424,9 +395,6 @@ class PulseExpression : public FunctionExpression
return m_state;
}
- void SetValue(ControlState value) override {}
- std::string GetFuncName() const override { return "pulse"; }
-
private:
mutable bool m_released = false;
mutable bool m_state = false;
@@ -435,7 +403,7 @@ private:
std::unique_ptr<FunctionExpression> MakeFunctionExpression(std::string name)
{
- if (name.empty())
+ if ("not" == name)
return std::make_unique<NotExpression>();
else if ("if" == name)
return std::make_unique<IfExpression>();
@@ -479,16 +447,6 @@ void FunctionExpression::UpdateReferences(ControlEnvironment& env)
arg->UpdateReferences(env);
}
-FunctionExpression::operator std::string() const
-{
- std::string result = '!' + GetFuncName();
-
- for (auto& arg : m_args)
- result += ' ' + static_cast<std::string>(*arg);
-
- return result;
-}
-
bool FunctionExpression::SetArguments(std::vector<std::unique_ptr<Expression>>&& args)
{
m_args = std::move(args);
@@ -511,5 +469,9 @@ u32 FunctionExpression::GetArgCount() const
return u32(m_args.size());
}
+void FunctionExpression::SetValue(ControlState)
+{
+}
+
} // namespace ExpressionParser
} // namespace ciface
diff --git a/Source/Core/InputCommon/ControlReference/FunctionExpression.h b/Source/Core/InputCommon/ControlReference/FunctionExpression.h
index 35e000a16f..14b438a299 100644
--- a/Source/Core/InputCommon/ControlReference/FunctionExpression.h
+++ b/Source/Core/InputCommon/ControlReference/FunctionExpression.h
@@ -20,12 +20,12 @@ class FunctionExpression : public Expression
public:
int CountNumControls() const override;
void UpdateReferences(ControlEnvironment& env) override;
- operator std::string() const override;
bool SetArguments(std::vector<std::unique_ptr<Expression>>&& args);
+ void SetValue(ControlState value) override;
+
protected:
- virtual std::string GetFuncName() const = 0;
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) = 0;
Expression& GetArg(u32 number);