diff options
Diffstat (limited to 'src/query.h')
-rw-r--r-- | src/query.h | 273 |
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 |