summaryrefslogtreecommitdiff
path: root/src/query.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/query.h')
-rw-r--r--src/query.h273
1 files changed, 157 insertions, 116 deletions
diff --git a/src/query.h b/src/query.h
index 59adfd72..b5b3b0fc 100644
--- a/src/query.h
+++ b/src/query.h
@@ -46,8 +46,11 @@
namespace ledger {
-class query_t : public predicate_t
+class query_t
{
+protected:
+ class parser_t;
+
public:
class lexer_t
{
@@ -57,6 +60,7 @@ public:
value_t::sequence_t::const_iterator begin;
value_t::sequence_t::const_iterator end;
+ string::const_iterator prev_arg_i;
string::const_iterator arg_i;
string::const_iterator arg_end;
@@ -68,107 +72,123 @@ public:
struct token_t
{
enum kind_t {
- UNKNOWN,
+ UNKNOWN,
+
+ LPAREN,
+ RPAREN,
- LPAREN,
- RPAREN,
+ TOK_NOT,
+ TOK_AND,
+ TOK_OR,
+ TOK_EQ,
- TOK_NOT,
- TOK_AND,
- TOK_OR,
- TOK_EQ,
+ TOK_CODE,
+ TOK_PAYEE,
+ TOK_NOTE,
+ TOK_ACCOUNT,
+ TOK_META,
+ TOK_EXPR,
- TOK_DATE,
- TOK_CODE,
- TOK_PAYEE,
- TOK_NOTE,
- TOK_ACCOUNT,
- TOK_META,
- TOK_EXPR,
+ TOK_SHOW,
+ TOK_ONLY,
+ TOK_BOLD,
+ TOK_FOR,
+ TOK_SINCE,
+ TOK_UNTIL,
- TERM,
+ TERM,
- END_REACHED
+ END_REACHED
} kind;
optional<string> value;
explicit token_t(kind_t _kind = UNKNOWN,
- const optional<string>& _value = none)
- : kind(_kind), value(_value) {
- TRACE_CTOR(query_t::lexer_t::token_t, "");
+ const optional<string>& _value = none)
+ : kind(_kind), value(_value) {
+ TRACE_CTOR(query_t::lexer_t::token_t, "");
}
token_t(const token_t& tok)
- : kind(tok.kind), value(tok.value) {
- TRACE_CTOR(query_t::lexer_t::token_t, "copy");
+ : kind(tok.kind), value(tok.value) {
+ TRACE_CTOR(query_t::lexer_t::token_t, "copy");
}
~token_t() throw() {
- TRACE_DTOR(query_t::lexer_t::token_t);
+ TRACE_DTOR(query_t::lexer_t::token_t);
}
token_t& operator=(const token_t& tok) {
- if (this != &tok) {
- kind = tok.kind;
- value = tok.value;
- }
- return *this;
+ if (this != &tok) {
+ kind = tok.kind;
+ value = tok.value;
+ }
+ return *this;
}
operator bool() const {
- return kind != END_REACHED;
+ return kind != END_REACHED;
}
string to_string() const {
- switch (kind) {
- case UNKNOWN: return "UNKNOWN";
- case LPAREN: return "LPAREN";
- case RPAREN: return "RPAREN";
- case TOK_NOT: return "TOK_NOT";
- case TOK_AND: return "TOK_AND";
- case TOK_OR: return "TOK_OR";
- case TOK_EQ: return "TOK_EQ";
- case TOK_DATE: return "TOK_DATE";
- case TOK_CODE: return "TOK_CODE";
- case TOK_PAYEE: return "TOK_PAYEE";
- case TOK_NOTE: return "TOK_NOTE";
- case TOK_ACCOUNT: return "TOK_ACCOUNT";
- case TOK_META: return "TOK_META";
- case TOK_EXPR: return "TOK_EXPR";
- case TERM: return string("TERM(") + *value + ")";
- case END_REACHED: return "END_REACHED";
- }
- assert(false);
- return empty_string;
+ switch (kind) {
+ case UNKNOWN: return "UNKNOWN";
+ case LPAREN: return "LPAREN";
+ case RPAREN: return "RPAREN";
+ case TOK_NOT: return "TOK_NOT";
+ case TOK_AND: return "TOK_AND";
+ case TOK_OR: return "TOK_OR";
+ case TOK_EQ: return "TOK_EQ";
+ case TOK_CODE: return "TOK_CODE";
+ case TOK_PAYEE: return "TOK_PAYEE";
+ case TOK_NOTE: return "TOK_NOTE";
+ case TOK_ACCOUNT: return "TOK_ACCOUNT";
+ case TOK_META: return "TOK_META";
+ case TOK_EXPR: return "TOK_EXPR";
+ case TOK_SHOW: return "TOK_SHOW";
+ case TOK_ONLY: return "TOK_ONLY";
+ case TOK_BOLD: return "TOK_BOLD";
+ case TOK_FOR: return "TOK_FOR";
+ case TOK_SINCE: return "TOK_SINCE";
+ case TOK_UNTIL: return "TOK_UNTIL";
+ case TERM: return string("TERM(") + *value + ")";
+ case END_REACHED: return "END_REACHED";
+ }
+ assert(false);
+ return empty_string;
}
string symbol() const {
- switch (kind) {
- case LPAREN: return "(";
- case RPAREN: return ")";
- case TOK_NOT: return "not";
- case TOK_AND: return "and";
- case TOK_OR: return "or";
- case TOK_EQ: return "=";
- case TOK_DATE: return "date";
- case TOK_CODE: return "code";
- case TOK_PAYEE: return "payee";
- case TOK_NOTE: return "note";
- case TOK_ACCOUNT: return "account";
- case TOK_META: return "meta";
- case TOK_EXPR: return "expr";
-
- case END_REACHED: return "<EOF>";
-
- case TERM:
- assert(false);
- return "<TERM>";
-
- case UNKNOWN:
- default:
- assert(false);
- return "<UNKNOWN>";
- }
+ switch (kind) {
+ case LPAREN: return "(";
+ case RPAREN: return ")";
+ case TOK_NOT: return "not";
+ case TOK_AND: return "and";
+ case TOK_OR: return "or";
+ case TOK_EQ: return "=";
+ case TOK_CODE: return "code";
+ case TOK_PAYEE: return "payee";
+ case TOK_NOTE: return "note";
+ case TOK_ACCOUNT: return "account";
+ case TOK_META: return "meta";
+ case TOK_EXPR: return "expr";
+ case TOK_SHOW: return "show";
+ case TOK_ONLY: return "only";
+ case TOK_BOLD: return "bold";
+ case TOK_FOR: return "for";
+ case TOK_SINCE: return "since";
+ case TOK_UNTIL: return "until";
+
+ case END_REACHED: return "<EOF>";
+
+ case TERM:
+ assert(false);
+ return "<TERM>";
+
+ case UNKNOWN:
+ default:
+ assert(false);
+ return "<UNKNOWN>";
+ }
}
void unexpected();
@@ -178,11 +198,11 @@ public:
token_t token_cache;
lexer_t(value_t::sequence_t::const_iterator _begin,
- value_t::sequence_t::const_iterator _end,
- bool _multiple_args = true)
+ value_t::sequence_t::const_iterator _end,
+ bool _multiple_args = true)
: begin(_begin), end(_end),
- consume_whitespace(false), consume_next_arg(false),
- multiple_args(_multiple_args)
+ consume_whitespace(false), consume_next_arg(false),
+ multiple_args(_multiple_args)
{
TRACE_CTOR(query_t::lexer_t, "");
assert(begin != end);
@@ -191,11 +211,10 @@ public:
}
lexer_t(const lexer_t& lexer)
: begin(lexer.begin), end(lexer.end),
- arg_i(lexer.arg_i), arg_end(lexer.arg_end),
- consume_whitespace(lexer.consume_whitespace),
- consume_next_arg(lexer.consume_next_arg),
- multiple_args(lexer.multiple_args),
- token_cache(lexer.token_cache)
+ arg_i(lexer.arg_i), arg_end(lexer.arg_end),
+ consume_whitespace(lexer.consume_whitespace),
+ consume_next_arg(lexer.consume_next_arg),
+ multiple_args(lexer.multiple_args), token_cache(lexer.token_cache)
{
TRACE_CTOR(query_t::lexer_t, "copy");
}
@@ -210,29 +229,45 @@ public:
}
token_t peek_token() {
if (token_cache.kind == token_t::UNKNOWN)
- token_cache = next_token();
+ token_cache = next_token();
return token_cache;
}
};
+ enum kind_t {
+ QUERY_LIMIT,
+ QUERY_SHOW,
+ QUERY_ONLY,
+ QUERY_BOLD,
+ QUERY_FOR
+ };
+
+ typedef std::map<kind_t, string> query_map_t;
+
protected:
class parser_t
{
friend class query_t;
- value_t args;
- lexer_t lexer;
+ value_t args;
+ lexer_t lexer;
+ keep_details_t what_to_keep;
+ query_map_t query_map;
expr_t::ptr_op_t parse_query_term(lexer_t::token_t::kind_t tok_context);
expr_t::ptr_op_t parse_unary_expr(lexer_t::token_t::kind_t tok_context);
expr_t::ptr_op_t parse_and_expr(lexer_t::token_t::kind_t tok_context);
expr_t::ptr_op_t parse_or_expr(lexer_t::token_t::kind_t tok_context);
- expr_t::ptr_op_t parse_query_expr(lexer_t::token_t::kind_t tok_context);
+ expr_t::ptr_op_t parse_query_expr(lexer_t::token_t::kind_t tok_context,
+ bool subexpression = false);
public:
- parser_t(const value_t& _args, bool multiple_args = true)
- : args(_args), lexer(args.begin(), args.end(), multiple_args) {
- TRACE_CTOR(query_t::parser_t, "");
+ parser_t(const value_t& _args,
+ const keep_details_t& _what_to_keep = keep_details_t(),
+ bool multiple_args = true)
+ : args(_args), lexer(args.begin(), args.end(), multiple_args),
+ what_to_keep(_what_to_keep) {
+ TRACE_CTOR(query_t::parser_t, "value_t, keep_details_t, bool");
}
parser_t(const parser_t& parser)
: args(parser.args), lexer(parser.lexer) {
@@ -242,8 +277,8 @@ protected:
TRACE_DTOR(query_t::parser_t);
}
- expr_t::ptr_op_t parse() {
- return parse_query_expr(lexer_t::token_t::TOK_ACCOUNT);
+ expr_t::ptr_op_t parse(bool subexpression = false) {
+ return parse_query_expr(lexer_t::token_t::TOK_ACCOUNT, subexpression);
}
bool tokens_remaining() {
@@ -254,55 +289,61 @@ protected:
};
optional<parser_t> parser;
+ query_map_t predicates;
public:
query_t() {
TRACE_CTOR(query_t, "");
}
query_t(const query_t& other)
- : predicate_t(other) {
+ : parser(other.parser), predicates(other.predicates) {
TRACE_CTOR(query_t, "copy");
}
- query_t(const string& arg,
- const keep_details_t& _what_to_keep = keep_details_t(),
- bool multiple_args = true)
- : predicate_t(_what_to_keep) {
- TRACE_CTOR(query_t, "string, keep_details_t");
+ query_t(const string& arg,
+ const keep_details_t& what_to_keep = keep_details_t(),
+ bool multiple_args = true) {
+ TRACE_CTOR(query_t, "string, keep_details_t, bool");
if (! arg.empty()) {
value_t temp(string_value(arg));
- parse_args(temp.to_sequence(), multiple_args);
+ parse_args(temp.to_sequence(), what_to_keep, multiple_args);
}
}
- query_t(const value_t& args,
- const keep_details_t& _what_to_keep = keep_details_t(),
- bool multiple_args = true)
- : predicate_t(_what_to_keep) {
- TRACE_CTOR(query_t, "value_t, keep_details_t");
+ query_t(const value_t& args,
+ const keep_details_t& what_to_keep = keep_details_t(),
+ bool multiple_args = true) {
+ TRACE_CTOR(query_t, "value_t, keep_details_t, bool");
if (! args.empty())
- parse_args(args, multiple_args);
+ parse_args(args, what_to_keep, multiple_args);
}
virtual ~query_t() {
TRACE_DTOR(query_t);
}
- void parse_args(const value_t& args, bool multiple_args = true) {
+ expr_t::ptr_op_t
+ parse_args(const value_t& args,
+ const keep_details_t& what_to_keep = keep_details_t(),
+ bool multiple_args = true,
+ bool subexpression = false) {
if (! parser)
- parser = parser_t(args, multiple_args);
- ptr = parser->parse(); // expr_t::ptr
+ parser = parser_t(args, what_to_keep, multiple_args);
+ return parser->parse(subexpression);
}
- void parse_again() {
- assert(parser);
- ptr = parser->parse(); // expr_t::ptr
+ bool has_query(const kind_t& id) const {
+ return parser && parser->query_map.find(id) != parser->query_map.end();
+ }
+ string get_query(const kind_t& id) const {
+ if (parser) {
+ query_map_t::const_iterator i = parser->query_map.find(id);
+ if (i != parser->query_map.end())
+ return (*i).second;
+ }
+ return empty_string;
}
bool tokens_remaining() {
return parser && parser->tokens_remaining();
}
-
- virtual string text() {
- return print_to_str();
- }
};
} // namespace ledger