Loading...
Searching...
No Matches
query.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003-2023, John Wiegley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of New Artisans LLC nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
42#pragma once
43
44#include "predicate.h"
45
46namespace ledger {
47
49{
50protected:
51 class parser_t;
52
53public:
54 class lexer_t
55 {
56 friend class query_t;
57 friend class parser_t;
58
59 value_t::sequence_t::const_iterator begin;
60 value_t::sequence_t::const_iterator end;
61
62 string::const_iterator prev_arg_i;
63 string::const_iterator arg_i;
64 string::const_iterator arg_end;
65
66 bool consume_whitespace;
67 bool consume_next_arg;
68 bool multiple_args;
69
70 public:
71 struct token_t
72 {
103
105
118
120 if (this != &tok) {
121 kind = tok.kind;
122 value = tok.value;
123 }
124 return *this;
125 }
126
127 operator bool() const {
128 return kind != END_REACHED;
129 }
130
131 string to_string() const {
132 switch (kind) {
133 case UNKNOWN: return "UNKNOWN";
134 case LPAREN: return "LPAREN";
135 case RPAREN: return "RPAREN";
136 case TOK_NOT: return "TOK_NOT";
137 case TOK_AND: return "TOK_AND";
138 case TOK_OR: return "TOK_OR";
139 case TOK_EQ: return "TOK_EQ";
140 case TOK_CODE: return "TOK_CODE";
141 case TOK_PAYEE: return "TOK_PAYEE";
142 case TOK_NOTE: return "TOK_NOTE";
143 case TOK_ACCOUNT: return "TOK_ACCOUNT";
144 case TOK_META: return "TOK_META";
145 case TOK_EXPR: return "TOK_EXPR";
146 case TOK_SHOW: return "TOK_SHOW";
147 case TOK_ONLY: return "TOK_ONLY";
148 case TOK_BOLD: return "TOK_BOLD";
149 case TOK_FOR: return "TOK_FOR";
150 case TOK_SINCE: return "TOK_SINCE";
151 case TOK_UNTIL: return "TOK_UNTIL";
152 case TERM: return string("TERM(") + *value + ")";
153 case END_REACHED: return "END_REACHED";
154 }
155 }
156
157 string symbol() const {
158 switch (kind) {
159 case LPAREN: return "(";
160 case RPAREN: return ")";
161 case TOK_NOT: return "not";
162 case TOK_AND: return "and";
163 case TOK_OR: return "or";
164 case TOK_EQ: return "=";
165 case TOK_CODE: return "code";
166 case TOK_PAYEE: return "payee";
167 case TOK_NOTE: return "note";
168 case TOK_ACCOUNT: return "account";
169 case TOK_META: return "meta";
170 case TOK_EXPR: return "expr";
171 case TOK_SHOW: return "show";
172 case TOK_ONLY: return "only";
173 case TOK_BOLD: return "bold";
174 case TOK_FOR: return "for";
175 case TOK_SINCE: return "since";
176 case TOK_UNTIL: return "until";
177
178 case END_REACHED: return "<EOF>";
179
180 case TERM:
181 assert(false);
182 return "<TERM>";
183
184 case UNKNOWN:
185 assert(false);
186 return "<UNKNOWN>";
187 }
188#if !defined(__clang__)
189 return "<ERROR>";
190#endif
191 }
192
193 void expected(char wanted);
194 };
195
197
198 lexer_t(value_t::sequence_t::const_iterator _begin,
199 value_t::sequence_t::const_iterator _end,
200 bool _multiple_args = true)
201 : begin(_begin), end(_end),
202 consume_whitespace(false), consume_next_arg(false),
203 multiple_args(_multiple_args)
204 {
205 assert(begin != end);
206 arg_i = (*begin).as_string().begin();
207 arg_end = (*begin).as_string().end();
208
210 }
211 lexer_t(const lexer_t& lexer)
212 : begin(lexer.begin), end(lexer.end),
213 arg_i(lexer.arg_i), arg_end(lexer.arg_end),
214 consume_whitespace(lexer.consume_whitespace),
215 consume_next_arg(lexer.consume_next_arg),
216 multiple_args(lexer.multiple_args), token_cache(lexer.token_cache)
217 {
219 }
223
234
235 bool unbalanced_braces(const string str);
236 };
237
245
246 typedef std::map<kind_t, string> query_map_t;
247
248protected:
250 {
251 friend class query_t;
252
253 value_t args;
254 lexer_t lexer;
255 keep_details_t what_to_keep;
256 query_map_t query_map;
257
263 bool subexpression = false);
264
265 public:
268 bool multiple_args = true)
269 : args(_args), lexer(args.begin(), args.end(), multiple_args),
270 what_to_keep(_what_to_keep) {
271 TRACE_CTOR(query_t::parser_t, "value_t, keep_details_t, bool");
272 }
274 : args(other.args), lexer(other.lexer) {
276 }
280
282 return parse_query_expr(lexer_t::token_t::TOK_ACCOUNT, subexpression);
283 }
284
290 };
291
294
295public:
297 TRACE_CTOR(query_t, "");
298 }
303 query_t(const string& arg,
304 const keep_details_t& what_to_keep = keep_details_t(),
305 bool multiple_args = true) {
306 if (! arg.empty()) {
308 parse_args(temp.to_sequence(), what_to_keep, multiple_args);
309 }
310 TRACE_CTOR(query_t, "string, keep_details_t, bool");
311 }
312 query_t(const value_t& args,
313 const keep_details_t& what_to_keep = keep_details_t(),
314 bool multiple_args = true) {
315 if (! args.empty())
316 parse_args(args, what_to_keep, multiple_args);
317
318 TRACE_CTOR(query_t, "value_t, keep_details_t, bool");
319 }
320 virtual ~query_t() {
322 }
323
325 parse_args(const value_t& args,
326 const keep_details_t& what_to_keep = keep_details_t(),
327 bool multiple_args = true,
328 bool subexpression = false) {
329 if (! parser)
330 parser = parser_t(args, what_to_keep, multiple_args);
331 return parser->parse(subexpression);
332 }
333
334 bool has_query(const kind_t& id) const {
335 return parser && parser->query_map.find(id) != parser->query_map.end();
336 }
337 string get_query(const kind_t& id) const {
338 if (parser) {
339 query_map_t::const_iterator i = parser->query_map.find(id);
340 if (i != parser->query_map.end())
341 return (*i).second;
342 }
343 return empty_string;
344 }
345
347 return parser && parser->tokens_remaining();
348 }
349};
350
351} // namespace ledger
#define TRACE_DTOR(cls)
Definition utils.h:144
#define TRACE_CTOR(cls, args)
Definition utils.h:143
#define assert(x)
Definition utils.h:92
string empty_string
value_t string_value(const string &str="")
Definition value.h:949
std::string string
Definition utils.h:59
T & downcast(U &object)
Definition utils.h:468
intrusive_ptr< op_t > ptr_op_t
Definition expr.h:57
query_map_t predicates
Definition query.h:293
bool has_query(const kind_t &id) const
Definition query.h:334
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)
Definition query.h:325
optional< parser_t > parser
Definition query.h:292
string get_query(const kind_t &id) const
Definition query.h:337
virtual ~query_t()
Definition query.h:320
query_t(const value_t &args, const keep_details_t &what_to_keep=keep_details_t(), bool multiple_args=true)
Definition query.h:312
std::map< kind_t, string > query_map_t
Definition query.h:246
bool tokens_remaining()
Definition query.h:346
query_t(const string &arg, const keep_details_t &what_to_keep=keep_details_t(), bool multiple_args=true)
Definition query.h:303
query_t(const query_t &other)
Definition query.h:299
lexer_t(const lexer_t &lexer)
Definition query.h:211
void push_token(token_t tok)
Definition query.h:225
lexer_t(value_t::sequence_t::const_iterator _begin, value_t::sequence_t::const_iterator _end, bool _multiple_args=true)
Definition query.h:198
token_t peek_token(token_t::kind_t tok_context=token_t::UNKNOWN)
Definition query.h:229
token_t next_token(token_t::kind_t tok_context=token_t::UNKNOWN)
bool unbalanced_braces(const string str)
token_t & operator=(const token_t &tok)
Definition query.h:119
token_t(const token_t &tok)
Definition query.h:111
optional< string > value
Definition query.h:104
enum ledger::query_t::lexer_t::token_t::kind_t kind
token_t(kind_t _kind=UNKNOWN, const optional< string > &_value=none)
Definition query.h:106
expr_t::ptr_op_t parse(bool subexpression=false)
Definition query.h:281
parser_t(const value_t &_args, const keep_details_t &_what_to_keep=keep_details_t(), bool multiple_args=true)
Definition query.h:266
parser_t(const parser_t &other)
Definition query.h:273
Dynamic type representing various numeric types.
Definition value.h:83
bool empty() const
Definition value.h:922