ExpressionParser: operator precedence.

This commit is contained in:
Jordan Woyak 2018-12-30 19:50:20 -06:00
parent 46c0ae7d1f
commit fa75ab404f
1 changed files with 51 additions and 29 deletions

View File

@ -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;
std::unique_ptr<Expression> 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<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 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)
{