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:
Paul Beckingham 2011-06-05 13:43:32 -04:00
parent 68a749ee16
commit 86dcec8aea
6 changed files with 98 additions and 11 deletions

View file

@ -40,7 +40,7 @@
extern Context context;
// Synonyms on the same line.
// Supported modifiers, synonyms on the same line.
static const char* modifierNames[] =
{
"before", "under", "below",
@ -57,7 +57,31 @@ static const char* modifierNames[] =
"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_OPERATORS (sizeof (operators) / sizeof (operators[0]))
////////////////////////////////////////////////////////////////////////////////
Arguments::Arguments ()
@ -268,6 +292,16 @@ void Arguments::categorize ()
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.
else
{
@ -698,6 +732,16 @@ bool Arguments::is_tag (const std::string& input)
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;
}
////////////////////////////////////////////////////////////////////////////////
bool Arguments::extract_operator (
const std::string& input,
std::string& op)
{
op = input;
return true;
}
////////////////////////////////////////////////////////////////////////////////
Arguments Arguments::extract_read_only_filter ()
{
@ -993,6 +1046,7 @@ Arguments Arguments::extract_read_only_filter ()
i->second == "attmod" ||
i->second == "id" ||
i->second == "uuid" ||
i->second == "op" ||
i->second == "word")
{
filter.push_back (*i);
@ -1037,6 +1091,7 @@ Arguments Arguments::extract_write_filter ()
i->second == "attmod" ||
i->second == "id" ||
i->second == "uuid" ||
i->second == "op" ||
i->second == "word")
{
filter.push_back (*i);
@ -1083,6 +1138,7 @@ Arguments Arguments::extract_modifications ()
else if (i->second == "tag" ||
i->second == "attribute" ||
i->second == "substitution" ||
i->second == "op" ||
i->second == "word")
{
modifications.push_back (*i);
@ -1139,6 +1195,7 @@ void Arguments::dump (const std::string& label)
color_map["id"] = Color ("yellow on gray3");
color_map["uuid"] = Color ("yellow 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 color_debug (context.config.get ("color.debug"));
@ -1172,7 +1229,6 @@ void Arguments::dump (const std::string& label)
out << view.render ();
context.debug (out.str ());
std::cout << out.str (); // TODO Remove
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -63,6 +63,7 @@ public:
bool is_id (const std::string&);
bool is_uuid (const std::string&);
bool is_tag (const std::string&);
bool is_operator (const std::string&);
// TODO Decide if these are really useful.
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_uuid (const std::string&, std::vector <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_write_filter ();

View file

@ -170,8 +170,6 @@ int Context::run ()
std::cout << colorizeDebug (*d) << "\n";
else
std::cout << *d << "\n";
args.dump ("Argument categorization");
}
// Dump all headers, controlled by 'header' verbosity token.
@ -222,6 +220,7 @@ int Context::dispatch (std::string &out)
if (c->displays_id ())
tdb.gc ();
args.dump ("Argument Categorization");
return c->execute (out);
}

View file

@ -25,15 +25,14 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <Context.h>
#include <Expression.h>
////////////////////////////////////////////////////////////////////////////////
Expression::Expression ()
{
}
extern Context context;
////////////////////////////////////////////////////////////////////////////////
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 ()
{
_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 ()
{
_postfix.clear ();
_postfix.dump ("Expression::toPostfix");
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -35,16 +35,18 @@
class Expression
{
public:
Expression ();
Expression (Arguments&);
~Expression ();
bool eval (Task&);
void toInfix ();
void toPostfix ();
void dump (const std::string&);
private:
void toInfix ();
void toPostfix ();
Arguments _original;
Arguments _infix;
Arguments _postfix;
};
#endif

View file

@ -95,6 +95,10 @@ int CmdCustom::execute (std::string& output)
////////////////////////////////////
Arguments f = context.args.extract_read_only_filter ();
Expression e (f);
e.toInfix ();
e.toPostfix ();
return 0;
// TODO e.apply (tasks);
////////////////////////////////////