mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-27 19:17:19 +02:00
Expressions
- Began Expression::toInfix to upgrade old-style filters to infix algebraic filters. - Added operator support to Arguments::categorize. - Modified CmdCustom.cpp as a read-only command guinea-pig for the new argument processing.
This commit is contained in:
parent
68a749ee16
commit
86dcec8aea
6 changed files with 98 additions and 11 deletions
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
extern Context context;
|
extern Context context;
|
||||||
|
|
||||||
// Synonyms on the same line.
|
// Supported modifiers, synonyms on the same line.
|
||||||
static const char* modifierNames[] =
|
static const char* modifierNames[] =
|
||||||
{
|
{
|
||||||
"before", "under", "below",
|
"before", "under", "below",
|
||||||
|
@ -57,7 +57,31 @@ static const char* modifierNames[] =
|
||||||
"noword"
|
"noword"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Supported operators, synonyms on same line.
|
||||||
|
static const char* operators[] =
|
||||||
|
{
|
||||||
|
"+", // Addition, unary plus
|
||||||
|
"-", // Subtraction, unary minus
|
||||||
|
"*", // Multiplication
|
||||||
|
"/", // Division
|
||||||
|
"%", // Modulus
|
||||||
|
"~", // Substring/regex match
|
||||||
|
"!~", // Substring/regex no-match
|
||||||
|
"<", "lt", // Less than
|
||||||
|
"<=", "le", // Less than or equal
|
||||||
|
"=", "eq", // Equal
|
||||||
|
"!=", "ne", // Not equal
|
||||||
|
">=", "ge", // Greater than or equal
|
||||||
|
">", "gt", // Greater than
|
||||||
|
"!", "not", // Not
|
||||||
|
"and", // Conjunction
|
||||||
|
"or", // Disjunction
|
||||||
|
"(", // Precedence start
|
||||||
|
")" // Precedence end
|
||||||
|
};
|
||||||
|
|
||||||
#define NUM_MODIFIER_NAMES (sizeof (modifierNames) / sizeof (modifierNames[0]))
|
#define NUM_MODIFIER_NAMES (sizeof (modifierNames) / sizeof (modifierNames[0]))
|
||||||
|
#define NUM_OPERATORS (sizeof (operators) / sizeof (operators[0]))
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Arguments::Arguments ()
|
Arguments::Arguments ()
|
||||||
|
@ -268,6 +292,16 @@ void Arguments::categorize ()
|
||||||
arg->second = "pattern";
|
arg->second = "pattern";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <operator>
|
||||||
|
else if (is_operator (arg->first))
|
||||||
|
{
|
||||||
|
found_non_sequence = true;
|
||||||
|
if (found_sequence)
|
||||||
|
found_something_after_sequence = true;
|
||||||
|
|
||||||
|
arg->second = "op";
|
||||||
|
}
|
||||||
|
|
||||||
// If the type is not known, it is treated as a generic word.
|
// If the type is not known, it is treated as a generic word.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -698,6 +732,16 @@ bool Arguments::is_tag (const std::string& input)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Arguments::is_operator (const std::string& input)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < NUM_OPERATORS; ++i)
|
||||||
|
if (operators[i] == input)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// ______________
|
// ______________
|
||||||
// | |
|
// | |
|
||||||
|
@ -969,6 +1013,15 @@ bool Arguments::extract_tag (
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Arguments::extract_operator (
|
||||||
|
const std::string& input,
|
||||||
|
std::string& op)
|
||||||
|
{
|
||||||
|
op = input;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Arguments Arguments::extract_read_only_filter ()
|
Arguments Arguments::extract_read_only_filter ()
|
||||||
{
|
{
|
||||||
|
@ -993,6 +1046,7 @@ Arguments Arguments::extract_read_only_filter ()
|
||||||
i->second == "attmod" ||
|
i->second == "attmod" ||
|
||||||
i->second == "id" ||
|
i->second == "id" ||
|
||||||
i->second == "uuid" ||
|
i->second == "uuid" ||
|
||||||
|
i->second == "op" ||
|
||||||
i->second == "word")
|
i->second == "word")
|
||||||
{
|
{
|
||||||
filter.push_back (*i);
|
filter.push_back (*i);
|
||||||
|
@ -1037,6 +1091,7 @@ Arguments Arguments::extract_write_filter ()
|
||||||
i->second == "attmod" ||
|
i->second == "attmod" ||
|
||||||
i->second == "id" ||
|
i->second == "id" ||
|
||||||
i->second == "uuid" ||
|
i->second == "uuid" ||
|
||||||
|
i->second == "op" ||
|
||||||
i->second == "word")
|
i->second == "word")
|
||||||
{
|
{
|
||||||
filter.push_back (*i);
|
filter.push_back (*i);
|
||||||
|
@ -1083,6 +1138,7 @@ Arguments Arguments::extract_modifications ()
|
||||||
else if (i->second == "tag" ||
|
else if (i->second == "tag" ||
|
||||||
i->second == "attribute" ||
|
i->second == "attribute" ||
|
||||||
i->second == "substitution" ||
|
i->second == "substitution" ||
|
||||||
|
i->second == "op" ||
|
||||||
i->second == "word")
|
i->second == "word")
|
||||||
{
|
{
|
||||||
modifications.push_back (*i);
|
modifications.push_back (*i);
|
||||||
|
@ -1139,6 +1195,7 @@ void Arguments::dump (const std::string& label)
|
||||||
color_map["id"] = Color ("yellow on gray3");
|
color_map["id"] = Color ("yellow on gray3");
|
||||||
color_map["uuid"] = Color ("yellow on gray3");
|
color_map["uuid"] = Color ("yellow on gray3");
|
||||||
color_map["substitution"] = Color ("bold cyan on gray3");
|
color_map["substitution"] = Color ("bold cyan on gray3");
|
||||||
|
color_map["op"] = Color ("bold blue on gray3");
|
||||||
color_map["none"] = Color ("white on gray3");
|
color_map["none"] = Color ("white on gray3");
|
||||||
|
|
||||||
Color color_debug (context.config.get ("color.debug"));
|
Color color_debug (context.config.get ("color.debug"));
|
||||||
|
@ -1172,7 +1229,6 @@ void Arguments::dump (const std::string& label)
|
||||||
|
|
||||||
out << view.render ();
|
out << view.render ();
|
||||||
context.debug (out.str ());
|
context.debug (out.str ());
|
||||||
std::cout << out.str (); // TODO Remove
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
bool is_id (const std::string&);
|
bool is_id (const std::string&);
|
||||||
bool is_uuid (const std::string&);
|
bool is_uuid (const std::string&);
|
||||||
bool is_tag (const std::string&);
|
bool is_tag (const std::string&);
|
||||||
|
bool is_operator (const std::string&);
|
||||||
|
|
||||||
// TODO Decide if these are really useful.
|
// TODO Decide if these are really useful.
|
||||||
bool extract_attr (const std::string&, std::string&, std::string&);
|
bool extract_attr (const std::string&, std::string&, std::string&);
|
||||||
|
@ -72,6 +73,7 @@ public:
|
||||||
bool extract_id (const std::string&, std::vector <int>&);
|
bool extract_id (const std::string&, std::vector <int>&);
|
||||||
bool extract_uuid (const std::string&, std::vector <std::string>&);
|
bool extract_uuid (const std::string&, std::vector <std::string>&);
|
||||||
bool extract_tag (const std::string&, char&, std::string&);
|
bool extract_tag (const std::string&, char&, std::string&);
|
||||||
|
bool extract_operator (const std::string&, std::string&);
|
||||||
|
|
||||||
Arguments extract_read_only_filter ();
|
Arguments extract_read_only_filter ();
|
||||||
Arguments extract_write_filter ();
|
Arguments extract_write_filter ();
|
||||||
|
|
|
@ -170,8 +170,6 @@ int Context::run ()
|
||||||
std::cout << colorizeDebug (*d) << "\n";
|
std::cout << colorizeDebug (*d) << "\n";
|
||||||
else
|
else
|
||||||
std::cout << *d << "\n";
|
std::cout << *d << "\n";
|
||||||
|
|
||||||
args.dump ("Argument categorization");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump all headers, controlled by 'header' verbosity token.
|
// Dump all headers, controlled by 'header' verbosity token.
|
||||||
|
@ -222,6 +220,7 @@ int Context::dispatch (std::string &out)
|
||||||
if (c->displays_id ())
|
if (c->displays_id ())
|
||||||
tdb.gc ();
|
tdb.gc ();
|
||||||
|
|
||||||
|
args.dump ("Argument Categorization");
|
||||||
return c->execute (out);
|
return c->execute (out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,14 @@
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <Context.h>
|
||||||
#include <Expression.h>
|
#include <Expression.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
extern Context context;
|
||||||
Expression::Expression ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Expression::Expression (Arguments& arguments)
|
Expression::Expression (Arguments& arguments)
|
||||||
|
: _original (arguments)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,13 +48,38 @@ bool Expression::eval (Task& task)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Inserts the 'and' operator by default between terms that are not separated by
|
||||||
|
// at least one operator.
|
||||||
|
//
|
||||||
|
// Converts: <term1> <term2> <op> <term3>
|
||||||
|
// to: <term1> and <term2> <op> <term3>
|
||||||
|
//
|
||||||
void Expression::toInfix ()
|
void Expression::toInfix ()
|
||||||
{
|
{
|
||||||
|
_infix.clear ();
|
||||||
|
|
||||||
|
std::string previous = "op";
|
||||||
|
std::vector <std::pair <std::string, std::string> >::iterator arg;
|
||||||
|
for (arg = _original.begin (); arg != _original.end (); ++arg)
|
||||||
|
{
|
||||||
|
if (previous != "op" &&
|
||||||
|
arg->second != "op")
|
||||||
|
_infix.push_back (std::make_pair ("and", "op"));
|
||||||
|
|
||||||
|
_infix.push_back (*arg);
|
||||||
|
previous = arg->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
_infix.dump ("Expression::toInfix");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Dijkstra Shunting Algorithm.
|
||||||
void Expression::toPostfix ()
|
void Expression::toPostfix ()
|
||||||
{
|
{
|
||||||
|
_postfix.clear ();
|
||||||
|
|
||||||
|
_postfix.dump ("Expression::toPostfix");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -35,16 +35,18 @@
|
||||||
class Expression
|
class Expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Expression ();
|
|
||||||
Expression (Arguments&);
|
Expression (Arguments&);
|
||||||
~Expression ();
|
~Expression ();
|
||||||
bool eval (Task&);
|
bool eval (Task&);
|
||||||
|
void toInfix ();
|
||||||
|
void toPostfix ();
|
||||||
|
|
||||||
void dump (const std::string&);
|
void dump (const std::string&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void toInfix ();
|
Arguments _original;
|
||||||
void toPostfix ();
|
Arguments _infix;
|
||||||
|
Arguments _postfix;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -95,6 +95,10 @@ int CmdCustom::execute (std::string& output)
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
Arguments f = context.args.extract_read_only_filter ();
|
Arguments f = context.args.extract_read_only_filter ();
|
||||||
Expression e (f);
|
Expression e (f);
|
||||||
|
e.toInfix ();
|
||||||
|
e.toPostfix ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
// TODO e.apply (tasks);
|
// TODO e.apply (tasks);
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue