summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2019-01-08 18:26:36 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2019-10-11 17:31:09 -0500
commit258832b1e89b62d582e42d23099570f03c407885 (patch)
tree4515e635e2648dd531172c573bfce762f5ec8432 /Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
parentccac3f1e495531f30764a1961a52f73131e09b9f (diff)
ExpressionParser: Change function argument syntax to something more c++-like.
Diffstat (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp')
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp135
1 files changed, 106 insertions, 29 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
index 85e19da972..3838a6a7e9 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -449,14 +449,19 @@ public:
return result;
}
- void AppendArg(std::unique_ptr<Expression> arg) { m_args.emplace_back(std::move(arg)); }
+ bool SetArguments(std::vector<std::unique_ptr<Expression>>&& args)
+ {
+ m_args = std::move(args);
- Expression& GetArg(u32 number) { return *m_args[number]; }
- const Expression& GetArg(u32 number) const { return *m_args[number]; }
- virtual int GetArity() const = 0;
+ return ValidateArguments(m_args);
+ }
protected:
virtual std::string GetFuncName() const = 0;
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) = 0;
+
+ Expression& GetArg(u32 number) { return *m_args[number]; }
+ const Expression& GetArg(u32 number) const { return *m_args[number]; }
private:
std::vector<std::unique_ptr<Expression>> m_args;
@@ -465,16 +470,24 @@ private:
// TODO: Return an oscillating value to make it apparent something was spelled wrong?
class UnknownFunctionExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return false;
+ }
ControlState GetValue() const override { return 0.0; }
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "Unknown"; }
- int GetArity() const override { return 0; }
};
class ToggleExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 1 == args.size();
+ }
+
ControlState GetValue() const override
{
const ControlState inner_value = GetArg(0).GetValue();
@@ -494,34 +507,45 @@ public:
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "Toggle"; }
- int GetArity() const override { return 1; }
-private:
mutable bool m_released{};
mutable bool m_state{};
};
class NotExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 1 == args.size();
+ }
+
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 ""; }
- int GetArity() const override { return 1; }
};
class SinExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 1 == args.size();
+ }
+
ControlState GetValue() const override { return std::sin(GetArg(0).GetValue()); }
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "Sin"; }
- int GetArity() const override { return 1; }
};
class TimerExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 1 == args.size();
+ }
+
ControlState GetValue() const override
{
const auto now = Clock::now();
@@ -551,7 +575,6 @@ public:
}
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "Timer"; }
- int GetArity() const override { return 1; }
private:
using Clock = std::chrono::steady_clock;
@@ -560,7 +583,12 @@ private:
class IfExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 3 == args.size();
+ }
+
ControlState GetValue() const override
{
return (GetArg(0).GetValue() > CONDITION_THRESHOLD) ? GetArg(1).GetValue() :
@@ -569,12 +597,16 @@ public:
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "If"; }
- int GetArity() const override { return 3; }
};
class UnaryMinusExpression : public FunctionExpression
{
-public:
+private:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 1 == args.size();
+ }
+
ControlState GetValue() const override
{
// Subtraction for clarity:
@@ -583,12 +615,15 @@ public:
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "Minus"; }
- int GetArity() const override { return 1; }
};
class WhileExpression : public FunctionExpression
{
-public:
+ virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ return 2 == args.size();
+ }
+
ControlState GetValue() const override
{
// Returns 1.0 on successful loop, 0.0 on reps exceeded. Sensible?
@@ -610,7 +645,6 @@ public:
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "While"; }
- int GetArity() const override { return 2; }
};
std::unique_ptr<FunctionExpression> MakeFunctionExpression(std::string name)
@@ -787,17 +821,61 @@ public:
ParseResult Parse() { return Toplevel(); }
private:
+ struct FunctionArguments
+ {
+ FunctionArguments(ParseStatus status_, std::vector<std::unique_ptr<Expression>>&& args_ = {})
+ : status(status_), args(std::move(args_))
+ {
+ }
+
+ ParseStatus status;
+ std::vector<std::unique_ptr<Expression>> args;
+ };
+
std::vector<Token> tokens;
std::vector<Token>::iterator m_it;
Token Chew() { return *m_it++; }
Token Peek() { return *m_it; }
+
bool Expects(TokenType type)
{
Token tok = Chew();
return tok.type == type;
}
+ FunctionArguments ParseFunctionArguments()
+ {
+ if (!Expects(TOK_LPAREN))
+ return {ParseStatus::SyntaxError};
+
+ // Check for empty argument list:
+ if (TOK_RPAREN == Peek().type)
+ return {ParseStatus::Successful};
+
+ std::vector<std::unique_ptr<Expression>> args;
+
+ while (true)
+ {
+ // Read one argument.
+ // Grab an expression, but stop at comma.
+ auto arg = Binary(BinaryOperatorPrecedence(TOK_COMMA));
+ if (ParseStatus::Successful != arg.status)
+ return {ParseStatus::SyntaxError};
+
+ 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 {ParseStatus::Successful, std::move(args)};
+
+ // Comma before the next argument.
+ if (TOK_COMMA != tok.type)
+ return {ParseStatus::SyntaxError};
+ }
+ }
+
ParseResult Atom(const Token& tok)
{
switch (tok.type)
@@ -805,15 +883,14 @@ private:
case TOK_FUNCTION:
{
auto func = MakeFunctionExpression(tok.data);
- int arity = func->GetArity();
- while (arity--)
- {
- auto arg = Atom(Chew());
- if (arg.status == ParseStatus::SyntaxError)
- return arg;
+ auto args = ParseFunctionArguments();
+
+ if (ParseStatus::Successful != args.status)
+ return {ParseStatus::SyntaxError};
+
+ if (!func->SetArguments(std::move(args.args)))
+ return {ParseStatus::SyntaxError};
- func->AppendArg(std::move(arg.expr));
- }
return {ParseStatus::Successful, std::move(func)};
}
case TOK_CONTROL: