diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | main.cc | 46 | ||||
-rw-r--r-- | option.cc | 16 | ||||
-rw-r--r-- | parsexp.cc | 1122 | ||||
-rw-r--r-- | parsexp.h | 59 | ||||
-rw-r--r-- | report.h | 4 | ||||
-rw-r--r-- | session.cc | 4 | ||||
-rw-r--r-- | valexpr.cc | 25 | ||||
-rw-r--r-- | valexpr.h | 32 | ||||
-rw-r--r-- | value.cc | 97 | ||||
-rw-r--r-- | value.h | 5 |
11 files changed, 170 insertions, 1241 deletions
@@ -10,6 +10,7 @@ .svn /.deps /.libs +/3.0 /AUTHORS /COPYING /ChangeLog @@ -45,6 +45,19 @@ #include <fdstream.hpp> #endif +namespace ledger { + value_t register_command(expr::call_scope_t& args) + { + expr::var_t<report_t> report(args, 0); + expr::var_t<std::ostream> ostream(args, 1); + + report->transactions_report + (xact_handler_ptr(new format_transactions + (*ostream, report->session.register_format))); + return true; + } +} + static int read_and_report(ledger::report_t& report, int argc, char * argv[], char * envp[]) { @@ -158,31 +171,29 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], value_expr expr(*arg); #if 0 - expr::context_scope_t doc_scope(report, &temp); - IF_INFO() { std::cout << "Value expression tree:" << std::endl; expr.dump(std::cout); std::cout << std::endl; std::cout << "Value expression parsed was:" << std::endl; - expr.print(std::cout, doc_scope); + expr.print(std::cout, report); std::cout << std::endl << std::endl; - expr.compile(doc_scope); + expr.compile(report); std::cout << "Value expression after compiling:" << std::endl; expr.dump(std::cout); std::cout << std::endl; std::cout << "Value expression is now:" << std::endl; - expr.print(std::cout, doc_scope); + expr.print(std::cout, report); std::cout << std::endl << std::endl; std::cout << "Result of calculation: "; } - std::cout << expr.calc(doc_scope).strip_annotations() << std::endl; + std::cout << expr.calc(report).strip_annotations() << std::endl; #endif return 0; @@ -218,8 +229,8 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], if (verb == "expr") { value_expr expr(*arg); - IF_INFO() { #if 0 + IF_INFO() { *out << "Value expression tree:" << std::endl; expr.dump(*out); *out << std::endl; @@ -227,10 +238,8 @@ 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 @@ -239,14 +248,13 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], // Read the command word and create a command object based on it + expr::function_t command; + if (verb == "register" || verb == "reg" || verb == "r") - report.transactions_report - (xact_handler_ptr(new format_transactions(*out, session.register_format))); - else if (verb == "balance" || verb == "bal" || verb == "b") - report.accounts_report - (acct_handler_ptr(new format_accounts(*out, session.balance_format, - report.display_predicate))); + command = register_command; #if 0 + else if (verb == "balance" || verb == "bal" || verb == "b") + command = balance_command(); else if (verb == "print" || verb == "p") command = print_command(); else if (verb == "equity") @@ -266,8 +274,8 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], else if (verb == "emacs" || verb == "lisp") command = emacs_command(); else if (verb == "xml") - command = bind(xml_command, _1); - ; + command = xml_command(); +#endif else if (verb == "expr") ; else if (verb == "xpath") @@ -289,6 +297,9 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], expr::call_scope_t command_args(report); + command_args.push_back(value_t(&report)); + command_args.push_back(value_t(out)); + for (strings_list::iterator i = arg; i != args.end(); i++) command_args.push_back(value_t(*i, true)); @@ -297,7 +308,6 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], command(command_args); INFO_FINISH(command); -#endif // Clean up memory, if it matters @@ -888,25 +888,25 @@ OPT_BEGIN(download, "Q") { } OPT_END(download); OPT_BEGIN(quantity, "O") { - ledger::amount_expr = "@a"; - ledger::total_expr = "@O"; + ledger::amount_expr = "a"; + ledger::total_expr = "O"; } OPT_END(quantity); OPT_BEGIN(basis, "B") { - ledger::amount_expr = "@b"; - ledger::total_expr = "@B"; + ledger::amount_expr = "b"; + ledger::total_expr = "B"; } OPT_END(basis); OPT_BEGIN(price, "I") { - ledger::amount_expr = "@i"; - ledger::total_expr = "@I"; + ledger::amount_expr = "i"; + ledger::total_expr = "I"; } OPT_END(price); OPT_BEGIN(market, "V") { report->show_revalued = true; - ledger::amount_expr = "@v"; - ledger::total_expr = "@V"; + ledger::amount_expr = "v"; + ledger::total_expr = "V"; } OPT_END(market); namespace { @@ -51,7 +51,7 @@ void parser_t::token_t::parse_ident(std::istream& in) } assert(in.good()); - kind = IDENT; + kind = IDENT; length = 0; char buf[256]; @@ -111,12 +111,6 @@ void parser_t::token_t::parse_ident(std::istream& in) value = true; } break; -#if 0 - case 'u': - if (std::strcmp(buf, "union") == 0) - kind = KW_UNION; - break; -#endif } if (kind == IDENT) @@ -155,12 +149,6 @@ void parser_t::token_t::next(std::istream& in, const flags_t flags) in.get(c); kind = AT_SYM; break; -#if 0 - case '$': - in.get(c); - kind = DOLLAR; - break; -#endif case '&': in.get(c); @@ -257,13 +245,6 @@ void parser_t::token_t::next(std::istream& in, const flags_t flags) kind = STAR; break; -#if 0 - case '/': - in.get(c); - kind = SLASH; - break; -#endif - case 'c': case 'C': case 'p': @@ -351,12 +332,6 @@ void parser_t::token_t::next(std::istream& in, const flags_t flags) kind = GREATER; break; -#if 0 - case '|': - in.get(c); - kind = PIPE; - break; -#endif case ',': in.get(c); kind = COMMA; @@ -522,86 +497,36 @@ parser_t::parse_value_term(std::istream& in, scope_t& scope, const flags_t tflag // An identifier followed by ( represents a function call tok = next_token(in, tflags); -#if 0 + if (tok.kind == token_t::LPAREN) { +#if 0 node = new op_t(op_t::FUNC_NAME); node->set_string(ident); ptr_op_t call_node(new op_t(op_t::O_CALL)); call_node->set_left(node); - call_node->set_right(parse_value_expr(in, scope, tflags | EXPR_PARSE_PARTIAL)); + call_node->set_right(parse_value_expr(in, scope, + tflags | EXPR_PARSE_PARTIAL)); tok = next_token(in, tflags); if (tok.kind != token_t::RPAREN) tok.unexpected(0xff, ')'); node = call_node; +#endif } else { if (std::isdigit(ident[0])) { - node = new op_t(op_t::ARG_INDEX); + node = new op_t(op_t::O_ARG); node->set_long(lexical_cast<unsigned int>(ident.c_str())); - } - else if (optional<node_t::nameid_t> id = - document_t::lookup_builtin_id(ident)) { - node = new op_t(op_t::NODE_ID); - node->set_name(*id); - } - else { - node = new op_t(op_t::NODE_NAME); + } else { + node = new op_t(op_t::O_LOOKUP); node->set_string(ident); } push_token(tok); } -#endif break; } -#if 0 - case token_t::AT_SYM: { - tok = next_token(in, tflags); - if (tok.kind != token_t::IDENT) - throw_(parse_error, "@ symbol must be followed by attribute name"); - - string ident = tok.value.as_string(); - if (optional<node_t::nameid_t> id = document_t::lookup_builtin_id(ident)) { - node = new op_t(op_t::ATTR_ID); - node->set_name(*id); - } - else { - node = new op_t(op_t::ATTR_NAME); - node->set_string(ident); - } - break; - } - - case token_t::DOLLAR: - tok = next_token(in, tflags); - if (tok.kind != token_t::IDENT) - throw parse_error("$ symbol must be followed by variable name"); - - node = new op_t(op_t::VAR_NAME); - node->set_string(tok.value.as_string()); - break; - - case token_t::DOT: - node = new op_t(op_t::NODE_ID); - node->set_name(document_t::CURRENT); - break; - case token_t::DOTDOT: - node = new op_t(op_t::NODE_ID); - node->set_name(document_t::PARENT); - break; - case token_t::SLASH: - node = new op_t(op_t::NODE_ID); - node->set_name(document_t::ROOT); - push_token(); - break; - case token_t::STAR: - node = new op_t(op_t::NODE_ID); - node->set_name(document_t::ALL); - break; -#endif - case token_t::LPAREN: node = new op_t(op_t::O_COMMA); node->set_left(parse_value_expr(in, scope, tflags | EXPR_PARSE_PARTIAL)); @@ -678,31 +603,6 @@ parser_t::parse_unary_expr(std::istream& in, scope_t& scope, return node; } -#if 0 -ptr_op_t -parser_t::parse_union_expr(std::istream& in, scope_t& scope, const flags_t tflags) const -{ - ptr_op_t node(parse_unary_expr(in, scope, tflags)); - - if (node) { - token_t& tok = next_token(in, tflags); - if (tok.kind == token_t::PIPE || tok.kind == token_t::KW_UNION) { - ptr_op_t prev(node); - node = new op_t(op_t::O_UNION); - node->set_left(prev); - node->set_right(parse_union_expr(in, scope, tflags)); - if (! node->right()) - throw_(parse_error, - tok.symbol << " operator not followed by argument"); - } else { - push_token(tok); - } - } - - return node; -} -#endif - ptr_op_t parser_t::parse_mul_expr(std::istream& in, scope_t& scope, const flags_t tflags) const { @@ -886,15 +786,6 @@ parser_t::parse_value_expr(std::istream& in, scope_t& scope, const flags_t tflag return node; } -#if 0 -bool print(std::ostream& out, op_t::print_context_t& context) const -{ - if (ptr) - ptr->print(out, context); - return true; -} -#endif - bool op_t::print(std::ostream& out, print_context_t& context) const { bool found = false; @@ -908,70 +799,11 @@ bool op_t::print(std::ostream& out, print_context_t& context) const switch (kind) { case VALUE: { - const value_t& value(as_value()); - switch (value.type()) { - case value_t::VOID: - out << "<VOID>"; - break; - case value_t::BOOLEAN: - if (value) - out << "1"; - else - out << "0"; - break; - case value_t::INTEGER: - out << value; - break; - case value_t::AMOUNT: - if (! context.relaxed) - out << '{'; - out << value; - if (! context.relaxed) - out << '}'; - break; - case value_t::BALANCE: - case value_t::BALANCE_PAIR: - assert(false); - break; - case value_t::DATETIME: - out << '[' << value << ']'; - break; - case value_t::STRING: - out << '"' << value << '"'; - break; - -#if 0 - case value_t::XML_NODE: - out << '<' << value << '>'; - break; -#endif - case value_t::POINTER: - out << '&' << value; - break; - case value_t::SEQUENCE: - out << '~' << value << '~'; - break; - } + as_value().print(out, context.relaxed); break; } #if 0 - case ATTR_ID: - out << '@'; - // fall through... - case NODE_ID: { - context_scope_t& node_scope(CONTEXT_SCOPE(context.scope)); - if (optional<const char *> name = - node_scope.xml_node().document().lookup_name(as_name())) - out << *name; - else - out << '#' << as_name(); - break; - } -#endif - -#if 0 - case NODE_NAME: case FUNC_NAME: out << as_string(); break; @@ -1004,16 +836,6 @@ bool op_t::print(std::ostream& out, print_context_t& context) const found = true; break; -#if 0 - case O_UNION: - if (left() && left()->print(out, context)) - found = true; - out << " | "; - if (right() && right()->print(out, context)) - found = true; - break; -#endif - case O_ADD: out << "("; if (left() && left()->print(out, context)) @@ -1142,29 +964,6 @@ bool op_t::print(std::ostream& out, print_context_t& context) const found = true; out << ")"; break; - - case O_FIND: - if (left() && left()->print(out, context)) - found = true; - out << "/"; - if (right() && right()->print(out, context)) - found = true; - break; - case O_RFIND: - if (left() && left()->print(out, context)) - found = true; - out << "//"; - if (right() && right()->print(out, context)) - found = true; - break; - case O_PRED: - if (left() && left()->print(out, context)) - found = true; - out << "["; - if (right() && right()->print(out, context)) - found = true; - out << "]"; - break; #endif case LAST: @@ -1200,19 +999,9 @@ void op_t::dump(std::ostream& out, const int depth) const break; #if 0 - case NODE_NAME: - out << "NODE_NAME - " << as_string(); - break; - case NODE_ID: - out << "NODE_ID - " << as_name(); - break; - case ATTR_NAME: out << "ATTR_NAME - " << as_string(); break; - case ATTR_ID: - out << "ATTR_ID - " << as_name(); - break; case FUNC_NAME: out << "FUNC_NAME - " << as_string(); @@ -1238,10 +1027,6 @@ void op_t::dump(std::ostream& out, const int depth) const case O_NOT: out << "O_NOT"; break; case O_NEG: out << "O_NEG"; break; -#if 0 - case O_UNION: out << "O_UNION"; break; -#endif - case O_ADD: out << "O_ADD"; break; case O_SUB: out << "O_SUB"; break; case O_MUL: out << "O_MUL"; break; @@ -1259,12 +1044,6 @@ void op_t::dump(std::ostream& out, const int depth) const case O_COMMA: out << "O_COMMA"; break; -#if 0 - case O_FIND: out << "O_FIND"; break; - case O_RFIND: out << "O_RFIND"; break; - case O_PRED: out << "O_PRED"; break; -#endif - case LAST: default: assert(false); @@ -1284,886 +1063,5 @@ void op_t::dump(std::ostream& out, const int depth) const } } -#if 0 -ptr_op_t parse_value_term(std::istream& in, scope_t * scope, - const short flags) -{ - value_expr node; - - char buf[256]; - char c = peek_next_nonws(in); - - if (flags & PARSE_VALEXPR_RELAXED) { - if (c == '@') { - in.get(c); - c = peek_next_nonws(in); - } - else if (! (c == '(' || c == '[' || c == '{' || c == '/')) { - amount_t temp; - char prev_c = c; - unsigned long pos = 0; - // When in relaxed parsing mode, we do want to migrate commodity - // flags, so that any precision specified by the user updates - // the current maximum precision displayed. - try { - pos = (long)in.tellg(); - - unsigned char parse_flags = 0; - if (flags & PARSE_VALEXPR_NO_MIGRATE) - parse_flags |= AMOUNT_PARSE_NO_MIGRATE; - if (flags & PARSE_VALEXPR_NO_REDUCE) - parse_flags |= AMOUNT_PARSE_NO_REDUCE; - - temp.parse(in, parse_flags); - } - catch (amount_error * err) { - // If the amount had no commodity, it must be an unambiguous - // variable reference - if (std::strcmp(err->what(), "No quantity specified for amount") == 0) { - in.clear(); - in.seekg(pos, std::ios::beg); - c = prev_c; - goto parse_ident; - } else { - throw err; - } - } - node.reset(new op_t(op_t::VALUE)); - node->set_value(temp); - goto parsed; - } - } - - parse_ident: - if (std::isdigit(c) || c == '.') { - READ_INTO(in, buf, 255, c, std::isdigit(c) || c == '.'); - amount_t temp; - temp.parse(buf, AMOUNT_PARSE_NO_MIGRATE); - node.reset(new op_t(op_t::VALUE)); - node->set_value(temp); - goto parsed; - } - else if (std::isalnum(c) || c == '_') { - bool have_args = false; - istream_pos_type beg; - - READ_INTO(in, buf, 255, c, std::isalnum(c) || c == '_'); - c = peek_next_nonws(in); - if (c == '(') { - in.get(c); - beg = in.tellg(); - - int paren_depth = 0; - while (! in.eof()) { - in.get(c); - if (c == '(' || c == '{' || c == '[') - paren_depth++; - else if (c == ')' || c == '}' || c == ']') { - if (paren_depth == 0) - break; - paren_depth--; - } - } - if (c != ')') - unexpected(c, ')'); - - have_args = true; - c = peek_next_nonws(in); - } - - bool definition = false; - if (c == '=') { - in.get(c); - if ((flags & EXPR_PARSE_NO_ASSIGN) || - peek_next_nonws(in) == '=') { - in.unget(); - c = '\0'; - } else { - definition = true; - } - } - - if (definition) { - std::auto_ptr<call_scope_t> params(new call_scope_t(*scope)); - - long arg_index = 0; - if (have_args) { - bool done = false; - - in.clear(); - in.seekg(beg, std::ios::beg); - while (! done && ! in.eof()) { - char ident[32]; - READ_INTO(in, ident, 31, c, std::isalnum(c) || c == '_'); - - c = peek_next_nonws(in); - in.get(c); - if (c != ',' && c != ')') - unexpected(c, ')'); - else if (c == ')') - done = true; - - // Define the parameter so that on lookup the parser will find - // an O_ARG value. - node.reset(new op_t(op_t::O_ARG)); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(arg_index++); - params->define(ident, node.release()); - } - - if (peek_next_nonws(in) != '=') { - in.get(c); - unexpected(c, '='); - } - in.get(c); - } - -#if 0 - // Define the value associated with the defined identifier - value_expr def(parse_boolean_expr(in, scope, params.get(), flags)); - if (! def.get()) - throw new value_expr_error(string("Definition failed for '") + buf + "'"); - - node.reset(new op_t(op_t::O_DEF)); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(arg_index); - node->set_right(def.release()); -#endif - - scope->define(buf, node.get()); - } else { - assert(scope); - ptr_op_t def = scope->lookup(buf); - if (! def) { - if (buf[1] == '\0' && - (buf[0] == 'c' || buf[0] == 'C' || buf[0] == 'p' || - buf[0] == 'w' || buf[0] == 'W' || buf[0] == 'e')) { - in.unget(); - goto find_term; - } - throw new value_expr_error(string("Unknown identifier '") + - buf + "'"); - } - else if (def->kind == op_t::O_DEF) { - node.reset(new op_t(op_t::O_REF)); - node->set_left(def->right()); - - unsigned int count = 0; - if (have_args) { - in.clear(); - in.seekg(beg, std::ios::beg); - value_expr args - (parse_value_expr(in, scope, flags | PARSE_VALEXPR_PARTIAL)); - - if (peek_next_nonws(in) != ')') { - in.get(c); - unexpected(c, ')'); - } - in.get(c); - - if (args.get()) { - count = count_leaves(args.get()); - node->set_right(args.release()); - } - } - - if (count != def->left()->as_long()) { - std::ostringstream errmsg; - errmsg << "Wrong number of arguments to '" << buf - << "': saw " << count - << ", wanted " << def->left()->as_long(); - throw new value_expr_error(errmsg.str()); - } - } - else { - node.reset(def); - } - } - goto parsed; - } - - find_term: - in.get(c); - switch (c) { - // Functions - case '^': - node.reset(new op_t(op_t::F_PARENT)); - node->set_left(parse_value_term(in, scope, flags)); - break; - - // Other - case '{': { - amount_t temp; - temp.parse(in, AMOUNT_PARSE_NO_MIGRATE); - in.get(c); - if (c != '}') - unexpected(c, '}'); - - node.reset(new op_t(op_t::VALUE)); - node->set_value(temp); - break; - } - - case '(': { - std::auto_ptr<symbol_scope_t> locals(new symbol_scope_t(*scope)); - node.reset(parse_value_expr(in, locals.get(), - flags | PARSE_VALEXPR_PARTIAL)); - in.get(c); - if (c != ')') - unexpected(c, ')'); - break; - } - - case '[': { - READ_INTO(in, buf, 255, c, c != ']'); - if (c != ']') - unexpected(c, ']'); - in.get(c); - - interval_t timespan(buf); - node.reset(new op_t(op_t::VALUE)); - node->set_value(timespan.first()); - break; - } - - default: - in.unget(); - break; - } - - parsed: - return node.release(); -} - -void init_value_expr() -{ - global_scope.reset(new symbol_scope_t()); - symbol_scope_t * globals = global_scope.get(); - - ptr_op_t node; - - // Basic terms - node = new op_t(op_t::F_NOW); - globals->define("m", node); - globals->define("now", node); - globals->define("today", node); - - node = new op_t(op_t::AMOUNT); - globals->define("a", node); - globals->define("amount", node); - - node = new op_t(op_t::PRICE); - globals->define("i", node); - globals->define("price", node); - - node = new op_t(op_t::COST); - globals->define("b", node); - globals->define("cost", node); - - node = new op_t(op_t::DATE); - globals->define("d", node); - globals->define("date", node); - - node = new op_t(op_t::ACT_DATE); - globals->define("act_date", node); - globals->define("actual_date", node); - - node = new op_t(op_t::EFF_DATE); - globals->define("eff_date", node); - globals->define("effective_date", node); - - node = new op_t(op_t::CLEARED); - globals->define("X", node); - globals->define("cleared", node); - - node = new op_t(op_t::PENDING); - globals->define("Y", node); - globals->define("pending", node); - - node = new op_t(op_t::REAL); - globals->define("R", node); - globals->define("real", node); - - node = new op_t(op_t::ACTUAL); - globals->define("L", node); - globals->define("actual", node); - - node = new op_t(op_t::INDEX); - globals->define("n", node); - globals->define("index", node); - - node = new op_t(op_t::COUNT); - globals->define("N", node); - globals->define("count", node); - - node = new op_t(op_t::DEPTH); - globals->define("l", node); - globals->define("depth", node); - - node = new op_t(op_t::TOTAL); - globals->define("O", node); - globals->define("total", node); - - node = new op_t(op_t::PRICE_TOTAL); - globals->define("I", node); - globals->define("total_price", node); - - node = new op_t(op_t::COST_TOTAL); - globals->define("B", node); - globals->define("total_cost", node); - - // Relating to format_t - globals->define("t", ptr_op_t(new op_t(op_t::VALUE_EXPR))); - globals->define("T", ptr_op_t(new op_t(op_t::TOTAL_EXPR))); - - // Functions - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_ABS)); - globals->define("U", node); - globals->define("abs", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_ROUND)); - globals->define("round", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_QUANTITY)); - globals->define("S", node); - globals->define("quant", node); - globals->define("quantity", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_COMMODITY)); - globals->define("comm", node); - globals->define("commodity", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(2); - node->set_right(new op_t(op_t::F_SET_COMMODITY)); - globals->define("setcomm", node); - globals->define("set_commodity", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_ARITH_MEAN)); - globals->define("A", node); - globals->define("avg", node); - globals->define("mean", node); - globals->define("average", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(2); - node->set_right(new op_t(op_t::F_VALUE)); - globals->define("P", node); - - parse_value_definition("@value=@P(@t,@m)", globals); - parse_value_definition("@total_value=@P(@T,@m)", globals); - parse_value_definition("@valueof(x)=@P(@x,@m)", globals); - parse_value_definition("@datedvalueof(x,y)=@P(@x,@y)", globals); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_PRICE)); - globals->define("priceof", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_DATE)); - globals->define("dateof", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(2); - node->set_right(new op_t(op_t::F_DATECMP)); - globals->define("datecmp", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_YEAR)); - globals->define("yearof", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_MONTH)); - globals->define("monthof", node); - - node = new op_t(op_t::O_DEF); - node->set_left(new op_t(op_t::ARG_INDEX)); - node->left()->set_long(1); - node->set_right(new op_t(op_t::F_DAY)); - globals->define("dayof", node); - - parse_value_definition("@year=@yearof(@d)", globals); - parse_value_definition("@month=@monthof(@d)", globals); - parse_value_definition("@day=@dayof(@d)", globals); - - // Macros - node = parse_value_expr("@P(@a,@d)"); - globals->define("v", node); - globals->define("market", node); - - node = parse_value_expr("@P(@O,@d)"); - globals->define("V", node); - globals->define("total_market", node); - - node = parse_value_expr("@v-@b"); - globals->define("g", node); - globals->define("gain", node); - - node = parse_value_expr("@V-@B"); - globals->define("G", node); - globals->define("total_gain", node); - - parse_value_definition("@min(x,y)=@x<@y?@x:@y", globals); - parse_value_definition("@max(x,y)=@x>@y?@x:@y", globals); -} - -bool print_value_expr(std::ostream& out, - const ptr_op_t node, - const bool relaxed, - const ptr_op_t op_to_find, - unsigned long * start_pos, - unsigned long * end_pos) -{ - bool found = false; - - if (start_pos && node == op_to_find) { - *start_pos = (long)out.tellp() - 1; - found = true; - } - - string symbol; - - switch (node->kind) { - case op_t::ARG_INDEX: - out << node->as_long(); - break; - - case op_t::VALUE: - switch (node->as_value().type()) { - case value_t::BOOLEAN: - assert(false); - break; - case value_t::DATETIME: - out << '[' << node->as_value().as_datetime() << ']'; - break; - case value_t::INTEGER: - case value_t::AMOUNT: - if (! relaxed) - out << '{'; - out << node->as_value(); - if (! relaxed) - out << '}'; - break; - //case value_t::BALANCE: - //case value_t::BALANCE_PAIR: - default: - assert(false); - break; - } - break; - - case op_t::AMOUNT: - symbol = "amount"; break; - case op_t::PRICE: - symbol = "price"; break; - case op_t::COST: - symbol = "cost"; break; - case op_t::DATE: - symbol = "date"; break; - case op_t::ACT_DATE: - symbol = "actual_date"; break; - case op_t::EFF_DATE: - symbol = "effective_date"; break; - case op_t::CLEARED: - symbol = "cleared"; break; - case op_t::PENDING: - symbol = "pending"; break; - case op_t::REAL: - symbol = "real"; break; - case op_t::ACTUAL: - symbol = "actual"; break; - case op_t::INDEX: - symbol = "index"; break; - case op_t::COUNT: - symbol = "count"; break; - case op_t::DEPTH: - symbol = "depth"; break; - case op_t::TOTAL: - symbol = "total"; break; - case op_t::PRICE_TOTAL: - symbol = "total_price"; break; - case op_t::COST_TOTAL: - symbol = "total_cost"; break; - case op_t::F_NOW: - symbol = "now"; break; - - case op_t::VALUE_EXPR: - if (print_value_expr(out, amount_expr.get(), relaxed, - op_to_find, start_pos, end_pos)) - found = true; - break; - case op_t::TOTAL_EXPR: - if (print_value_expr(out, total_expr.get(), relaxed, - op_to_find, start_pos, end_pos)) - found = true; - break; - - case op_t::F_ARITH_MEAN: - symbol = "average"; break; - case op_t::F_ABS: - symbol = "abs"; break; - case op_t::F_QUANTITY: - symbol = "quantity"; break; - case op_t::F_COMMODITY: - symbol = "commodity"; break; - case op_t::F_SET_COMMODITY: - symbol = "set_commodity"; break; - case op_t::F_VALUE: - symbol = "valueof"; break; - case op_t::F_PRICE: - symbol = "priceof"; break; - case op_t::F_DATE: - symbol = "dateof"; break; - case op_t::F_DATECMP: - symbol = "datecmp"; break; - case op_t::F_YEAR: - symbol = "yearof"; break; - case op_t::F_MONTH: - symbol = "monthof"; break; - case op_t::F_DAY: - symbol = "dayof"; break; - -#if 0 - case op_t::F_CODE_MASK: - out << "c/" << node->mask->expr.str() << "/"; - break; - case op_t::F_PAYEE_MASK: - out << "p/" << node->mask->expr.str() << "/"; - break; - case op_t::F_NOTE_MASK: - out << "e/" << node->mask->expr.str() << "/"; - break; - case op_t::F_ACCOUNT_MASK: - out << "W/" << node->mask->expr.str() << "/"; - break; - case op_t::F_SHORT_ACCOUNT_MASK: - out << "w/" << node->mask->expr.str() << "/"; - break; - case op_t::F_COMMODITY_MASK: - out << "C/" << node->mask->expr.str() << "/"; - break; -#endif - - case op_t::O_NOT: - out << "!"; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - break; - case op_t::O_NEG: - out << "-"; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - break; - case op_t::O_PERC: - out << "%"; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - break; - - case op_t::O_ARG: - out << "@arg" << node->as_long(); - break; - case op_t::O_DEF: - out << "<def args=\""; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << "\" value=\""; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << "\">"; - break; - - case op_t::O_REF: - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - if (node->right()) { - out << "("; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - } - break; - - case op_t::O_COM: - if (node->left() && - print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ", "; - if (node->right() && - print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - break; - case op_t::O_QUES: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " ? "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_COL: - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " : "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - break; - - case op_t::O_AND: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " & "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_OR: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " | "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - - case op_t::O_NEQ: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " != "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_EQ: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " == "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_LT: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " < "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_LTE: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " <= "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_GT: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " > "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_GTE: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " >= "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - - case op_t::O_ADD: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " + "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_SUB: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " - "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_MUL: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " * "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - case op_t::O_DIV: - out << "("; - if (print_value_expr(out, node->left(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << " / "; - if (print_value_expr(out, node->right(), relaxed, op_to_find, start_pos, end_pos)) - found = true; - out << ")"; - break; - - case op_t::LAST: - default: - assert(false); - break; - } - - if (! symbol.empty()) { - if (amount_t::current_pool->find(symbol)) - out << '@'; - out << symbol; - } - - if (end_pos && node == op_to_find) - *end_pos = (long)out.tellp() - 1; - - return found; -} - -void dump_value_expr(std::ostream& out, const ptr_op_t node, - const int depth) -{ - out.setf(std::ios::left); - out.width(10); - out << node << " "; - - for (int i = 0; i < depth; i++) - out << " "; - - switch (node->kind) { - case op_t::ARG_INDEX: - out << "ARG_INDEX - " << node->as_long(); - break; - case op_t::VALUE: - out << "VALUE - " << node->as_value(); - break; - - case op_t::AMOUNT: out << "AMOUNT"; break; - case op_t::PRICE: out << "PRICE"; break; - case op_t::COST: out << "COST"; break; - case op_t::DATE: out << "DATE"; break; - case op_t::ACT_DATE: out << "ACT_DATE"; break; - case op_t::EFF_DATE: out << "EFF_DATE"; break; - case op_t::CLEARED: out << "CLEARED"; break; - case op_t::PENDING: out << "PENDING"; break; - case op_t::REAL: out << "REAL"; break; - case op_t::ACTUAL: out << "ACTUAL"; break; - case op_t::INDEX: out << "INDEX"; break; - case op_t::COUNT: out << "COUNT"; break; - case op_t::DEPTH: out << "DEPTH"; break; - case op_t::TOTAL: out << "TOTAL"; break; - case op_t::PRICE_TOTAL: out << "PRICE_TOTAL"; break; - case op_t::COST_TOTAL: out << "COST_TOTAL"; break; - - case op_t::VALUE_EXPR: out << "VALUE_EXPR"; break; - case op_t::TOTAL_EXPR: out << "TOTAL_EXPR"; break; - - case op_t::F_NOW: out << "F_NOW"; break; - case op_t::F_ARITH_MEAN: out << "F_ARITH_MEAN"; break; - case op_t::F_ABS: out << "F_ABS"; break; - case op_t::F_QUANTITY: out << "F_QUANTITY"; break; - case op_t::F_COMMODITY: out << "F_COMMODITY"; break; - case op_t::F_SET_COMMODITY: out << "F_SET_COMMODITY"; break; - case op_t::F_CODE_MASK: out << "F_CODE_MASK"; break; - case op_t::F_PAYEE_MASK: out << "F_PAYEE_MASK"; break; - case op_t::F_NOTE_MASK: out << "F_NOTE_MASK"; break; - case op_t::F_ACCOUNT_MASK: - out << "F_ACCOUNT_MASK"; break; - case op_t::F_SHORT_ACCOUNT_MASK: - out << "F_SHORT_ACCOUNT_MASK"; break; - case op_t::F_COMMODITY_MASK: - out << "F_COMMODITY_MASK"; break; - case op_t::F_VALUE: out << "F_VALUE"; break; - case op_t::F_PRICE: out << "F_PRICE"; break; - case op_t::F_DATE: out << "F_DATE"; break; - case op_t::F_DATECMP: out << "F_DATECMP"; break; - case op_t::F_YEAR: out << "F_YEAR"; break; - case op_t::F_MONTH: out << "F_MONTH"; break; - case op_t::F_DAY: out << "F_DAY"; break; - - case op_t::O_NOT: out << "O_NOT"; break; - case op_t::O_ARG: out << "O_ARG"; break; - case op_t::O_DEF: out << "O_DEF"; break; - case op_t::O_REF: out << "O_REF"; break; - case op_t::O_COM: out << "O_COM"; break; - case op_t::O_QUES: out << "O_QUES"; break; - case op_t::O_COL: out << "O_COL"; break; - case op_t::O_AND: out << "O_AND"; break; - case op_t::O_OR: out << "O_OR"; break; - case op_t::O_NEQ: out << "O_NEQ"; break; - case op_t::O_EQ: out << "O_EQ"; break; - case op_t::O_LT: out << "O_LT"; break; - case op_t::O_LTE: out << "O_LTE"; break; - case op_t::O_GT: out << "O_GT"; break; - case op_t::O_GTE: out << "O_GTE"; break; - case op_t::O_NEG: out << "O_NEG"; break; - case op_t::O_ADD: out << "O_ADD"; break; - case op_t::O_SUB: out << "O_SUB"; break; - case op_t::O_MUL: out << "O_MUL"; break; - case op_t::O_DIV: out << "O_DIV"; break; - case op_t::O_PERC: out << "O_PERC"; break; - - case op_t::LAST: - default: - assert(false); - break; - } - - out << " (" << node->refc << ')' << std::endl; - - if (node->kind > op_t::TERMINALS) { - dump_value_expr(out, node->left(), depth + 1); - if (node->right()) - dump_value_expr(out, node->right(), depth + 1); - } -} - -#endif - } // namespace expr } // namespace ledger @@ -95,11 +95,6 @@ private: KW_OR, KW_MOD, -#if 0 - PIPE, // | - KW_UNION, -#endif - COMMA, // , TOK_EOF, @@ -113,13 +108,6 @@ private: explicit token_t() : kind(UNKNOWN), length(0) { TRACE_CTOR(token_t, ""); } -#if 0 - token_t(const token_t& other) { - assert(false); - TRACE_CTOR(token_t, "copy"); - *this = other; - } -#endif ~token_t() throw() { TRACE_DTOR(token_t); } @@ -166,29 +154,16 @@ private: assert(&tok == &lookahead); use_lookahead = true; } + void push_token() const { use_lookahead = true; } -public: - value_expr expr; - -private: ptr_op_t parse_value_term(std::istream& in, scope_t& scope, const flags_t flags) const; -#if 0 - ptr_op_t parse_predicate_expr(std::istream& in, scope_t& scope, - const flags_t flags) const; - ptr_op_t parse_path_expr(std::istream& in, scope_t& scope, - const flags_t flags) const; -#endif ptr_op_t parse_unary_expr(std::istream& in, scope_t& scope, const flags_t flags) const; -#if 0 - ptr_op_t parse_union_expr(std::istream& in, scope_t& scope, - const flags_t flags) const; -#endif ptr_op_t parse_mul_expr(std::istream& in, scope_t& scope, const flags_t flags) const; ptr_op_t parse_add_expr(std::istream& in, scope_t& scope, @@ -204,17 +179,18 @@ private: ptr_op_t parse_value_expr(std::istream& in, scope_t& scope, const flags_t flags) const; - value_expr& parse_expr(std::istream& in, string& str, - scope_t& scope, const flags_t flags) { + value_expr parse_expr(std::istream& in, string& str, + scope_t& scope, const flags_t flags) { try { ptr_op_t top_node = parse_value_expr(in, scope, flags); - expr = value_expr(top_node, str); if (use_lookahead) { use_lookahead = false; lookahead.rewind(in); } lookahead.clear(); + + return value_expr(top_node, str); } catch (error * err) { err->context.push_back @@ -222,48 +198,37 @@ private: "While parsing value expression:")); throw err; } - - return expr; } public: parser_t() : use_lookahead(false) {} - value_expr& parse(std::istream& in, - const flags_t flags = EXPR_PARSE_RELAXED) + value_expr parse(std::istream& in, + const flags_t flags = EXPR_PARSE_RELAXED) { return parse_expr(in, empty_string, *global_scope, flags); } - value_expr& parse(std::istream& in, scope_t& scope, - const flags_t flags = EXPR_PARSE_RELAXED) + value_expr parse(std::istream& in, scope_t& scope, + const flags_t flags = EXPR_PARSE_RELAXED) { return parse_expr(in, empty_string, scope, flags); } - value_expr& parse(string& str, const flags_t flags = EXPR_PARSE_RELAXED) + value_expr parse(string& str, const flags_t flags = EXPR_PARSE_RELAXED) { std::istringstream stream(str); return parse_expr(stream, str, *global_scope, flags); } - value_expr& parse(string& str, scope_t& scope, - const flags_t flags = EXPR_PARSE_RELAXED) + value_expr parse(string& str, scope_t& scope, + const flags_t flags = EXPR_PARSE_RELAXED) { std::istringstream stream(str); return parse_expr(stream, str, scope, flags); } }; -void dump(std::ostream& out, const ptr_op_t node, const int depth = 0); - -bool print(std::ostream& out, - const ptr_op_t node, - const bool relaxed = true, - const ptr_op_t node_to_find = NULL, - unsigned long * start_pos = NULL, - unsigned long * end_pos = NULL); - } // namespace expr } // namespace ledger @@ -168,8 +168,8 @@ public: eval("t=total,TOT=0,T()=(TOT=TOT+t,TOT)"); #endif - value_expr::amount_expr.reset(new value_expr("@a")); - value_expr::total_expr.reset(new value_expr("@O")); + value_expr::amount_expr.reset(new value_expr("a")); + value_expr::total_expr.reset(new value_expr("O")); } virtual ~report_t() { @@ -86,9 +86,9 @@ session_t::session_t() equity_format ("\n%D %Y%C%P\n%/ %-34W %12t\n"), plot_amount_format - ("%D %(@S(@t))\n"), + ("%D %(S(t))\n"), plot_total_format - ("%D %(@S(@T))\n"), + ("%D %(S(T))\n"), write_hdr_format ("%d %Y%C%P\n"), write_xact_format @@ -163,26 +163,17 @@ namespace { } } +value_t get_amount(scope_t& scope) +{ + assert("I can't get the amount!"); +} + 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 + case 'a': + if (name[1] == '\0' || name == "amount") + return WRAP_FUNCTOR(bind(get_amount, _1)); break; } @@ -449,6 +449,7 @@ public: O_DEF, O_REF, O_ARG, + O_LOOKUP, LAST }; @@ -902,6 +903,37 @@ public: return temp; } +#if 0 + void compile(scope_t& scope) { + if (ptr.get()) + ptr = ptr->compile(scope); + } + + value_t calc(scope_t& scope) const { + if (ptr.get()) + return ptr->calc(scope); + return NULL_VALUE; + } + + static value_t eval(const string& _expr, scope_t& scope) { + return xpath_t(_expr).calc(scope); + } + + path_iterator_t find_all(scope_t& scope) { + return path_iterator_t(*this, scope); + } + + void print(std::ostream& out, scope_t& scope) const { + op_t::print_context_t context(scope); + print(out, context); + } + + void dump(std::ostream& out) const { + if (ptr) + ptr->dump(out, 0); + } +#endif + friend bool print_value_expr(std::ostream& out, const expr::ptr_op_t node, const expr::ptr_op_t node_to_find, @@ -1482,8 +1482,8 @@ value_t& value_t::add(const amount_t& amount, const optional<amount_t>& tcost) return *this; } -void value_t::print(std::ostream& out, const int first_width, - const int latter_width) const +void value_t::dump(std::ostream& out, const int first_width, + const int latter_width) const { switch (type()) { case VOID: @@ -1523,7 +1523,7 @@ void value_t::print(std::ostream& out, const int first_width, else out << ", "; - value.print(out, first_width, latter_width); + value.dump(out, first_width, latter_width); } out << ')'; break; @@ -1541,6 +1541,66 @@ void value_t::print(std::ostream& out, const int first_width, } } +void value_t::print(std::ostream& out, const bool relaxed) const +{ + switch (type()) { + case VOID: + out << ""; + break; + + case BOOLEAN: + if (as_boolean()) + out << "true"; + else + out << "false"; + break; + + case INTEGER: + out << as_long(); + break; + + case AMOUNT: + if (! relaxed) + out << '{'; + out << as_amount(); + if (! relaxed) + out << '}'; + break; + + case BALANCE: + case BALANCE_PAIR: + assert(false); + break; + + case DATETIME: + out << '[' << format_datetime(as_datetime()) << ']'; + break; + + case STRING: + out << '"' << as_string() << '"'; + break; + + case POINTER: + assert(false); + break; + + case SEQUENCE: { + out << '('; + bool first = true; + foreach (const value_t& value, as_sequence()) { + if (first) + first = false; + else + out << ", "; + + value.print(out, relaxed); + } + out << ')'; + break; + } + } +} + bool value_t::valid() const { switch (type()) { @@ -1561,38 +1621,9 @@ void value_context::describe(std::ostream& out) const throw() if (! desc.empty()) out << desc << std::endl; - const balance_t * ptr = NULL; - out << std::right; out.width(20); - - switch (bal.type()) { - case value_t::BOOLEAN: - out << (bal.as_boolean() ? "true" : "false"); - break; - case value_t::INTEGER: - out << bal.as_long(); - break; - case value_t::DATETIME: - out << bal.as_datetime(); - break; - case value_t::AMOUNT: - out << bal.as_amount(); - break; - case value_t::BALANCE: - ptr = &bal.as_balance(); - // fall through... - - case value_t::BALANCE_PAIR: - if (! ptr) - ptr = &bal.as_balance_pair().quantity(); - - ptr->print(out, 20); - break; - default: - assert(0); - break; - } + bal.print(out); out << std::endl; } @@ -832,8 +832,9 @@ public: /** * Printing methods. */ - void print(std::ostream& out, const int first_width, - const int latter_width = -1) const; + void dump(std::ostream& out, const int first_width, + const int latter_width = -1) const; + void print(std::ostream& out, const bool relaxed = true) const; /** * Debugging methods. |