Revised the way that parsing flags get passed around.
This commit is contained in:
parent
5b388af626
commit
8b75b5cbfb
12 changed files with 178 additions and 94 deletions
|
|
@ -149,9 +149,6 @@ EXC_TRANSLATOR(amount_error)
|
|||
|
||||
void export_amount()
|
||||
{
|
||||
scope().attr("AMOUNT_PARSE_NO_MIGRATE") = AMOUNT_PARSE_NO_MIGRATE;
|
||||
scope().attr("AMOUNT_PARSE_NO_REDUCE") = AMOUNT_PARSE_NO_REDUCE;
|
||||
|
||||
class_< amount_t > ("Amount")
|
||||
.def("initialize", &amount_t::initialize)
|
||||
.staticmethod("initialize")
|
||||
|
|
@ -385,6 +382,13 @@ internal precision.")
|
|||
.def("valid", &amount_t::valid)
|
||||
;
|
||||
|
||||
enum_< amount_t::parse_flags_enum_t >("AmountParse")
|
||||
.value("PARSE_DEFAULT", amount_t::PARSE_DEFAULT)
|
||||
.value("PARSE_NO_MIGRATE", amount_t::PARSE_NO_MIGRATE)
|
||||
.value("PARSE_NO_REDUCE", amount_t::PARSE_NO_REDUCE)
|
||||
.value("PARSE_SOFT_FAIL", amount_t::PARSE_SOFT_FAIL)
|
||||
;
|
||||
|
||||
register_optional_to_python<amount_t>();
|
||||
|
||||
#ifdef HAVE_GDTOA
|
||||
|
|
|
|||
|
|
@ -859,7 +859,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
bool amount_t::parse(std::istream& in, flags_t flags)
|
||||
bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
|
||||
{
|
||||
// The possible syntax for an amount is:
|
||||
//
|
||||
|
|
@ -911,7 +911,7 @@ bool amount_t::parse(std::istream& in, flags_t flags)
|
|||
}
|
||||
|
||||
if (quant.empty()) {
|
||||
if (flags & AMOUNT_PARSE_SOFT_FAIL)
|
||||
if (flags.has_flags(PARSE_SOFT_FAIL))
|
||||
return false;
|
||||
else
|
||||
throw_(amount_error, "No quantity specified for amount");
|
||||
|
|
@ -983,7 +983,7 @@ bool amount_t::parse(std::istream& in, flags_t flags)
|
|||
|
||||
// Set the commodity's flags and precision accordingly
|
||||
|
||||
if (commodity_ && ! (flags & AMOUNT_PARSE_NO_MIGRATE)) {
|
||||
if (commodity_ && ! flags.has_flags(PARSE_NO_MIGRATE)) {
|
||||
commodity().add_flags(comm_flags);
|
||||
|
||||
if (quantity->prec > commodity().precision())
|
||||
|
|
@ -992,7 +992,7 @@ bool amount_t::parse(std::istream& in, flags_t flags)
|
|||
|
||||
// Setup the amount's own flags
|
||||
|
||||
if (flags & AMOUNT_PARSE_NO_MIGRATE)
|
||||
if (flags.has_flags(PARSE_NO_MIGRATE))
|
||||
quantity->add_flags(BIGINT_KEEP_PREC);
|
||||
|
||||
// Now we have the final number. Remove commas and periods, if
|
||||
|
|
@ -1020,7 +1020,7 @@ bool amount_t::parse(std::istream& in, flags_t flags)
|
|||
if (negative)
|
||||
in_place_negate();
|
||||
|
||||
if (! (flags & AMOUNT_PARSE_NO_REDUCE))
|
||||
if (! flags.has_flags(PARSE_NO_REDUCE))
|
||||
in_place_reduce();
|
||||
|
||||
safe_holder.release(); // `this->quantity' owns the pointer
|
||||
|
|
@ -1035,8 +1035,8 @@ void amount_t::parse_conversion(const string& larger_str,
|
|||
{
|
||||
amount_t larger, smaller;
|
||||
|
||||
larger.parse(larger_str, AMOUNT_PARSE_NO_REDUCE);
|
||||
smaller.parse(smaller_str, AMOUNT_PARSE_NO_REDUCE);
|
||||
larger.parse(larger_str, PARSE_NO_REDUCE);
|
||||
smaller.parse(smaller_str, PARSE_NO_REDUCE);
|
||||
|
||||
larger *= smaller.number();
|
||||
|
||||
|
|
@ -1324,8 +1324,8 @@ void amount_t::read(const char *& data,
|
|||
|
||||
quantity->prec = *reinterpret_cast<precision_t *>(const_cast<char *>(data));
|
||||
data += sizeof(precision_t);
|
||||
quantity->set_flags(*reinterpret_cast<flags_t *>(const_cast<char *>(data)));
|
||||
data += sizeof(flags_t);
|
||||
quantity->set_flags(*reinterpret_cast<bigint_t::flags_t *>(const_cast<char *>(data)));
|
||||
data += sizeof(bigint_t::flags_t);
|
||||
|
||||
if (byte == 2)
|
||||
quantity->add_flags(BIGINT_BULK_ALLOC);
|
||||
|
|
|
|||
31
src/amount.h
31
src/amount.h
|
|
@ -633,17 +633,36 @@ public:
|
|||
* between scaling commodity values. For example, Ledger uses it to
|
||||
* define the relationships among various time values:
|
||||
*
|
||||
* @code
|
||||
* amount_t::parse_conversion("1.0m", "60s"); // a minute is 60 seconds
|
||||
* amount_t::parse_conversion("1.0h", "60m"); // an hour is 60 minutes
|
||||
* @endcode
|
||||
*/
|
||||
#define AMOUNT_PARSE_NO_MIGRATE 0x01
|
||||
#define AMOUNT_PARSE_NO_REDUCE 0x02
|
||||
#define AMOUNT_PARSE_SOFT_FAIL 0x04
|
||||
enum parse_flags_enum_t {
|
||||
PARSE_DEFAULT = 0x00,
|
||||
PARSE_NO_MIGRATE = 0x01,
|
||||
PARSE_NO_REDUCE = 0x02,
|
||||
PARSE_SOFT_FAIL = 0x04
|
||||
};
|
||||
|
||||
typedef uint_least8_t flags_t;
|
||||
typedef basic_flags_t<parse_flags_enum_t, uint_least8_t> parse_flags_t;
|
||||
|
||||
bool parse(std::istream& in, flags_t flags = 0);
|
||||
bool parse(const string& str, flags_t flags = 0) {
|
||||
/**
|
||||
* The method parse() is used to parse an amount from an input stream
|
||||
* or a string. A global operator>>() is also defined which simply
|
||||
* calls parse on the input stream. The parse() method has two forms:
|
||||
*
|
||||
* parse(istream, flags_t) parses an amount from the given input
|
||||
* stream.
|
||||
*
|
||||
* parse(string, flags_t) parses an amount from the given string.
|
||||
*
|
||||
* parse(string, flags_t) also parses an amount from a string.
|
||||
*/
|
||||
bool parse(std::istream& in,
|
||||
const parse_flags_t& flags = PARSE_DEFAULT);
|
||||
bool parse(const string& str,
|
||||
const parse_flags_t& flags = PARSE_DEFAULT) {
|
||||
std::istringstream stream(str);
|
||||
bool result = parse(stream, flags);
|
||||
assert(stream.eof());
|
||||
|
|
|
|||
|
|
@ -630,7 +630,7 @@ void annotation_t::parse(std::istream& in)
|
|||
throw_(amount_error, "Commodity price lacks closing brace");
|
||||
|
||||
amount_t temp;
|
||||
temp.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
|
||||
temp.parse(buf, amount_t::PARSE_NO_MIGRATE);
|
||||
temp.in_place_reduce();
|
||||
|
||||
// Since this price will maintain its own precision, make sure
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ expr_t::expr_t(const expr_t& other)
|
|||
TRACE_CTOR(expr_t, "copy");
|
||||
}
|
||||
|
||||
expr_t::expr_t(const string& _str, const unsigned int flags)
|
||||
expr_t::expr_t(const string& _str, const uint_least8_t flags)
|
||||
: str(_str), compiled(false)
|
||||
{
|
||||
TRACE_CTOR(expr_t, "const string&");
|
||||
|
|
@ -57,7 +57,7 @@ expr_t::expr_t(const string& _str, const unsigned int flags)
|
|||
ptr = parser->parse(str, flags);
|
||||
}
|
||||
|
||||
expr_t::expr_t(std::istream& in, const unsigned int flags)
|
||||
expr_t::expr_t(std::istream& in, const uint_least8_t flags)
|
||||
: compiled(false)
|
||||
{
|
||||
TRACE_CTOR(expr_t, "std::istream&");
|
||||
|
|
|
|||
14
src/expr.h
14
src/expr.h
|
|
@ -57,6 +57,16 @@ public:
|
|||
class op_t;
|
||||
typedef intrusive_ptr<op_t> ptr_op_t;
|
||||
|
||||
enum parse_flags_enum_t {
|
||||
PARSE_NORMAL = 0x00,
|
||||
PARSE_PARTIAL = 0x01,
|
||||
PARSE_SINGLE = 0x02,
|
||||
PARSE_NO_MIGRATE = 0x04,
|
||||
PARSE_NO_REDUCE = 0x08,
|
||||
PARSE_NO_ASSIGN = 0x10,
|
||||
PARSE_NO_DATES = 0x20
|
||||
};
|
||||
|
||||
private:
|
||||
ptr_op_t ptr;
|
||||
string str;
|
||||
|
|
@ -75,8 +85,8 @@ public:
|
|||
expr_t(const expr_t& other);
|
||||
expr_t(const ptr_op_t& _ptr, const string& _str = "");
|
||||
|
||||
expr_t(const string& _str, const unsigned int flags = 0);
|
||||
expr_t(std::istream& in, const unsigned int flags = 0);
|
||||
expr_t(const string& _str, const uint_least8_t flags = 0);
|
||||
expr_t(std::istream& in, const uint_least8_t flags = 0);
|
||||
|
||||
virtual ~expr_t() throw();
|
||||
|
||||
|
|
|
|||
57
src/flags.h
57
src/flags.h
|
|
@ -32,7 +32,7 @@
|
|||
#ifndef _FLAGS_H
|
||||
#define _FLAGS_H
|
||||
|
||||
template <typename T = boost::uint_least8_t>
|
||||
template <typename T = boost::uint_least8_t, typename U = T>
|
||||
class supports_flags
|
||||
{
|
||||
public:
|
||||
|
|
@ -42,7 +42,7 @@ protected:
|
|||
flags_t _flags;
|
||||
|
||||
public:
|
||||
supports_flags() : _flags(0) {
|
||||
supports_flags() : _flags(static_cast<T>(0)) {
|
||||
TRACE_CTOR(supports_flags, "");
|
||||
}
|
||||
supports_flags(const supports_flags& arg) : _flags(arg._flags) {
|
||||
|
|
@ -66,13 +66,60 @@ public:
|
|||
_flags = arg;
|
||||
}
|
||||
void clear_flags() {
|
||||
_flags = 0;
|
||||
_flags = static_cast<T>(0);
|
||||
}
|
||||
void add_flags(const flags_t arg) {
|
||||
_flags |= arg;
|
||||
_flags = static_cast<T>(static_cast<U>(_flags) | static_cast<U>(arg));
|
||||
}
|
||||
void drop_flags(const flags_t arg) {
|
||||
_flags &= ~arg;
|
||||
_flags = static_cast<T>(static_cast<U>(_flags) & static_cast<U>(~arg));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T = boost::uint_least8_t, typename U = T>
|
||||
class basic_flags_t : public supports_flags<T, U>
|
||||
{
|
||||
public:
|
||||
basic_flags_t() {
|
||||
TRACE_CTOR(basic_flags_t, "");
|
||||
}
|
||||
basic_flags_t(const T& bits) {
|
||||
TRACE_CTOR(basic_flags_t, "const T&");
|
||||
set_flags(bits);
|
||||
}
|
||||
basic_flags_t(const U& bits) {
|
||||
TRACE_CTOR(basic_flags_t, "const U&");
|
||||
set_flags(static_cast<T>(bits));
|
||||
}
|
||||
~basic_flags_t() throw() {
|
||||
TRACE_DTOR(basic_flags_t);
|
||||
}
|
||||
|
||||
basic_flags_t& operator=(const basic_flags_t& other) {
|
||||
set_flags(other.flags());
|
||||
return *this;
|
||||
}
|
||||
basic_flags_t& operator=(const T& bits) {
|
||||
set_flags(bits);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return supports_flags<T, U>::flags();
|
||||
}
|
||||
operator U() const {
|
||||
return supports_flags<T, U>::flags();
|
||||
}
|
||||
|
||||
basic_flags_t plus_flags(const T& arg) const {
|
||||
basic_flags_t temp(*this);
|
||||
temp.add_flags(arg);
|
||||
return temp;
|
||||
}
|
||||
basic_flags_t minus_flags(const T& arg) const {
|
||||
basic_flags_t temp(*this);
|
||||
temp.drop_flags(arg);
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "format.h"
|
||||
#include "account.h"
|
||||
#include "parser.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
@ -213,7 +212,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt)
|
|||
std::istringstream str(p);
|
||||
current->type = element_t::EXPR;
|
||||
string temp(p);
|
||||
current->expr.parse(str, EXPR_PARSE_SINGLE, &temp);
|
||||
current->expr.parse(str, expr_t::PARSE_SINGLE, &temp);
|
||||
if (str.eof()) {
|
||||
current->expr.set_text(p);
|
||||
p += std::strlen(p);
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
namespace ledger {
|
||||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_value_term(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
expr_t::parser_t::parse_value_term(std::istream& in,
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node;
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
|||
node = call_node;
|
||||
|
||||
push_token(tok); // let the parser see it again
|
||||
node->set_right(parse_value_expr(in, tflags | EXPR_PARSE_SINGLE));
|
||||
node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE)));
|
||||
} else {
|
||||
push_token(tok);
|
||||
}
|
||||
|
|
@ -74,8 +74,7 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
|||
}
|
||||
|
||||
case token_t::LPAREN:
|
||||
node = parse_value_expr(in, (tflags | EXPR_PARSE_PARTIAL) &
|
||||
~EXPR_PARSE_SINGLE);
|
||||
node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL).minus_flags(PARSE_SINGLE));
|
||||
tok = next_token(in, tflags);
|
||||
if (tok.kind != token_t::RPAREN)
|
||||
tok.expected(')');
|
||||
|
|
@ -91,7 +90,7 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_unary_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node;
|
||||
|
||||
|
|
@ -143,11 +142,11 @@ expr_t::parser_t::parse_unary_expr(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_mul_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_unary_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
token_t& tok = next_token(in, tflags);
|
||||
|
||||
if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) {
|
||||
|
|
@ -169,11 +168,11 @@ expr_t::parser_t::parse_mul_expr(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_add_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_mul_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
token_t& tok = next_token(in, tflags);
|
||||
|
||||
if (tok.kind == token_t::PLUS ||
|
||||
|
|
@ -196,19 +195,19 @@ expr_t::parser_t::parse_add_expr(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_logic_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_add_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
op_t::kind_t kind = op_t::LAST;
|
||||
flags_t _flags = tflags;
|
||||
token_t& tok = next_token(in, tflags);
|
||||
bool negate = false;
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
op_t::kind_t kind = op_t::LAST;
|
||||
parse_flags_t _flags = tflags;
|
||||
token_t& tok = next_token(in, tflags);
|
||||
bool negate = false;
|
||||
|
||||
switch (tok.kind) {
|
||||
case token_t::EQUAL:
|
||||
if (tflags & EXPR_PARSE_NO_ASSIGN)
|
||||
if (tflags.has_flags(PARSE_NO_ASSIGN))
|
||||
tok.rewind(in);
|
||||
else
|
||||
kind = op_t::O_EQ;
|
||||
|
|
@ -264,11 +263,11 @@ expr_t::parser_t::parse_logic_expr(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_and_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_logic_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
token_t& tok = next_token(in, tflags);
|
||||
|
||||
if (tok.kind == token_t::KW_AND) {
|
||||
|
|
@ -288,11 +287,11 @@ expr_t::parser_t::parse_and_expr(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_or_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_and_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
token_t& tok = next_token(in, tflags);
|
||||
|
||||
if (tok.kind == token_t::KW_OR) {
|
||||
|
|
@ -312,11 +311,11 @@ expr_t::parser_t::parse_or_expr(std::istream& in,
|
|||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse_querycolon_expr(std::istream& in,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_or_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
token_t& tok = next_token(in, tflags);
|
||||
|
||||
if (tok.kind == token_t::QUERY) {
|
||||
|
|
@ -348,11 +347,11 @@ 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,
|
||||
const flags_t tflags) const
|
||||
const parse_flags_t& tflags) const
|
||||
{
|
||||
ptr_op_t node(parse_querycolon_expr(in, tflags));
|
||||
|
||||
if (node && ! (tflags & EXPR_PARSE_SINGLE)) {
|
||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||
token_t& tok = next_token(in, tflags);
|
||||
|
||||
if (tok.kind == token_t::COMMA) {
|
||||
|
|
@ -367,14 +366,14 @@ expr_t::parser_t::parse_value_expr(std::istream& in,
|
|||
}
|
||||
|
||||
if (tok.kind != token_t::TOK_EOF) {
|
||||
if (tflags & EXPR_PARSE_PARTIAL)
|
||||
if (tflags.has_flags(PARSE_PARTIAL))
|
||||
push_token(tok);
|
||||
else
|
||||
tok.unexpected();
|
||||
}
|
||||
}
|
||||
else if (! (tflags & (EXPR_PARSE_PARTIAL |
|
||||
EXPR_PARSE_SINGLE))) {
|
||||
else if (! tflags.has_flags(PARSE_PARTIAL) &&
|
||||
! tflags.has_flags(PARSE_SINGLE)) {
|
||||
throw_(parse_error, "Failed to parse value expression");
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +381,7 @@ expr_t::parser_t::parse_value_expr(std::istream& in,
|
|||
}
|
||||
|
||||
expr_t::ptr_op_t
|
||||
expr_t::parser_t::parse(std::istream& in, const flags_t flags,
|
||||
expr_t::parser_t::parse(std::istream& in, const parse_flags_t& flags,
|
||||
const string * original_string)
|
||||
{
|
||||
try {
|
||||
|
|
|
|||
47
src/parser.h
47
src/parser.h
|
|
@ -39,22 +39,14 @@ namespace ledger {
|
|||
|
||||
class expr_t::parser_t : public noncopyable
|
||||
{
|
||||
#define EXPR_PARSE_NORMAL 0x00
|
||||
#define EXPR_PARSE_PARTIAL 0x01
|
||||
#define EXPR_PARSE_SINGLE 0x02
|
||||
#define EXPR_PARSE_NO_MIGRATE 0x04
|
||||
#define EXPR_PARSE_NO_REDUCE 0x08
|
||||
#define EXPR_PARSE_NO_ASSIGN 0x10
|
||||
#define EXPR_PARSE_NO_DATES 0x20
|
||||
|
||||
public:
|
||||
typedef uint_least8_t flags_t;
|
||||
typedef basic_flags_t<parse_flags_enum_t, uint_least8_t> parse_flags_t;
|
||||
|
||||
private:
|
||||
mutable token_t lookahead;
|
||||
mutable bool use_lookahead;
|
||||
|
||||
token_t& next_token(std::istream& in, flags_t tflags) const {
|
||||
token_t& next_token(std::istream& in, const parse_flags_t& tflags) const {
|
||||
if (use_lookahead)
|
||||
use_lookahead = false;
|
||||
else
|
||||
|
|
@ -70,15 +62,24 @@ private:
|
|||
use_lookahead = true;
|
||||
}
|
||||
|
||||
ptr_op_t parse_value_term(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_unary_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_mul_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_add_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_logic_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_and_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_or_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_querycolon_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_value_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_value_term(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
ptr_op_t parse_unary_expr(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
ptr_op_t parse_mul_expr(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
ptr_op_t parse_add_expr(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
ptr_op_t parse_logic_expr(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
ptr_op_t parse_and_expr(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
ptr_op_t parse_or_expr(std::istream& in,
|
||||
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_value_expr(std::istream& in,
|
||||
const parse_flags_t& flags) const;
|
||||
|
||||
public:
|
||||
parser_t() : use_lookahead(false) {
|
||||
|
|
@ -88,9 +89,11 @@ public:
|
|||
TRACE_DTOR(parser_t);
|
||||
}
|
||||
|
||||
ptr_op_t parse(std::istream& in, const flags_t flags = EXPR_PARSE_NORMAL,
|
||||
const string * original_string = NULL);
|
||||
ptr_op_t parse(string& str, const flags_t flags = EXPR_PARSE_NORMAL) {
|
||||
ptr_op_t parse(std::istream& in,
|
||||
const parse_flags_t& flags = PARSE_NORMAL,
|
||||
const string * original_string = NULL);
|
||||
ptr_op_t parse(const string& str,
|
||||
const parse_flags_t& flags = PARSE_NORMAL) {
|
||||
std::istringstream stream(str);
|
||||
return parse(stream, flags, &str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ namespace {
|
|||
optional<expr_t> parse_amount_expr(std::istream& in,
|
||||
amount_t& amount,
|
||||
xact_t * xact,
|
||||
unsigned short flags = 0)
|
||||
uint_least8_t flags = 0)
|
||||
{
|
||||
expr_t expr(in, flags | EXPR_PARSE_PARTIAL);
|
||||
expr_t expr(in, flags | static_cast<uint_least8_t>(expr_t::PARSE_PARTIAL));
|
||||
|
||||
DEBUG("textual.parse", "line " << linenum << ": " <<
|
||||
"Parsed an amount expression");
|
||||
|
|
@ -204,7 +204,8 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
|||
|
||||
xact->amount_expr =
|
||||
parse_amount_expr(in, xact->amount, xact.get(),
|
||||
EXPR_PARSE_NO_REDUCE | EXPR_PARSE_NO_ASSIGN);
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_REDUCE) |
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN));
|
||||
saw_amount = true;
|
||||
|
||||
if (! xact->amount.is_null()) {
|
||||
|
|
@ -257,8 +258,8 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
|||
|
||||
xact->cost_expr =
|
||||
parse_amount_expr(in, *xact->cost, xact.get(),
|
||||
EXPR_PARSE_NO_MIGRATE |
|
||||
EXPR_PARSE_NO_ASSIGN);
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE) |
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN));
|
||||
|
||||
if (xact->cost_expr) {
|
||||
istream_pos_type end = in.tellg();
|
||||
|
|
@ -315,7 +316,7 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
|||
|
||||
xact->assigned_amount_expr =
|
||||
parse_amount_expr(in, *xact->assigned_amount, xact.get(),
|
||||
EXPR_PARSE_NO_MIGRATE);
|
||||
static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE));
|
||||
|
||||
if (xact->assigned_amount->is_null())
|
||||
throw parse_error
|
||||
|
|
|
|||
16
src/token.cc
16
src/token.cc
|
|
@ -198,7 +198,7 @@ void expr_t::token_t::next(std::istream& in, const uint_least8_t pflags)
|
|||
case '{': {
|
||||
in.get(c);
|
||||
amount_t temp;
|
||||
temp.parse(in, AMOUNT_PARSE_NO_MIGRATE);
|
||||
temp.parse(in, amount_t::PARSE_NO_MIGRATE);
|
||||
in.get(c);
|
||||
if (c != '}')
|
||||
expected('}', c);
|
||||
|
|
@ -343,15 +343,17 @@ void expr_t::token_t::next(std::istream& in, const uint_least8_t pflags)
|
|||
// When in relaxed parsing mode, we want to migrate commodity flags
|
||||
// so that any precision specified by the user updates the current
|
||||
// maximum displayed precision.
|
||||
amount_t::flags_t parse_flags = 0;
|
||||
if (pflags & EXPR_PARSE_NO_MIGRATE)
|
||||
parse_flags |= AMOUNT_PARSE_NO_MIGRATE;
|
||||
if (pflags & EXPR_PARSE_NO_REDUCE)
|
||||
parse_flags |= AMOUNT_PARSE_NO_REDUCE;
|
||||
amount_t::parse_flags_t parse_flags;
|
||||
parser_t::parse_flags_t pflags_copy(pflags);
|
||||
|
||||
if (pflags_copy.has_flags(PARSE_NO_MIGRATE))
|
||||
parse_flags.add_flags(amount_t::PARSE_NO_MIGRATE);
|
||||
if (pflags_copy.has_flags(PARSE_NO_REDUCE))
|
||||
parse_flags.add_flags(amount_t::PARSE_NO_REDUCE);
|
||||
|
||||
try {
|
||||
amount_t temp;
|
||||
if (! temp.parse(in, parse_flags | AMOUNT_PARSE_SOFT_FAIL)) {
|
||||
if (! temp.parse(in, parse_flags.plus_flags(amount_t::PARSE_SOFT_FAIL))) {
|
||||
// If the amount had no commodity, it must be an unambiguous
|
||||
// variable reference
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue