ExpressionParser: Fix negative literals and support unary minus operator.

This commit is contained in:
Jordan Woyak 2019-01-06 10:03:21 -06:00
parent 7cf903a209
commit ccac3f1e49
1 changed files with 25 additions and 4 deletions

View File

@ -572,6 +572,20 @@ public:
int GetArity() const override { return 3; } int GetArity() const override { return 3; }
}; };
class UnaryMinusExpression : public FunctionExpression
{
public:
ControlState GetValue() const override
{
// Subtraction for clarity:
return 0.0 - GetArg(0).GetValue();
}
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "Minus"; }
int GetArity() const override { return 1; }
};
class WhileExpression : public FunctionExpression class WhileExpression : public FunctionExpression
{ {
public: public:
@ -617,6 +631,8 @@ std::unique_ptr<FunctionExpression> MakeFunctionExpression(std::string name)
return std::make_unique<ToggleExpression>(); return std::make_unique<ToggleExpression>();
else if ("while" == name) else if ("while" == name)
return std::make_unique<WhileExpression>(); return std::make_unique<WhileExpression>();
else if ("minus" == name)
return std::make_unique<UnaryMinusExpression>();
else else
return std::make_unique<UnknownFunctionExpression>(); return std::make_unique<UnknownFunctionExpression>();
} }
@ -782,9 +798,8 @@ private:
return tok.type == type; return tok.type == type;
} }
ParseResult Atom() ParseResult Atom(const Token& tok)
{ {
const Token tok = Chew();
switch (tok.type) switch (tok.type)
{ {
case TOK_FUNCTION: case TOK_FUNCTION:
@ -793,7 +808,7 @@ private:
int arity = func->GetArity(); int arity = func->GetArity();
while (arity--) while (arity--)
{ {
auto arg = Atom(); auto arg = Atom(Chew());
if (arg.status == ParseStatus::SyntaxError) if (arg.status == ParseStatus::SyntaxError)
return arg; return arg;
@ -819,6 +834,12 @@ private:
{ {
return Paren(); return Paren();
} }
case TOK_SUB:
{
// An atom was expected but we got a subtraction symbol.
// Interpret it as a unary minus function.
return Atom(Token(TOK_FUNCTION, "minus"));
}
default: default:
return {ParseStatus::SyntaxError}; return {ParseStatus::SyntaxError};
} }
@ -859,7 +880,7 @@ private:
ParseResult Binary(int precedence = 999) ParseResult Binary(int precedence = 999)
{ {
ParseResult lhs = Atom(); ParseResult lhs = Atom(Chew());
if (lhs.status == ParseStatus::SyntaxError) if (lhs.status == ParseStatus::SyntaxError)
return lhs; return lhs;