mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
Expressions
- Added Expression::eval short-circuit. - Added int/number exlclusions for Nibbler::getDOM. - Added Variant::boolean for exatracting filter results.
This commit is contained in:
parent
6a48d86f2c
commit
4fca40fc69
4 changed files with 63 additions and 9 deletions
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <iostream> // TODO Remove.
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <Context.h>
|
||||
#include <Lexer.h>
|
||||
#include <Date.h>
|
||||
|
@ -70,6 +71,12 @@ Expression::~Expression ()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Expression::eval (Task& task)
|
||||
{
|
||||
// If there are no elements in the filter, then all tasks pass.
|
||||
if (_args.size () == 0)
|
||||
return true;
|
||||
|
||||
// There are elements in the filter, so the expression must be evaluated
|
||||
// against each task.
|
||||
std::vector <Variant> value_stack;
|
||||
|
||||
std::vector <std::pair <std::string, std::string> >::iterator arg;
|
||||
|
@ -88,18 +95,19 @@ bool Expression::eval (Task& task)
|
|||
// TODO Need helpers that pop, and error out if necessary.
|
||||
if (arg->first == "+")
|
||||
{
|
||||
// TODO This needs to be type-aware.
|
||||
Variant right (value_stack.back ());
|
||||
value_stack.pop_back ();
|
||||
Variant left (value_stack.back ());
|
||||
value_stack.pop_back ();
|
||||
|
||||
context.debug ("eval left=" + left.format ());
|
||||
context.debug ("eval right=" + right.format ());
|
||||
left = left + right;
|
||||
context.debug ("eval + --> " + left.format ());
|
||||
|
||||
value_stack.push_back (left);
|
||||
}
|
||||
|
||||
|
||||
else if (arg->first == "and")
|
||||
{
|
||||
}
|
||||
|
@ -183,15 +191,41 @@ bool Expression::eval (Task& task)
|
|||
else
|
||||
throw std::string ("Unsupported operator '") + arg->first + "'.";
|
||||
}
|
||||
/*
|
||||
|
||||
// It's not an operator, it's either and lvalue or some form of rvalue.
|
||||
else
|
||||
value_stack.push_back (Variant (*arg));
|
||||
*/
|
||||
{
|
||||
if (arg->second == "lvalue")
|
||||
value_stack.push_back (Variant (context.dom.get (arg->first)));
|
||||
|
||||
else if (arg->second == "int")
|
||||
value_stack.push_back (Variant ((int) strtol (arg->first.c_str (), NULL, 10)));
|
||||
|
||||
else if (arg->second == "number")
|
||||
value_stack.push_back (Variant (strtod (arg->first.c_str (), NULL)));
|
||||
|
||||
else if (arg->second == "rvalue" ||
|
||||
arg->second == "string" ||
|
||||
arg->second == "rx")
|
||||
value_stack.push_back (Variant (arg->first));
|
||||
|
||||
else
|
||||
throw std::string ("Error: Expression::eval unrecognized operand '") + + "'.";
|
||||
}
|
||||
|
||||
// TODO Any more values on stack? Error.
|
||||
// TODO Return the value that is on the stack.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Coerce stack element to boolean.
|
||||
Variant result (value_stack.back ());
|
||||
context.debug ("eval result=" + result.format ());
|
||||
value_stack.pop_back ();
|
||||
bool pass_fail = result.boolean ();
|
||||
|
||||
// Check for stack remnants.
|
||||
if (value_stack.size ())
|
||||
throw std::string ("Error: Expression::eval found extra items on the stack.");
|
||||
|
||||
return pass_fail;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -316,7 +350,7 @@ void Expression::expand_tokens ()
|
|||
temp.push_back (std::make_pair (s, "op"));
|
||||
|
||||
else if (n.getDOM (s))
|
||||
temp.push_back (std::make_pair (s, "dom"));
|
||||
temp.push_back (std::make_pair (s, "lvalue"));
|
||||
|
||||
else if (n.getNumber (d))
|
||||
temp.push_back (std::make_pair (format (d), "number"));
|
||||
|
|
|
@ -927,6 +927,17 @@ bool Nibbler::getDOM (std::string& found)
|
|||
if (i > mCursor)
|
||||
{
|
||||
found = mInput.substr (start, i - start);
|
||||
|
||||
// If found is simple a number, then it is not a DOM reference.
|
||||
double d;
|
||||
Nibbler exclusion (found);
|
||||
if (exclusion.getNumber (d) && exclusion.depleted ())
|
||||
return false;
|
||||
|
||||
int in;
|
||||
if (exclusion.getInt (in) && exclusion.depleted ())
|
||||
return false;
|
||||
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -852,4 +852,12 @@ void Variant::promote (Variant& lhs, Variant& rhs)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Casts to boolean and returns the value. Used to evaluating expression
|
||||
// results.
|
||||
bool Variant::boolean ()
|
||||
{
|
||||
cast (v_boolean);
|
||||
return mBool;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
void cast (const variant_type);
|
||||
variant_type type ();
|
||||
void promote (Variant&, Variant&);
|
||||
bool boolean ();
|
||||
|
||||
private:
|
||||
variant_type mType;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue