- Added Daniel Kullmann as thanks for the code patches, although they
  are not being applied.  We still appreciate the effort.
This commit is contained in:
Paul Beckingham
2011-07-27 22:42:18 -04:00
parent 8651bbec8e
commit 2460502be8
4 changed files with 265 additions and 128 deletions

View File

@@ -55,6 +55,7 @@ The following submitted code, packages or analysis, and deserve special thanks:
Bryce Harrington Bryce Harrington
Brendan O'Flaherty Brendan O'Flaherty
Matt Kraai Matt Kraai
Daniel Kullmann
Thanks to the following, who submitted detailed bug reports and excellent Thanks to the following, who submitted detailed bug reports and excellent
suggestions: suggestions:

View File

@@ -653,15 +653,15 @@ const bool Config::getBoolean (const std::string& key)
if ((*this).find (key) != (*this).end ()) if ((*this).find (key) != (*this).end ())
{ {
std::string value = lowerCase ((*this)[key]); std::string value = lowerCase ((*this)[key]);
if (value == "t" || // TODO i18n if (value == "t" ||
value == "true" || // TODO i18n value == "true" ||
value == "1" || // no i18n value == "1" ||
value == "+" || // no i18n value == "+" ||
value == "y" || // TODO i18n value == "y" ||
value == "yes" || // TODO i18n value == "yes" ||
value == "on" || // TODO i18n value == "on" ||
value == "enable" || // TODO i18n value == "enable" ||
value == "enabled") // TODO i18n value == "enabled")
return true; return true;
} }

View File

