diff --git a/src/Arguments.cpp b/src/Arguments.cpp index b8955a23b..1843051bd 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -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"; } + // + 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 } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Arguments.h b/src/Arguments.h index b0cda3bbc..87b8c5641 100644 --- a/src/Arguments.h +++ b/src/Arguments.h @@ -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 &); bool extract_uuid (const std::string&, std::vector &); 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 (); diff --git a/src/Context.cpp b/src/Context.cpp index f49774584..b5933bf62 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -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); } diff --git a/src/Expression.cpp b/src/Expression.cpp index 5a4fef3d1..a19215e2a 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -25,15 +25,14 @@ // //////////////////////////////////////////////////////////////////////////////// +#include #include -//////////////////////////////////////////////////////////////////////////////// -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: +// to: and +// void Expression::toInfix () { + _infix.clear (); + + std::string previous = "op"; + std::vector >::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"); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Expression.h b/src/Expression.h index 33da38890..54bd4f138 100644 --- a/src/Expression.h +++ b/src/Expression.h @@ -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 diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 5a3ea5a80..502a0caa7 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -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); ////////////////////////////////////