summaryrefslogtreecommitdiff
path: root/src/textual.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/textual.cc')
-rw-r--r--src/textual.cc123
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;
}