summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2018-12-30 19:50:20 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2019-10-11 17:14:45 -0500
commitfa75ab404f065670671a614c7839a3f963ef352b (patch)
treeaf216e1dc2dc34e9c163e58ac507ae9318d00911 /Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
parent46c0ae7d1fd0eeca12f3406be8919a5fac3d6847 (diff)
ExpressionParser: operator precedence.
Diffstat (limited to 'Source/Core/InputCommon/ControlReference/ExpressionParser.cpp')
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp78
1 files changed, 50 insertions, 28 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<UnaryExpression> 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;
+ switch (type)
+ {
+ 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<Expression> expr = std::move(result.expr);
- while (IsBinaryToken(Peek().type))
+ std::unique_ptr<Expression> expr = std::move(lhs.expr);
+
+ // TODO: handle LTR/RTL associativity?
+ while (IsBinaryToken(Peek().type) && BinaryOperatorPrecedence(Peek().type) < precedence)
{
- Token tok = Chew();
- ParseResult unary_result = Unary();
- if (unary_result.status == ParseStatus::SyntaxError)
+ const Token tok = Chew();
+ ParseResult rhs = Binary(BinaryOperatorPrecedence(tok.type));
+ if (rhs.status == ParseStatus::SyntaxError)
{
- return unary_result;
+ return rhs;
}
- expr = std::make_unique<BinaryExpression>(tok.type, std::move(expr),
- std::move(unary_result.expr));
+ expr = std::make_unique<BinaryExpression>(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)
{