From fa75ab404f065670671a614c7839a3f963ef352b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 30 Dec 2018 19:50:20 -0600 Subject: [PATCH] ExpressionParser: operator precedence. --- .../ControlReference/ExpressionParser.cpp | 80 ++++++++++++------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 4d68a090d8..a5c4036167 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -139,7 +139,7 @@ public: return '\'' + data + '\''; case TOK_VARIABLE: return '$' + data; - case TOK_INVALID: + default: break; } @@ -528,7 +528,7 @@ public: ControlState GetValue() const override { constexpr int MAX_REPS = 10000; - constexpr int COND_THRESHOLD = 0.5; + constexpr ControlState COND_THRESHOLD = 0.5; // Returns 1.0 on successful loop, 0.0 on reps exceeded. Sensible? @@ -543,7 +543,7 @@ public: return 0.0; } void SetValue(ControlState value) override {} - std::string GetFuncName() const override { return "Sin"; } + std::string GetFuncName() const override { return "While"; } }; std::unique_ptr MakeUnaryExpression(std::string name, @@ -782,22 +782,13 @@ private: } } - bool IsUnaryExpression(TokenType type) - { - switch (type) - { - case TOK_UNARY: - return true; - default: - return false; - } - } + static bool IsUnaryExpression(TokenType type) { return TOK_UNARY == type; } ParseResult Unary() { if (IsUnaryExpression(Peek().type)) { - Token tok = Chew(); + const Token tok = Chew(); ParseResult result = Atom(); if (result.status == ParseStatus::SyntaxError) return result; @@ -807,29 +798,60 @@ private: return Atom(); } - bool IsBinaryToken(TokenType type) + static bool IsBinaryToken(TokenType type) { return type >= TOK_BINARY_OPS_BEGIN && type < TOK_BINARY_OPS_END; } - ParseResult Binary() + static int BinaryOperatorPrecedence(TokenType type) { - ParseResult result = Unary(); - if (result.status == ParseStatus::SyntaxError) - return result; - - std::unique_ptr expr = std::move(result.expr); - while (IsBinaryToken(Peek().type)) + switch (type) { - Token tok = Chew(); - ParseResult unary_result = Unary(); - if (unary_result.status == ParseStatus::SyntaxError) + case TOK_MUL: + case TOK_DIV: + case TOK_MOD: + return 1; + case TOK_ADD: + case TOK_SUB: + return 2; + case TOK_GTHAN: + case TOK_LTHAN: + return 3; + case TOK_AND: + return 4; + case TOK_OR: + return 5; + case TOK_COND: + case TOK_ASSIGN: + return 6; + case TOK_COMMA: + return 7; + default: + assert(false); + return 0; + } + } + + ParseResult Binary(int precedence = 999) + { + ParseResult lhs = Unary(); + + if (lhs.status == ParseStatus::SyntaxError) + return lhs; + + std::unique_ptr expr = std::move(lhs.expr); + + // TODO: handle LTR/RTL associativity? + while (IsBinaryToken(Peek().type) && BinaryOperatorPrecedence(Peek().type) < precedence) + { + const Token tok = Chew(); + ParseResult rhs = Binary(BinaryOperatorPrecedence(tok.type)); + if (rhs.status == ParseStatus::SyntaxError) { - return unary_result; + return rhs; } - expr = std::make_unique(tok.type, std::move(expr), - std::move(unary_result.expr)); + expr = std::make_unique(tok.type, std::move(expr), std::move(rhs.expr)); } return {ParseStatus::Successful, std::move(expr)}; @@ -851,7 +873,7 @@ private: } ParseResult Toplevel() { return Binary(); } -}; +}; // namespace ExpressionParser static ParseResult ParseComplexExpression(const std::string& str) {