diff options
author | John Wiegley <johnw@newartisans.com> | 2010-09-05 01:38:47 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-09-05 01:38:47 -0400 |
commit | e162455ebb545ea33580e58f52ebe424ef9e68fa (patch) | |
tree | df9c98fb39f31b9003db07d7806815bf71031a2d /src | |
parent | 9fcf48482626f20151d75a2ebb81371b45d4540a (diff) | |
download | fork-ledger-e162455ebb545ea33580e58f52ebe424ef9e68fa.tar.gz fork-ledger-e162455ebb545ea33580e58f52ebe424ef9e68fa.tar.bz2 fork-ledger-e162455ebb545ea33580e58f52ebe424ef9e68fa.zip |
Minor simplifications to valexpr parser
The most significant change is the way CONS sequences are parsed, and
that now instead of =/:=, the operators are ==/=.
Diffstat (limited to 'src')
-rw-r--r-- | src/amount.cc | 6 | ||||
-rw-r--r-- | src/amount.h | 2 | ||||
-rw-r--r-- | src/compare.cc | 8 | ||||
-rw-r--r-- | src/expr.cc | 26 | ||||
-rw-r--r-- | src/op.cc | 45 | ||||
-rw-r--r-- | src/parser.cc | 53 | ||||
-rw-r--r-- | src/py_amount.cc | 1 | ||||
-rw-r--r-- | src/report.cc | 1 | ||||
-rw-r--r-- | src/token.cc | 22 | ||||
-rw-r--r-- | src/token.h | 11 |
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; @@ -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); |