mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-09-08 06:10:36 +02:00
Parser Lib
- Relocated all old code into the parser lib.
This commit is contained in:
parent
0bd6363e1c
commit
3caf05b0c1
8 changed files with 5 additions and 5 deletions
2177
src/parser/A3.cpp
Normal file
2177
src/parser/A3.cpp
Normal file
File diff suppressed because it is too large
Load diff
110
src/parser/A3.h
Normal file
110
src/parser/A3.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006-2013, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_A3
|
||||
#define INCLUDED_A3
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <Arg.h>
|
||||
#include <Nibbler.h>
|
||||
#include <File.h>
|
||||
|
||||
class A3 : public std::vector <Arg>
|
||||
{
|
||||
public:
|
||||
A3 ();
|
||||
A3 (const A3&);
|
||||
A3& operator= (const A3&);
|
||||
~A3 ();
|
||||
|
||||
|
||||
void capture (int, const char**);
|
||||
void capture (const std::string&);
|
||||
void capture_first (const std::string&);
|
||||
|
||||
void categorize ();
|
||||
static bool is_command (const std::vector <std::string>&, std::string&);
|
||||
static const std::vector <std::string> operator_list ();
|
||||
|
||||
void append_stdin ();
|
||||
void rc_override (std::string&, File&);
|
||||
void get_data_location (std::string&);
|
||||
void resolve_aliases ();
|
||||
void apply_overrides ();
|
||||
void inject_defaults ();
|
||||
|
||||
const std::string combine () const;
|
||||
const std::vector <std::string> list () const;
|
||||
bool find_command (std::string&) const;
|
||||
const std::string find_limit () const;
|
||||
|
||||
const A3 extract_filter () const;
|
||||
const A3 extract_modifications () const;
|
||||
const std::vector <std::string> extract_words () const;
|
||||
|
||||
const A3 tokenize (const A3&) const;
|
||||
const A3 infix (const A3&) const;
|
||||
const A3 expand (const A3&) const;
|
||||
const A3 sequence (const A3&) const;
|
||||
const A3 postfix (const A3&) const;
|
||||
|
||||
static bool is_attr (Nibbler&, Arg&);
|
||||
static bool is_attmod (Nibbler&, Arg&);
|
||||
static bool is_attribute (const std::string&, std::string&);
|
||||
static bool is_modifier (const std::string&, std::string&);
|
||||
static bool is_dom (Nibbler&, Arg&);
|
||||
static bool is_date (Nibbler&, std::string&);
|
||||
static bool is_duration (Nibbler&, std::string&);
|
||||
static bool is_pattern (Nibbler&, std::string&);
|
||||
static bool is_subst (Nibbler&, std::string&);
|
||||
static bool is_id (Nibbler&, std::string&);
|
||||
static bool is_uuid (Nibbler&, std::string&);
|
||||
static bool is_tag (Nibbler&, std::string&);
|
||||
static bool is_number (Nibbler&, std::string&);
|
||||
static bool is_integer (Nibbler&, int&);
|
||||
static bool is_operator (std::vector <std::string>&, Nibbler&, std::string&);
|
||||
|
||||
static bool extract_pattern (const std::string&, std::string&);
|
||||
static bool extract_tag (const std::string&, char&, std::string&);
|
||||
static bool extract_attr (const std::string&, std::string&, std::string&);
|
||||
static bool extract_attmod (const std::string&, std::string&, std::string&, std::string&, std::string&);
|
||||
static bool extract_subst (const std::string&, std::string&, std::string&, bool&);
|
||||
static bool extract_id (const std::string&, std::vector <int>&);
|
||||
static bool extract_uuid (const std::string&, std::vector <std::string>&);
|
||||
|
||||
static bool which_operator (const std::string&, char&, int&, char&);
|
||||
|
||||
void dump (const std::string&) const;
|
||||
|
||||
private:
|
||||
bool _read_only_command;
|
||||
std::string _limit;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
187
src/parser/Arg.cpp
Normal file
187
src/parser/Arg.cpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006-2013, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <Arg.h>
|
||||
#include <Context.h>
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Arg::Arg ()
|
||||
: _value ("")
|
||||
, _raw ("")
|
||||
, _type (type_none)
|
||||
, _category (cat_none)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Arg::Arg (const std::string& raw)
|
||||
: _value ("")
|
||||
, _raw (raw)
|
||||
, _type (type_none)
|
||||
, _category (cat_none)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Arg::Arg (
|
||||
const std::string& raw,
|
||||
const category c)
|
||||
: _value ("")
|
||||
, _raw (raw)
|
||||
, _type (type_none)
|
||||
, _category (c)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Arg::Arg (
|
||||
const std::string& raw,
|
||||
const type t,
|
||||
const category c)
|
||||
: _value ("")
|
||||
, _raw (raw)
|
||||
, _type (t)
|
||||
, _category (c)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Arg::Arg (const Arg& other)
|
||||
{
|
||||
_value = other._value;
|
||||
_raw = other._raw;
|
||||
_type = other._type;
|
||||
_category = other._category;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Arg& Arg::operator= (const Arg& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
_value = other._value;
|
||||
_raw = other._raw;
|
||||
_type = other._type;
|
||||
_category = other._category;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Arg::operator== (const Arg& other) const
|
||||
{
|
||||
return _value == other._value &&
|
||||
_raw == other._raw &&
|
||||
_type == other._type &&
|
||||
_category == other._category;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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 "";
|
||||
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 "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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 "";
|
||||
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_dom_: return "[dom]";
|
||||
case Arg::cat_op: return "op";
|
||||
case Arg::cat_literal: return "literal";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
61
src/parser/Arg.h
Normal file
61
src/parser/Arg.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006-2013, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ARG
|
||||
#define INCLUDED_ARG
|
||||
|
||||
#include <string>
|
||||
|
||||
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_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 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
|
||||
type _type; // Data type
|
||||
category _category; // Categorized argument
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -9,7 +9,10 @@ include_directories (${CMAKE_SOURCE_DIR}
|
|||
set (parser_SRCS LRParser.cpp LRParser.h
|
||||
Parser.cpp Parser.h
|
||||
Tree.cpp Tree.h
|
||||
A3t.cpp A3t.h)
|
||||
A3.cpp A3.h
|
||||
A3t.cpp A3t.h
|
||||
Arg.cpp Arg.h
|
||||
E9.cpp E9.h)
|
||||
|
||||
add_library (parser STATIC ${parser_SRCS})
|
||||
add_executable (parser_executable bnf.cpp)
|
||||
|
|
837
src/parser/E9.cpp
Normal file
837
src/parser/E9.cpp
Normal file
|
@ -0,0 +1,837 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006-2013, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <Context.h>
|
||||
#include <Date.h>
|
||||
#include <Duration.h>
|
||||
#include <i18n.h>
|
||||
#include <text.h>
|
||||
#include <E9.h>
|
||||
|
||||
extern Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::ostream& operator<< (std::ostream& out, const Arg& term)
|
||||
{
|
||||
out << term._value << "|"
|
||||
<< term._raw << "|"
|
||||
<< Arg::type_name (term._type) << "|"
|
||||
<< Arg::category_name (term._category);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Perform all the necessary steps prior to an eval call.
|
||||
E9::E9 (const A3& args)
|
||||
{
|
||||
_terms = args;
|
||||
_dateformat = context.config.get ("dateformat");
|
||||
_dom = context.config.getBoolean ("dom");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
E9::~E9 ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool E9::evalFilter (const Task& task)
|
||||
{
|
||||
if (_terms.size () == 0)
|
||||
return true;
|
||||
|
||||
std::vector <Arg> value_stack;
|
||||
eval (task, value_stack);
|
||||
|
||||
// Coerce result to Boolean.
|
||||
Arg result = value_stack.back ();
|
||||
value_stack.pop_back ();
|
||||
return get_bool (coerce (result, Arg::type_bool));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string E9::evalExpression (const Task& task)
|
||||
{
|
||||
if (_terms.size () == 0)
|
||||
return "";
|
||||
|
||||
std::vector <Arg> value_stack;
|
||||
eval (task, value_stack);
|
||||
|
||||
return value_stack.back ()._value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::eval (const Task& task, std::vector <Arg>& value_stack)
|
||||
{
|
||||
// Case sensitivity is configurable.
|
||||
bool case_sensitive = context.config.getBoolean ("search.case.sensitive");
|
||||
|
||||
std::vector <Arg>::const_iterator arg;
|
||||
for (arg = _terms.begin (); arg != _terms.end (); ++arg)
|
||||
{
|
||||
if (arg->_category == Arg::cat_op)
|
||||
{
|
||||
Arg result;
|
||||
|
||||
// Unary operators.
|
||||
if (arg->_raw == "!")
|
||||
{
|
||||
if (value_stack.size () < 1)
|
||||
throw format (STRING_E9_NO_OPERANDS, "not");
|
||||
|
||||
Arg right = value_stack.back ();
|
||||
value_stack.pop_back ();
|
||||
|
||||
operator_not (result, right);
|
||||
}
|
||||
|
||||
// TODO Not sure this is correct.
|
||||
// TODO No longer sure why I was unsure in the first place.
|
||||
else if (arg->_raw == "-" && value_stack.size () == 1)
|
||||
{
|
||||
Arg right = value_stack.back ();
|
||||
value_stack.pop_back ();
|
||||
|
||||
operator_negate (result, right);
|
||||
}
|
||||
|
||||
// Binary operators.
|
||||
else
|
||||
{
|
||||
if (value_stack.size () < 2)
|
||||
throw format (STRING_E9_INSUFFICIENT_OP, arg->_raw);
|
||||
|
||||
Arg right = value_stack.back ();
|
||||
value_stack.pop_back ();
|
||||
|
||||
Arg left = value_stack.back ();
|
||||
value_stack.pop_back ();
|
||||
|
||||
if (arg->_raw == "and") operator_and (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 == "<") operator_lt (result, left, right);
|
||||
else if (arg->_raw == "<=") operator_lte (result, left, right);
|
||||
else if (arg->_raw == ">=") operator_gte (result, left, right);
|
||||
else if (arg->_raw == ">") operator_gt (result, left, right);
|
||||
else if (arg->_raw == "!=") operator_inequal (result, left, right, case_sensitive);
|
||||
else if (arg->_raw == "=") operator_equal (result, left, right, case_sensitive);
|
||||
else if (arg->_raw == "~") operator_match (result, left, right, case_sensitive, task);
|
||||
else if (arg->_raw == "!~") operator_nomatch (result, left, right, case_sensitive, task);
|
||||
else if (arg->_raw == "*") operator_multiply (result, left, right);
|
||||
else if (arg->_raw == "/") operator_divide (result, left, right);
|
||||
else if (arg->_raw == "+") operator_add (result, left, right);
|
||||
else if (arg->_raw == "-") operator_subtract (result, left, right);
|
||||
else if (arg->_raw == "_hastag_") operator_hastag (result, right, false, task);
|
||||
else if (arg->_raw == "_notag_") operator_hastag (result, right, true, task);
|
||||
else
|
||||
throw format (STRING_E9_UNSUPPORTED, arg->_raw);
|
||||
}
|
||||
|
||||
// Store the result.
|
||||
value_stack.push_back (result);
|
||||
}
|
||||
|
||||
// Operand (non-op).
|
||||
else
|
||||
{
|
||||
// Derive _value from _raw, and push on the stack.
|
||||
Arg operand (*arg);
|
||||
|
||||
if (operand._category == Arg::cat_dom && _dom)
|
||||
{
|
||||
operand._category = Arg::cat_literal;
|
||||
operand._value = context.dom.get (operand._raw, task);
|
||||
}
|
||||
else if (operand._type == Arg::type_date)
|
||||
{
|
||||
// Could be a date, could be a duration, added to 'now'.
|
||||
operand._category = Arg::cat_literal;
|
||||
if (operand._raw != "")
|
||||
{
|
||||
if (Date::valid (operand._raw, _dateformat))
|
||||
operand._value = Date (operand._raw, _dateformat).toEpochString ();
|
||||
|
||||
else if (Duration::valid (operand._raw))
|
||||
{
|
||||
Duration dur (operand._raw);
|
||||
Date now;
|
||||
now += (int)(time_t) dur;
|
||||
operand._value = now.toEpochString ();
|
||||
}
|
||||
else
|
||||
operand._value = "";
|
||||
}
|
||||
else
|
||||
operand._value = "";
|
||||
}
|
||||
else if (operand._type == Arg::type_duration)
|
||||
{
|
||||
operand._category = Arg::cat_literal;
|
||||
operand._value = (operand._raw != "")
|
||||
? (std::string)Duration (operand._raw)
|
||||
: "";
|
||||
}
|
||||
else
|
||||
operand._value = operand._raw;
|
||||
|
||||
value_stack.push_back (operand);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for stack remnants.
|
||||
if (value_stack.size () != 1)
|
||||
throw std::string (STRING_E9_MORE_OP);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool E9::eval_match (Arg& left, Arg& right, bool case_sensitive)
|
||||
{
|
||||
if (right._category == Arg::cat_rx)
|
||||
{
|
||||
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 ())
|
||||
_regexes[right._value] = RX (right._value, case_sensitive);
|
||||
|
||||
if (_regexes[right._value].match (left._value))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO Is there a danger of a raw date '1234567890' matching '234'?
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_not (Arg& result, Arg& right)
|
||||
{
|
||||
result = coerce (right, Arg::type_bool);
|
||||
|
||||
if (result._value == "true")
|
||||
result._value = "false";
|
||||
else
|
||||
result._value = "true";
|
||||
|
||||
// std::cout << "# <operator_not> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_negate (Arg& result, Arg& right)
|
||||
{
|
||||
result = coerce (right, Arg::type_number);
|
||||
result._value = format (- strtod (result._value.c_str (), NULL));
|
||||
|
||||
// std::cout << "# <operator_negate> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_and (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
result._value = "false";
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
if (coerce (left, Arg::type_bool)._value == "true" &&
|
||||
coerce (right, Arg::type_bool)._value == "true" )
|
||||
{
|
||||
result._value = "true";
|
||||
}
|
||||
|
||||
// std::cout << "# " << left << " <operator_and> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_or (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
result._value = "false";
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
if (coerce (left, Arg::type_bool)._value == "true" ||
|
||||
coerce (right, Arg::type_bool)._value == "true" )
|
||||
{
|
||||
result._value = "true";
|
||||
}
|
||||
|
||||
// std::cout << "# " << left << " <operator_or> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_xor (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
result._value = "false";
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
// std::cout << "# " << left << " <operator_xor> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_lt (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
if (left._raw == "priority")
|
||||
{
|
||||
if (left._value != "H" && right._value == "H") result._value = "true";
|
||||
else if (left._value == "L" && right._value == "M") result._value = "true";
|
||||
else if (left._value == "" && right._value != "") result._value = "true";
|
||||
else result._value = "false";
|
||||
}
|
||||
else if (left._type == Arg::type_date ||
|
||||
right._type == Arg::type_date)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Date left_date (left._value, _dateformat);
|
||||
Date right_date (right._value, _dateformat);
|
||||
|
||||
result._value = (left_date < right_date)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_duration ||
|
||||
right._type == Arg::type_duration)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Duration left_duration (left._value);
|
||||
Duration right_duration (right._value);
|
||||
|
||||
result._value = (left_duration < right_duration)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_number ||
|
||||
right._type == Arg::type_number)
|
||||
{
|
||||
float left_number = strtof (left._value.c_str (), NULL);
|
||||
float right_number = strtof (right._value.c_str (), NULL);
|
||||
|
||||
result._value = (left_number < right_number)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
result._value = (left._value < right._value)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
// std::cout << "# " << left << " <operator_lt> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_lte (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
if (left._raw == "priority")
|
||||
{
|
||||
if (left._value == right._value ) result._value = "true";
|
||||
else if ( right._value == "H") result._value = "true";
|
||||
else if (left._value == "L" && right._value == "M") result._value = "true";
|
||||
else if (left._value == "" ) result._value = "true";
|
||||
else result._value = "false";
|
||||
}
|
||||
else if (left._type == Arg::type_date ||
|
||||
right._type == Arg::type_date)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Date left_date (left._value, _dateformat);
|
||||
Date right_date (right._value, _dateformat);
|
||||
|
||||
result._value = (left_date <= right_date)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_duration ||
|
||||
right._type == Arg::type_duration)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Duration left_duration (left._value);
|
||||
Duration right_duration (right._value);
|
||||
|
||||
result._value = (left_duration <= right_duration)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_number ||
|
||||
right._type == Arg::type_number)
|
||||
{
|
||||
float left_number = strtof (left._value.c_str (), NULL);
|
||||
float right_number = strtof (right._value.c_str (), NULL);
|
||||
|
||||
result._value = (left_number <= right_number)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
result._value = (left._value <= right._value)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
// std::cout << "# " << left << " <operator_lte> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_gte (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
if (left._raw == "priority")
|
||||
{
|
||||
if (left._value == right._value ) result._value = "true";
|
||||
else if (left._value == "H" ) result._value = "true";
|
||||
else if (left._value == "M" && right._value == "L") result._value = "true";
|
||||
else if ( right._value == "" ) result._value = "true";
|
||||
else result._value = "false";
|
||||
}
|
||||
else if (left._type == Arg::type_date ||
|
||||
right._type == Arg::type_date)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Date left_date (left._value, _dateformat);
|
||||
Date right_date (right._value, _dateformat);
|
||||
|
||||
result._value = (left_date >= right_date)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_duration ||
|
||||
right._type == Arg::type_duration)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Duration left_duration (left._value);
|
||||
Duration right_duration (right._value);
|
||||
|
||||
result._value = (left_duration >= right_duration)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_number ||
|
||||
right._type == Arg::type_number)
|
||||
{
|
||||
float left_number = strtof (left._value.c_str (), NULL);
|
||||
float right_number = strtof (right._value.c_str (), NULL);
|
||||
|
||||
result._value = (left_number >= right_number)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
result._value = (left._value >= right._value)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
// std::cout << "# " << left << " <operator_gte> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_gt (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
if (left._raw == "priority")
|
||||
{
|
||||
if (left._value == "H" && right._value != "H") result._value = "true";
|
||||
else if (left._value == "M" && right._value == "L") result._value = "true";
|
||||
else if (left._value != "" && right._value == "") result._value = "true";
|
||||
else result._value = "false";
|
||||
}
|
||||
else if (left._type == Arg::type_date ||
|
||||
right._type == Arg::type_date)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Date left_date (left._value, _dateformat);
|
||||
Date right_date (right._value, _dateformat);
|
||||
|
||||
result._value = result._value = (left_date > right_date)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_duration ||
|
||||
right._type == Arg::type_duration)
|
||||
{
|
||||
if (left._value == "" ||
|
||||
right._value == "")
|
||||
result._value = "false";
|
||||
else
|
||||
{
|
||||
Duration left_duration (left._value);
|
||||
Duration right_duration (right._value);
|
||||
|
||||
result._value = result._value = (left_duration > right_duration)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
}
|
||||
else if (left._type == Arg::type_number ||
|
||||
right._type == Arg::type_number)
|
||||
{
|
||||
float left_number = strtof (left._value.c_str (), NULL);
|
||||
float right_number = strtof (right._value.c_str (), NULL);
|
||||
|
||||
result._value = (left_number > right_number)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
result._value = (left._value > right._value)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
// std::cout << "# " << left << " <operator_gt> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_inequal (
|
||||
Arg& result,
|
||||
Arg& left,
|
||||
Arg& right,
|
||||
bool case_sensitive)
|
||||
{
|
||||
operator_equal (result, left, right, case_sensitive);
|
||||
result._value = result._value == "false"
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
// std::cout << "# " << left << " <operator_inequal> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_equal (
|
||||
Arg& result,
|
||||
Arg& left,
|
||||
Arg& right,
|
||||
bool case_sensitive)
|
||||
{
|
||||
// Assume failure.
|
||||
result._value = "false";
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
// 'project' is matched leftmost.
|
||||
if (left._raw == "project")
|
||||
{
|
||||
// Bug 856.
|
||||
//
|
||||
// Special case for checking absent projects. Without the explicit "" check
|
||||
// the right._value.length() is used, which is 0, and therefore generates
|
||||
// a false match.
|
||||
if (right._value == "")
|
||||
{
|
||||
if (left._value == "")
|
||||
result._value = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int right_len = right._value.length ();
|
||||
if (compare (right._value,
|
||||
(right_len < left._value.length ()
|
||||
? left._value.substr (0, right_len)
|
||||
: left._value),
|
||||
case_sensitive))
|
||||
{
|
||||
result._value = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dates. Note that missing data causes processing to transfer to the generic
|
||||
// string comparison below.
|
||||
else if ((left._type == Arg::type_date ||
|
||||
right._type == Arg::type_date) &&
|
||||
left._value != "" &&
|
||||
right._value != "")
|
||||
{
|
||||
Date left_date (left._value, _dateformat);
|
||||
Date right_date (right._value, _dateformat);
|
||||
|
||||
result._value = (left_date == right_date)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
// Case-insensitive comparison for status. Fixes #1110.
|
||||
// Also priority, fixing #1154.
|
||||
else if (left._raw == "status" ||
|
||||
left._raw == "priority")
|
||||
{
|
||||
result._value = compare (left._value, right._value, false)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
// Regular equality matching.
|
||||
else
|
||||
{
|
||||
result._value = compare (left._value, right._value, case_sensitive)
|
||||
? "true"
|
||||
: "false";
|
||||
}
|
||||
|
||||
// std::cout << "# " << left << " <operator_equal> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Match may occur in description or any annotation. Short circuits.
|
||||
void E9::operator_match (
|
||||
Arg& result,
|
||||
Arg& left,
|
||||
Arg& right,
|
||||
bool case_sensitive,
|
||||
const Task& task)
|
||||
{
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
if (eval_match (left, right, case_sensitive))
|
||||
{
|
||||
result._value = "true";
|
||||
}
|
||||
else if (left._raw == "description")
|
||||
{
|
||||
std::map <std::string, std::string> annotations;
|
||||
task.getAnnotations (annotations);
|
||||
|
||||
std::map <std::string, std::string>::iterator a;
|
||||
for (a = annotations.begin (); a != annotations.end (); ++a)
|
||||
{
|
||||
// Clone 'left', override _value.
|
||||
Arg alternate (left);
|
||||
alternate._value = a->second;
|
||||
|
||||
if (eval_match (alternate, right, case_sensitive))
|
||||
{
|
||||
result._value = "true";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
result._value = "false";
|
||||
|
||||
// std::cout << "# " << left << " <operator_match> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Match may not occur in description or any annotation. Short circuits.
|
||||
void E9::operator_nomatch (
|
||||
Arg& result,
|
||||
Arg& left,
|
||||
Arg& right,
|
||||
bool case_sensitive,
|
||||
const Task& task)
|
||||
{
|
||||
result._type = Arg::type_bool;
|
||||
result._value = "true";
|
||||
|
||||
if (eval_match (left, right, case_sensitive))
|
||||
{
|
||||
result._value = "false";
|
||||
}
|
||||
else if (left._raw == "description")
|
||||
{
|
||||
std::map <std::string, std::string> annotations;
|
||||
task.getAnnotations (annotations);
|
||||
|
||||
std::map <std::string, std::string>::iterator a;
|
||||
for (a = annotations.begin (); a != annotations.end (); ++a)
|
||||
{
|
||||
// Clone 'left', override _value.
|
||||
Arg alternate (left);
|
||||
alternate._value = a->second;
|
||||
|
||||
if (eval_match (alternate, right, case_sensitive))
|
||||
{
|
||||
result._value = "false";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// std::cout << "# " << left << " <operator_nomatch> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_multiply (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
// std::cout << "# " << left << " <operator_multiply> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_divide (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
// std::cout << "# " << left << " <operator_divide> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_add (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
// std::cout << "# " << left << " <operator_add> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_subtract (Arg& result, Arg& left, Arg& right)
|
||||
{
|
||||
// std::cout << "# " << left << " <operator_subtract> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_hastag (
|
||||
Arg& result,
|
||||
Arg& right,
|
||||
bool invert,
|
||||
const Task& task)
|
||||
{
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
if (task.hasTag (right._raw))
|
||||
result._value = invert ? "false" : "true";
|
||||
else
|
||||
result._value = invert ? "true" : "false";
|
||||
|
||||
// std::cout << "# tags" << (invert ? " <operator_notag> " : " <operator_hastag> ") << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const Arg E9::coerce (const Arg& input, const Arg::type type)
|
||||
{
|
||||
Arg result;
|
||||
|
||||
if (type == Arg::type_bool)
|
||||
{
|
||||
result._raw = input._raw;
|
||||
result._value = get_bool (input) ? "true" : "false";
|
||||
result._type = Arg::type_bool;
|
||||
result._category = input._category;
|
||||
}
|
||||
|
||||
else if (type == Arg::type_string)
|
||||
{
|
||||
// TODO Convert date?
|
||||
result._raw = input._raw;
|
||||
result._value = input._value;
|
||||
result._type = Arg::type_string;
|
||||
result._category = input._category;
|
||||
}
|
||||
|
||||
else if (type == Arg::type_number)
|
||||
{
|
||||
result._raw = input._raw;
|
||||
result._value = input._value;
|
||||
result._type = Arg::type_number;
|
||||
result._category = input._category;
|
||||
}
|
||||
|
||||
// TODO Date
|
||||
// TODO Duration
|
||||
else
|
||||
{
|
||||
result = input;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool E9::get_bool (const Arg& input)
|
||||
{
|
||||
std::string value = lowerCase (input._value);
|
||||
if (value == "true" ||
|
||||
value == "t" ||
|
||||
value == "1" ||
|
||||
value == "+" ||
|
||||
value == "y" ||
|
||||
value == "yes" ||
|
||||
value == "on" ||
|
||||
value == "enable" ||
|
||||
value == "enabled")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
82
src/parser/E9.h
Normal file
82
src/parser/E9.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006-2013, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_E9
|
||||
#define INCLUDED_E9
|
||||
|
||||
#include <string>
|
||||
#include <A3.h>
|
||||
#include <Task.h>
|
||||
#include <RX.h>
|
||||
|
||||
class E9
|
||||
{
|
||||
public:
|
||||
E9 (const A3&);
|
||||
~E9 ();
|
||||
|
||||
bool evalFilter (const Task&);
|
||||
std::string evalExpression (const Task&);
|
||||
|
||||
private:
|
||||
void eval (const Task&, std::vector <Arg>&);
|
||||
bool eval_match (Arg&, Arg&, bool);
|
||||
|
||||
// Unary.
|
||||
void operator_not (Arg&, Arg&);
|
||||
void operator_negate (Arg&, Arg&);
|
||||
|
||||
// Binary.
|
||||
void operator_and (Arg&, Arg&, Arg&);
|
||||
void operator_or (Arg&, Arg&, Arg&);
|
||||
void operator_xor (Arg&, Arg&, Arg&);
|
||||
void operator_lt (Arg&, Arg&, Arg&);
|
||||
void operator_lte (Arg&, Arg&, Arg&);
|
||||
void operator_gte (Arg&, Arg&, Arg&);
|
||||
void operator_gt (Arg&, Arg&, Arg&);
|
||||
void operator_inequal (Arg&, Arg&, Arg&, bool);
|
||||
void operator_equal (Arg&, Arg&, Arg&, bool);
|
||||
void operator_match (Arg&, Arg&, Arg&, bool, const Task&);
|
||||
void operator_nomatch (Arg&, Arg&, Arg&, bool, const Task&);
|
||||
void operator_multiply (Arg&, Arg&, Arg&);
|
||||
void operator_divide (Arg&, Arg&, Arg&);
|
||||
void operator_add (Arg&, Arg&, Arg&);
|
||||
void operator_subtract (Arg&, Arg&, Arg&);
|
||||
void operator_hastag (Arg&, Arg&, bool, const Task&);
|
||||
|
||||
const Arg coerce (const Arg&, const Arg::type);
|
||||
bool get_bool (const Arg&);
|
||||
|
||||
private:
|
||||
std::vector <Arg> _terms;
|
||||
std::map <std::string, RX> _regexes;
|
||||
std::string _dateformat;
|
||||
bool _dom;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
Loading…
Add table
Add a link
Reference in a new issue