summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/textual.cc89
-rw-r--r--test/baseline/dir-apply.dat3
-rw-r--r--test/baseline/dir-apply.test34
3 files changed, 93 insertions, 33 deletions
diff --git a/src/textual.cc b/src/textual.cc
index ab87a945..7d96310a 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -92,11 +92,30 @@ namespace {
return _("textual parser");
}
+ template <typename T>
+ void get_applications(std::vector<T>& result) {
+ foreach (application_t& state, apply_stack) {
+ if (state.value.type() == typeid(T))
+ result.push_back(boost::get<T>(state.value));
+ }
+ if (parent)
+ parent->get_applications<T>(result);
+ }
+
+ template <typename T>
+ optional<T> get_application() {
+ foreach (application_t& state, apply_stack) {
+ if (state.value.type() == typeid(T))
+ return boost::get<T>(state.value);
+ }
+ return parent ? parent->get_application<T>() : none;
+ }
+
account_t * top_account() {
- foreach (application_t& state, apply_stack)
- if (state.value.type() == typeid(account_t *))
- return boost::get<account_t *>(state.value);
- return NULL;
+ if (optional<account_t *> acct = get_application<account_t *>())
+ return *acct;
+ else
+ return NULL;
}
void parse();
@@ -744,12 +763,15 @@ void instance_t::include_directive(char * line)
#endif // BOOST_VERSION >= 103700
if (glob.match(base)) {
journal_t * journal = context.journal;
- account_t * master = context.master;
+ account_t * master = top_account();
scope_t * scope = context.scope;
std::size_t& errors = context.errors;
std::size_t& count = context.count;
std::size_t& sequence = context.sequence;
+ DEBUG("textual.include", "Including: " << *iter);
+ DEBUG("textual.include", "Master account: " << master->fullname());
+
context_stack.push(*iter);
context_stack.get_current().journal = journal;
@@ -848,15 +870,21 @@ void instance_t::apply_year_directive(char * line)
void instance_t::end_apply_directive(char * kind)
{
- char * b = next_element(kind);
- string name(b ? b : " ");
+ char * b = kind ? next_element(kind) : NULL;
+ string name(b ? b : "");
- if (apply_stack.size() <= 1)
- throw_(std::runtime_error,
- _("'end apply %1' found, but no enclosing 'apply %2' directive")
- << name << name);
+ if (apply_stack.size() <= 1) {
+ if (name.empty()) {
+ throw_(std::runtime_error,
+ _("'end' or 'end apply' found, but no enclosing 'apply' directive"));
+ } else {
+ throw_(std::runtime_error,
+ _("'end apply %1' found, but no enclosing 'apply' directive")
+ << name);
+ }
+ }
- if (name != " " && name != apply_stack.front().label)
+ if (! name.empty() && name != apply_stack.front().label)
throw_(std::runtime_error,
_("'end apply %1' directive does not match 'apply %2' directive")
<< name << apply_stack.front().label);
@@ -1425,15 +1453,14 @@ post_t * instance_t::parse_post(char * line,
context.journal->register_commodity(post->amount.commodity(), post.get());
if (! post->amount.has_annotation()) {
- foreach (application_t& state, apply_stack) {
- if (state.value.type() == typeid(fixed_rate_t)) {
- fixed_rate_t& rate(boost::get<fixed_rate_t>(state.value));
- if (*rate.first == post->amount.commodity()) {
- annotation_t details(rate.second);
- details.add_flags(ANNOTATION_PRICE_FIXATED);
- post->amount.annotate(details);
- break;
- }
+ std::vector<fixed_rate_t> rates;
+ get_applications<fixed_rate_t>(rates);
+ foreach (fixed_rate_t& rate, rates) {
+ if (*rate.first == post->amount.commodity()) {
+ annotation_t details(rate.second);
+ details.add_flags(ANNOTATION_PRICE_FIXATED);
+ post->amount.annotate(details);
+ break;
}
}
}
@@ -1631,12 +1658,10 @@ post_t * instance_t::parse_post(char * line,
post->pos->end_pos = context.curr_pos;
post->pos->end_line = context.linenum;
- if (! apply_stack.empty()) {
- foreach (const application_t& state, apply_stack)
- if (state.value.type() == typeid(string))
- post->parse_tags(boost::get<string>(state.value).c_str(),
- *context.scope, true);
- }
+ std::vector<string> tags;
+ get_applications<string>(tags);
+ foreach (string& tag, tags)
+ post->parse_tags(tag.c_str(), *context.scope, true);
TRACE_STOP(post_details, 1);
@@ -1849,12 +1874,10 @@ xact_t * instance_t::parse_xact(char * line,
xact->pos->end_pos = context.curr_pos;
xact->pos->end_line = context.linenum;
- if (! apply_stack.empty()) {
- foreach (const application_t& state, apply_stack)
- if (state.value.type() == typeid(string))
- xact->parse_tags(boost::get<string>(state.value).c_str(),
- *context.scope, false);
- }
+ std::vector<string> tags;
+ get_applications<string>(tags);
+ foreach (string& tag, tags)
+ xact->parse_tags(tag.c_str(), *context.scope, false);
TRACE_STOP(xact_details, 1);
diff --git a/test/baseline/dir-apply.dat b/test/baseline/dir-apply.dat
new file mode 100644
index 00000000..bcdcacf1
--- /dev/null
+++ b/test/baseline/dir-apply.dat
@@ -0,0 +1,3 @@
+2012-03-12 KFC
+ Expenses:Food $40
+ Assets:Cash
diff --git a/test/baseline/dir-apply.test b/test/baseline/dir-apply.test
new file mode 100644
index 00000000..7d9e91d9
--- /dev/null
+++ b/test/baseline/dir-apply.test
@@ -0,0 +1,34 @@
+apply account Master Account
+
+2012-03-12 KFC
+ Expenses:Food $20
+ Assets:Cash
+
+end apply account
+
+apply account Master Account
+
+2012-03-12 KFC
+ Expenses:Food $20
+ Assets:Cash
+
+end apply
+
+apply account Master Account
+
+2012-03-12 KFC
+ Expenses:Food $20
+ Assets:Cash
+
+end
+
+apply account Master Account
+include dir-apply.dat
+end
+
+test reg food
+12-Mar-12 KFC Master A:Expenses:Food $20 $20
+12-Mar-12 KFC Master A:Expenses:Food $20 $40
+12-Mar-12 KFC Master A:Expenses:Food $20 $60
+12-Mar-12 KFC Master A:Expenses:Food $40 $100
+end test