From d2821e14fa9735ece3be6eec9d6bdf4cf96c1280 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 14:53:41 -0700 Subject: ParseExpression: return a std::pair --- .../ControlReference/ExpressionParser.cpp | 41 ++++++++++------------ 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index d520015cf3..92e6bde502 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -369,15 +369,14 @@ public: m_it = tokens.begin(); } - ParseStatus Parse(Expression** expr_out) + std::pair Parse() { ExpressionNode* node; ParseStatus status = Toplevel(&node); if (status != ParseStatus::Successful) - return status; + return std::make_pair(status, nullptr); - *expr_out = new Expression(node); - return ParseStatus::Successful; + return std::make_pair(ParseStatus::Successful, new Expression(node)); } private: @@ -522,32 +521,28 @@ Expression::~Expression() delete node; } -static ParseStatus ParseExpressionInner(const std::string& str, ControlFinder& finder, - Expression** expr_out) +static std::pair ParseExpressionInner(const std::string& str, + ControlFinder& finder) { - ParseStatus status; - Expression* expr; - *expr_out = nullptr; - if (str == "") - return ParseStatus::Successful; + return std::make_pair(ParseStatus::Successful, nullptr); Lexer l(str); std::vector tokens; - status = l.Tokenize(tokens); - if (status != ParseStatus::Successful) - return status; + ParseStatus tokenize_status = l.Tokenize(tokens); + if (tokenize_status != ParseStatus::Successful) + return std::make_pair(tokenize_status, nullptr); - Parser p(tokens, finder); - status = p.Parse(&expr); + ParseStatus status; + Expression* expr; + std::tie(status, expr) = Parser(tokens, finder).Parse(); if (status != ParseStatus::Successful) - return status; + return std::make_pair(status, nullptr); - *expr_out = expr; - return ParseStatus::Successful; + return std::make_pair(ParseStatus::Successful, expr); } -ParseStatus ParseExpression(const std::string& str, ControlFinder& finder, Expression** expr_out) +std::pair ParseExpression(const std::string& str, ControlFinder& finder) { // Add compatibility with old simple expressions, which are simple // barewords control names. @@ -560,11 +555,11 @@ ParseStatus ParseExpression(const std::string& str, ControlFinder& finder, Expre Device::Control* control = finder.FindControl(qualifier); if (control) { - *expr_out = new Expression(new ControlExpression(qualifier, device, control)); - return ParseStatus::Successful; + Expression* expr = new Expression(new ControlExpression(qualifier, device, control)); + return std::make_pair(ParseStatus::Successful, expr); } - return ParseExpressionInner(str, finder, expr_out); + return ParseExpressionInner(str, finder); } } } -- cgit v1.2.3 From bbb7c1723569b1f897041851f97a46327a302e48 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:08:55 -0700 Subject: ExpressionParser: use internal ParseResult struct instead of out-params --- .../ControlReference/ExpressionParser.cpp | 97 ++++++++++------------ 1 file changed, 44 insertions(+), 53 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 92e6bde502..a414c669a0 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -361,6 +361,15 @@ Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const return device->FindOutput(qualifier.control_name); } +struct ParseResult +{ + ParseResult(ParseStatus status_, ExpressionNode* expr_ = nullptr) : status(status_), expr(expr_) + { + } + ParseStatus status; + ExpressionNode* expr; +}; + class Parser { public: @@ -369,16 +378,7 @@ public: m_it = tokens.begin(); } - std::pair Parse() - { - ExpressionNode* node; - ParseStatus status = Toplevel(&node); - if (status != ParseStatus::Successful) - return std::make_pair(status, nullptr); - - return std::make_pair(ParseStatus::Successful, new Expression(node)); - } - + ParseResult Parse() { return Toplevel(); } private: std::vector tokens; std::vector::iterator m_it; @@ -392,7 +392,7 @@ private: return tok.type == type; } - ParseStatus Atom(ExpressionNode** expr_out) + ParseResult Atom() { Token tok = Chew(); switch (tok.type) @@ -402,18 +402,14 @@ private: std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); if (control == nullptr) - { - *expr_out = new DummyExpression(tok.qualifier); - return ParseStatus::NoDevice; - } + return {ParseStatus::NoDevice, new DummyExpression(tok.qualifier)}; - *expr_out = new ControlExpression(tok.qualifier, device, control); - return ParseStatus::Successful; + return {ParseStatus::Successful, new ControlExpression(tok.qualifier, device, control)}; } case TOK_LPAREN: - return Paren(expr_out); + return Paren(); default: - return ParseStatus::SyntaxError; + return {ParseStatus::SyntaxError}; } } @@ -428,20 +424,18 @@ private: } } - ParseStatus Unary(ExpressionNode** expr_out) + ParseResult Unary() { if (IsUnaryExpression(Peek().type)) { Token tok = Chew(); - ExpressionNode* atom_expr; - ParseStatus status = Atom(&atom_expr); - if (status == ParseStatus::SyntaxError) - return status; - *expr_out = new UnaryExpression(tok.type, atom_expr); - return ParseStatus::Successful; + ParseResult result = Atom(); + if (result.status == ParseStatus::SyntaxError) + return result; + return {ParseStatus::Successful, new UnaryExpression(tok.type, result.expr)}; } - return Atom(expr_out); + return Atom(); } bool IsBinaryToken(TokenType type) @@ -457,47 +451,46 @@ private: } } - ParseStatus Binary(ExpressionNode** expr_out) + ParseResult Binary() { - ParseStatus status = Unary(expr_out); - if (status == ParseStatus::SyntaxError) - return status; + ParseResult result = Unary(); + if (result.status == ParseStatus::SyntaxError) + return result; + ExpressionNode* expr = result.expr; while (IsBinaryToken(Peek().type)) { Token tok = Chew(); - ExpressionNode* unary_expr; - status = Unary(&unary_expr); - if (status == ParseStatus::SyntaxError) + ParseResult unary_result = Unary(); + if (unary_result.status == ParseStatus::SyntaxError) { - delete *expr_out; - return status; + delete expr; + return unary_result; } - *expr_out = new BinaryExpression(tok.type, *expr_out, unary_expr); + expr = new BinaryExpression(tok.type, expr, unary_result.expr); } - return ParseStatus::Successful; + return {ParseStatus::Successful, expr}; } - ParseStatus Paren(ExpressionNode** expr_out) + ParseResult Paren() { - ParseStatus status; - // lparen already chewed - if ((status = Toplevel(expr_out)) != ParseStatus::Successful) - return status; + ParseResult result = Toplevel(); + if (result.status != ParseStatus::Successful) + return result; if (!Expects(TOK_RPAREN)) { - delete *expr_out; - return ParseStatus::SyntaxError; + delete result.expr; + return {ParseStatus::SyntaxError}; } - return ParseStatus::Successful; + return result; } - ParseStatus Toplevel(ExpressionNode** expr_out) { return Binary(expr_out); } + ParseResult Toplevel() { return Binary(); } }; ControlState Expression::GetValue() const @@ -533,13 +526,11 @@ static std::pair ParseExpressionInner(const std::strin if (tokenize_status != ParseStatus::Successful) return std::make_pair(tokenize_status, nullptr); - ParseStatus status; - Expression* expr; - std::tie(status, expr) = Parser(tokens, finder).Parse(); - if (status != ParseStatus::Successful) - return std::make_pair(status, nullptr); + ParseResult result = Parser(tokens, finder).Parse(); + if (result.status != ParseStatus::Successful) + return std::make_pair(result.status, nullptr); - return std::make_pair(ParseStatus::Successful, expr); + return std::make_pair(ParseStatus::Successful, new Expression(result.expr)); } std::pair ParseExpression(const std::string& str, ControlFinder& finder) -- cgit v1.2.3 From 3df945f8d0c34677b009c210dd0400b2e9655024 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:29:00 -0700 Subject: ExpressionParser: replace bare pointers with unique_ptrs --- .../ControlReference/ExpressionParser.cpp | 68 ++++++++++++---------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index a414c669a0..4f498d6f37 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -253,18 +253,14 @@ class BinaryExpression : public ExpressionNode { public: TokenType op; - ExpressionNode* lhs; - ExpressionNode* rhs; + std::unique_ptr lhs; + std::unique_ptr rhs; - BinaryExpression(TokenType op_, ExpressionNode* lhs_, ExpressionNode* rhs_) - : op(op_), lhs(lhs_), rhs(rhs_) + BinaryExpression(TokenType op_, std::unique_ptr&& lhs_, + std::unique_ptr&& rhs_) + : op(op_), lhs(std::move(lhs_)), rhs(std::move(rhs_)) { } - virtual ~BinaryExpression() - { - delete lhs; - delete rhs; - } ControlState GetValue() const override { @@ -307,10 +303,12 @@ class UnaryExpression : public ExpressionNode { public: TokenType op; - ExpressionNode* inner; + std::unique_ptr inner; - UnaryExpression(TokenType op_, ExpressionNode* inner_) : op(op_), inner(inner_) {} - virtual ~UnaryExpression() { delete inner; } + UnaryExpression(TokenType op_, std::unique_ptr&& inner_) + : op(op_), inner(std::move(inner_)) + { + } ControlState GetValue() const override { ControlState value = inner->GetValue(); @@ -363,11 +361,13 @@ Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const struct ParseResult { - ParseResult(ParseStatus status_, ExpressionNode* expr_ = nullptr) : status(status_), expr(expr_) + ParseResult(ParseStatus status_, std::unique_ptr&& expr_ = {}) + : status(status_), expr(std::move(expr_)) { } + ParseStatus status; - ExpressionNode* expr; + std::unique_ptr expr; }; class Parser @@ -402,9 +402,10 @@ private: std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); if (control == nullptr) - return {ParseStatus::NoDevice, new DummyExpression(tok.qualifier)}; + return {ParseStatus::NoDevice, std::make_unique(tok.qualifier)}; - return {ParseStatus::Successful, new ControlExpression(tok.qualifier, device, control)}; + return {ParseStatus::Successful, + std::make_unique(tok.qualifier, device, control)}; } case TOK_LPAREN: return Paren(); @@ -432,7 +433,8 @@ private: ParseResult result = Atom(); if (result.status == ParseStatus::SyntaxError) return result; - return {ParseStatus::Successful, new UnaryExpression(tok.type, result.expr)}; + return {ParseStatus::Successful, + std::make_unique(tok.type, std::move(result.expr))}; } return Atom(); @@ -457,21 +459,21 @@ private: if (result.status == ParseStatus::SyntaxError) return result; - ExpressionNode* expr = result.expr; + std::unique_ptr expr = std::move(result.expr); while (IsBinaryToken(Peek().type)) { Token tok = Chew(); ParseResult unary_result = Unary(); if (unary_result.status == ParseStatus::SyntaxError) { - delete expr; return unary_result; } - expr = new BinaryExpression(tok.type, expr, unary_result.expr); + expr = std::make_unique(tok.type, std::move(expr), + std::move(unary_result.expr)); } - return {ParseStatus::Successful, expr}; + return {ParseStatus::Successful, std::move(expr)}; } ParseResult Paren() @@ -483,7 +485,6 @@ private: if (!Expects(TOK_RPAREN)) { - delete result.expr; return {ParseStatus::SyntaxError}; } @@ -503,19 +504,19 @@ void Expression::SetValue(ControlState value) node->SetValue(value); } -Expression::Expression(ExpressionNode* node_) +Expression::Expression(std::unique_ptr&& node_) { - node = node_; - num_controls = node->CountNumControls(); + node = std::move(node_); + if (node) + num_controls = node->CountNumControls(); } Expression::~Expression() { - delete node; } -static std::pair ParseExpressionInner(const std::string& str, - ControlFinder& finder) +static std::pair> +ParseExpressionInner(const std::string& str, ControlFinder& finder) { if (str == "") return std::make_pair(ParseStatus::Successful, nullptr); @@ -530,10 +531,12 @@ static std::pair ParseExpressionInner(const std::strin if (result.status != ParseStatus::Successful) return std::make_pair(result.status, nullptr); - return std::make_pair(ParseStatus::Successful, new Expression(result.expr)); + return std::make_pair(ParseStatus::Successful, + std::make_unique(std::move(result.expr))); } -std::pair ParseExpression(const std::string& str, ControlFinder& finder) +std::pair> ParseExpression(const std::string& str, + ControlFinder& finder) { // Add compatibility with old simple expressions, which are simple // barewords control names. @@ -546,8 +549,9 @@ std::pair ParseExpression(const std::string& str, Cont Device::Control* control = finder.FindControl(qualifier); if (control) { - Expression* expr = new Expression(new ControlExpression(qualifier, device, control)); - return std::make_pair(ParseStatus::Successful, expr); + return std::make_pair(ParseStatus::Successful, + std::make_unique( + std::make_unique(qualifier, device, control))); } return ParseExpressionInner(str, finder); -- cgit v1.2.3 From f1ff1e3d084c1dd8ae28f2dd8cc409949e378334 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:54:59 -0700 Subject: ExpressionParser: clean up ControlExpression --- .../Core/InputCommon/ControlReference/ExpressionParser.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 4f498d6f37..277cfb3c70 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -234,19 +234,19 @@ class ControlExpression : public ExpressionNode public: ControlQualifier qualifier; Device::Control* control; + // Keep a shared_ptr to the device so the control pointer doesn't become invalid + std::shared_ptr m_device; ControlExpression(ControlQualifier qualifier_, std::shared_ptr device, Device::Control* control_) - : qualifier(qualifier_), control(control_), m_device(device) + : qualifier(qualifier_), control(control_), m_device(std::move(device)) { } ControlState GetValue() const override { return control->ToInput()->GetState(); } void SetValue(ControlState value) override { control->ToOutput()->SetState(value); } int CountNumControls() const override { return 1; } - operator std::string() const override { return "`" + (std::string)qualifier + "`"; } -private: - std::shared_ptr m_device; + operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; class BinaryExpression : public ExpressionNode @@ -405,7 +405,7 @@ private: return {ParseStatus::NoDevice, std::make_unique(tok.qualifier)}; return {ParseStatus::Successful, - std::make_unique(tok.qualifier, device, control)}; + std::make_unique(tok.qualifier, std::move(device), control)}; } case TOK_LPAREN: return Paren(); @@ -550,8 +550,8 @@ std::pair> ParseExpression(const std::s if (control) { return std::make_pair(ParseStatus::Successful, - std::make_unique( - std::make_unique(qualifier, device, control))); + std::make_unique(std::make_unique( + qualifier, std::move(device), control))); } return ParseExpressionInner(str, finder); -- cgit v1.2.3 From 754efd75c5f8b843e25f2ff8510bfc2a25fd1de1 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 15:56:49 -0700 Subject: ExpressionParser: remove DummyExpression --- .../ControlReference/ExpressionParser.cpp | 24 ++++++++-------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 277cfb3c70..4bd4901cdd 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -217,18 +217,6 @@ public: virtual operator std::string() const { return ""; } }; -class DummyExpression : public ExpressionNode -{ -public: - std::string name; - - DummyExpression(const std::string& name_) : name(name_) {} - ControlState GetValue() const override { return 0.0; } - void SetValue(ControlState value) override {} - int CountNumControls() const override { return 0; } - operator std::string() const override { return "`" + name + "`"; } -}; - class ControlExpression : public ExpressionNode { public: @@ -243,9 +231,13 @@ public: { } - ControlState GetValue() const override { return control->ToInput()->GetState(); } - void SetValue(ControlState value) override { control->ToOutput()->SetState(value); } - int CountNumControls() const override { return 1; } + ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; } + void SetValue(ControlState value) override + { + if (control) + control->ToOutput()->SetState(value); + } + int CountNumControls() const override { return control ? 1 : 0; } operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; @@ -402,7 +394,7 @@ private: std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); if (control == nullptr) - return {ParseStatus::NoDevice, std::make_unique(tok.qualifier)}; + return {ParseStatus::NoDevice, std::make_unique(tok.qualifier, control)}; return {ParseStatus::Successful, std::make_unique(tok.qualifier, std::move(device), control)}; -- cgit v1.2.3 From 85301e2baeda9a97c4c5ebbf07807566831e22d1 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 16:03:36 -0700 Subject: ParseStatus: replace NoDevice with EmptyExpression --- Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 4bd4901cdd..d2cef8c917 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -10,6 +10,7 @@ #include #include +#include "Common/StringUtil.h" #include "InputCommon/ControlReference/ExpressionParser.h" using namespace ciface::Core; @@ -393,9 +394,6 @@ private: { std::shared_ptr device = finder.FindDevice(tok.qualifier); Device::Control* control = finder.FindControl(tok.qualifier); - if (control == nullptr) - return {ParseStatus::NoDevice, std::make_unique(tok.qualifier, control)}; - return {ParseStatus::Successful, std::make_unique(tok.qualifier, std::move(device), control)}; } @@ -510,8 +508,8 @@ Expression::~Expression() static std::pair> ParseExpressionInner(const std::string& str, ControlFinder& finder) { - if (str == "") - return std::make_pair(ParseStatus::Successful, nullptr); + if (StripSpaces(str).empty()) + return std::make_pair(ParseStatus::EmptyExpression, nullptr); Lexer l(str); std::vector tokens; -- cgit v1.2.3 From 7e74961eb150f28a56405403335f4904f888e058 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 17:30:07 -0700 Subject: ExpressionParser: expose ExpressionNode directly --- .../ControlReference/ExpressionParser.cpp | 76 ++++++---------------- 1 file changed, 20 insertions(+), 56 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index d2cef8c917..82829ed818 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -208,17 +208,7 @@ public: } }; -class ExpressionNode -{ -public: - virtual ~ExpressionNode() {} - virtual ControlState GetValue() const { return 0; } - virtual void SetValue(ControlState state) {} - virtual int CountNumControls() const { return 0; } - virtual operator std::string() const { return ""; } -}; - -class ControlExpression : public ExpressionNode +class ControlExpression : public Expression { public: ControlQualifier qualifier; @@ -242,15 +232,15 @@ public: operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; -class BinaryExpression : public ExpressionNode +class BinaryExpression : public Expression { public: TokenType op; - std::unique_ptr lhs; - std::unique_ptr rhs; + std::unique_ptr lhs; + std::unique_ptr rhs; - BinaryExpression(TokenType op_, std::unique_ptr&& lhs_, - std::unique_ptr&& rhs_) + BinaryExpression(TokenType op_, std::unique_ptr&& lhs_, + std::unique_ptr&& rhs_) : op(op_), lhs(std::move(lhs_)), rhs(std::move(rhs_)) { } @@ -292,13 +282,13 @@ public: } }; -class UnaryExpression : public ExpressionNode +class UnaryExpression : public Expression { public: TokenType op; - std::unique_ptr inner; + std::unique_ptr inner; - UnaryExpression(TokenType op_, std::unique_ptr&& inner_) + UnaryExpression(TokenType op_, std::unique_ptr&& inner_) : op(op_), inner(std::move(inner_)) { } @@ -354,13 +344,13 @@ Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const struct ParseResult { - ParseResult(ParseStatus status_, std::unique_ptr&& expr_ = {}) + ParseResult(ParseStatus status_, std::unique_ptr&& expr_ = {}) : status(status_), expr(std::move(expr_)) { } ParseStatus status; - std::unique_ptr expr; + std::unique_ptr expr; }; class Parser @@ -449,7 +439,7 @@ private: if (result.status == ParseStatus::SyntaxError) return result; - std::unique_ptr expr = std::move(result.expr); + std::unique_ptr expr = std::move(result.expr); while (IsBinaryToken(Peek().type)) { Token tok = Chew(); @@ -484,45 +474,19 @@ private: ParseResult Toplevel() { return Binary(); } }; -ControlState Expression::GetValue() const -{ - return node->GetValue(); -} - -void Expression::SetValue(ControlState value) -{ - node->SetValue(value); -} - -Expression::Expression(std::unique_ptr&& node_) -{ - node = std::move(node_); - if (node) - num_controls = node->CountNumControls(); -} - -Expression::~Expression() -{ -} - -static std::pair> -ParseExpressionInner(const std::string& str, ControlFinder& finder) +static ParseResult ParseExpressionInner(const std::string& str, ControlFinder& finder) { if (StripSpaces(str).empty()) - return std::make_pair(ParseStatus::EmptyExpression, nullptr); + return {ParseStatus::EmptyExpression}; Lexer l(str); std::vector tokens; ParseStatus tokenize_status = l.Tokenize(tokens); if (tokenize_status != ParseStatus::Successful) - return std::make_pair(tokenize_status, nullptr); + return {tokenize_status}; ParseResult result = Parser(tokens, finder).Parse(); - if (result.status != ParseStatus::Successful) - return std::make_pair(result.status, nullptr); - - return std::make_pair(ParseStatus::Successful, - std::make_unique(std::move(result.expr))); + return result; } std::pair> ParseExpression(const std::string& str, @@ -539,12 +503,12 @@ std::pair> ParseExpression(const std::s Device::Control* control = finder.FindControl(qualifier); if (control) { - return std::make_pair(ParseStatus::Successful, - std::make_unique(std::make_unique( - qualifier, std::move(device), control))); + return std::make_pair(ParseStatus::Successful, std::make_unique( + qualifier, std::move(device), control)); } - return ParseExpressionInner(str, finder); + ParseResult result = ParseExpressionInner(str, finder); + return std::make_pair(result.status, std::move(result.expr)); } } } -- cgit v1.2.3 From ba87a503389a6db8e4ddae5a87f9d1ebc52db46a Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 18:29:02 -0700 Subject: ExpressionParser: add FallbackExpression node type --- .../ControlReference/ExpressionParser.cpp | 71 +++++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 82829ed818..3bac0243dc 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -322,6 +322,40 @@ public: operator std::string() const override { return OpName(op) + "(" + (std::string)(*inner) + ")"; } }; +// 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 +{ +public: + CoalesceExpression(std::unique_ptr&& lhs, std::unique_ptr&& rhs) + : m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) + { + } + + ControlState GetValue() const override { return GetActiveChild()->GetValue(); } + void SetValue(ControlState value) override + { + m_lhs->SetValue(GetActiveChild() == m_lhs ? value : 0.0); + m_rhs->SetValue(GetActiveChild() == m_rhs ? value : 0.0); + } + + int CountNumControls() const override { return GetActiveChild()->CountNumControls(); } + operator std::string() const override + { + return "Coalesce(" + static_cast(*m_lhs) + ", " + + static_cast(*m_rhs) + ')'; + } + +private: + const std::unique_ptr& GetActiveChild() const + { + return m_lhs->CountNumControls() > 0 ? m_lhs : m_rhs; + } + + std::unique_ptr m_lhs; + std::unique_ptr m_rhs; +}; + std::shared_ptr ControlFinder::FindDevice(ControlQualifier qualifier) const { if (qualifier.has_device) @@ -474,41 +508,46 @@ private: ParseResult Toplevel() { return Binary(); } }; -static ParseResult ParseExpressionInner(const std::string& str, ControlFinder& finder) +static ParseResult ParseComplexExpression(const std::string& str, ControlFinder& finder) { - if (StripSpaces(str).empty()) - return {ParseStatus::EmptyExpression}; - Lexer l(str); std::vector tokens; ParseStatus tokenize_status = l.Tokenize(tokens); if (tokenize_status != ParseStatus::Successful) return {tokenize_status}; - ParseResult result = Parser(tokens, finder).Parse(); - return result; + return Parser(tokens, finder).Parse(); } -std::pair> ParseExpression(const std::string& str, - ControlFinder& finder) +static std::unique_ptr ParseBarewordExpression(const std::string& str, + ControlFinder& finder) { - // Add compatibility with old simple expressions, which are simple - // barewords control names. - ControlQualifier qualifier; qualifier.control_name = str; qualifier.has_device = false; std::shared_ptr device = finder.FindDevice(qualifier); Device::Control* control = finder.FindControl(qualifier); - if (control) + return std::make_unique(qualifier, std::move(device), control); +} + +std::pair> ParseExpression(const std::string& str, + ControlFinder& finder) +{ + if (StripSpaces(str).empty()) + return std::make_pair(ParseStatus::EmptyExpression, nullptr); + + auto bareword_expr = ParseBarewordExpression(str, finder); + ParseResult complex_result = ParseComplexExpression(str, finder); + + if (complex_result.status != ParseStatus::Successful) { - return std::make_pair(ParseStatus::Successful, std::make_unique( - qualifier, std::move(device), control)); + return std::make_pair(complex_result.status, std::move(bareword_expr)); } - ParseResult result = ParseExpressionInner(str, finder); - return std::make_pair(result.status, std::move(result.expr)); + auto combined_expr = std::make_unique(std::move(bareword_expr), + std::move(complex_result.expr)); + return std::make_pair(complex_result.status, std::move(combined_expr)); } } } -- cgit v1.2.3 From c332580b83ea8cd5650d53378843ceadcbfeb9cb Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 18:48:17 -0700 Subject: ControlReference/ExpressionParser: separate parsing from binding --- .../ControlReference/ExpressionParser.cpp | 59 +++++++++++----------- 1 file changed, 29 insertions(+), 30 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 3bac0243dc..ce58b0f968 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -212,16 +212,11 @@ class ControlExpression : public Expression { public: ControlQualifier qualifier; - Device::Control* control; + Device::Control* control = nullptr; // Keep a shared_ptr to the device so the control pointer doesn't become invalid std::shared_ptr m_device; - ControlExpression(ControlQualifier qualifier_, std::shared_ptr device, - Device::Control* control_) - : qualifier(qualifier_), control(control_), m_device(std::move(device)) - { - } - + ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; } void SetValue(ControlState value) override { @@ -229,6 +224,11 @@ public: control->ToOutput()->SetState(value); } int CountNumControls() const override { return control ? 1 : 0; } + void UpdateReferences(ControlFinder& finder) override + { + m_device = finder.FindDevice(qualifier); + control = finder.FindControl(qualifier); + } operator std::string() const override { return "`" + static_cast(qualifier) + "`"; } }; @@ -276,6 +276,12 @@ public: return lhs->CountNumControls() + rhs->CountNumControls(); } + void UpdateReferences(ControlFinder& finder) override + { + lhs->UpdateReferences(finder); + rhs->UpdateReferences(finder); + } + operator std::string() const override { return OpName(op) + "(" + (std::string)(*lhs) + ", " + (std::string)(*rhs) + ")"; @@ -319,6 +325,7 @@ public: } int CountNumControls() const override { return inner->CountNumControls(); } + void UpdateReferences(ControlFinder& finder) override { inner->UpdateReferences(finder); } operator std::string() const override { return OpName(op) + "(" + (std::string)(*inner) + ")"; } }; @@ -346,6 +353,12 @@ public: static_cast(*m_rhs) + ')'; } + void UpdateReferences(ControlFinder& finder) override + { + m_lhs->UpdateReferences(finder); + m_rhs->UpdateReferences(finder); + } + private: const std::unique_ptr& GetActiveChild() const { @@ -390,16 +403,11 @@ struct ParseResult class Parser { public: - Parser(std::vector tokens_, ControlFinder& finder_) : tokens(tokens_), finder(finder_) - { - m_it = tokens.begin(); - } - + explicit Parser(std::vector tokens_) : tokens(tokens_) { m_it = tokens.begin(); } ParseResult Parse() { return Toplevel(); } private: std::vector tokens; std::vector::iterator m_it; - ControlFinder& finder; Token Chew() { return *m_it++; } Token Peek() { return *m_it; } @@ -415,12 +423,7 @@ private: switch (tok.type) { case TOK_CONTROL: - { - std::shared_ptr device = finder.FindDevice(tok.qualifier); - Device::Control* control = finder.FindControl(tok.qualifier); - return {ParseStatus::Successful, - std::make_unique(tok.qualifier, std::move(device), control)}; - } + return {ParseStatus::Successful, std::make_unique(tok.qualifier)}; case TOK_LPAREN: return Paren(); default: @@ -508,7 +511,7 @@ private: ParseResult Toplevel() { return Binary(); } }; -static ParseResult ParseComplexExpression(const std::string& str, ControlFinder& finder) +static ParseResult ParseComplexExpression(const std::string& str) { Lexer l(str); std::vector tokens; @@ -516,29 +519,25 @@ static ParseResult ParseComplexExpression(const std::string& str, ControlFinder& if (tokenize_status != ParseStatus::Successful) return {tokenize_status}; - return Parser(tokens, finder).Parse(); + return Parser(tokens).Parse(); } -static std::unique_ptr ParseBarewordExpression(const std::string& str, - ControlFinder& finder) +static std::unique_ptr ParseBarewordExpression(const std::string& str) { ControlQualifier qualifier; qualifier.control_name = str; qualifier.has_device = false; - std::shared_ptr device = finder.FindDevice(qualifier); - Device::Control* control = finder.FindControl(qualifier); - return std::make_unique(qualifier, std::move(device), control); + return std::make_unique(qualifier); } -std::pair> ParseExpression(const std::string& str, - ControlFinder& finder) +std::pair> ParseExpression(const std::string& str) { if (StripSpaces(str).empty()) return std::make_pair(ParseStatus::EmptyExpression, nullptr); - auto bareword_expr = ParseBarewordExpression(str, finder); - ParseResult complex_result = ParseComplexExpression(str, finder); + auto bareword_expr = ParseBarewordExpression(str); + ParseResult complex_result = ParseComplexExpression(str); if (complex_result.status != ParseStatus::Successful) { -- cgit v1.2.3 From 31f1c062264fcf8628e3a13c44de893d4bac0aa0 Mon Sep 17 00:00:00 2001 From: Michael M Date: Wed, 7 Jun 2017 19:02:16 -0700 Subject: ControlReference: don't reparse expression when references are updated --- Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index ce58b0f968..c9cf998ea9 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -216,7 +216,7 @@ public: // Keep a shared_ptr to the device so the control pointer doesn't become invalid std::shared_ptr m_device; - ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} + explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {} ControlState GetValue() const override { return control ? control->ToInput()->GetState() : 0.0; } void SetValue(ControlState value) override { -- cgit v1.2.3 From 294b1895ef2963cfc6fda1818d9a9f3b8b0af48f Mon Sep 17 00:00:00 2001 From: Michael M Date: Thu, 8 Jun 2017 00:23:38 -0700 Subject: ExpressionParser: std::move() tokens vector to parser --- Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index c9cf998ea9..85eb86d598 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -519,7 +519,7 @@ static ParseResult ParseComplexExpression(const std::string& str) if (tokenize_status != ParseStatus::Successful) return {tokenize_status}; - return Parser(tokens).Parse(); + return Parser(std::move(tokens)).Parse(); } static std::unique_ptr ParseBarewordExpression(const std::string& str) -- cgit v1.2.3