From 47df7dd60e9209db3be91a7b29a91911ee4a846b Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 28 Oct 2009 18:40:31 -0400 Subject: Rewrote the report query parser It is now a full parser that parses report queries directly into value expression trees. These then get rendered into text so that other options may extend the expression. --- src/report.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/report.cc') diff --git a/src/report.cc b/src/report.cc index 62b54ad1..febe43e3 100644 --- a/src/report.cc +++ b/src/report.cc @@ -380,7 +380,7 @@ namespace { value_t::sequence_t::const_iterator end = args.value().as_sequence().end(); - string limit = args_to_predicate_expr(begin, end); + string limit = args_to_predicate(begin, end).text(); if (! limit.empty()) report.HANDLER(limit_).on(whence, limit); @@ -390,7 +390,7 @@ namespace { string display; if (begin != end) - display = args_to_predicate_expr(begin, end); + display = args_to_predicate(begin, end).text(); if (! display.empty()) report.HANDLER(display_).on(whence, display); -- cgit v1.2.3 From 218a333e8394aac053b7d7acce2a95deb56709a4 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 28 Oct 2009 23:07:03 -0400 Subject: Fixes to the new query expression parser --- src/precmd.cc | 7 +++++-- src/predicate.cc | 15 ++++++++++++--- src/predicate.h | 14 ++++++++++++-- src/report.cc | 7 +++++-- 4 files changed, 34 insertions(+), 9 deletions(-) (limited to 'src/report.cc') diff --git a/src/precmd.cc b/src/precmd.cc index 999261fa..d6ff1ba5 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -226,7 +226,10 @@ value_t args_command(call_scope_t& args) args.value().dump(out); out << std::endl << std::endl; - string predicate = args_to_predicate(begin, end).text(); + std::pair + info = args_to_predicate(begin, end); + begin = info.first; + string predicate = info.second.text(); call_scope_t sub_args(static_cast(args)); sub_args.push_back(string_value(predicate)); @@ -237,7 +240,7 @@ value_t args_command(call_scope_t& args) out << std::endl << _("====== Display predicate ======") << std::endl << std::endl; - predicate = args_to_predicate(begin, end).text(); + predicate = args_to_predicate(begin, end).second.text(); call_scope_t disp_sub_args(static_cast(args)); disp_sub_args.push_back(string_value(predicate)); diff --git a/src/predicate.cc b/src/predicate.cc index 4f712904..a39aece0 100644 --- a/src/predicate.cc +++ b/src/predicate.cc @@ -140,6 +140,12 @@ query_lexer_t::token_t query_lexer_t::next_token() return token_t(token_t::TOK_META); else if (ident == "data") return token_t(token_t::TOK_META); + else if (ident == "show") { + // The "show" keyword is special, and separates a limiting predicate + // from a display predicate. + ++begin; + return token_t(token_t::END_REACHED); + } else if (ident == "expr") { // The expr keyword takes the whole of the next string as its // argument. @@ -351,11 +357,14 @@ expr_t::ptr_op_t query_parser_t::parse() return parse_query_expr(query_lexer_t::token_t::TOK_ACCOUNT); } -expr_t args_to_predicate(value_t::sequence_t::const_iterator& begin, - value_t::sequence_t::const_iterator end) +std::pair +args_to_predicate(value_t::sequence_t::const_iterator begin, + value_t::sequence_t::const_iterator end) { query_parser_t parser(begin, end); - return expr_t(parser.parse()); + expr_t expr(parser.parse()); + return std::pair + (parser.begin(), expr); } } // namespace ledger diff --git a/src/predicate.h b/src/predicate.h index e1048f83..dc39f2f2 100644 --- a/src/predicate.h +++ b/src/predicate.h @@ -98,6 +98,8 @@ public: class query_lexer_t { + friend class query_parser_t; + value_t::sequence_t::const_iterator begin; value_t::sequence_t::const_iterator end; @@ -246,10 +248,18 @@ public: : lexer(begin, end) {} expr_t::ptr_op_t parse(); + + value_t::sequence_t::const_iterator begin() const { + return lexer.begin; + } + value_t::sequence_t::const_iterator end() const { + return lexer.end; + } }; -expr_t args_to_predicate(value_t::sequence_t::const_iterator& begin, - value_t::sequence_t::const_iterator end); +std::pair +args_to_predicate(value_t::sequence_t::const_iterator begin, + value_t::sequence_t::const_iterator end); } // namespace ledger diff --git a/src/report.cc b/src/report.cc index febe43e3..7755c911 100644 --- a/src/report.cc +++ b/src/report.cc @@ -380,8 +380,11 @@ namespace { value_t::sequence_t::const_iterator end = args.value().as_sequence().end(); - string limit = args_to_predicate(begin, end).text(); + std::pair + info = args_to_predicate(begin, end); + begin = info.first; + string limit = info.second.text(); if (! limit.empty()) report.HANDLER(limit_).on(whence, limit); @@ -390,7 +393,7 @@ namespace { string display; if (begin != end) - display = args_to_predicate(begin, end).text(); + display = args_to_predicate(begin, end).second.text(); if (! display.empty()) report.HANDLER(display_).on(whence, display); -- cgit v1.2.3 From 52433e56e562976887325ce48a6271abb82a89aa Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 28 Oct 2009 23:41:51 -0400 Subject: Fixed "show" keywords, and added // syntax --- src/precmd.cc | 14 +++++--------- src/predicate.cc | 36 ++++++++++++++++++++++++++++++++---- src/predicate.h | 44 ++++++++++++++++++++++++++++++++++++-------- src/report.cc | 20 +++++++++----------- 4 files changed, 82 insertions(+), 32 deletions(-) (limited to 'src/report.cc') diff --git a/src/precmd.cc b/src/precmd.cc index d6ff1ba5..590d2553 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -226,24 +226,20 @@ value_t args_command(call_scope_t& args) args.value().dump(out); out << std::endl << std::endl; - std::pair - info = args_to_predicate(begin, end); - begin = info.first; - string predicate = info.second.text(); + std::pair info = args_to_predicate(begin, end); call_scope_t sub_args(static_cast(args)); - sub_args.push_back(string_value(predicate)); + sub_args.push_back(string_value(info.first.text())); parse_command(sub_args); - if (begin != end) { + if (info.second.tokens_remaining()) { out << std::endl << _("====== Display predicate ======") << std::endl << std::endl; - predicate = args_to_predicate(begin, end).second.text(); - call_scope_t disp_sub_args(static_cast(args)); - disp_sub_args.push_back(string_value(predicate)); + disp_sub_args.push_back + (string_value(args_to_predicate(info.second).first.text())); parse_command(disp_sub_args); } diff --git a/src/predicate.cc b/src/predicate.cc index a39aece0..b3926116 100644 --- a/src/predicate.cc +++ b/src/predicate.cc @@ -64,6 +64,29 @@ query_lexer_t::token_t query_lexer_t::next_token() return next_token(); goto resume; + case '/': { + string pat; + bool found_end_slash = false; + for (++arg_i; arg_i != arg_end; ++arg_i) { + if (*arg_i == '\\') { + if (++arg_i == arg_end) + throw_(parse_error, _("Unexpected '\\' at end of pattern")); + } + else if (*arg_i == '/') { + ++arg_i; + found_end_slash = true; + break; + } + pat.push_back(*arg_i); + } + if (! found_end_slash) + throw_(parse_error, _("Expected '/' at end of pattern")); + if (pat.empty()) + throw_(parse_error, _("Match pattern is empty")); + + return token_t(token_t::TERM, pat); + } + case '(': ++arg_i; return token_t(token_t::LPAREN); case ')': ++arg_i; return token_t(token_t::RPAREN); case '&': ++arg_i; return token_t(token_t::TOK_AND); @@ -143,7 +166,7 @@ query_lexer_t::token_t query_lexer_t::next_token() else if (ident == "show") { // The "show" keyword is special, and separates a limiting predicate // from a display predicate. - ++begin; + DEBUG("pred.show", "string = " << (*begin).as_string()); return token_t(token_t::END_REACHED); } else if (ident == "expr") { @@ -357,14 +380,19 @@ expr_t::ptr_op_t query_parser_t::parse() return parse_query_expr(query_lexer_t::token_t::TOK_ACCOUNT); } -std::pair +std::pair args_to_predicate(value_t::sequence_t::const_iterator begin, value_t::sequence_t::const_iterator end) { query_parser_t parser(begin, end); expr_t expr(parser.parse()); - return std::pair - (parser.begin(), expr); + return std::pair(expr, parser); +} + +std::pair args_to_predicate(query_parser_t parser) +{ + expr_t expr(parser.parse()); + return std::pair(expr, parser); } } // namespace ledger diff --git a/src/predicate.h b/src/predicate.h index dc39f2f2..555fac05 100644 --- a/src/predicate.h +++ b/src/predicate.h @@ -106,7 +106,7 @@ class query_lexer_t string::const_iterator arg_i; string::const_iterator arg_end; - bool consume_whitespace; + bool consume_whitespace; public: struct token_t @@ -220,16 +220,33 @@ public: value_t::sequence_t::const_iterator _end) : begin(_begin), end(_end), consume_whitespace(false) { + TRACE_CTOR(query_lexer_t, ""); assert(begin != end); arg_i = (*begin).as_string().begin(); arg_end = (*begin).as_string().end(); } + query_lexer_t(const query_lexer_t& lexer) + : begin(lexer.begin), end(lexer.end), + arg_i(lexer.arg_i), arg_end(lexer.arg_end), + consume_whitespace(lexer.consume_whitespace), + token_cache(lexer.token_cache) + { + TRACE_CTOR(query_lexer_t, "copy"); + } + ~query_lexer_t() throw() { + TRACE_DTOR(query_lexer_t); + } token_t next_token(); void push_token(token_t tok) { assert(token_cache.kind == token_t::UNKNOWN); token_cache = tok; } + token_t peek_token() { + if (token_cache.kind == token_t::UNKNOWN) + token_cache = next_token(); + return token_cache; + } }; class query_parser_t @@ -245,22 +262,33 @@ class query_parser_t public: query_parser_t(value_t::sequence_t::const_iterator begin, value_t::sequence_t::const_iterator end) - : lexer(begin, end) {} + : lexer(begin, end) { + TRACE_CTOR(query_parser_t, ""); + } + query_parser_t(const query_parser_t& parser) + : lexer(parser.lexer) { + TRACE_CTOR(query_parser_t, "copy"); + } + ~query_parser_t() throw() { + TRACE_DTOR(query_parser_t); + } expr_t::ptr_op_t parse(); - value_t::sequence_t::const_iterator begin() const { - return lexer.begin; - } - value_t::sequence_t::const_iterator end() const { - return lexer.end; + bool tokens_remaining() { + query_lexer_t::token_t tok = lexer.peek_token(); + assert(tok.kind != query_lexer_t::token_t::UNKNOWN); + return tok.kind != query_lexer_t::token_t::END_REACHED; } }; -std::pair +std::pair args_to_predicate(value_t::sequence_t::const_iterator begin, value_t::sequence_t::const_iterator end); +std::pair +args_to_predicate(query_parser_t parser); + } // namespace ledger #endif // _PREDICATE_H diff --git a/src/report.cc b/src/report.cc index 7755c911..281057d3 100644 --- a/src/report.cc +++ b/src/report.cc @@ -380,26 +380,24 @@ namespace { value_t::sequence_t::const_iterator end = args.value().as_sequence().end(); - std::pair - info = args_to_predicate(begin, end); - begin = info.first; + std::pair info = args_to_predicate(begin, end); - string limit = info.second.text(); + string limit = info.first.text(); if (! limit.empty()) report.HANDLER(limit_).on(whence, limit); DEBUG("report.predicate", "Predicate = " << report.HANDLER(limit_).str()); - string display; - if (begin != end) - display = args_to_predicate(begin, end).second.text(); + if (info.second.tokens_remaining()) { + string display = args_to_predicate(info.second).first.text(); - if (! display.empty()) - report.HANDLER(display_).on(whence, display); + if (! display.empty()) + report.HANDLER(display_).on(whence, display); - DEBUG("report.predicate", - "Display predicate = " << report.HANDLER(display_).str()); + DEBUG("report.predicate", + "Display predicate = " << report.HANDLER(display_).str()); + } } (report.*report_method)(handler_ptr(handler)); -- cgit v1.2.3