Skip to content
Permalink
Browse files

ExpressionParser: operator precedence.

  • Loading branch information...
jordan-woyak committed Dec 31, 2018
1 parent 46c0ae7 commit fa75ab404f065670671a614c7839a3f963ef352b
Showing with 50 additions and 28 deletions.
  1. +50 −28 Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -139,7 +139,7 @@ class Token
return '\'' + data + '\'';
case TOK_VARIABLE:
return '$' + data;
case TOK_INVALID:
default:
break;
}

@@ -528,7 +528,7 @@ class UnaryWhileExpression : public UnaryExpression
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 @@ class UnaryWhileExpression : public UnaryExpression
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 @@ class Parser
}
}

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 @@ class Parser
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 @@ class Parser
}

ParseResult Toplevel() { return Binary(); }
};
}; // namespace ExpressionParser

static ParseResult ParseComplexExpression(const std::string& str)
{

0 comments on commit fa75ab4

Please sign in to comment.
You can’t perform that action at this time.