Expression Refactor

- Refactoring complete.  Arg objects now uses enumerations for _type
  and _category, which should help with performance.
This commit is contained in:
Paul Beckingham 2011-08-21 01:06:50 -04:00
parent 9086f51d29
commit 7aa4efef8d
6 changed files with 331 additions and 247 deletions

View file

@ -160,8 +160,8 @@ void A3::capture_first (const std::string& arg)
// immediately after the program and command arguments.
std::vector <Arg>::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:<file>
// 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.<name>:<value>
// 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 <Arg>::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 <Arg>::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 <Arg>::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 <Arg>::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 <Arg>::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 <Arg>::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 <Arg>::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 <std::string> A3::extract_words () const
std::vector <Arg>::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 <op sub mod> 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 <Arg>::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 <std::string, Color> 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 <int, Color> 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 ();

View file

@ -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";
}
///////////////////////////////////////////////////////////////////////////////

View file

@ -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

View file

@ -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 <Arg>& value_stack)
std::vector <Arg>::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 <Arg>& 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 <Arg>& 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 << "# <operator_not> " << 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 << " <operator_and> " << 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 << " <operator_or> " << 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 << " <operator_xor> " << 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 << " <operator_lt> " << 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 << " <operator_lte> " << 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 << " <operator_gte> " << 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 << " <operator_gt> " << 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

View file

@ -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:

View file

@ -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;