summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/account.h4
-rw-r--r--src/amount.cc6
-rw-r--r--src/amount.h2
-rw-r--r--src/commodity.cc64
-rw-r--r--src/compare.cc8
-rw-r--r--src/expr.cc42
-rw-r--r--src/expr.h4
-rw-r--r--src/flags.h4
-rw-r--r--src/global.h4
-rw-r--r--src/op.cc138
-rw-r--r--src/op.h11
-rw-r--r--src/output.cc20
-rw-r--r--src/parser.cc135
-rw-r--r--src/parser.h6
-rw-r--r--src/post.h10
-rw-r--r--src/py_amount.cc1
-rw-r--r--src/py_item.cc2
-rw-r--r--src/py_xact.cc2
-rw-r--r--src/query.cc42
-rw-r--r--src/query.h4
-rw-r--r--src/report.cc29
-rw-r--r--src/report.h8
-rw-r--r--src/scope.h33
-rw-r--r--src/session.h4
-rw-r--r--src/stream.cc4
-rw-r--r--src/system.hh.in6
-rw-r--r--src/textual.cc4
-rw-r--r--src/token.cc31
-rw-r--r--src/token.h15
-rw-r--r--src/xact.h30
30 files changed, 453 insertions, 220 deletions
diff --git a/src/account.h b/src/account.h
index 26ebe261..7a632b35 100644
--- a/src/account.h
+++ b/src/account.h
@@ -89,6 +89,10 @@ public:
}
~account_t();
+ virtual string description() {
+ return string(_("account ")) + fullname();
+ }
+
operator string() const {
return fullname();
}
diff --git a/src/amount.cc b/src/amount.cc
index 1fbc96c8..d5b7f03d 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -998,7 +998,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
if (! symbol.empty())
comm_flags |= COMMODITY_STYLE_SUFFIXED;
- if (! in.eof() && ((n = static_cast<char>(in.peek())) != '\n'))
+ if (! flags.has_flags(PARSE_NO_ANNOT) &&
+ ! in.eof() && ((n = static_cast<char>(in.peek())) != '\n'))
details.parse(in);
}
} else {
@@ -1010,7 +1011,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
parse_quantity(in, quant);
- if (! quant.empty() && ! in.eof() &&
+ if (! flags.has_flags(PARSE_NO_ANNOT) &&
+ ! quant.empty() && ! in.eof() &&
((n = static_cast<char>(in.peek())) != '\n'))
details.parse(in);
}
diff --git a/src/amount.h b/src/amount.h
index 1dfb4234..8a2ebf04 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -72,7 +72,7 @@ enum parse_flags_enum_t {
PARSE_NO_MIGRATE = 0x04,
PARSE_NO_REDUCE = 0x08,
PARSE_NO_ASSIGN = 0x10,
- PARSE_NO_DATES = 0x20,
+ PARSE_NO_ANNOT = 0x20,
PARSE_OP_CONTEXT = 0x40,
PARSE_SOFT_FAIL = 0x80
};
diff --git a/src/commodity.cc b/src/commodity.cc
index 179bbc05..81183b25 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -490,16 +490,32 @@ commodity_t::operator bool() const
return this != pool().null_commodity;
}
-bool commodity_t::symbol_needs_quotes(const string& symbol)
-{
- foreach (char ch, symbol)
- if (std::isspace(ch) || std::isdigit(ch) || ch == '-' || ch == '.')
- return true;
+namespace {
+ // Invalid commodity characters:
+ // SPACE, TAB, NEWLINE, RETURN
+ // 0-9 . , ; : ? ! - + * / ^ & | =
+ // < > { } [ ] ( ) @
- return false;
-}
+ static int invalid_chars[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
+ /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 20 */ 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 40 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
+ /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
-namespace {
bool is_reserved_token(const char * buf)
{
switch (buf[0]) {
@@ -524,33 +540,17 @@ namespace {
}
}
-void commodity_t::parse_symbol(std::istream& in, string& symbol)
+bool commodity_t::symbol_needs_quotes(const string& symbol)
{
- // Invalid commodity characters:
- // SPACE, TAB, NEWLINE, RETURN
- // 0-9 . , ; : ? ! - + * / ^ & | =
- // < > { } [ ] ( ) @
+ foreach (char ch, symbol)
+ if (invalid_chars[static_cast<unsigned char>(ch)])
+ return true;
- static int invalid_chars[256] = {
- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
- /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
- /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 20 */ 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- /* 40 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
- /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
- /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- };
+ return false;
+}
+void commodity_t::parse_symbol(std::istream& in, string& symbol)
+{
istream_pos_type pos = in.tellg();
char buf[256];
diff --git a/src/compare.cc b/src/compare.cc
index 99e430a7..12114c7d 100644
--- a/src/compare.cc
+++ b/src/compare.cc
@@ -42,8 +42,10 @@ void push_sort_value(std::list<sort_value_t>& sort_values,
expr_t::ptr_op_t node, scope_t& scope)
{
if (node->kind == expr_t::op_t::O_CONS) {
- push_sort_value(sort_values, node->left(), scope);
- push_sort_value(sort_values, node->right(), scope);
+ while (node && node->kind == expr_t::op_t::O_CONS) {
+ push_sort_value(sort_values, node->left(), scope);
+ node = node->right();
+ }
} else {
bool inverted = false;
@@ -54,7 +56,7 @@ void push_sort_value(std::list<sort_value_t>& sort_values,
sort_values.push_back(sort_value_t());
sort_values.back().inverted = inverted;
- sort_values.back().value = expr_t(node).calc(scope).simplified();
+ sort_values.back().value = expr_t(node).calc(scope).simplified();
if (sort_values.back().value.is_null())
throw_(calc_error,
diff --git a/src/expr.cc b/src/expr.cc
index 5bc537d9..b3d4abcd 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -33,6 +33,7 @@
#include "expr.h"
#include "parser.h"
+#include "scope.h"
namespace ledger {
@@ -162,4 +163,45 @@ void expr_t::dump(std::ostream& out) const
if (ptr) ptr->dump(out, 0);
}
+value_t source_command(call_scope_t& args)
+{
+ std::istream * in = NULL;
+ scoped_ptr<ifstream> stream;
+ string pathname;
+
+ if (args.has(0)) {
+ pathname = args.get<string>(0);
+ stream.reset(new ifstream(path(pathname)));
+ in = stream.get();
+ } else {
+ pathname = "<stdin>";
+ in = &std::cin;
+ }
+
+ symbol_scope_t file_locals(args);
+ std::size_t linenum = 0;
+ char buf[4096];
+ istream_pos_type pos;
+
+ while (in->good() && ! in->eof()) {
+ pos = in->tellg();
+ in->getline(buf, 4095);
+ linenum++;
+
+ char * p = skip_ws(buf);
+ if (*p && *p != ';') {
+ try {
+ expr_t(p).calc(file_locals);
+ }
+ catch (const std::exception&) {
+ add_error_context(_("While parsing value expression on line %1:")
+ << linenum);
+ add_error_context(source_context(pathname, pos, in->tellg(), "> "));
+ }
+ }
+ }
+
+ return true;
+}
+
} // namespace ledger
diff --git a/src/expr.h b/src/expr.h
index e6eeebf6..a3ae5669 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -160,6 +160,10 @@ inline value_t expr_value(expr_t::ptr_op_t op) {
return temp;
}
+class call_scope_t;
+
+value_t source_command(call_scope_t& scope);
+
} // namespace ledger
#endif // _EXPR_H
diff --git a/src/flags.h b/src/flags.h
index 03f47ff9..09b7eec4 100644
--- a/src/flags.h
+++ b/src/flags.h
@@ -112,11 +112,11 @@ public:
}
basic_flags_t(const T& bits) {
TRACE_CTOR(basic_flags_t, "const T&");
- set_flags(bits);
+ supports_flags<T, U>::set_flags(bits);
}
basic_flags_t(const U& bits) {
TRACE_CTOR(basic_flags_t, "const U&");
- set_flags(static_cast<T>(bits));
+ supports_flags<T, U>::set_flags(static_cast<T>(bits));
}
~basic_flags_t() throw() {
TRACE_DTOR(basic_flags_t);
diff --git a/src/global.h b/src/global.h
index 115183a5..6504230d 100644
--- a/src/global.h
+++ b/src/global.h
@@ -55,6 +55,10 @@ public:
global_scope_t(char ** envp);
~global_scope_t();
+ virtual string description() {
+ return _("global scope");
+ }
+
void read_init();
void read_environment_settings(char * envp[]);
strings_list read_command_arguments(scope_t& scope, strings_list args);
diff --git a/src/op.cc b/src/op.cc
index 95ad5abd..86057f66 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -108,10 +108,15 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
break;
case O_CALL:
- if (left()->left()->is_ident())
- scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this);
- else
+ if (left()->left()->is_ident()) {
+ ptr_op_t node(new op_t(op_t::O_LAMBDA));
+ node->set_left(left()->right());
+ node->set_right(right());
+
+ scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), node);
+ } else {
throw_(compile_error, _("Invalid function definition"));
+ }
break;
default:
throw_(compile_error, _("Invalid function definition"));
@@ -151,15 +156,21 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
break;
case IDENT: {
- if (! left())
+ ptr_op_t definition = left();
+ if (! definition) {
+ // If no definition was pre-compiled for this identifier, look it
+ // up in the current scope.
+ definition = scope.lookup(symbol_t::FUNCTION, as_ident());
+ }
+ if (! definition)
throw_(calc_error, _("Unknown identifier '%1'") << as_ident());
// Evaluating an identifier is the same as calling its definition
// directly, so we create an empty call_scope_t to reflect the scope for
// this implicit call.
call_scope_t call_args(scope, locus, depth);
- result = left()->compile(call_args, depth + 1)
- ->calc(call_args, locus, depth + 1);
+ result = definition->compile(call_args, depth + 1)
+ ->calc(call_args, locus, depth + 1);
check_type_context(scope, result);
break;
}
@@ -177,74 +188,68 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
break;
}
- case O_DEFINE: {
+ case O_LAMBDA: {
call_scope_t& call_args(downcast<call_scope_t>(scope));
- std::size_t args_count = call_args.size();
- std::size_t args_index = 0;
-
- assert(left()->kind == O_CALL);
+ std::size_t args_count(call_args.size());
+ std::size_t args_index(0);
+ symbol_scope_t call_scope(call_args);
+ ptr_op_t sym(left());
- for (ptr_op_t sym = left()->right();
- sym;
- sym = sym->has_right() ? sym->right() : NULL) {
+ for (; sym; sym = sym->has_right() ? sym->right() : NULL) {
ptr_op_t varname = sym;
if (sym->kind == O_CONS)
varname = sym->left();
- if (! varname->is_ident())
+ if (! varname->is_ident()) {
throw_(calc_error, _("Invalid function definition"));
- else if (args_index == args_count)
- scope.define(symbol_t::FUNCTION, varname->as_ident(),
- wrap_value(false));
- else
- scope.define(symbol_t::FUNCTION, varname->as_ident(),
- wrap_value(call_args[args_index++]));
+ }
+ else if (args_index == args_count) {
+ call_scope.define(symbol_t::FUNCTION, varname->as_ident(),
+ wrap_value(NULL_VALUE));
+ }
+ else {
+ DEBUG("expr.compile",
+ "Defining function parameter " << varname->as_ident());
+ call_scope.define(symbol_t::FUNCTION, varname->as_ident(),
+ wrap_value(call_args[args_index++]));
+ }
}
if (args_index < args_count)
throw_(calc_error,
- _("Too many arguments in function call (saw %1)") << args_count);
+ _("Too few arguments in function call (saw %1)") << args_count);
- result = right()->calc(scope, locus, depth + 1);
+ result = right()->calc(call_scope, locus, depth + 1);
break;
}
case O_LOOKUP: {
context_scope_t context_scope(scope, value_t::SCOPE);
+ bool scope_error = true;
if (value_t obj = left()->calc(context_scope, locus, depth + 1)) {
- if (obj.is_scope()) {
- if (obj.as_scope() == NULL) {
- throw_(calc_error, _("Left operand of . operator is NULL"));
- } else {
- scope_t& objscope(*obj.as_scope());
- if (ptr_op_t member =
- objscope.lookup(symbol_t::FUNCTION, right()->as_ident())) {
- result = member->calc(objscope, NULL, depth + 1);
- break;
- }
- }
+ if (obj.is_scope() && obj.as_scope() != NULL) {
+ bind_scope_t bound_scope(scope, *obj.as_scope());
+ result = right()->calc(bound_scope, locus, depth + 1);
+ scope_error = false;
}
}
- if (right()->kind != IDENT)
- throw_(calc_error,
- _("Right operand of . operator must be an identifier"));
- else
- throw_(calc_error,
- _("Failed to lookup member '%1'") << right()->as_ident());
+ if (scope_error)
+ throw_(calc_error, _("Left operand does not evaluate to an object"));
break;
}
case O_CALL: {
call_scope_t call_args(scope, locus, depth);
if (has_right())
- call_args.set_args(split_cons_expr(right()->kind == O_SEQ ?
- right()->left() : right()));
+ call_args.set_args(split_cons_expr(right()));
ptr_op_t func = left();
const string& name(func->as_ident());
func = func->left();
if (! func)
+ func = scope.lookup(symbol_t::FUNCTION, name);
+ if (! func)
throw_(calc_error, _("Calling unknown function '%1'") << name);
if (func->is_function())
@@ -467,6 +472,9 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
string symbol;
+ if (kind > TERMINALS && (kind != O_CALL && kind != O_DEFINE))
+ out << '(';
+
switch (kind) {
case VALUE:
as_value().dump(out, context.relaxed);
@@ -481,118 +489,94 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
break;
case O_NOT:
- out << "!(";
+ out << "! ";
if (left() && left()->print(out, context))
found = true;
- out << ")";
break;
case O_NEG:
- out << "-(";
+ out << "- ";
if (left() && left()->print(out, context))
found = true;
- out << ")";
break;
case O_ADD:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " + ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_SUB:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " - ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_MUL:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " * ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_DIV:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " / ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_EQ:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " == ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_LT:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " < ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_LTE:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " <= ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_GT:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " > ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_GTE:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " >= ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_AND:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " & ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_OR:
- out << "(";
if (left() && left()->print(out, context))
found = true;
out << " | ";
if (has_right() && right()->print(out, context))
found = true;
- out << ")";
break;
case O_QUERY:
@@ -616,15 +600,13 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
break;
case O_SEQ:
- out << "(";
found = print_seq(out, this, context);
- out << ")";
break;
case O_DEFINE:
if (left() && left()->print(out, context))
found = true;
- out << " := ";
+ out << " = ";
if (has_right() && right()->print(out, context))
found = true;
break;
@@ -637,11 +619,19 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
found = true;
break;
+ case O_LAMBDA:
+ if (left() && left()->print(out, context))
+ found = true;
+ out << " -> ";
+ if (has_right() && right()->print(out, context))
+ found = true;
+ break;
+
case O_CALL:
if (left() && left()->print(out, context))
found = true;
if (has_right()) {
- if (right()->kind == O_SEQ) {
+ if (right()->kind == O_CONS) {
if (right()->print(out, context))
found = true;
} else {
@@ -669,6 +659,9 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
break;
}
+ if (kind > TERMINALS && (kind != O_CALL && kind != O_DEFINE))
+ out << ')';
+
if (! symbol.empty()) {
if (commodity_pool_t::current_pool->find(symbol))
out << '@';
@@ -708,6 +701,7 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const
case O_DEFINE: out << "O_DEFINE"; break;
case O_LOOKUP: out << "O_LOOKUP"; break;
+ case O_LAMBDA: out << "O_LAMBDA"; break;
case O_CALL: out << "O_CALL"; break;
case O_MATCH: out << "O_MATCH"; break;
diff --git a/src/op.h b/src/op.h
index aa591b28..6f7d7904 100644
--- a/src/op.h
+++ b/src/op.h
@@ -104,6 +104,7 @@ public:
O_DEFINE,
O_LOOKUP,
+ O_LAMBDA,
O_CALL,
O_MATCH,
@@ -266,8 +267,10 @@ public:
ostream_pos_type * end_pos;
bool relaxed;
- context_t(const ptr_op_t& _expr_op = NULL,
- const ptr_op_t& _op_to_find = NULL,
+ context_t() : start_pos(NULL), end_pos(NULL), relaxed(false) {}
+
+ context_t(const ptr_op_t& _expr_op,
+ const ptr_op_t& _op_to_find,
ostream_pos_type * const _start_pos = NULL,
ostream_pos_type * const _end_pos = NULL,
const bool _relaxed = true)
@@ -280,7 +283,7 @@ public:
void dump(std::ostream& out, const int depth = 0) const;
static ptr_op_t wrap_value(const value_t& val);
- static ptr_op_t wrap_functor(const expr_t::func_t& fobj);
+ static ptr_op_t wrap_functor(expr_t::func_t fobj);
#if defined(HAVE_BOOST_SERIALIZATION)
private:
@@ -326,7 +329,7 @@ inline expr_t::ptr_op_t expr_t::op_t::wrap_value(const value_t& val) {
}
inline expr_t::ptr_op_t
-expr_t::op_t::wrap_functor(const expr_t::func_t& fobj) {
+expr_t::op_t::wrap_functor(expr_t::func_t fobj) {
ptr_op_t temp(new op_t(op_t::FUNCTION));
temp->set_function(fobj);
return temp;
diff --git a/src/output.cc b/src/output.cc
index f53e60c9..9d2e0cb6 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -90,14 +90,10 @@ void format_posts::operator()(post_t& post)
else
out << '\n';
- value_scope_t val_scope(string_value(report_title));
- bind_scope_t inner_scope(bound_scope, val_scope);
-
- format_t group_title_format;
- group_title_format
- .parse_format(report.HANDLER(group_title_format_).str());
+ value_scope_t val_scope(bound_scope, string_value(report_title));
+ format_t group_title_format(report.HANDLER(group_title_format_).str());
- out << group_title_format(inner_scope);
+ out << group_title_format(val_scope);
report_title = "";
}
@@ -176,14 +172,10 @@ std::size_t format_accounts::post_account(account_t& account, const bool flat)
else
out << '\n';
- value_scope_t val_scope(string_value(report_title));
- bind_scope_t inner_scope(bound_scope, val_scope);
-
- format_t group_title_format;
- group_title_format
- .parse_format(report.HANDLER(group_title_format_).str());
+ value_scope_t val_scope(bound_scope, string_value(report_title));
+ format_t group_title_format(report.HANDLER(group_title_format_).str());
- out << group_title_format(inner_scope);
+ out << group_title_format(val_scope);
report_title = "";
}
diff --git a/src/parser.cc b/src/parser.cc
index 9a1ebf6f..f0085295 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -65,9 +65,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
push_token(tok); // let the parser see it again
node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE)));
-
- if (node->has_right() && node->right()->kind == op_t::O_CONS)
- node->set_right(node->right()->left());
} else {
push_token(tok);
}
@@ -78,12 +75,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL)
.minus_flags(PARSE_SINGLE));
tok = next_token(in, tflags, ')');
-
- if (node && node->kind == op_t::O_CONS) {
- ptr_op_t prev(node);
- node = new op_t(op_t::O_SEQ);
- node->set_left(prev);
- }
break;
default:
@@ -241,15 +232,12 @@ expr_t::parser_t::parse_logic_expr(std::istream& in,
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
while (true) {
- op_t::kind_t kind = op_t::LAST;
+ op_t::kind_t kind = op_t::LAST;
parse_flags_t _flags = tflags;
- token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
- bool negate = false;
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ bool negate = false;
switch (tok.kind) {
- case token_t::DEFINE:
- kind = op_t::O_DEFINE;
- break;
case token_t::EQUAL:
if (tflags.has_flags(PARSE_NO_ASSIGN))
tok.rewind(in);
@@ -431,39 +419,120 @@ expr_t::parser_t::parse_querycolon_expr(std::istream& in,
}
expr_t::ptr_op_t
-expr_t::parser_t::parse_value_expr(std::istream& in,
+expr_t::parser_t::parse_comma_expr(std::istream& in,
const parse_flags_t& tflags) const
{
ptr_op_t node(parse_querycolon_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
- token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ ptr_op_t next;
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
- if (tok.kind == token_t::COMMA || tok.kind == token_t::SEMI) {
- bool comma_op = tok.kind == token_t::COMMA;
+ if (tok.kind == token_t::COMMA) {
+ if (! next) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_CONS);
+ node->set_left(prev);
+
+ next = node;
+ }
+
+ token_t& ntok = next_token(in, tflags);
+ push_token(ntok);
+ if (ntok.kind == token_t::RPAREN)
+ break;
+
+ ptr_op_t chain(new op_t(op_t::O_CONS));
+ chain->set_left(parse_querycolon_expr(in, tflags));
+ next->set_right(chain);
+ next = chain;
+ } else {
+ push_token(tok);
+ break;
+ }
+ }
+ }
+
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_lambda_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_comma_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::ARROW) {
ptr_op_t prev(node);
- node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
+ node = new op_t(op_t::O_LAMBDA);
node->set_left(prev);
- node->set_right(parse_value_expr(in, tflags));
- if (! node->right())
- throw_(parse_error,
- _("%1 operator not followed by argument") << tok.symbol);
+ node->set_right(parse_querycolon_expr(in, tflags));
+ } else {
+ push_token(tok);
+ }
+ }
- tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+ return node;
+}
+
+expr_t::ptr_op_t
+expr_t::parser_t::parse_assign_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_lambda_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::ASSIGN) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_DEFINE);
+ node->set_left(prev);
+ node->set_right(parse_lambda_expr(in, tflags));
+ } else {
+ push_token(tok);
}
+ }
+
+ return node;
+}
- if (tok.kind != token_t::TOK_EOF) {
- if (tflags.has_flags(PARSE_PARTIAL))
+expr_t::ptr_op_t
+expr_t::parser_t::parse_value_expr(std::istream& in,
+ const parse_flags_t& tflags) const
+{
+ ptr_op_t node(parse_assign_expr(in, tflags));
+
+ if (node && ! tflags.has_flags(PARSE_SINGLE)) {
+ ptr_op_t next;
+ while (true) {
+ token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
+
+ if (tok.kind == token_t::SEMI) {
+ if (! next) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_SEQ);
+ node->set_left(prev);
+
+ next = node;
+ }
+
+ ptr_op_t chain(new op_t(op_t::O_SEQ));
+ chain->set_left(parse_assign_expr(in, tflags));
+
+ next->set_right(chain);
+ next = chain;
+ } else {
push_token(tok);
- else
- tok.unexpected();
+ break;
+ }
}
}
- else if (! tflags.has_flags(PARSE_PARTIAL) &&
- ! tflags.has_flags(PARSE_SINGLE)) {
- throw_(parse_error, _("Failed to parse value expression"));
- }
return node;
}
diff --git a/src/parser.h b/src/parser.h
index 93ea994f..9a65765d 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -93,6 +93,12 @@ class expr_t::parser_t : public noncopyable
const parse_flags_t& flags) const;
ptr_op_t parse_querycolon_expr(std::istream& in,
const parse_flags_t& flags) const;
+ ptr_op_t parse_comma_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_lambda_expr(std::istream& in,
+ const parse_flags_t& flags) const;
+ ptr_op_t parse_assign_expr(std::istream& in,
+ const parse_flags_t& flags) const;
ptr_op_t parse_value_expr(std::istream& in,
const parse_flags_t& flags) const;
diff --git a/src/post.h b/src/post.h
index e1535a46..7d5abcd8 100644
--- a/src/post.h
+++ b/src/post.h
@@ -99,6 +99,16 @@ public:
TRACE_DTOR(post_t);
}
+ virtual string description() {
+ if (pos) {
+ std::ostringstream buf;
+ buf << _("posting at line %1") << pos->beg_line;
+ return buf.str();
+ } else {
+ return string(_("generated posting"));
+ }
+ }
+
virtual bool has_tag(const string& tag,
bool inherit = true) const;
virtual bool has_tag(const mask_t& tag_mask,
diff --git a/src/py_amount.cc b/src/py_amount.cc
index 3cb9f0eb..0b9e0410 100644
--- a/src/py_amount.cc
+++ b/src/py_amount.cc
@@ -295,7 +295,6 @@ internal precision."))
.value("NoMigrate", PARSE_NO_MIGRATE)
.value("NoReduce", PARSE_NO_REDUCE)
.value("NoAssign", PARSE_NO_ASSIGN)
- .value("NoDates", PARSE_NO_DATES)
.value("OpContext", PARSE_OP_CONTEXT)
.value("SoftFail", PARSE_SOFT_FAIL)
;
diff --git a/src/py_item.cc b/src/py_item.cc
index 0e95f24f..e37228fe 100644
--- a/src/py_item.cc
+++ b/src/py_item.cc
@@ -106,7 +106,7 @@ void export_item()
#if 0
class_< item_t, bases<scope_t> > ("JournalItem", init<uint_least8_t>())
#else
- class_< item_t > ("JournalItem", init<uint_least8_t>())
+ class_< item_t, noncopyable > ("JournalItem", no_init)
#endif
#if 1
.add_property("flags", &supports_flags<>::flags,
diff --git a/src/py_xact.cc b/src/py_xact.cc
index 5ab0d90d..b7582854 100644
--- a/src/py_xact.cc
+++ b/src/py_xact.cc
@@ -82,7 +82,7 @@ using namespace boost::python;
void export_xact()
{
- class_< xact_base_t, bases<item_t> > ("TransactionBase")
+ class_< xact_base_t, bases<item_t>, noncopyable > ("TransactionBase", no_init)
.add_property("journal",
make_getter(&xact_base_t::journal,
return_internal_reference<>()),
diff --git a/src/query.cc b/src/query.cc
index bed6afae..5480336c 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -186,6 +186,8 @@ test_ident:
return token_t(token_t::TOK_META);
else if (ident == "show")
return token_t(token_t::TOK_SHOW);
+ else if (ident == "only")
+ return token_t(token_t::TOK_ONLY);
else if (ident == "bold")
return token_t(token_t::TOK_BOLD);
else if (ident == "for")
@@ -249,6 +251,7 @@ query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_contex
lexer_t::token_t tok = lexer.next_token();
switch (tok.kind) {
case lexer_t::token_t::TOK_SHOW:
+ case lexer_t::token_t::TOK_ONLY:
case lexer_t::token_t::TOK_BOLD:
case lexer_t::token_t::TOK_FOR:
case lexer_t::token_t::TOK_SINCE:
@@ -452,9 +455,26 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
lexer_t::token_t tok = lexer.peek_token();
while (tok.kind != lexer_t::token_t::END_REACHED) {
switch (tok.kind) {
- case lexer_t::token_t::TOK_SHOW: {
+ case lexer_t::token_t::TOK_SHOW:
+ case lexer_t::token_t::TOK_ONLY:
+ case lexer_t::token_t::TOK_BOLD: {
lexer.next_token();
+ kind_t kind;
+ switch (tok.kind) {
+ case lexer_t::token_t::TOK_SHOW:
+ kind = QUERY_SHOW;
+ break;
+ case lexer_t::token_t::TOK_ONLY:
+ kind = QUERY_ONLY;
+ break;
+ case lexer_t::token_t::TOK_BOLD:
+ kind = QUERY_BOLD;
+ break;
+ default:
+ break;
+ }
+
expr_t::ptr_op_t node;
while (expr_t::ptr_op_t next = parse_or_expr(tok_context)) {
if (! node) {
@@ -470,25 +490,7 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
if (node)
query_map.insert
(query_map_t::value_type
- (QUERY_SHOW, predicate_t(node, what_to_keep).print_to_str()));
- break;
- }
-
- case lexer_t::token_t::TOK_BOLD: {
- lexer.next_token();
-
- expr_t::ptr_op_t node = parse_or_expr(tok_context);
- while (expr_t::ptr_op_t next = parse_or_expr(tok_context)) {
- expr_t::ptr_op_t prev(node);
- node = new expr_t::op_t(expr_t::op_t::O_OR);
- node->set_left(prev);
- node->set_right(next);
- }
-
- if (node)
- query_map.insert
- (query_map_t::value_type
- (QUERY_BOLD, predicate_t(node, what_to_keep).print_to_str()));
+ (kind, predicate_t(node, what_to_keep).print_to_str()));
break;
}
diff --git a/src/query.h b/src/query.h
index 5a4651a0..b5b3b0fc 100644
--- a/src/query.h
+++ b/src/query.h
@@ -90,6 +90,7 @@ public:
TOK_EXPR,
TOK_SHOW,
+ TOK_ONLY,
TOK_BOLD,
TOK_FOR,
TOK_SINCE,
@@ -144,6 +145,7 @@ public:
case TOK_META: return "TOK_META";
case TOK_EXPR: return "TOK_EXPR";
case TOK_SHOW: return "TOK_SHOW";
+ case TOK_ONLY: return "TOK_ONLY";
case TOK_BOLD: return "TOK_BOLD";
case TOK_FOR: return "TOK_FOR";
case TOK_SINCE: return "TOK_SINCE";
@@ -170,6 +172,7 @@ public:
case TOK_META: return "meta";
case TOK_EXPR: return "expr";
case TOK_SHOW: return "show";
+ case TOK_ONLY: return "only";
case TOK_BOLD: return "bold";
case TOK_FOR: return "for";
case TOK_SINCE: return "since";
@@ -234,6 +237,7 @@ public:
enum kind_t {
QUERY_LIMIT,
QUERY_SHOW,
+ QUERY_ONLY,
QUERY_BOLD,
QUERY_FOR
};
diff --git a/src/report.cc b/src/report.cc
index 9d733674..5c7bf01d 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -267,6 +267,11 @@ void report_t::parse_query_args(const value_t& args, const string& whence)
DEBUG("report.predicate", "Limit predicate = " << HANDLER(limit_).str());
}
+ if (query.has_query(query_t::QUERY_ONLY)) {
+ HANDLER(only_).on(whence, query.get_query(query_t::QUERY_ONLY));
+ DEBUG("report.predicate", "Only predicate = " << HANDLER(only_).str());
+ }
+
if (query.has_query(query_t::QUERY_SHOW)) {
HANDLER(display_).on(whence, query.get_query(query_t::QUERY_SHOW));
DEBUG("report.predicate", "Display predicate = " << HANDLER(display_).str());
@@ -544,17 +549,19 @@ value_t report_t::fn_trim(call_scope_t& args)
}
}
+value_t report_t::fn_format(call_scope_t& args)
+{
+ format_t format(args.get<string>(0));
+ std::ostringstream out;
+ out << format(args);
+ return string_value(out.str());
+}
+
value_t report_t::fn_print(call_scope_t& args)
{
- std::ostream& out(output_stream);
- bool first = true;
- for (std::size_t i = 0; i < args.size(); i++) {
- if (first)
- first = false;
- else
- out << ' ';
- args[i].print(out);
- }
+ for (std::size_t i = 0; i < args.size(); i++)
+ args[i].print(output_stream);
+ static_cast<std::ostream&>(output_stream) << std::endl;
return true;
}
@@ -1173,6 +1180,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 'f':
if (is_eq(p, "format_date"))
return MAKE_FUNCTOR(report_t::fn_format_date);
+ else if (is_eq(p, "format"))
+ return MAKE_FUNCTOR(report_t::fn_format);
else if (is_eq(p, "floor"))
return MAKE_FUNCTOR(report_t::fn_floor);
break;
@@ -1444,6 +1453,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 's':
if (is_eq(p, "stats") || is_eq(p, "stat"))
return WRAP_FUNCTOR(report_statistics);
+ else if (is_eq(p, "source"))
+ return WRAP_FUNCTOR(source_command);
break;
case 'x':
diff --git a/src/report.h b/src/report.h
index 59a632e6..5c172ee9 100644
--- a/src/report.h
+++ b/src/report.h
@@ -125,6 +125,10 @@ public:
output_stream.close();
}
+ virtual string description() {
+ return _("current report");
+ }
+
void normalize_options(const string& verb);
void normalize_period();
void parse_query_args(const value_t& args, const string& whence);
@@ -147,6 +151,7 @@ public:
value_t fn_is_seq(call_scope_t& scope);
value_t fn_strip(call_scope_t& scope);
value_t fn_trim(call_scope_t& scope);
+ value_t fn_format(call_scope_t& scope);
value_t fn_print(call_scope_t& scope);
value_t fn_scrub(call_scope_t& scope);
value_t fn_quantity(call_scope_t& scope);
@@ -389,6 +394,7 @@ public:
" ansify_if(partial_account(options.flat), blue if color),"
" bold if should_bold))\n%/"
"%$1\n%/"
+ "%(prepend_width ? \" \" * prepend_width : \"\")"
"--------------------\n");
});
@@ -446,6 +452,7 @@ public:
" %(!options.flat ? depth_spacer : \"\")"
"%-(ansify_if(partial_account(options.flat), blue if color))\n"
"%/%$1 %$2 %$3 %$4\n%/"
+ "%(prepend_width ? \" \" * prepend_width : \"\")"
"------------ ------------ ------------ -----\n");
});
@@ -464,6 +471,7 @@ public:
" %(!options.flat ? depth_spacer : \"\")"
"%-(ansify_if(partial_account(options.flat), blue if color))\n%/"
"%$1 %$2 %$3\n%/"
+ "%(prepend_width ? \" \" * prepend_width : \"\")"
"---------------- ---------------- ---------\n");
});
diff --git a/src/scope.h b/src/scope.h
index dac6eba3..31b10f6b 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -109,6 +109,8 @@ public:
TRACE_DTOR(scope_t);
}
+ virtual string description() = 0;
+
virtual void define(const symbol_t::kind_t, const string&,
expr_t::ptr_op_t) {}
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
@@ -191,6 +193,10 @@ public:
TRACE_DTOR(bind_scope_t);
}
+ virtual string description() {
+ return grandchild.description();
+ }
+
virtual void define(const symbol_t::kind_t kind, const string& name,
expr_t::ptr_op_t def) {
parent->define(kind, name, def);
@@ -262,6 +268,16 @@ public:
TRACE_DTOR(symbol_scope_t);
}
+ virtual string description() {
+ if (parent)
+ return parent->description();
+#if !defined(NO_ASSERTS)
+ else
+ assert(false);
+#endif
+ return empty_string;
+ }
+
virtual void define(const symbol_t::kind_t kind, const string& name,
expr_t::ptr_op_t def);
@@ -299,6 +315,10 @@ public:
TRACE_DTOR(context_scope_t);
}
+ virtual string description() {
+ return parent->description();
+ }
+
virtual value_t::type_t type_context() const {
return value_type_context;
}
@@ -351,6 +371,10 @@ public:
TRACE_DTOR(call_scope_t);
}
+ virtual string description() {
+ return context_scope_t::description();
+ }
+
void set_args(const value_t& _args) {
args = _args;
}
@@ -605,7 +629,7 @@ call_scope_t::get<expr_t::ptr_op_t>(std::size_t index, bool) {
return args[index].as_any<expr_t::ptr_op_t>();
}
-class value_scope_t : public scope_t
+class value_scope_t : public child_scope_t
{
value_t value;
@@ -614,8 +638,13 @@ class value_scope_t : public scope_t
}
public:
- value_scope_t(const value_t& _value) : value(_value) {}
+ value_scope_t(scope_t& _parent, const value_t& _value)
+ : child_scope_t(_parent), value(_value) {}
+ virtual string description() {
+ return parent->description();
+ }
+
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
const string& name)
{
diff --git a/src/session.h b/src/session.h
index 6de4b2dd..b8fd52f2 100644
--- a/src/session.h
+++ b/src/session.h
@@ -64,6 +64,10 @@ public:
TRACE_DTOR(session_t);
}
+ virtual string description() {
+ return _("current session");
+ }
+
void set_flush_on_next_data_file(const bool truth) {
flush_on_next_data_file = truth;
}
diff --git a/src/stream.cc b/src/stream.cc
index 001e7760..5d4cf5e0 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -102,7 +102,11 @@ namespace {
else { // parent
close(pfd[0]);
typedef iostreams::stream<iostreams::file_descriptor_sink> fdstream;
+#if BOOST_VERSION >= 104400
+ *os = new fdstream(pfd[1], iostreams::never_close_handle);
+#else // BOOST_VERSION >= 104400
*os = new fdstream(pfd[1]);
+#endif // BOOST_VERSION >= 104400
}
return pfd[1];
#else
diff --git a/src/system.hh.in b/src/system.hh.in
index d9e664e3..6f709684 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -160,7 +160,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/operators.hpp>
#include <boost/optional.hpp>
#include <boost/ptr_container/ptr_list.hpp>
-#include <boost/ptr_container/serialize_ptr_deque.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/uniform_real.hpp>
@@ -194,6 +193,7 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/date_time/posix_time/time_serialize.hpp>
#include <boost/date_time/gregorian/greg_serialize.hpp>
+#include <boost/ptr_container/serialize_ptr_deque.hpp>
namespace boost {
namespace serialization {
@@ -239,6 +239,10 @@ void serialize(Archive& ar, istream_pos_type& pos, const unsigned int)
} // namespace serialization
} // namespace boost
+#else // HAVE_BOOST_SERIALIZATION
+
+#include <boost/ptr_container/ptr_deque.hpp>
+
#endif // HAVE_BOOST_SERIALIZATION
#if defined(HAVE_BOOST_PYTHON)
diff --git a/src/textual.cc b/src/textual.cc
index 7ddb5251..3dbae9a1 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -112,6 +112,10 @@ namespace {
~instance_t();
+ virtual string description() {
+ return _("textual parser");
+ }
+
void parse();
std::streamsize read_line(char *& line);
bool peek_whitespace_line() {
diff --git a/src/token.cc b/src/token.cc
index 67cff65e..199c3b3c 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -60,8 +60,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 'd':
if (std::strcmp(buf, "div") == 0) {
symbol[0] = '/';
- symbol[1] = '/';
- symbol[2] = '\0';
+ symbol[1] = '\0';
kind = KW_DIV;
return 1;
}
@@ -69,9 +68,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 'e':
if (std::strcmp(buf, "else") == 0) {
- symbol[0] = 'L';
- symbol[1] = 'S';
- symbol[2] = '\0';
+ std::strcpy(symbol, "else");
kind = KW_ELSE;
return 1;
}
@@ -79,6 +76,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 'f':
if (std::strcmp(buf, "false") == 0) {
+ std::strcpy(symbol, "false");
kind = VALUE;
value = false;
return 1;
@@ -115,6 +113,7 @@ int expr_t::token_t::parse_reserved_word(std::istream& in)
case 't':
if (std::strcmp(buf, "true") == 0) {
+ std::strcpy(symbol, "true");
kind = VALUE;
value = true;
return 1;
@@ -231,6 +230,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
break;
}
+#if 0
case '{': {
in.get(c);
amount_t temp;
@@ -243,6 +243,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
value = temp;
break;
}
+#endif
case '!':
in.get(c);
@@ -268,6 +269,15 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
case '-':
in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == '>') {
+ in.get(c);
+ symbol[1] = c;
+ symbol[2] = '\0';
+ kind = ARROW;
+ length = 2;
+ break;
+ }
kind = MINUS;
break;
case '+':
@@ -287,14 +297,6 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
case ':':
in.get(c);
c = static_cast<char>(in.peek());
- if (c == '=') {
- in.get(c);
- symbol[1] = c;
- symbol[2] = '\0';
- kind = DEFINE;
- length = 2;
- break;
- }
kind = COLON;
break;
@@ -336,7 +338,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
length = 2;
break;
}
- kind = EQUAL;
+ kind = ASSIGN;
break;
case '<':
@@ -403,6 +405,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
// maximum displayed precision.
parse_flags_t parse_flags;
+ parse_flags.add_flags(PARSE_NO_ANNOT);
if (pflags.has_flags(PARSE_NO_MIGRATE))
parse_flags.add_flags(PARSE_NO_MIGRATE);
if (pflags.has_flags(PARSE_NO_REDUCE))
diff --git a/src/token.h b/src/token.h
index aae73837..13a799cb 100644
--- a/src/token.h
+++ b/src/token.h
@@ -56,6 +56,8 @@ struct expr_t::token_t : public noncopyable
LPAREN, // (
RPAREN, // )
+ LBRACE, // {
+ RBRACE, // }
EQUAL, // ==
NEQUAL, // !=
@@ -64,7 +66,6 @@ struct expr_t::token_t : public noncopyable
GREATER, // >
GREATEREQ, // >=
- DEFINE, // :=
ASSIGN, // =
MATCH, // =~
NMATCH, // !~
@@ -72,6 +73,7 @@ struct expr_t::token_t : public noncopyable
PLUS, // +
STAR, // *
SLASH, // /
+ ARROW, // ->
KW_DIV, // div
EXCLAM, // !, not
@@ -94,7 +96,7 @@ struct expr_t::token_t : public noncopyable
} kind;
- char symbol[3];
+ char symbol[6];
value_t value;
std::size_t length;
@@ -113,13 +115,10 @@ struct expr_t::token_t : public noncopyable
}
void clear() {
- kind = UNKNOWN;
- length = 0;
- value = NULL_VALUE;
-
+ kind = UNKNOWN;
+ length = 0;
+ value = NULL_VALUE;
symbol[0] = '\0';
- symbol[1] = '\0';
- symbol[2] = '\0';
}
int parse_reserved_word(std::istream& in);
diff --git a/src/xact.h b/src/xact.h
index 41e58545..4879967f 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -117,6 +117,16 @@ public:
TRACE_DTOR(xact_t);
}
+ virtual string description() {
+ if (pos) {
+ std::ostringstream buf;
+ buf << _("transaction at line %1") << pos->beg_line;
+ return buf.str();
+ } else {
+ return string(_("generated transaction"));
+ }
+ }
+
virtual void add_post(post_t * post);
string idstring() const;
@@ -194,6 +204,16 @@ public:
TRACE_DTOR(auto_xact_t);
}
+ virtual string description() {
+ if (pos) {
+ std::ostringstream buf;
+ buf << _("automated transaction at line %1") << pos->beg_line;
+ return buf.str();
+ } else {
+ return string(_("generated automated transaction"));
+ }
+ }
+
virtual void parse_tags(const char * p,
scope_t&,
bool overwrite_existing = true) {
@@ -242,6 +262,16 @@ class period_xact_t : public xact_base_t
TRACE_DTOR(period_xact_t);
}
+ virtual string description() {
+ if (pos) {
+ std::ostringstream buf;
+ buf << _("periodic transaction at line %1") << pos->beg_line;
+ return buf.str();
+ } else {
+ return string(_("generated periodic transaction"));
+ }
+ }
+
#if defined(HAVE_BOOST_SERIALIZATION)
private:
/** Serialization. */