ExpressionParser: operator precedence.

This commit is contained in:
Jordan Woyak 2018-12-30 19:50:20 -06:00
parent 46c0ae7d1f
commit fa75ab404f

View file

@ -139,7 +139,7 @@ public:
return '\'' + data + '\''; return '\'' + data + '\'';
case TOK_VARIABLE: case TOK_VARIABLE:
return '$' + data; return '$' + data;
case TOK_INVALID: default:
break; break;
} }
@ -528,7 +528,7 @@ public:
ControlState GetValue() const override ControlState GetValue() const override
{ {
constexpr int MAX_REPS = 10000; 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? // Returns 1.0 on successful loop, 0.0 on reps exceeded. Sensible?
@ -543,7 +543,7 @@ public:
return 0.0; return 0.0;
} }
void SetValue(ControlState value) override {} 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, std::unique_ptr<UnaryExpression> MakeUnaryExpression(std::string name,
@ -782,22 +782,13 @@ private:
} }
} }
bool IsUnaryExpression(TokenType type) static bool IsUnaryExpression(TokenType type) { return TOK_UNARY == type; }
{
switch (type)
{
case TOK_UNARY:
return true;
default:
return false;
}
}
ParseResult Unary() ParseResult Unary()
{ {
if (IsUnaryExpression(Peek().type)) if (IsUnaryExpression(Peek().type))
{ {
Token tok = Chew(); const Token tok = Chew();
ParseResult result = Atom(); ParseResult result = Atom();
if (result.status == ParseStatus::SyntaxError) if (result.status == ParseStatus::SyntaxError)
return result; return result;
@ -807,29 +798,60 @@ private:
return Atom(); return Atom();
} }
bool IsBinaryToken(TokenType type) static bool IsBinaryToken(TokenType type)
{ {
return type >= TOK_BINARY_OPS_BEGIN && type < TOK_BINARY_OPS_END; return type >= TOK_BINARY_OPS_BEGIN && type < TOK_BINARY_OPS_END;
} }
ParseResult Binary() static int BinaryOperatorPrecedence(TokenType type)
{ {
ParseResult result = Unary(); switch (type)
if (result.status == ParseStatus::SyntaxError)
return result;
std::unique_ptr<Expression> expr = std::move(result.expr);
while (IsBinaryToken(Peek().type))
{ {
Token tok = Chew(); case TOK_MUL:
ParseResult unary_result = Unary(); case TOK_DIV:
if (unary_result.status == ParseStatus::SyntaxError) case TOK_MOD:
{ return 1;
return unary_result; 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;
}
} }
expr = std::make_unique<BinaryExpression>(tok.type, std::move(expr), ParseResult Binary(int precedence = 999)
std::move(unary_result.expr)); {
ParseResult lhs = Unary();
if (lhs.status == ParseStatus::SyntaxError)
return lhs;
std::unique_ptr<Expression> 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 rhs;
}
expr = std::make_unique<BinaryExpression>(tok.type, std::move(expr), std::move(rhs.expr));
} }
return {ParseStatus::Successful, std::move(expr)}; return {ParseStatus::Successful, std::move(expr)};
@ -851,7 +873,7 @@ private:
} }
ParseResult Toplevel() { return Binary(); } ParseResult Toplevel() { return Binary(); }
}; }; // namespace ExpressionParser
static ParseResult ParseComplexExpression(const std::string& str) static ParseResult ParseComplexExpression(const std::string& str)
{ {