@@ -27,6 +27,7 @@
#include <iostream> // TODO Remove. #include <iostream> // TODO Remove.
#include <Context.h> #include <Context.h>
#include <text.h>
#include <A3.h> #include <A3.h>
#include <E9.h> #include <E9.h>
@@ -34,9 +35,11 @@ extern Context context;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Perform all the necessary steps prior to an eval call. // Perform all the necessary steps prior to an eval call.
E9::E9 (A3& args) E9::E9 (const A3& args)
: _args (args)
{ {
std::vector <Arg>::const_iterator arg;
for (arg = args.begin (); arg != args.end (); ++arg)
_terms.push_back (Term (*arg));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -47,59 +50,85 @@ E9::~E9 ()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool E9::evalFilter (const Task& task) bool E9::evalFilter (const Task& task)
{ {
if (_args.size () == 0) if (_terms.size () == 0)
return true; return true;
std::vector <Arg> value_stack; std::vector <Term> value_stack;
eval (task, value_stack); eval (task, value_stack);
// TODO Coerce result to Boolean. // Coerce result to Boolean.
return true; Term result = value_stack.back ();
value_stack.pop_back ();
return get_bool (coerce (result, "bool"));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string E9::evalExpression (const Task& task) std::string E9::evalExpression (const Task& task)
{ {
if (_args.size () == 0) if (_terms.size () == 0)
return ""; return "";
std::vector <Arg> value_stack; std::vector <Term> value_stack;
eval (task, value_stack); eval (task, value_stack);
return value_stack.back ()._raw; return value_stack.back ()._value;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::eval (const Task& task, std::vector <Arg>& value_stack) void E9::eval (const Task& task, std::vector <Term>& value_stack)
{ {
// Case sensitivity is configurable. // Case sensitivity is configurable.
bool case_sensitive = context.config.getBoolean ("search.case.sensitive"); bool case_sensitive = context.config.getBoolean ("search.case.sensitive");
std::vector <Arg>::iterator arg; std::vector <Term>::iterator arg;
for (arg = _args.begin (); arg != _args.end (); ++arg) for (arg = _terms.begin (); arg != _terms.end (); ++arg)
{ {
if (arg->_category == "op") if (arg->_category == "op")
{ {
Arg result; Term result;
// Unary operators. // Unary operators.
if (arg->_raw == "!") if (arg->_raw == "!")
{ {
// TODO Are there sufficient arguments? if (value_stack.size () < 1)
Arg right = value_stack.back (); throw std::string ("There are no operands for the 'not' operator.");
Term right = value_stack.back ();
value_stack.pop_back (); value_stack.pop_back ();
if (right._category == "dom")
{
right._value = context.dom.get (right._raw, task);
right._category = "string";
}
operator_not (result, right); operator_not (result, right);
} }
// Binary operators. // Binary operators.
else else
{ {
// TODO Are there sufficient arguments? if (value_stack.size () < 2)
Arg right = value_stack.back (); throw std::string ("There are not enough operands for the '") + arg->_raw + "' operator.";
Term right = value_stack.back ();
value_stack.pop_back (); value_stack.pop_back ();
Arg left = value_stack.back ();
if (right._category == "dom")
{
right._value = context.dom.get (right._raw, task);
right._category = "string";
}
Term left = value_stack.back ();
value_stack.pop_back (); value_stack.pop_back ();
if (left._category == "dom")
{
left._value = context.dom.get (left._raw, task);
left._category = "string";
}
if (arg->_raw == "and") operator_and (result, left, right); if (arg->_raw == "and") operator_and (result, left, right);
else if (arg->_raw == "or") operator_or (result, left, right); else if (arg->_raw == "or") operator_or (result, left, right);
else if (arg->_raw == "xor") operator_xor (result, left, right); else if (arg->_raw == "xor") operator_xor (result, left, right);
@@ -136,48 +165,74 @@ void E9::eval (const Task& task, std::vector <Arg>& value_stack)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_not (Arg& result, Arg& left) bool E9::eval_match (Term& left, Term& right, bool case_sensitive)
{ {
if (right._category == "rx")
{
coerce (left, "string");
coerce (right, "string");
std::cout << "# not " << left._raw << "/" << left._category // Create a cached entry, if it does not already exist.
if (_regexes.find (right._value) == _regexes.end ())
_regexes[right._value] = RX (right._value, case_sensitive);
if (_regexes[right._value].match (left._value))
return true;
}
else
{
coerce (left, "string");
coerce (right, "string");
if (find (left._value, right._value, (bool) case_sensitive) != std::string::npos)
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
void E9::operator_not (Term& result, Term& right)
{
result = Term (right._raw, coerce (right, "bool")._value, "bool");
std::cout << "# not " << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_and (Arg& result, Arg& left, Arg& right) void E9::operator_and (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " and " << " and "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_or (Arg& result, Arg& left, Arg& right) void E9::operator_or (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " or " << " or "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_xor (Arg& result, Arg& left, Arg& right) void E9::operator_xor (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " xor " << " xor "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
@@ -186,14 +241,14 @@ void E9::operator_xor (Arg& result, Arg& left, Arg& right)
// if (left._string != "H" && right._string == "H") result = true; // if (left._string != "H" && right._string == "H") result = true;
// else if (left._string == "L" && right._string == "M") result = true; // else if (left._string == "L" && right._string == "M") result = true;
// else if (left._string == "" && right._string != "") result = true; // else if (left._string == "" && right._string != "") result = true;
void E9::operator_lt (Arg& result, Arg& left, Arg& right) void E9::operator_lt (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " < " << " < "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
@@ -203,14 +258,14 @@ void E9::operator_lt (Arg& result, Arg& left, Arg& right)
// else if ( right._string == "H") result = true; // else if ( right._string == "H") result = true;
// else if (left._string == "L" && right._string == "M") result = true; // else if (left._string == "L" && right._string == "M") result = true;
// else if (left._string == "" ) result = true; // else if (left._string == "" ) result = true;
void E9::operator_lte (Arg& result, Arg& left, Arg& right) void E9::operator_lte (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " <= " << " <= "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
@@ -220,14 +275,14 @@ void E9::operator_lte (Arg& result, Arg& left, Arg& right)
// else if (left._string == "H" ) result = true; // else if (left._string == "H" ) result = true;
// else if (left._string == "M" && right._string == "L") result = true; // else if (left._string == "M" && right._string == "L") result = true;
// else if ( right._string == "" ) result = true; // else if ( right._string == "" ) result = true;
void E9::operator_gte (Arg& result, Arg& left, Arg& right) void E9::operator_gte (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " >= " << " >= "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
@@ -236,26 +291,26 @@ void E9::operator_gte (Arg& result, Arg& left, Arg& right)
// if (left._string == "H" && right._string != "H") result = true; // if (left._string == "H" && right._string != "H") result = true;
// else if (left._string == "M" && right._string == "L") result = true; // else if (left._string == "M" && right._string == "L") result = true;
// else if (left._string != "" && right._string == "") result = true; // else if (left._string != "" && right._string == "") result = true;
void E9::operator_gt (Arg& result, Arg& left, Arg& right) void E9::operator_gt (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " > " << " > "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_inequal (Arg& result, Arg& left, Arg& right) void E9::operator_inequal (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " != " << " != "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
@@ -272,26 +327,31 @@ void E9::operator_inequal (Arg& result, Arg& left, Arg& right)
// } // }
// else // else
// result = (left == right); // result = (left == right);
void E9::operator_equal (Arg& result, Arg& left, Arg& right) void E9::operator_equal (Term& result, Term& left, Term& right)
{ {
if (left._value == right._value)
{
result._raw = result._value = "true";
result._category = "bool";
}
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " = " << " = "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_match (Arg& result, Arg& left, Arg& right) void E9::operator_match (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " ~ " << " ~ "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
@@ -306,90 +366,103 @@ void E9::operator_match (Arg& result, Arg& left, Arg& right)
// { // {
// // TODO check further. // // TODO check further.
// } // }
void E9::operator_nomatch (Arg& result, Arg& left, Arg& right) void E9::operator_nomatch (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " !~ " << " !~ "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_multiply (Arg& result, Arg& left, Arg& right) void E9::operator_multiply (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " * " << " * "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_divide (Arg& result, Arg& left, Arg& right) void E9::operator_divide (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " / " << " / "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_add (Arg& result, Arg& left, Arg& right) void E9::operator_add (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " + " << " + "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void E9::operator_subtract (Arg& result, Arg& left, Arg& right) void E9::operator_subtract (Term& result, Term& left, Term& right)
{ {
std::cout << "# " << left._raw << "/" << left._category std::cout << "# " << left._raw << "/" << left._value << "/" << left._category
<< " - " << " - "
<< right._raw << "/" << right._category << right._raw << "/" << right._value << "/" << right._category
<< " --> " << " --> "
<< result._raw << "/" << result._category << result._raw << "/" << result._value << "/" << result._category
<< "\n"; << "\n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/* const Term E9::coerce (const Term& input, const std::string& type)
bool Expression::eval_match (Variant& left, Variant& right, bool case_sensitive)
{ {
if (right._raw_type == "rx") Term result;
{
left.cast (Variant::v_string);
right.cast (Variant::v_string);
// Create a cached entry, if it does not already exist. if (type == "bool")
if (_regexes.find (right._string) == _regexes.end ())
_regexes[right._string] = RX (right._string, case_sensitive);
if (_regexes[right._string].match (left._string))
return true;
}
else
{ {
left.cast (Variant::v_string); result._category = "bool";
right.cast (Variant::v_string); result._value = get_bool (input) ? "true" : "false";
if (find (left._string, right._string, (bool) case_sensitive) != std::string::npos)
return true;
} }
if (type == "string")
{
result._category = "string";
}
// TODO Date
// TODO Duration
return result;
}
////////////////////////////////////////////////////////////////////////////////
bool E9::get_bool (const Term& input)
{
std::string value = lowerCase (input._raw);
if (value == "true" ||
value == "t" ||
value == "1" ||
value == "+" ||
value == "y" ||
value == "yes" ||
value == "on" ||
value == "enable" ||
value == "enabled")
return true;
return false; return false;
} }
*/
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

101
src/E9.h
View File

@@ -33,40 +33,103 @@
#include <Task.h> #include <Task.h>
#include <RX.h> #include <RX.h>
class Term
{
public:
Term ()
: _raw ("")
, _value ("")
, _category ("")
{
}
Term (const Arg& arg)
: _raw (arg._raw)
, _value (arg._raw)
, _category (arg._category)
{
}
Term (
const std::string& raw,
const std::string& value,
const std::string& category)
: _raw (raw)
, _value (value)
, _category (category)
{
}
Term (const Term& other)
{
_raw = other._raw;
_value = other._value;
_category = other._category;
}
Term& operator= (const Term& other)
{
if (this != &other)
{
_raw = other._raw;
_value = other._value;
_category = other._category;
}
return *this;
}
bool operator== (const Term& other) const
{
return _raw == other._raw &&
_value == other._value &&
_category == other._category;
}
public:
std::string _raw; // Raw input token, never modified
std::string _value; // Evaluated raw token, sometimes identical
std::string _category; // Categorized argument
};
class E9 class E9
{ {
public: public:
E9 (A3&); E9 (const A3&);
~E9 (); ~E9 ();
bool evalFilter (const Task&); bool evalFilter (const Task&);
std::string evalExpression (const Task&); std::string evalExpression (const Task&);
private: private:
void eval (const Task&, std::vector <Arg>&); void eval (const Task&, std::vector <Term>&);
bool eval_match (Term&, Term&, bool);
// Unary. // Unary.
void operator_not (Arg&, Arg&); void operator_not (Term&, Term&);
// Binary. // Binary.
void operator_and (Arg&, Arg&, Arg&); void operator_and (Term&, Term&, Term&);
void operator_or (Arg&, Arg&, Arg&); void operator_or (Term&, Term&, Term&);
void operator_xor (Arg&, Arg&, Arg&); void operator_xor (Term&, Term&, Term&);
void operator_lt (Arg&, Arg&, Arg&); void operator_lt (Term&, Term&, Term&);
void operator_lte (Arg&, Arg&, Arg&); void operator_lte (Term&, Term&, Term&);
void operator_gte (Arg&, Arg&, Arg&); void operator_gte (Term&, Term&, Term&);
void operator_gt (Arg&, Arg&, Arg&); void operator_gt (Term&, Term&, Term&);
void operator_inequal (Arg&, Arg&, Arg&); void operator_inequal (Term&, Term&, Term&);
void operator_equal (Arg&, Arg&, Arg&); void operator_equal (Term&, Term&, Term&);
void operator_match (Arg&, Arg&, Arg&); void operator_match (Term&, Term&, Term&);
void operator_nomatch (Arg&, Arg&, Arg&); void operator_nomatch (Term&, Term&, Term&);
void operator_multiply (Arg&, Arg&, Arg&); void operator_multiply (Term&, Term&, Term&);
void operator_divide (Arg&, Arg&, Arg&); void operator_divide (Term&, Term&, Term&);
void operator_add (Arg&, Arg&, Arg&); void operator_add (Term&, Term&, Term&);
void operator_subtract (Arg&, Arg&, Arg&); void operator_subtract (Term&, Term&, Term&);
const Term coerce (const Term&, const std::string&);
bool get_bool (const Term&);
private: private:
A3 _args; std::vector <Term> _terms;
std::map <std::string, RX> _regexes; std::map <std::string, RX> _regexes;
}; };