summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/amount.cc6
-rw-r--r--src/amount.h2
-rw-r--r--src/compare.cc8
-rw-r--r--src/expr.cc26
-rw-r--r--src/op.cc45
-rw-r--r--src/parser.cc53
-rw-r--r--src/py_amount.cc1
-rw-r--r--src/report.cc1
-rw-r--r--src/token.cc22
-rw-r--r--src/token.h11
10 files changed, 79 insertions, 96 deletions
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/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 bcf83edb..b3d4abcd 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -167,22 +167,38 @@ value_t source_command(call_scope_t& args)
{
std::istream * in = NULL;
scoped_ptr<ifstream> stream;
+ string pathname;
if (args.has(0)) {
- stream.reset(new ifstream(path(args.get<string>(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);
+ symbol_scope_t file_locals(args);
+ std::size_t linenum = 0;
+ char buf[4096];
+ istream_pos_type pos;
while (in->good() && ! in->eof()) {
- char buf[4096];
+ pos = in->tellg();
in->getline(buf, 4095);
+ linenum++;
- if (buf[0] != ';')
- expr_t(buf).calc(file_locals);
+ 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;
diff --git a/src/op.cc b/src/op.cc
index f37bfa1f..6105e38e 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -191,8 +191,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
assert(left()->kind == O_CALL);
ptr_op_t sym = left()->right();
- if (sym->kind == O_SEQ)
- sym = sym->left();
symbol_scope_t call_scope(call_args);
@@ -242,8 +240,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
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());
@@ -474,6 +471,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);
@@ -488,118 +488,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:
@@ -623,15 +599,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;
@@ -648,7 +622,7 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
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 {
@@ -676,6 +650,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 << '@';
diff --git a/src/parser.cc b/src/parser.cc
index 9a1ebf6f..a5b1e6e3 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:
@@ -437,33 +428,37 @@ expr_t::parser_t::parse_value_expr(std::istream& in,
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 || tok.kind == token_t::SEMI) {
+ bool comma_op = tok.kind == token_t::COMMA;
- ptr_op_t prev(node);
- node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
- 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);
+ if (! next) {
+ ptr_op_t prev(node);
+ node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
+ node->set_left(prev);
- tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
- }
+ next = node;
+ }
+
+ token_t& ntok = next_token(in, tflags);
+ push_token(ntok);
+ if (ntok.kind == token_t::RPAREN)
+ break;
- if (tok.kind != token_t::TOK_EOF) {
- if (tflags.has_flags(PARSE_PARTIAL))
+ ptr_op_t chain(new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ));
+ chain->set_left(parse_querycolon_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/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/report.cc b/src/report.cc
index aaf5270a..5c7bf01d 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -561,6 +561,7 @@ value_t report_t::fn_print(call_scope_t& args)
{
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;
}
diff --git a/src/token.cc b/src/token.cc
index 67cff65e..be39205c 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);
@@ -287,14 +288,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 +329,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
length = 2;
break;
}
- kind = EQUAL;
+ kind = DEFINE;
break;
case '<':
@@ -403,6 +396,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..28e29752 100644
--- a/src/token.h
+++ b/src/token.h
@@ -94,7 +94,7 @@ struct expr_t::token_t : public noncopyable
} kind;
- char symbol[3];
+ char symbol[6];
value_t value;
std::size_t length;
@@ -113,13 +113,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);