diff options
Diffstat (limited to 'src/textual.cc')
-rw-r--r-- | src/textual.cc | 123 |
1 files changed, 86 insertions, 37 deletions
diff --git a/src/textual.cc b/src/textual.cc index 1d0d7998..8f0dd89c 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -132,10 +132,12 @@ namespace { std::streamsize len, account_t * account, xact_t * xact, - bool honor_strict = true); + bool honor_strict = true, + bool defer_expr = false); - bool parse_posts(account_t * account, - xact_base_t& xact); + bool parse_posts(account_t * account, + xact_base_t& xact, + const bool defer_expr = false); xact_t * parse_xact(char * line, std::streamsize len, @@ -145,11 +147,13 @@ namespace { const string& name); }; - void parse_amount_expr(scope_t& scope, - std::istream& in, - amount_t& amount, - post_t * post, - const parse_flags_t& flags = PARSE_DEFAULT) + void parse_amount_expr(scope_t& scope, + std::istream& in, + amount_t& amount, + optional<expr_t> * amount_expr, + post_t * post, + const parse_flags_t& flags = PARSE_DEFAULT, + const bool defer_expr = false) { expr_t expr(in, flags.plus_flags(PARSE_PARTIAL)); @@ -166,17 +170,22 @@ namespace { if (expr) { bind_scope_t bound_scope(scope, *post); - - value_t result(expr.calc(bound_scope)); - if (result.is_long()) { - amount = result.to_amount(); + if (defer_expr) { + assert(amount_expr); + *amount_expr = expr; + (*amount_expr)->compile(bound_scope); } else { - if (! result.is_amount()) - throw_(parse_error, _("Postings may only specify simple amounts")); - - amount = result.as_amount(); + value_t result(expr.calc(bound_scope)); + if (result.is_long()) { + amount = result.to_amount(); + } else { + if (! result.is_amount()) + throw_(amount_error, + _("Amount expressions must result in a simple amount")); + amount = result.as_amount(); + } + DEBUG("textual.parse", "The posting amount is " << amount); } - DEBUG("textual.parse", "The posting amount is " << amount); } } } @@ -413,11 +422,28 @@ void instance_t::clock_in_directive(char * line, { string datetime(line, 2, 19); - char * p = skip_ws(line + 22); - char * n = next_element(p, true); + char * p = skip_ws(line + 22); + char * n = next_element(p, true); + char * end = n ? next_element(n, true) : NULL; + + if (end && *end == ';') + end = skip_ws(end + 1); + else + end = NULL; + + position_t position; + position.pathname = pathname; + position.beg_pos = line_beg_pos; + position.beg_line = linenum; + position.end_pos = curr_pos; + position.end_line = linenum; - timelog.clock_in(parse_datetime(datetime, current_year), - account_stack.front()->find_account(p), n ? n : ""); + time_xact_t event(position, parse_datetime(datetime, current_year), + p ? account_stack.front()->find_account(p) : NULL, + n ? n : "", + end ? end : ""); + + timelog.clock_in(event); } void instance_t::clock_out_directive(char * line, @@ -427,9 +453,26 @@ void instance_t::clock_out_directive(char * line, char * p = skip_ws(line + 22); char * n = next_element(p, true); + char * end = n ? next_element(n, true) : NULL; + + if (end && *end == ';') + end = skip_ws(end + 1); + else + end = NULL; + + position_t position; + position.pathname = pathname; + position.beg_pos = line_beg_pos; + position.beg_line = linenum; + position.end_pos = curr_pos; + position.end_line = linenum; + + time_xact_t event(position, parse_datetime(datetime, current_year), + p ? account_stack.front()->find_account(p) : NULL, + n ? n : "", + end ? end : ""); - timelog.clock_out(parse_datetime(datetime, current_year), - p ? account_stack.front()->find_account(p) : NULL, n ? n : ""); + timelog.clock_out(event); count++; } @@ -514,7 +557,7 @@ void instance_t::automated_xact_directive(char * line) reveal_context = false; - if (parse_posts(account_stack.front(), *ae.get())) { + if (parse_posts(account_stack.front(), *ae.get(), true)) { reveal_context = true; journal.auto_xacts.push_back(ae.get()); @@ -558,7 +601,7 @@ void instance_t::period_xact_directive(char * line) pe->journal = &journal; if (pe->finalize()) { - extend_xact_base(&journal, *pe.get(), true); + extend_xact_base(&journal, *pe.get()); journal.period_xacts.push_back(pe.get()); @@ -628,7 +671,7 @@ void instance_t::include_directive(char * line) if (! exists(filename)) throw_(std::runtime_error, - _("File to include was not found: '%1'" << filename)); + _("File to include was not found: '%1'") << filename); ifstream stream(filename); @@ -783,7 +826,8 @@ post_t * instance_t::parse_post(char * line, std::streamsize len, account_t * account, xact_t * xact, - bool honor_strict) + bool honor_strict, + bool defer_expr) { TRACE_START(post_details, 1, "Time spent parsing postings:"); @@ -885,8 +929,9 @@ post_t * instance_t::parse_post(char * line, if (*next != '(') // indicates a value expression post->amount.parse(stream, PARSE_NO_REDUCE); else - parse_amount_expr(scope, stream, post->amount, post.get(), - PARSE_NO_REDUCE | PARSE_SINGLE | PARSE_NO_ASSIGN); + parse_amount_expr(scope, stream, post->amount, &post->amount_expr, + post.get(), PARSE_NO_REDUCE | PARSE_SINGLE | + PARSE_NO_ASSIGN, defer_expr); if (! post->amount.is_null() && honor_strict && strict && post->amount.has_commodity() && @@ -931,9 +976,9 @@ post_t * instance_t::parse_post(char * line, if (*p != '(') // indicates a value expression post->cost->parse(cstream, PARSE_NO_MIGRATE); else - parse_amount_expr(scope, cstream, *post->cost, post.get(), - PARSE_NO_MIGRATE | PARSE_SINGLE | - PARSE_NO_ASSIGN); + parse_amount_expr(scope, cstream, *post->cost, NULL, post.get(), + PARSE_NO_MIGRATE | PARSE_SINGLE | PARSE_NO_ASSIGN, + defer_expr); if (post->cost->sign() < 0) throw parse_error(_("A posting's cost may not be negative")); @@ -983,8 +1028,9 @@ post_t * instance_t::parse_post(char * line, if (*p != '(') // indicates a value expression post->assigned_amount->parse(stream, PARSE_NO_MIGRATE); else - parse_amount_expr(scope, stream, *post->assigned_amount, post.get(), - PARSE_SINGLE | PARSE_NO_MIGRATE); + parse_amount_expr(scope, stream, *post->assigned_amount, NULL, + post.get(), PARSE_SINGLE | PARSE_NO_MIGRATE, + defer_expr); if (post->assigned_amount->is_null()) { if (post->amount.is_null()) @@ -1084,8 +1130,9 @@ post_t * instance_t::parse_post(char * line, } } -bool instance_t::parse_posts(account_t * account, - xact_base_t& xact) +bool instance_t::parse_posts(account_t * account, + xact_base_t& xact, + const bool defer_expr) { TRACE_START(xact_posts, 1, "Time spent parsing postings:"); @@ -1096,7 +1143,9 @@ bool instance_t::parse_posts(account_t * account, std::streamsize len = read_line(line); assert(len > 0); - if (post_t * post = parse_post(line, len, account, NULL, false)) { + if (post_t * post = + parse_post(line, len, account, NULL, /* honor_strict= */ false, + defer_expr)) { xact.add_post(post); added = true; } |