ExpressionParser: Show error message with expected arguments.

This commit is contained in:
Jordan Woyak 2019-10-11 19:38:18 -05:00
parent b57178d246
commit 4d41bd64c8
3 changed files with 102 additions and 34 deletions

View File

@ -469,7 +469,8 @@ private:
return tok.type == type; return tok.type == type;
} }
ParseResult ParseFunctionArguments(std::unique_ptr<FunctionExpression>&& func, ParseResult ParseFunctionArguments(const std::string_view& func_name,
std::unique_ptr<FunctionExpression>&& func,
const Token& func_tok) const Token& func_tok)
{ {
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
@ -518,10 +519,15 @@ private:
} }
} }
if (!func->SetArguments(std::move(args))) const auto argument_validation = func->SetArguments(std::move(args));
if (std::holds_alternative<FunctionExpression::ExpectedArguments>(argument_validation))
{ {
// TODO: It would be nice to output how many arguments are expected. const auto text = std::string(func_name) + '(' +
return ParseResult::MakeErrorResult(func_tok, _trans("Wrong number of arguments.")); std::get<FunctionExpression::ExpectedArguments>(argument_validation).text +
')';
return ParseResult::MakeErrorResult(func_tok, _trans("Expected arguments: " + text));
} }
return ParseResult::MakeSuccessfulResult(std::move(func)); return ParseResult::MakeSuccessfulResult(std::move(func));
@ -543,7 +549,7 @@ private:
return ParseAtom(control_tok); return ParseAtom(control_tok);
} }
return ParseFunctionArguments(std::move(func), tok); return ParseFunctionArguments(tok.data, std::move(func), tok);
} }
case TOK_CONTROL: case TOK_CONTROL:
{ {
@ -553,7 +559,7 @@ private:
} }
case TOK_NOT: case TOK_NOT:
{ {
return ParseFunctionArguments(MakeFunctionExpression("not"), tok); return ParseFunctionArguments("not", MakeFunctionExpression("not"), tok);
} }
case TOK_LITERAL: case TOK_LITERAL:
{ {
@ -571,7 +577,7 @@ private:
{ {
// An atom was expected but we got a subtraction symbol. // An atom was expected but we got a subtraction symbol.
// Interpret it as a unary minus function. // Interpret it as a unary minus function.
return ParseFunctionArguments(MakeFunctionExpression("minus"), tok); return ParseFunctionArguments("minus", MakeFunctionExpression("minus"), tok);
} }
default: default:
{ {

View File

@ -21,10 +21,14 @@ using FSec = std::chrono::duration<ControlState>;
class ToggleExpression : public FunctionExpression class ToggleExpression : public FunctionExpression
{ {
private: private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
// Optional 2nd argument for clearing state: // Optional 2nd argument for clearing state:
return 1 == args.size() || 2 == args.size(); if (1 == args.size() || 2 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"toggle_state_input, [clear_state_input]"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -57,9 +61,13 @@ private:
class NotExpression : public FunctionExpression class NotExpression : public FunctionExpression
{ {
private: private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 1 == args.size(); if (1 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"expression"};
} }
ControlState GetValue() const override { return 1.0 - GetArg(0).GetValue(); } ControlState GetValue() const override { return 1.0 - GetArg(0).GetValue(); }
@ -70,9 +78,13 @@ private:
class SinExpression : public FunctionExpression class SinExpression : public FunctionExpression
{ {
private: private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 1 == args.size(); if (1 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"expression"};
} }
ControlState GetValue() const override { return std::sin(GetArg(0).GetValue()); } ControlState GetValue() const override { return std::sin(GetArg(0).GetValue()); }
@ -82,9 +94,13 @@ private:
class TimerExpression : public FunctionExpression class TimerExpression : public FunctionExpression
{ {
private: private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 1 == args.size(); if (1 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"seconds"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -121,9 +137,13 @@ private:
class IfExpression : public FunctionExpression class IfExpression : public FunctionExpression
{ {
private: private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 3 == args.size(); if (3 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"condition, true_expression, false_expression"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -137,9 +157,13 @@ private:
class UnaryMinusExpression : public FunctionExpression class UnaryMinusExpression : public FunctionExpression
{ {
private: private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 1 == args.size(); if (1 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"expression"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -152,9 +176,13 @@ private:
// usage: deadzone(input, amount) // usage: deadzone(input, amount)
class DeadzoneExpression : public FunctionExpression class DeadzoneExpression : public FunctionExpression
{ {
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 2 == args.size(); if (2 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"input, amount"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -169,9 +197,13 @@ class DeadzoneExpression : public FunctionExpression
// seconds is seconds to change from 0.0 to 1.0 // seconds is seconds to change from 0.0 to 1.0
class SmoothExpression : public FunctionExpression class SmoothExpression : public FunctionExpression
{ {
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 2 == args.size() || 3 == args.size(); if (2 == args.size() || 3 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"input, seconds_up, seconds_down = seconds_up"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -209,9 +241,13 @@ private:
// usage: hold(input, seconds) // usage: hold(input, seconds)
class HoldExpression : public FunctionExpression class HoldExpression : public FunctionExpression
{ {
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 2 == args.size(); if (2 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"input, seconds"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -244,9 +280,13 @@ private:
// usage: tap(input, seconds, taps=2) // usage: tap(input, seconds, taps=2)
class TapExpression : public FunctionExpression class TapExpression : public FunctionExpression
{ {
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 2 == args.size() || 3 == args.size(); if (2 == args.size() || 3 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"input, seconds, taps = 2"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -300,9 +340,13 @@ private:
// speed is max movement per second // speed is max movement per second
class RelativeExpression : public FunctionExpression class RelativeExpression : public FunctionExpression
{ {
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return args.size() >= 2 && args.size() <= 4; if (args.size() >= 2 && args.size() <= 4)
return ArgumentsAreValid{};
else
return ExpectedArguments{"input, speed, [max_abs_value, [shared_state]]"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -355,9 +399,13 @@ private:
// usage: pulse(input, seconds) // usage: pulse(input, seconds)
class PulseExpression : public FunctionExpression class PulseExpression : public FunctionExpression
{ {
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{ {
return 2 == args.size(); if (2 == args.size())
return ArgumentsAreValid{};
else
return ExpectedArguments{"input, seconds"};
} }
ControlState GetValue() const override ControlState GetValue() const override
@ -447,7 +495,8 @@ void FunctionExpression::UpdateReferences(ControlEnvironment& env)
arg->UpdateReferences(env); arg->UpdateReferences(env);
} }
bool FunctionExpression::SetArguments(std::vector<std::unique_ptr<Expression>>&& args) FunctionExpression::ArgumentValidation
FunctionExpression::SetArguments(std::vector<std::unique_ptr<Expression>>&& args)
{ {
m_args = std::move(args); m_args = std::move(args);

View File

@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
#include "InputCommon/ControlReference/ExpressionParser.h" #include "InputCommon/ControlReference/ExpressionParser.h"
@ -18,15 +19,27 @@ namespace ExpressionParser
class FunctionExpression : public Expression class FunctionExpression : public Expression
{ {
public: public:
struct ArgumentsAreValid
{
};
struct ExpectedArguments
{
std::string text;
};
using ArgumentValidation = std::variant<ArgumentsAreValid, ExpectedArguments>;
int CountNumControls() const override; int CountNumControls() const override;
void UpdateReferences(ControlEnvironment& env) override; void UpdateReferences(ControlEnvironment& env) override;
bool SetArguments(std::vector<std::unique_ptr<Expression>>&& args); ArgumentValidation SetArguments(std::vector<std::unique_ptr<Expression>>&& args);
void SetValue(ControlState value) override; void SetValue(ControlState value) override;
protected: protected:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) = 0; virtual ArgumentValidation
ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) = 0;
Expression& GetArg(u32 number); Expression& GetArg(u32 number);
const Expression& GetArg(u32 number) const; const Expression& GetArg(u32 number) const;