From 7aa4efef8dd51a74d64325ae5a888d034d4ecbc1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 21 Aug 2011 01:06:50 -0400 Subject: [PATCH] Expression Refactor - Refactoring complete. Arg objects now uses enumerations for _type and _category, which should help with performance. --- src/A3.cpp | 338 +++++++++++++++++++-------------------- src/Arg.cpp | 101 ++++++++++-- src/Arg.h | 17 +- src/E9.cpp | 114 +++++++------ src/E9.h | 2 +- src/commands/Command.cpp | 6 +- 6 files changed, 331 insertions(+), 247 deletions(-) diff --git a/src/A3.cpp b/src/A3.cpp index 438146e0a..cb6dd0db1 100644 --- a/src/A3.cpp +++ b/src/A3.cpp @@ -160,8 +160,8 @@ void A3::capture_first (const std::string& arg) // immediately after the program and command arguments. std::vector ::iterator position; for (position = this->begin (); position != this->end (); ++position) - if (position->_category != "program" && - position->_category != "command") + if (position->_category != Arg::cat_program && + position->_category != Arg::cat_command) break; this->insert (position, series.begin (), series.end ()); @@ -194,13 +194,13 @@ void A3::categorize () if (arg->_raw == "--") { terminated = true; - arg->_category = "terminator"; + arg->_category = Arg::cat_terminator; } // program else if (arg == this->begin ()) { - arg->_category = "program"; + arg->_category = Arg::cat_program; if ((arg->_raw.length () >= 3 && arg->_raw.substr (arg->_raw.length () - 3) == "cal") || @@ -208,7 +208,7 @@ void A3::categorize () arg->_raw.substr (arg->_raw.length () - 8) == "calendar")) { arg->_raw = "calendar"; - arg->_category = "command"; + arg->_category = Arg::cat_command; found_command = true; } } @@ -218,26 +218,26 @@ void A3::categorize () is_command (keywords, arg->_raw)) { found_command = true; - arg->_category = "command"; + arg->_category = Arg::cat_command; _read_only_command = context.commands[arg->_raw]->read_only (); } // rc: // Note: This doesn't break a sequence chain. else if (arg->_raw.substr (0, 3) == "rc:") - arg->_category = "rc"; + arg->_category = Arg::cat_rc; // rc.: // Note: This doesn't break a sequence chain. else if (arg->_raw.substr (0, 3) == "rc.") - arg->_category = "override"; + arg->_category = Arg::cat_override; // If the type is not known, it is treated as a generic word. } // All post-termination arguments are simply words. else - arg->_category = "literal"; + arg->_category = Arg::cat_literal; } } @@ -295,7 +295,7 @@ void A3::rc_override ( std::vector ::iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "rc") + if (arg->_category == Arg::cat_rc) { rc = File (arg->_raw.substr (3)); home = rc; @@ -325,7 +325,7 @@ void A3::get_data_location (std::string& data) std::vector ::iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "override") + if (arg->_category == Arg::cat_override) { if (arg->_raw.substr (0, 16) == "rc.data.location" && (arg->_raw[16] == ':' || arg->_raw[16] == '=')) @@ -404,7 +404,7 @@ void A3::apply_overrides () std::vector ::iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "override") + if (arg->_category == Arg::cat_override) { std::string name; std::string value; @@ -436,18 +436,18 @@ void A3::inject_defaults () std::vector ::iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "command") + if (arg->_category == Arg::cat_command) found_command = true; /* TODO no "id" or "uuid" categories exist at this time. Hmm. - else if (arg->_category == "id" || - arg->_category == "uuid") + else if (arg->_category == Arg::cat_id || + arg->_category == Arg::cat_uuid) found_sequence = true; */ - else if (arg->_category != "program" && - arg->_category != "override" && - arg->_category != "rc") + else if (arg->_category != Arg::cat_program && + arg->_category != Arg::cat_override && + arg->_category != Arg::cat_rc) found_other = true; } @@ -522,7 +522,7 @@ bool A3::find_command (std::string& command) const std::vector ::const_iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "command") + if (arg->_category == Arg::cat_command) { command = arg->_raw; return true; @@ -556,14 +556,14 @@ const A3 A3::extract_filter () const std::vector ::const_iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "command") + if (arg->_category == Arg::cat_command) before_command = false; - if (arg->_category == "program" || - arg->_category == "rc" || - arg->_category == "override" || - arg->_category == "command" || - arg->_category == "terminator") + if (arg->_category == Arg::cat_program || + arg->_category == Arg::cat_rc || + arg->_category == Arg::cat_override || + arg->_category == Arg::cat_command || + arg->_category == Arg::cat_terminator) ; else if (before_command || _read_only_command) @@ -585,14 +585,14 @@ const A3 A3::extract_modifications () const std::vector ::const_iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "command") + if (arg->_category == Arg::cat_command) before_command = false; else if (! before_command) { - // "rc" and "override" categories are not included. - if (arg->_category == "rc" || - arg->_category == "override") + // rc and override categories are not included. + if (arg->_category == Arg::cat_rc || + arg->_category == Arg::cat_override) { ; } @@ -603,12 +603,12 @@ const A3 A3::extract_modifications () const // lines that do not otherwise include an id, such as: // // task add Read the article on page 2 - else if (arg->_category == "id" || - arg->_category == "uuid") + else if (arg->_category == Arg::cat_id || + arg->_category == Arg::cat_uuid) { Arg downgrade (*arg); - downgrade._type = "string"; - downgrade._category = "literal"; + downgrade._type = Arg::type_string; + downgrade._category = Arg::cat_literal; mods.push_back (downgrade); } @@ -630,11 +630,11 @@ const std::vector A3::extract_words () const std::vector ::const_iterator arg; for (arg = this->begin (); arg != this->end (); ++arg) { - if (arg->_category == "program" || - arg->_category == "rc" || - arg->_category == "override" || - arg->_category == "command" || - arg->_category == "terminator") + if (arg->_category == Arg::cat_program || + arg->_category == Arg::cat_rc || + arg->_category == Arg::cat_override || + arg->_category == Arg::cat_command || + arg->_category == Arg::cat_terminator) ; else @@ -690,28 +690,28 @@ const A3 A3::tokenize (const A3& input) const else if (n.getQuoted ('"', s, true) || n.getQuoted ('\'', s, true)) { - output.push_back (Arg (s, "string", "literal")); + output.push_back (Arg (s, Arg::type_string, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } else if (is_subst (n, s)) { - output.push_back (Arg (s, "subst")); + output.push_back (Arg (s, Arg::cat_subst)); if (found_sequence) found_something_after_sequence = true; } else if (is_pattern (n, s)) { - output.push_back (Arg (s, "", "pattern")); + output.push_back (Arg (s, Arg::cat_pattern)); if (found_sequence) found_something_after_sequence = true; } else if (is_tag (n, s)) { - output.push_back (Arg (s, "", "tag")); + output.push_back (Arg (s, Arg::cat_tag)); if (found_sequence) found_something_after_sequence = true; } @@ -720,7 +720,7 @@ const A3 A3::tokenize (const A3& input) const // Must be higher than operator. else if (n.getDate (date_format, t)) { - output.push_back (Arg (Date (t).toString (date_format), "date", "literal")); + output.push_back (Arg (Date (t).toString (date_format), Arg::type_date, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } @@ -729,14 +729,14 @@ const A3 A3::tokenize (const A3& input) const // Must be higher than operator. else if (is_duration (n, s)) { - output.push_back (Arg (s, "duration", "literal")); + output.push_back (Arg (s, Arg::type_duration, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } else if (n.getOneOf (operators, s)) { - output.push_back (Arg (s, "op")); + output.push_back (Arg (s, Arg::cat_op)); if (found_sequence) found_something_after_sequence = true; } @@ -773,7 +773,7 @@ const A3 A3::tokenize (const A3& input) const else if (n.getDateISO (t)) { - output.push_back (Arg (Date (t).toISO (), "date", "literal")); + output.push_back (Arg (Date (t).toISO (), Arg::type_date, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } @@ -782,11 +782,11 @@ const A3 A3::tokenize (const A3& input) const { if (found_something_after_sequence) { - output.push_back (Arg (s, "number", "literal")); + output.push_back (Arg (s, Arg::type_number, Arg::cat_literal)); } else { - output.push_back (Arg (s, "number", "id")); + output.push_back (Arg (s, Arg::type_number, Arg::cat_id)); found_sequence = true; } } @@ -795,25 +795,25 @@ const A3 A3::tokenize (const A3& input) const { if (found_something_after_sequence) { - output.push_back (Arg (s, "string", "literal")); + output.push_back (Arg (s, Arg::type_string, Arg::cat_literal)); } else { - output.push_back (Arg (s, "string", "uuid")); + output.push_back (Arg (s, Arg::type_string, Arg::cat_uuid)); found_sequence = true; } } else if (is_number (n, d)) { - output.push_back (Arg (format (d), "number", "literal")); + output.push_back (Arg (format (d), Arg::type_number, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } else if (is_integer (n, i)) { - output.push_back (Arg (format (i), "number", "literal")); + output.push_back (Arg (format (i), Arg::type_number, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } @@ -822,9 +822,9 @@ const A3 A3::tokenize (const A3& input) const n.getWord (s)) { if (Date::valid (s)) - output.push_back (Arg (s, "date", "literal")); + output.push_back (Arg (s, Arg::type_date, Arg::cat_literal)); else - output.push_back (Arg (s, "string", "literal")); + output.push_back (Arg (s, Arg::type_string, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; @@ -835,7 +835,7 @@ const A3 A3::tokenize (const A3& input) const if (! n.getUntilWS (s)) n.getUntilEOS (s); - output.push_back (Arg (s, "string", "literal")); + output.push_back (Arg (s, Arg::type_string, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } @@ -844,7 +844,7 @@ const A3 A3::tokenize (const A3& input) const { if (n.getUntilEOS (s)) { - output.push_back (Arg (s, "string", "literal")); + output.push_back (Arg (s, Arg::type_string, Arg::cat_literal)); if (found_sequence) found_something_after_sequence = true; } @@ -867,7 +867,7 @@ const A3 A3::tokenize (const A3& input) const // const A3 A3::infix (const A3& input) const { - Arg previous ("?", "op"); + Arg previous ("?", Arg::cat_op); A3 modified; modified._limit = input._limit; @@ -876,10 +876,10 @@ const A3 A3::infix (const A3& input) const for (arg = input.begin (); arg != input.end (); ++arg) { // Old-style filters need 'and' conjunctions. - if ((previous._category != "op" || previous._raw == ")") && - (arg->_category != "op" || arg->_raw == "(")) + if ((previous._category != Arg::cat_op || previous._raw == ")") && + (arg->_category != Arg::cat_op || arg->_raw == "(")) { - modified.push_back (Arg ("and", "op")); + modified.push_back (Arg ("and", Arg::cat_op)); } // Now insert the adjacent non-operator. @@ -902,19 +902,19 @@ const A3 A3::expand (const A3& input) const for (arg = input.begin (); arg != input.end (); ++arg) { // name:value --> name = value - if (arg->_category == "attr") + if (arg->_category == Arg::cat_attr) { std::string name; std::string value; A3::extract_attr (arg->_raw, name, value); - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("=", "op")); - expanded.push_back (Arg (value, "string", "literal")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("=", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_literal)); } // name.mod:value --> name value - else if (arg->_category == "attmod") + else if (arg->_category == Arg::cat_attmod) { std::string name; std::string mod; @@ -925,133 +925,133 @@ const A3 A3::expand (const A3& input) const // name.before:value --> name < value if (mod == "before" || mod == "under" || mod == "below") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("<", "op")); - expanded.push_back (Arg (value, "string", "literal")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("<", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_literal)); } // name.after:value --> name > value else if (mod == "after" || mod == "over" || mod == "above") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg (">", "op")); - expanded.push_back (Arg (value, "string", "literal")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg (">", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_literal)); } // name.none: --> name == "" else if (mod == "none") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("=", "op")); - expanded.push_back (Arg ("", "string", "")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("=", Arg::cat_op)); + expanded.push_back (Arg ("", Arg::type_string, Arg::cat_none)); } // name.any: --> name != "" else if (mod == "any") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("!=", "op")); - expanded.push_back (Arg ("", "string", "")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("!=", Arg::cat_op)); + expanded.push_back (Arg ("", Arg::type_string, Arg::cat_none)); } // name.is:value --> name = value else if (mod == "is" || mod == "equals") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("=", "op")); - expanded.push_back (Arg (value, "string", "")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("=", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_none)); } // name.isnt:value --> name != value else if (mod == "isnt" || mod == "not") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("!=", "op")); - expanded.push_back (Arg (value, "string", "")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("!=", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_none)); } // name.has:value --> name ~ value else if (mod == "has" || mod == "contains") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("~", "op")); - expanded.push_back (Arg (value, "string", "rx")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("~", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_rx)); } // name.hasnt:value --> name !~ value else if (mod == "hasnt") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("!~", "op")); - expanded.push_back (Arg (value, "string", "rx")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("!~", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_rx)); } // name.startswith:value --> name ~ ^value else if (mod == "startswith" || mod == "left") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("~", "op")); - expanded.push_back (Arg ("^" + value, "string", "rx")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("~", Arg::cat_op)); + expanded.push_back (Arg ("^" + value, Arg::type_string, Arg::cat_rx)); } // name.endswith:value --> name ~ value$ else if (mod == "endswith" || mod == "right") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("~", "op")); - expanded.push_back (Arg (value + "$", "string", "rx")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("~", Arg::cat_op)); + expanded.push_back (Arg (value + "$", Arg::type_string, Arg::cat_rx)); } // name.word:value --> name ~ \bvalue\b else if (mod == "word") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("~", "op")); - expanded.push_back (Arg ("\\b" + value + "\\b", "string", "rx")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("~", Arg::cat_op)); + expanded.push_back (Arg ("\\b" + value + "\\b", Arg::type_string, Arg::cat_rx)); } // name.noword:value --> name !~ \bvalue\n else if (mod == "noword") { - expanded.push_back (Arg (name, "string", "dom")); - expanded.push_back (Arg ("!~", "op")); - expanded.push_back (Arg ("\\b" + value + "\\b", "string", "rx")); + expanded.push_back (Arg (name, Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("!~", Arg::cat_op)); + expanded.push_back (Arg ("\\b" + value + "\\b", Arg::type_string, Arg::cat_rx)); } else throw std::string ("Error: unrecognized attribute modifier '") + mod + "'."; } // [+-]value --> tags ~/!~ value - else if (arg->_category == "tag") + else if (arg->_category == Arg::cat_tag) { char type; std::string value; extract_tag (arg->_raw, type, value); - expanded.push_back (Arg ("tags", "string", "dom")); - expanded.push_back (Arg (type == '+' ? "~" : "!~", "op")); - expanded.push_back (Arg (value, "string", "literal")); + expanded.push_back (Arg ("tags", Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg (type == '+' ? "~" : "!~", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_literal)); } // word --> description ~ word // Note: use of previous prevents desc~foo --> desc~desc~foo - else if (arg->_category == "literal" && - previous->_category != "op") + else if (arg->_category == Arg::cat_literal && + previous->_category != Arg::cat_op) { - expanded.push_back (Arg ("description", "string", "dom")); - expanded.push_back (Arg ("~", "op")); - expanded.push_back (Arg (arg->_raw, "string", "literal")); + expanded.push_back (Arg ("description", Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("~", Arg::cat_op)); + expanded.push_back (Arg (arg->_raw, Arg::type_string, Arg::cat_literal)); } // /pattern/ --> description ~ pattern - else if (arg->_category == "pattern") + else if (arg->_category == Arg::cat_pattern) { std::string value; extract_pattern (arg->_raw, value); - expanded.push_back (Arg ("description", "string", "dom")); - expanded.push_back (Arg ("~", "op")); - expanded.push_back (Arg (value, "string", "rx")); + expanded.push_back (Arg ("description", Arg::type_string, Arg::cat_dom)); + expanded.push_back (Arg ("~", Arg::cat_op)); + expanded.push_back (Arg (value, Arg::type_string, Arg::cat_rx)); } // Default --> preserve @@ -1079,10 +1079,10 @@ const A3 A3::sequence (const A3& input) const std::vector ::const_iterator arg; for (arg = input.begin (); arg != input.end (); ++arg) { - if (arg->_category == "id") + if (arg->_category == Arg::cat_id) extract_id (arg->_raw, ids); - else if (arg->_category == "uuid") + else if (arg->_category == Arg::cat_uuid) extract_uuid (arg->_raw, uuids); } @@ -1093,42 +1093,42 @@ const A3 A3::sequence (const A3& input) const // Copy everything up to the first id/uuid. for (arg = input.begin (); arg != input.end (); ++arg) { - if (arg->_category == "id" || arg->_category == "uuid") + if (arg->_category == Arg::cat_id || arg->_category == Arg::cat_uuid) break; sequenced.push_back (*arg); } // Insert the algebraic form. - sequenced.push_back (Arg ("(", "op")); + sequenced.push_back (Arg ("(", Arg::cat_op)); for (unsigned int i = 0; i < ids.size (); ++i) { if (i) - sequenced.push_back (Arg ("or", "op")); + sequenced.push_back (Arg ("or", Arg::cat_op)); - sequenced.push_back (Arg ("id", "number", "dom")); - sequenced.push_back (Arg ("=", "op")); - sequenced.push_back (Arg (format(ids[i]), "number", "literal")); + sequenced.push_back (Arg ("id", Arg::type_number, Arg::cat_dom)); + sequenced.push_back (Arg ("=", Arg::cat_op)); + sequenced.push_back (Arg (format(ids[i]), Arg::type_number, Arg::cat_literal)); } for (unsigned int i = 0; i < uuids.size (); ++i) { if (ids.size ()) - sequenced.push_back (Arg ("or", "op")); + sequenced.push_back (Arg ("or", Arg::cat_op)); - sequenced.push_back (Arg ("uuid", "string", "dom")); - sequenced.push_back (Arg ("=", "op")); - sequenced.push_back (Arg (uuids[i], "string", "literal")); + sequenced.push_back (Arg ("uuid", Arg::type_string, Arg::cat_dom)); + sequenced.push_back (Arg ("=", Arg::cat_op)); + sequenced.push_back (Arg (uuids[i], Arg::type_string, Arg::cat_literal)); } - sequenced.push_back (Arg (")", "op")); + sequenced.push_back (Arg (")", Arg::cat_op)); // Now copy everything after the last id/uuid. bool found_id = false; for (arg = input.begin (); arg != input.end (); ++arg) { - if (arg->_category == "id" || arg->_category == "uuid") + if (arg->_category == Arg::cat_id || arg->_category == Arg::cat_uuid) found_id = true; else if (found_id) @@ -1271,16 +1271,16 @@ bool A3::is_attr (Nibbler& n, Arg& arg) */ arg._raw = name + ':' + value; - arg._category = "attr"; + arg._category = Arg::cat_attr; // Most attributes are standard, some are pseudo-attributes, such as // 'limit:page', which is not represented by a column object, and // therefore not stored. Column* col = context.columns[name]; if (col) - arg._type = col->type (); + arg._type = Arg::type_id (col->type ()); else - arg._type = "pseudo"; + arg._type = Arg::type_pseudo; return true; } @@ -1340,8 +1340,8 @@ bool A3::is_attmod (Nibbler& n, Arg& arg) */ arg._raw = name + '.' + modifier + ':' + value; - arg._type = context.columns[name]->type (); - arg._category = "attmod"; + arg._type = Arg::type_id (context.columns[name]->type ()); + arg._category = Arg::cat_attmod; return true; } } @@ -1437,7 +1437,7 @@ bool A3::is_dom (Nibbler& n, Arg& arg) } arg._raw = result; - arg._category = "dom"; + arg._category = Arg::cat_dom; return true; } @@ -1452,8 +1452,8 @@ bool A3::is_dom (Nibbler& n, Arg& arg) { result = format (id) + '.' + name; arg._raw = result; - arg._type = context.columns[name]->type (); - arg._category = "dom"; + arg._type = Arg::type_id (context.columns[name]->type ()); + arg._category = Arg::cat_dom; return true; } @@ -1467,8 +1467,8 @@ bool A3::is_dom (Nibbler& n, Arg& arg) is_attribute (name, name)) { arg._raw = uuid + '.' + name; - arg._type = context.columns[name]->type (); - arg._category = "dom"; + arg._type = Arg::type_id (context.columns[name]->type ()); + arg._category = Arg::cat_dom; return true; } @@ -1480,8 +1480,8 @@ bool A3::is_dom (Nibbler& n, Arg& arg) is_attribute (name, name)) { arg._raw = name; - arg._type = context.columns[name]->type (); - arg._category = "dom"; + arg._type = Arg::type_id (context.columns[name]->type ()); + arg._category = Arg::cat_dom; return true; } @@ -1990,30 +1990,30 @@ bool A3::is_operator ( void A3::dump (const std::string& label) { // Set up a color mapping. - std::map color_map; - color_map["program"] = Color ("bold blue on blue"); - color_map["command"] = Color ("bold cyan on cyan"); - color_map["rc"] = Color ("bold red on red"); - color_map["override"] = Color ("bold red on red"); - color_map["terminator"] = Color ("bold yellow on yellow"); - color_map["literal"] = Color ("white on gray4"); + std::map color_map; + color_map[Arg::cat_program] = Color ("bold blue on blue"); + color_map[Arg::cat_command] = Color ("bold cyan on cyan"); + color_map[Arg::cat_rc] = Color ("bold red on red"); + color_map[Arg::cat_override] = Color ("bold red on red"); + color_map[Arg::cat_terminator] = Color ("bold yellow on yellow"); + color_map[Arg::cat_literal] = Color ("white on gray4"); // Filter colors. - color_map["attr"] = Color ("bold red on gray4"); - color_map["attmod"] = Color ("bold red on gray4"); - color_map["pattern"] = Color ("cyan on gray4"); - color_map["subst"] = Color ("bold cyan on gray4"); - color_map["op"] = Color ("green on gray4"); - color_map["string"] = Color ("bold yellow on gray4"); - color_map["rx"] = Color ("bold yellow on gray4"); - color_map["date"] = Color ("bold yellow on gray4"); - color_map["dom"] = Color ("bold white on gray4"); - color_map["duration"] = Color ("magenta on gray4"); - color_map["id"] = Color ("white on gray4"); - color_map["uuid"] = Color ("white on gray4"); + color_map[Arg::cat_attr] = Color ("bold red on gray4"); + color_map[Arg::cat_attmod] = Color ("bold red on gray4"); + color_map[Arg::cat_pattern] = Color ("cyan on gray4"); + color_map[Arg::cat_subst] = Color ("bold cyan on gray4"); + color_map[Arg::cat_op] = Color ("green on gray4"); + color_map[Arg::type_string] = Color ("bold yellow on gray4"); + color_map[Arg::cat_rx] = Color ("bold yellow on gray4"); + color_map[Arg::type_date] = Color ("bold yellow on gray4"); + color_map[Arg::cat_dom] = Color ("bold white on gray4"); + color_map[Arg::type_duration] = Color ("magenta on gray4"); + color_map[Arg::cat_id] = Color ("white on gray4"); + color_map[Arg::cat_uuid] = Color ("white on gray4"); // Default. - color_map["none"] = Color ("black on white"); + color_map[Arg::cat_none] = Color ("black on white"); Color color_debug (context.config.get ("color.debug")); std::stringstream out; @@ -2033,21 +2033,21 @@ void A3::dump (const std::string& label) for (unsigned int i = 0; i < this->size (); ++i) { - std::string value = (*this)[i]._value; - std::string raw = (*this)[i]._raw; - std::string type = (*this)[i]._type; - std::string category = (*this)[i]._category; + std::string value = (*this)[i]._value; + std::string raw = (*this)[i]._raw; + Arg::type type = (*this)[i]._type; + Arg::category category = (*this)[i]._category; Color c; if (color_map[category].nontrivial ()) c = color_map[category]; else - c = color_map["none"]; + c = color_map[Arg::cat_none]; - view.set (0, i, value, c); - view.set (1, i, raw, c); - view.set (2, i, type, c); - view.set (3, i, category, c); + view.set (0, i, value, c); + view.set (1, i, raw, c); + view.set (2, i, Arg::type_name (type), c); + view.set (3, i, Arg::category_name (category), c); } out << view.render (); diff --git a/src/Arg.cpp b/src/Arg.cpp index a379fcb04..5356c1333 100644 --- a/src/Arg.cpp +++ b/src/Arg.cpp @@ -34,8 +34,8 @@ extern Context context; Arg::Arg () : _value ("") , _raw ("") -, _type ("") -, _category ("") +, _type (type_none) +, _category (cat_none) { } @@ -43,31 +43,31 @@ Arg::Arg () Arg::Arg (const std::string& raw) : _value ("") , _raw (raw) -, _type ("") -, _category ("") +, _type (type_none) +, _category (cat_none) { } //////////////////////////////////////////////////////////////////////////////// Arg::Arg ( const std::string& raw, - const std::string& category) + const category c) : _value ("") , _raw (raw) -, _type ("") -, _category (category) +, _type (type_none) +, _category (c) { } //////////////////////////////////////////////////////////////////////////////// Arg::Arg ( const std::string& raw, - const std::string& type, - const std::string& category) + const type t, + const category c) : _value ("") , _raw (raw) -, _type (type) -, _category (category) +, _type (t) +, _category (c) { } @@ -104,4 +104,83 @@ bool Arg::operator== (const Arg& other) const } //////////////////////////////////////////////////////////////////////////////// +const Arg::type Arg::type_id (const std::string& input) +{ + if (input == "bool") return Arg::type_bool; + else if (input == "string") return Arg::type_string; + else if (input == "date") return Arg::type_date; + else if (input == "duration") return Arg::type_duration; + else if (input == "number") return Arg::type_number; + else if (input == "pseudo") return Arg::type_pseudo; + return Arg::type_none; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string Arg::type_name (Arg::type t) +{ + switch (t) + { + case Arg::type_none: return "none"; + case Arg::type_pseudo: return "pseudo"; + case Arg::type_bool: return "bool"; + case Arg::type_string: return "string"; + case Arg::type_date: return "date"; + case Arg::type_duration: return "duration"; + case Arg::type_number: return "number"; + } + + return "none"; +} + +//////////////////////////////////////////////////////////////////////////////// +const Arg::category Arg::category_id (const std::string& input) +{ + if (input == "terminator") return Arg::cat_terminator; + else if (input == "program") return Arg::cat_program; + else if (input == "command") return Arg::cat_command; + else if (input == "rc") return Arg::cat_rc; + else if (input == "rx") return Arg::cat_rx; + else if (input == "override") return Arg::cat_override; + else if (input == "attr") return Arg::cat_attr; + else if (input == "attmod") return Arg::cat_attmod; + else if (input == "id") return Arg::cat_id; + else if (input == "uuid") return Arg::cat_uuid; + else if (input == "subst") return Arg::cat_subst; + else if (input == "pattern") return Arg::cat_pattern; + else if (input == "tag") return Arg::cat_tag; + else if (input == "dom") return Arg::cat_dom; + else if (input == "op") return Arg::cat_op; + else if (input == "literal") return Arg::cat_literal; + + return Arg::cat_none; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::string Arg::category_name (Arg::category c) +{ + switch (c) + { + case Arg::cat_none: return "none"; + case Arg::cat_terminator: return "terminator"; + case Arg::cat_program: return "program"; + case Arg::cat_command: return "command"; + case Arg::cat_rc: return "rc"; + case Arg::cat_rx: return "rx"; + case Arg::cat_override: return "override"; + case Arg::cat_attr: return "attr"; + case Arg::cat_attmod: return "attmod"; + case Arg::cat_id: return "id"; + case Arg::cat_uuid: return "uuid"; + case Arg::cat_subst: return "subst"; + case Arg::cat_pattern: return "pattern"; + case Arg::cat_tag: return "tag"; + case Arg::cat_dom: return "dom"; + case Arg::cat_op: return "op"; + case Arg::cat_literal: return "literal"; + } + + return "none"; +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/Arg.h b/src/Arg.h index e9659c6a7..023618702 100644 --- a/src/Arg.h +++ b/src/Arg.h @@ -35,19 +35,28 @@ class Arg { public: + enum category {cat_none=1, cat_terminator, cat_program, cat_command, cat_rc, cat_override, cat_attr, cat_attmod, cat_id, cat_uuid, cat_subst, cat_pattern, cat_rx, cat_tag, cat_dom, cat_op, cat_literal}; + enum type {type_none=20, type_pseudo, type_bool, type_string, type_date, type_duration, type_number}; + Arg (); Arg (const std::string&); - Arg (const std::string&, const std::string&); - Arg (const std::string&, const std::string&, const std::string&); + Arg (const std::string&, const category); + Arg (const std::string&, const type, const category); Arg (const Arg&); Arg& operator= (const Arg&); bool operator== (const Arg&) const; + static const type type_id (const std::string&); + static const std::string type_name (type); + + static const category category_id (const std::string&); + static const std::string category_name (category); + public: std::string _value; // Interpreted value std::string _raw; // Raw input token, never modified - std::string _type; // Data type - std::string _category; // Categorized argument + type _type; // Data type + category _category; // Categorized argument }; #endif diff --git a/src/E9.cpp b/src/E9.cpp index 82d9e16ec..1fe247731 100644 --- a/src/E9.cpp +++ b/src/E9.cpp @@ -36,10 +36,10 @@ extern Context context; std::ostream& operator<< (std::ostream& out, const Arg& term) { - out << term._value << "|" - << term._raw << "|" - << term._type << "|" - << term._category; + out << term._value << "|" + << term._raw << "|" + << Arg::type_name (term._type) << "|" + << Arg::category_name (term._category); return out; } @@ -70,7 +70,7 @@ bool E9::evalFilter (const Task& task) // Coerce result to Boolean. Arg result = value_stack.back (); value_stack.pop_back (); - return get_bool (coerce (result, "bool")); + return get_bool (coerce (result, Arg::type_bool)); } //////////////////////////////////////////////////////////////////////////////// @@ -94,7 +94,7 @@ void E9::eval (const Task& task, std::vector & value_stack) std::vector ::const_iterator arg; for (arg = _terms.begin (); arg != _terms.end (); ++arg) { - if (arg->_category == "op") + if (arg->_category == Arg::cat_op) { Arg result; @@ -156,22 +156,22 @@ void E9::eval (const Task& task, std::vector & value_stack) Arg operand (*arg); // Expand the value if possible. - if (operand._category == "dom" && _dom) + if (operand._category == Arg::cat_dom && _dom) { operand._value = context.dom.get (operand._raw, task); - operand._category = "literal"; + operand._category = Arg::cat_literal; } - else if (operand._type == "date" && - operand._category == "literal") + else if (operand._type == Arg::type_date && + operand._category == Arg::cat_literal) { operand._value = Date (operand._raw, _dateformat).toEpochString (); - operand._category = "literal"; + operand._category = Arg::cat_literal; } - else if (operand._type == "duration" && - operand._category == "literal") + else if (operand._type == Arg::type_duration && + operand._category == Arg::cat_literal) { operand._value = (std::string)Duration (operand._raw); - operand._category = "literal"; + operand._category = Arg::cat_literal; } else operand._value = operand._raw; @@ -189,10 +189,10 @@ void E9::eval (const Task& task, std::vector & value_stack) //////////////////////////////////////////////////////////////////////////////// bool E9::eval_match (Arg& left, Arg& right, bool case_sensitive) { - if (right._category == "rx") + if (right._category == Arg::cat_rx) { - left = coerce (left, "string"); - right = coerce (right, "string"); + left = coerce (left, Arg::type_string); + right = coerce (right, Arg::type_string); // Create a cached entry, if it does not already exist. if (_regexes.find (right._value) == _regexes.end ()) @@ -203,8 +203,8 @@ bool E9::eval_match (Arg& left, Arg& right, bool case_sensitive) } else { - left = coerce (left, "string"); - right = coerce (right, "string"); + left = coerce (left, Arg::type_string); + right = coerce (right, Arg::type_string); if (find (left._value, right._value, (bool) case_sensitive) != std::string::npos) return true; } @@ -216,7 +216,7 @@ bool E9::eval_match (Arg& left, Arg& right, bool case_sensitive) void E9::operator_not (Arg& result, Arg& right) { // TODO This is not right. - result = Arg (right._value, "bool", right._category); + result = Arg (right._value, Arg::type_bool, right._category); // std::cout << "# " << right << " --> " << result << "\n"; } @@ -226,13 +226,12 @@ void E9::operator_and (Arg& result, Arg& left, Arg& right) { // Assume failure. result._value = "false"; - result._category = "bool"; + result._type = Arg::type_bool; - if (coerce (left, "bool")._value == "true" && - coerce (right, "bool")._value == "true" ) + if (coerce (left, Arg::type_bool)._value == "true" && + coerce (right, Arg::type_bool)._value == "true" ) { result._value = "true"; - result._category = "bool"; } // std::cout << "# " << left << " " << right << " --> " << result << "\n"; @@ -243,13 +242,12 @@ void E9::operator_or (Arg& result, Arg& left, Arg& right) { // Assume failure. result._value = "false"; - result._category = "bool"; + result._type = Arg::type_bool; - if (coerce (left, "bool")._value == "true" || - coerce (right, "bool")._value == "true" ) + if (coerce (left, Arg::type_bool)._value == "true" || + coerce (right, Arg::type_bool)._value == "true" ) { result._value = "true"; - result._category = "bool"; } // std::cout << "# " << left << " " << right << " --> " << result << "\n"; @@ -260,16 +258,15 @@ void E9::operator_xor (Arg& result, Arg& left, Arg& right) { // Assume failure. result._value = "false"; - result._category = "bool"; + result._type = Arg::type_bool; - bool bool_left = coerce (left, "bool")._value == "true"; - bool bool_right = coerce (right, "bool")._value == "true"; + bool bool_left = coerce (left, Arg::type_bool)._value == "true"; + bool bool_right = coerce (right, Arg::type_bool)._value == "true"; if ((bool_left && !bool_right) || (!bool_left && bool_right)) { result._value = "true"; - result._category = "bool"; } // std::cout << "# " << left << " " << right << " --> " << result << "\n"; @@ -285,8 +282,8 @@ void E9::operator_lt (Arg& result, Arg& left, Arg& right) else if (left._value == "" && right._value != "") result._value = "true"; else result._value = "false"; } - else if (left._category == "date" || - right._category == "date") + else if (left._type == Arg::type_date || + right._type == Arg::type_date) { Date left_date (left._value, _dateformat); Date right_date (right._value, _dateformat); @@ -302,7 +299,7 @@ void E9::operator_lt (Arg& result, Arg& left, Arg& right) : "false"; } - result._category = "bool"; + result._type = Arg::type_bool; // std::cout << "# " << left << " " << right << " --> " << result << "\n"; } @@ -318,8 +315,8 @@ void E9::operator_lte (Arg& result, Arg& left, Arg& right) else if (left._value == "" ) result._value = "true"; else result._value = "false"; } - else if (left._category == "date" || - right._category == "date") + else if (left._type == Arg::type_date || + right._type == Arg::type_date) { Date left_date (left._value, _dateformat); Date right_date (right._value, _dateformat); @@ -335,7 +332,7 @@ void E9::operator_lte (Arg& result, Arg& left, Arg& right) : "false"; } - result._category = "bool"; + result._type = Arg::type_bool; // std::cout << "# " << left << " " << right << " --> " << result << "\n"; } @@ -351,8 +348,8 @@ void E9::operator_gte (Arg& result, Arg& left, Arg& right) else if ( right._value == "" ) result._value = "true"; else result._value = "false"; } - else if (left._category == "date" || - right._category == "date") + else if (left._type == Arg::type_date || + right._type == Arg::type_date) { Date left_date (left._value, _dateformat); Date right_date (right._value, _dateformat); @@ -368,7 +365,7 @@ void E9::operator_gte (Arg& result, Arg& left, Arg& right) : "false"; } - result._category = "bool"; + result._type = Arg::type_bool; // std::cout << "# " << left << " " << right << " --> " << result << "\n"; } @@ -383,8 +380,8 @@ void E9::operator_gt (Arg& result, Arg& left, Arg& right) else if (left._value != "" && right._value == "") result._value = "true"; else result._value = "false"; } - else if (left._category == "date" || - right._category == "date") + else if (left._type == Arg::type_date || + right._type == Arg::type_date) { Date left_date (left._value, _dateformat); Date right_date (right._value, _dateformat); @@ -400,7 +397,7 @@ void E9::operator_gt (Arg& result, Arg& left, Arg& right) : "false"; } - result._category = "bool"; + result._type = Arg::type_bool; // std::cout << "# " << left << " " << right << " --> " << result << "\n"; } @@ -429,14 +426,14 @@ void E9::operator_equal ( { // Assume failure. result._value = "false"; - result._category = "bool"; + result._type = Arg::type_bool; // 'project' and 'recur' attributes are matched leftmost. if (left._raw == "project" || left._raw == "recur") { // std::cout << "# project/recur matching\n"; - coerce (left, "string"); - coerce (right, "string"); + coerce (left, Arg::type_string); + coerce (right, Arg::type_string); if (right._value.length () <= left._value.length () && compare (right._value, @@ -444,13 +441,12 @@ void E9::operator_equal ( case_sensitive)) { result._raw = "true"; - result._category = "bool"; } } // Dates. - else if (left._category == "date" || - right._category == "date") + else if (left._type == Arg::type_date || + right._type == Arg::type_date) { // std::cout << "# date matching\n"; Date left_date (left._value, _dateformat); @@ -472,7 +468,7 @@ void E9::operator_equal ( if (left._value == right._value) { result._value = "true"; - result._category = "bool"; + result._type = Arg::type_bool; } } @@ -486,7 +482,7 @@ void E9::operator_match ( Arg& right, bool case_sensitive) { - result._category = "bool"; + result._type = Arg::type_bool; result._value = eval_match (left, right, case_sensitive) ? "true" : "false"; @@ -511,7 +507,7 @@ void E9::operator_nomatch ( Arg& right, bool case_sensitive) { - result._category = "bool"; + result._type = Arg::type_bool; result._value = eval_match (left, right, case_sensitive) ? "false" : "true"; @@ -544,21 +540,21 @@ void E9::operator_subtract (Arg& result, Arg& left, Arg& right) } //////////////////////////////////////////////////////////////////////////////// -const Arg E9::coerce (const Arg& input, const std::string& type) +const Arg E9::coerce (const Arg& input, const Arg::type type) { Arg result; - if (type == "bool") + if (type == Arg::type_bool) { - result._category = "bool"; + result._type = Arg::type_bool; result._value = get_bool (input) ? "true" : "false"; } - if (type == "string") + if (type == Arg::type_string) { // TODO Convert date? - result._value = input._value; - result._category = "string"; + result._value = input._value; + result._type = Arg::type_string; } // TODO Date diff --git a/src/E9.h b/src/E9.h index 365fc7487..db4773249 100644 --- a/src/E9.h +++ b/src/E9.h @@ -66,7 +66,7 @@ private: void operator_add (Arg&, Arg&, Arg&); void operator_subtract (Arg&, Arg&, Arg&); - const Arg coerce (const Arg&, const std::string&); + const Arg coerce (const Arg&, const Arg::type); bool get_bool (const Arg&); private: diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 5908eee99..407ab7d8d 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -411,7 +411,7 @@ void Command::modify_task ( { // Attributes are essentially name:value pairs, and correspond directly // to stored attributes. - if (arg->_category == "attr") + if (arg->_category == Arg::cat_attr) { std::string name; std::string value; @@ -477,7 +477,7 @@ void Command::modify_task ( // Tags need special handling because they are essentially a vector stored // in a single string, therefore Task::{add,remove}Tag must be called as // appropriate. - else if (arg->_category == "tag") + else if (arg->_category == Arg::cat_tag) { char type; std::string value; @@ -490,7 +490,7 @@ void Command::modify_task ( } // Substitutions. - else if (arg->_category == "subst") + else if (arg->_category == Arg::cat_subst) { std::string from; std::string to;