diff options
-rw-r--r-- | journal.cc | 37 | ||||
-rw-r--r-- | journal.h | 4 | ||||
-rw-r--r-- | main.cc | 10 | ||||
-rw-r--r-- | valexpr.cc | 54 | ||||
-rw-r--r-- | valexpr.h | 37 |
5 files changed, 94 insertions, 48 deletions
@@ -32,6 +32,7 @@ #include "journal.h" #include "utils.h" #include "valexpr.h" +#include "format.h" #include "mask.h" namespace ledger { @@ -639,42 +640,6 @@ bool journal_t::valid() const return true; } -void print_entry(std::ostream& out, const entry_base_t& entry_base, - const string& prefix) -{ - string print_format; - - if (dynamic_cast<const entry_t *>(&entry_base)) { - print_format = (prefix + "%D %X%C%P\n" + - prefix + " %-34A %12o\n%/" + - prefix + " %-34A %12o\n"); - } - else if (const auto_entry_t * entry = - dynamic_cast<const auto_entry_t *>(&entry_base)) { - out << "= " << entry->predicate.predicate.expr << '\n'; - print_format = prefix + " %-34A %12o\n"; - } - else if (const period_entry_t * entry = - dynamic_cast<const period_entry_t *>(&entry_base)) { - out << "~ " << entry->period_string << '\n'; - print_format = prefix + " %-34A %12o\n"; - } - else { - assert(false); - } - -#if 0 - format_entries formatter(out, print_format); - walk_transactions(const_cast<transactions_list&>(entry_base.transactions), - formatter); - formatter.flush(); - - clear_transaction_xdata cleaner; - walk_transactions(const_cast<transactions_list&>(entry_base.transactions), - cleaner); -#endif -} - void entry_context::describe(std::ostream& out) const throw() { if (! desc.empty()) @@ -252,7 +252,9 @@ class auto_entry_t : public entry_base_t public: item_predicate<transaction_t> predicate; - auto_entry_t(); + auto_entry_t() { + TRACE_CTOR(auto_entry_t, ""); + } auto_entry_t(const string& _predicate) : predicate(_predicate) { @@ -266,12 +266,11 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], // Are we handling the expr commands? Do so now. - expr::context_scope_t doc_scope(report, &xml_document); - if (verb == "expr") { value_expr expr(*arg); IF_INFO() { +#if 0 *out << "Value expression tree:" << std::endl; expr.dump(*out); *out << std::endl; @@ -279,9 +278,12 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], expr.print(*out, doc_scope); *out << std::endl << std::endl; *out << "Result of calculation: "; +#endif } +#if 0 *out << expr.calc(doc_scope).strip_annotations() << std::endl; +#endif return 0; } @@ -289,13 +291,13 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], // Apply transforms to the hierarchical document structure INFO_START(transforms, "Applied transforms"); - report.apply_transforms(doc_scope); + report.apply_transforms(*expr::global_scope); INFO_FINISH(transforms); // Create an argument scope containing the report command's // arguments, and then invoke the command. - xml::xpath_t::call_scope_t command_args(doc_scope); + expr::call_scope_t command_args(*expr::global_scope); for (strings_list::iterator i = arg; i != args.end(); i++) command_args.push_back(value_t(*i, true)); @@ -41,6 +41,29 @@ bool compute_amount(ptr_op_t expr, amount_t& amt, return true; } +void scope_t::define(const string& name, const value_t& val) { + define(name, op_t::wrap_value(val)); +} + +void symbol_scope_t::define(const string& name, ptr_op_t def) +{ + DEBUG("ledger.xpath.syms", "Defining '" << name << "' = " << def); + + std::pair<symbol_map::iterator, bool> result + = symbols.insert(symbol_map::value_type(name, def)); + if (! result.second) { + symbol_map::iterator i = symbols.find(name); + assert(i != symbols.end()); + symbols.erase(i); + + std::pair<symbol_map::iterator, bool> result2 + = symbols.insert(symbol_map::value_type(name, def)); + if (! result2.second) + throw_(compile_error, + "Redefinition of '" << name << "' in same scope"); + } +} + namespace { int count_leaves(ptr_op_t expr) { @@ -98,6 +121,37 @@ namespace { } } +ptr_op_t symbol_scope_t::lookup(const string& name) +{ + switch (name[0]) { +#if 0 + case 'l': + if (name == "last") + return WRAP_FUNCTOR(bind(xpath_fn_last, _1)); + break; + + case 'p': + if (name == "position") + return WRAP_FUNCTOR(bind(xpath_fn_position, _1)); + break; + + case 't': + if (name == "text") + return WRAP_FUNCTOR(bind(xpath_fn_text, _1)); + else if (name == "type") + return WRAP_FUNCTOR(bind(xpath_fn_type, _1)); +#endif + break; + } + + symbol_map::const_iterator i = symbols.find(name); + if (i != symbols.end()) + return (*i).second; + + return child_scope_t::lookup(name); +} + + void op_t::compute(value_t& result, const details_t& details, ptr_op_t context) const { @@ -15,6 +15,10 @@ class account_t; namespace expr { +DECLARE_EXCEPTION(error, parse_error); +DECLARE_EXCEPTION(error, compile_error); +DECLARE_EXCEPTION(error, calc_error); + #if 0 struct context_t { @@ -642,9 +646,12 @@ bool compute_amount(const ptr_op_t expr, amount_t& amt, #define PARSE_VALEXPR_NO_MIGRATE 0x04 #define PARSE_VALEXPR_NO_REDUCE 0x08 +ptr_op_t parse_boolean_expr(std::istream& in, scope_t * scope, + const short flags); + ptr_op_t parse_value_expr(std::istream& in, - scope_t * scope = NULL, - const short flags = PARSE_VALEXPR_RELAXED); + scope_t * scope = NULL, + const short flags = PARSE_VALEXPR_RELAXED); inline ptr_op_t parse_value_expr(const string& str, @@ -743,6 +750,25 @@ scope_t::find_scope<context_scope_t>(bool skip_this) { #define CONTEXT_SCOPE(scope_ref) \ FIND_SCOPE(context_scope_t, scope_ref) +inline ptr_op_t op_t::new_node(kind_t _kind, ptr_op_t _left, ptr_op_t _right) { + ptr_op_t node(new op_t(_kind)); + node->set_left(_left); + node->set_right(_right); + return node; +} + +inline ptr_op_t op_t::wrap_value(const value_t& val) { + ptr_op_t temp(new op_t(op_t::VALUE)); + temp->set_value(val); + return temp; +} + +inline ptr_op_t op_t::wrap_functor(const function_t& fobj) { + ptr_op_t temp(new op_t(op_t::FUNCTION)); + temp->set_function(fobj); + return temp; +} + } // namespace expr ////////////////////////////////////////////////////////////////////// @@ -866,15 +892,12 @@ inline value_t compute_total(const details_t& details = details_t()) { return total_expr->compute(details); } -expr::ptr_op_t parse_boolean_expr(std::istream& in, expr::scope_t * scope, - const short flags); - inline void parse_value_definition(const string& str, expr::scope_t * scope = NULL) { std::istringstream def(str); value_expr expr - (parse_boolean_expr(def, scope ? scope : expr::global_scope.get(), - PARSE_VALEXPR_RELAXED)); + (expr::parse_boolean_expr(def, scope ? scope : expr::global_scope.get(), + PARSE_VALEXPR_RELAXED)); } ////////////////////////////////////////////////////////////////////// |