Segregated symbols into 5 separate namespaces
The different namespaces are:
Function Value expression functions, which receive a "context"
Option Command-line options
Precommand Commands which are invoked before reading the journal
Command Commands which are invoked after reading the journal
Directive Directives that occur at column 0 in a data file
This greatly eases the ability for Python uses to add intercept hooks to
change how the basic Ledger module functions. An example of what should
be possible soon:
import ledger
def my_foo_handler(value):
print "--foo received:", value
ledger.add_handler(ledger.Option, "foo=", my_foo_handler)
This commit is contained in:
parent
4a14f3224b
commit
78e6770c4c
23 changed files with 509 additions and 423 deletions
|
|
@ -241,8 +241,12 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t account_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
if (kind != symbol_t::FUNCTION)
|
||||
return NULL;
|
||||
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
if (name == "amount")
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ public:
|
|||
}
|
||||
bool remove_post(post_t * post);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -314,28 +314,32 @@ option_t<global_scope_t> * global_scope_t::lookup_option(const char * p)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t global_scope_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t global_scope_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'o':
|
||||
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
||||
if (option_t<global_scope_t> * handler = lookup_option(p))
|
||||
return MAKE_OPT_HANDLER(global_scope_t, handler);
|
||||
}
|
||||
switch (kind) {
|
||||
case symbol_t::FUNCTION:
|
||||
if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
|
||||
return MAKE_OPT_FUNCTOR(global_scope_t, handler);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
|
||||
switch (*q) {
|
||||
case 'p':
|
||||
if (is_eq(q, "push"))
|
||||
return MAKE_FUNCTOR(global_scope_t::push_command);
|
||||
else if (is_eq(q, "pop"))
|
||||
return MAKE_FUNCTOR(global_scope_t::pop_command);
|
||||
break;
|
||||
}
|
||||
case symbol_t::OPTION:
|
||||
if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
|
||||
return MAKE_OPT_HANDLER(global_scope_t, handler);
|
||||
break;
|
||||
|
||||
case symbol_t::PRECOMMAND: {
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'p':
|
||||
if (is_eq(p, "push"))
|
||||
return MAKE_FUNCTOR(global_scope_t::push_command);
|
||||
else if (is_eq(p, "pop"))
|
||||
return MAKE_FUNCTOR(global_scope_t::pop_command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +400,7 @@ void global_scope_t::normalize_session_options()
|
|||
function_t global_scope_t::look_for_precommand(scope_t& scope,
|
||||
const string& verb)
|
||||
{
|
||||
if (expr_t::ptr_op_t def = scope.lookup(string(PRECMD_PREFIX) + verb))
|
||||
if (expr_t::ptr_op_t def = scope.lookup(symbol_t::PRECOMMAND, verb))
|
||||
return def->as_function();
|
||||
else
|
||||
return function_t();
|
||||
|
|
@ -405,7 +409,7 @@ function_t global_scope_t::look_for_precommand(scope_t& scope,
|
|||
function_t global_scope_t::look_for_command(scope_t& scope,
|
||||
const string& verb)
|
||||
{
|
||||
if (expr_t::ptr_op_t def = scope.lookup(string(CMD_PREFIX) + verb))
|
||||
if (expr_t::ptr_op_t def = scope.lookup(symbol_t::COMMAND, verb))
|
||||
return def->as_function();
|
||||
else
|
||||
return function_t();
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ See LICENSE file included with the distribution for details and disclaimer.");
|
|||
|
||||
option_t<global_scope_t> * lookup_option(const char * p);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
OPTION(global_scope_t, args_only);
|
||||
OPTION(global_scope_t, debug_);
|
||||
|
|
|
|||
|
|
@ -304,8 +304,12 @@ value_t get_comment(item_t& item)
|
|||
}
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t item_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
if (kind != symbol_t::FUNCTION)
|
||||
return NULL;
|
||||
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
if (name == "actual")
|
||||
|
|
|
|||
|
|
@ -189,7 +189,8 @@ public:
|
|||
return _state;
|
||||
}
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
|
|
|
|||
14
src/op.cc
14
src/op.cc
|
|
@ -43,7 +43,7 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
|||
if (is_ident()) {
|
||||
DEBUG("expr.compile", "lookup: " << as_ident());
|
||||
|
||||
if (ptr_op_t def = scope.lookup(as_ident())) {
|
||||
if (ptr_op_t def = scope.lookup(symbol_t::FUNCTION, as_ident())) {
|
||||
// Identifier references are first looked up at the point of
|
||||
// definition, and then at the point of every use if they could
|
||||
// not be found there.
|
||||
|
|
@ -65,11 +65,11 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
|||
if (kind == O_DEFINE) {
|
||||
switch (left()->kind) {
|
||||
case IDENT:
|
||||
scope.define(left()->as_ident(), right());
|
||||
scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
|
||||
break;
|
||||
case O_CALL:
|
||||
if (left()->left()->is_ident())
|
||||
scope.define(left()->left()->as_ident(), this);
|
||||
scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this);
|
||||
else
|
||||
throw_(compile_error, _("Invalid function definition"));
|
||||
break;
|
||||
|
|
@ -152,9 +152,10 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
|||
if (! varname->is_ident())
|
||||
throw_(calc_error, _("Invalid function definition"));
|
||||
else if (args_index == args_count)
|
||||
local_scope.define(varname->as_ident(), wrap_value(false));
|
||||
local_scope.define(symbol_t::FUNCTION, varname->as_ident(),
|
||||
wrap_value(false));
|
||||
else
|
||||
local_scope.define(varname->as_ident(),
|
||||
local_scope.define(symbol_t::FUNCTION, varname->as_ident(),
|
||||
wrap_value(call_args[args_index++]));
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +179,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
|||
_("Left operand of . operator is NULL"));
|
||||
} else {
|
||||
scope_t& objscope(*obj.as_scope());
|
||||
if (ptr_op_t member = objscope.lookup(right()->as_ident())) {
|
||||
if (ptr_op_t member =
|
||||
objscope.lookup(symbol_t::FUNCTION, right()->as_ident())) {
|
||||
result = member->calc(objscope, NULL, depth + 1);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ namespace {
|
|||
op_bool_tuple find_option(scope_t& scope, const string& name)
|
||||
{
|
||||
char buf[128];
|
||||
std::strcpy(buf, "opt_");
|
||||
char * p = &buf[4];
|
||||
char * p = buf;
|
||||
foreach (char ch, name) {
|
||||
if (ch == '-')
|
||||
*p++ = '_';
|
||||
|
|
@ -52,28 +51,27 @@ namespace {
|
|||
*p++ = '_';
|
||||
*p = '\0';
|
||||
|
||||
if (expr_t::ptr_op_t op = scope.lookup(buf))
|
||||
if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
|
||||
return op_bool_tuple(op, true);
|
||||
|
||||
*--p = '\0';
|
||||
|
||||
return op_bool_tuple(scope.lookup(buf), false);
|
||||
return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
|
||||
}
|
||||
|
||||
op_bool_tuple find_option(scope_t& scope, const char letter)
|
||||
{
|
||||
char buf[10];
|
||||
std::strcpy(buf, "opt_");
|
||||
buf[4] = letter;
|
||||
buf[5] = '_';
|
||||
buf[6] = '\0';
|
||||
char buf[4];
|
||||
buf[0] = letter;
|
||||
buf[1] = '_';
|
||||
buf[2] = '\0';
|
||||
|
||||
if (expr_t::ptr_op_t op = scope.lookup(buf))
|
||||
if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
|
||||
return op_bool_tuple(op, true);
|
||||
|
||||
buf[5] = '\0';
|
||||
buf[1] = '\0';
|
||||
|
||||
return op_bool_tuple(scope.lookup(buf), false);
|
||||
return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
|
||||
}
|
||||
|
||||
void process_option(const string& whence, const function_t& opt,
|
||||
|
|
|
|||
24
src/option.h
24
src/option.h
|
|
@ -283,30 +283,6 @@ inline bool is_eq(const char * p, const char * n) {
|
|||
} \
|
||||
END(name)
|
||||
|
||||
#define OPT_PREFIX "opt_"
|
||||
#define OPT_PREFIX_LEN 4
|
||||
|
||||
#define WANT_OPT() \
|
||||
(std::strncmp(p, OPT_PREFIX, OPT_PREFIX_LEN) == 0)
|
||||
|
||||
#define PRECMD_PREFIX "precmd_"
|
||||
#define PRECMD_PREFIX_LEN 7
|
||||
|
||||
#define WANT_PRECMD() \
|
||||
(std::strncmp(p, PRECMD_PREFIX, PRECMD_PREFIX_LEN) == 0)
|
||||
|
||||
#define CMD_PREFIX "cmd_"
|
||||
#define CMD_PREFIX_LEN 4
|
||||
|
||||
#define WANT_CMD() \
|
||||
(std::strncmp(p, CMD_PREFIX, CMD_PREFIX_LEN) == 0)
|
||||
|
||||
#define DIR_PREFIX "dir_"
|
||||
#define DIR_PREFIX_LEN 4
|
||||
|
||||
#define WANT_DIR() \
|
||||
(std::strncmp(p, DIR_PREFIX, DIR_PREFIX_LEN) == 0)
|
||||
|
||||
bool process_option(const string& whence, const string& name, scope_t& scope,
|
||||
const char * arg, const string& varname);
|
||||
|
||||
|
|
|
|||
|
|
@ -271,8 +271,12 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t post_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
if (kind != symbol_t::FUNCTION)
|
||||
return item_t::lookup(kind, name);
|
||||
|
||||
switch (name[0]) {
|
||||
case 'a':
|
||||
if (name[1] == '\0' || name == "amount")
|
||||
|
|
@ -366,7 +370,7 @@ expr_t::ptr_op_t post_t::lookup(const string& name)
|
|||
break;
|
||||
}
|
||||
|
||||
return item_t::lookup(name);
|
||||
return item_t::lookup(kind, name);
|
||||
}
|
||||
|
||||
bool post_t::valid() const
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ public:
|
|||
return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE);
|
||||
}
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace {
|
|||
{
|
||||
if (value.is_scope()) {
|
||||
if (scope_t * scope = value.as_scope())
|
||||
return expr_t(scope->lookup(name), scope);
|
||||
return expr_t(scope->lookup(symbol_t::FUNCTION, name), scope);
|
||||
}
|
||||
throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
|
||||
return expr_t();
|
||||
|
|
|
|||
|
|
@ -285,38 +285,40 @@ python_interpreter_t::lookup_option(const char * p)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t python_interpreter_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
// Give our superclass first dibs on symbol definitions
|
||||
if (expr_t::ptr_op_t op = session_t::lookup(name))
|
||||
if (expr_t::ptr_op_t op = session_t::lookup(kind, name))
|
||||
return op;
|
||||
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'o':
|
||||
if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN;
|
||||
if (option_t<python_interpreter_t> * handler = lookup_option(q))
|
||||
return MAKE_OPT_HANDLER(python_interpreter_t, handler);
|
||||
switch (kind) {
|
||||
case symbol_t::FUNCTION:
|
||||
if (is_initialized && main_nspace.has_key(name.c_str())) {
|
||||
DEBUG("python.interp", "Python lookup: " << name);
|
||||
|
||||
if (python::object obj = main_nspace.get(name.c_str()))
|
||||
return WRAP_FUNCTOR(functor_t(name, obj));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
|
||||
switch (*q) {
|
||||
case 'p':
|
||||
if (is_eq(q, "python"))
|
||||
return MAKE_FUNCTOR(python_interpreter_t::python_command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case symbol_t::OPTION:
|
||||
if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
|
||||
return MAKE_OPT_HANDLER(python_interpreter_t, handler);
|
||||
break;
|
||||
|
||||
case symbol_t::PRECOMMAND: {
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'p':
|
||||
if (is_eq(p, "python"))
|
||||
return MAKE_FUNCTOR(python_interpreter_t::python_command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_initialized && main_nspace.has_key(name.c_str())) {
|
||||
DEBUG("python.interp", "Python lookup: " << name);
|
||||
|
||||
if (python::object obj = main_nspace.get(name.c_str()))
|
||||
return WRAP_FUNCTOR(functor_t(name, obj));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ public:
|
|||
|
||||
option_t<python_interpreter_t> * lookup_option(const char * p);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
#if BOOST_VERSION >= 103700
|
||||
OPTION_(python_interpreter_t, import_, DO_(scope) {
|
||||
|
|
|
|||
566
src/report.cc
566
src/report.cc
|
|
@ -464,8 +464,8 @@ value_t report_t::echo_command(call_scope_t& scope)
|
|||
|
||||
bool report_t::maybe_import(const string& module)
|
||||
{
|
||||
if (lookup(string(OPT_PREFIX) + "import_")) {
|
||||
expr_t(string(OPT_PREFIX) + "import_(\"" + module + "\")").calc(*this);
|
||||
if (lookup(symbol_t::OPTION, "import_")) {
|
||||
expr_t(string("import_(\"") + module + "\")").calc(*this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -707,304 +707,316 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void report_t::define(const string& name, expr_t::ptr_op_t def)
|
||||
void report_t::define(const symbol_t::kind_t kind, const string& name,
|
||||
expr_t::ptr_op_t def)
|
||||
{
|
||||
session.define(name, def);
|
||||
session.define(kind, name, def);
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t report_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
if (expr_t::ptr_op_t def = session.lookup(name))
|
||||
if (expr_t::ptr_op_t def = session.lookup(kind, name))
|
||||
return def;
|
||||
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
if (is_eq(p, "amount_expr"))
|
||||
return MAKE_FUNCTOR(report_t::fn_amount_expr);
|
||||
else if (is_eq(p, "ansify_if"))
|
||||
return MAKE_FUNCTOR(report_t::fn_ansify_if);
|
||||
else if (is_eq(p, "abs"))
|
||||
return MAKE_FUNCTOR(report_t::fn_abs);
|
||||
|
||||
switch (kind) {
|
||||
case symbol_t::FUNCTION:
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
if (is_eq(p, "amount_expr"))
|
||||
return MAKE_FUNCTOR(report_t::fn_amount_expr);
|
||||
else if (is_eq(p, "ansify_if"))
|
||||
return MAKE_FUNCTOR(report_t::fn_ansify_if);
|
||||
else if (is_eq(p, "abs"))
|
||||
return MAKE_FUNCTOR(report_t::fn_abs);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if (is_eq(p, "black"))
|
||||
return WRAP_FUNCTOR(fn_black);
|
||||
else if (is_eq(p, "blink"))
|
||||
return WRAP_FUNCTOR(fn_blink);
|
||||
else if (is_eq(p, "blue"))
|
||||
return WRAP_FUNCTOR(fn_blue);
|
||||
else if (is_eq(p, "bold"))
|
||||
return WRAP_FUNCTOR(fn_bold);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (is_eq(p, "cyan"))
|
||||
return WRAP_FUNCTOR(fn_cyan);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (is_eq(p, "display_amount"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
||||
else if (is_eq(p, "display_total"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_total);
|
||||
else if (is_eq(p, "date"))
|
||||
return MAKE_FUNCTOR(report_t::fn_now);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (is_eq(p, "format_date"))
|
||||
return MAKE_FUNCTOR(report_t::fn_format_date);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
if (is_eq(p, "get_at"))
|
||||
return MAKE_FUNCTOR(report_t::fn_get_at);
|
||||
else if (is_eq(p, "green"))
|
||||
return WRAP_FUNCTOR(fn_green);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
if (is_eq(p, "is_seq"))
|
||||
return MAKE_FUNCTOR(report_t::fn_is_seq);
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
if (is_eq(p, "justify"))
|
||||
return MAKE_FUNCTOR(report_t::fn_justify);
|
||||
else if (is_eq(p, "join"))
|
||||
return MAKE_FUNCTOR(report_t::fn_join);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (is_eq(p, "market"))
|
||||
return MAKE_FUNCTOR(report_t::fn_market);
|
||||
else if (is_eq(p, "magenta"))
|
||||
return WRAP_FUNCTOR(fn_magenta);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (is_eq(p, "null"))
|
||||
return WRAP_FUNCTOR(fn_null);
|
||||
else if (is_eq(p, "now"))
|
||||
return MAKE_FUNCTOR(report_t::fn_now);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (is_eq(p, "options"))
|
||||
return MAKE_FUNCTOR(report_t::fn_options);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (is_eq(p, "post"))
|
||||
return WRAP_FUNCTOR(fn_false);
|
||||
else if (is_eq(p, "percent"))
|
||||
return MAKE_FUNCTOR(report_t::fn_percent);
|
||||
else if (is_eq(p, "price"))
|
||||
return MAKE_FUNCTOR(report_t::fn_price);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
if (is_eq(p, "quoted"))
|
||||
return MAKE_FUNCTOR(report_t::fn_quoted);
|
||||
else if (is_eq(p, "quantity"))
|
||||
return MAKE_FUNCTOR(report_t::fn_quantity);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (is_eq(p, "rounded"))
|
||||
return MAKE_FUNCTOR(report_t::fn_rounded);
|
||||
else if (is_eq(p, "red"))
|
||||
return WRAP_FUNCTOR(fn_red);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (is_eq(p, "scrub"))
|
||||
return MAKE_FUNCTOR(report_t::fn_scrub);
|
||||
else if (is_eq(p, "strip"))
|
||||
return MAKE_FUNCTOR(report_t::fn_strip);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (is_eq(p, "truncated"))
|
||||
return MAKE_FUNCTOR(report_t::fn_truncated);
|
||||
else if (is_eq(p, "total_expr"))
|
||||
return MAKE_FUNCTOR(report_t::fn_total_expr);
|
||||
else if (is_eq(p, "today"))
|
||||
return MAKE_FUNCTOR(report_t::fn_today);
|
||||
else if (is_eq(p, "t"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (is_eq(p, "T"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_total);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (is_eq(p, "underline"))
|
||||
return WRAP_FUNCTOR(fn_underline);
|
||||
else if (is_eq(p, "unrounded"))
|
||||
return MAKE_FUNCTOR(report_t::fn_unrounded);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (is_eq(p, "white"))
|
||||
return WRAP_FUNCTOR(fn_white);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
if (is_eq(p, "yellow"))
|
||||
return WRAP_FUNCTOR(fn_yellow);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if they are trying to access an option's setting or value.
|
||||
if (option_t<report_t> * handler = lookup_option(p))
|
||||
return MAKE_OPT_FUNCTOR(report_t, handler);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if (is_eq(p, "black"))
|
||||
return WRAP_FUNCTOR(fn_black);
|
||||
else if (is_eq(p, "blink"))
|
||||
return WRAP_FUNCTOR(fn_blink);
|
||||
else if (is_eq(p, "blue"))
|
||||
return WRAP_FUNCTOR(fn_blue);
|
||||
else if (is_eq(p, "bold"))
|
||||
return WRAP_FUNCTOR(fn_bold);
|
||||
case symbol_t::OPTION:
|
||||
if (option_t<report_t> * handler = lookup_option(p))
|
||||
return MAKE_OPT_HANDLER(report_t, handler);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (WANT_CMD()) { const char * q = p + CMD_PREFIX_LEN;
|
||||
switch (*q) {
|
||||
case 'b':
|
||||
if (*(q + 1) == '\0' || is_eq(q, "bal") || is_eq(q, "balance")) {
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||
(new format_accounts(*this, report_format(HANDLER(balance_format_))),
|
||||
*this, "#balance"));
|
||||
}
|
||||
else if (is_eq(q, "budget")) {
|
||||
HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
|
||||
|
||||
budget_flags |= BUDGET_WRAP_VALUES;
|
||||
if (! (budget_flags & ~BUDGET_WRAP_VALUES))
|
||||
budget_flags |= BUDGET_BUDGETED;
|
||||
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||
(new format_accounts(*this, report_format(HANDLER(budget_format_))),
|
||||
*this, "#budget"));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (is_eq(q, "csv")) {
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(csv_format_))),
|
||||
*this, "#csv"));
|
||||
}
|
||||
else if (is_eq(q, "cleared")) {
|
||||
HANDLER(amount_).set_expr(string("#cleared"),
|
||||
"(amount, cleared ? amount : 0)");
|
||||
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||
(new format_accounts(*this, report_format(HANDLER(cleared_format_))),
|
||||
*this, "#cleared"));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
if (is_eq(q, "equity"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(print_format_))),
|
||||
*this, "#equity"));
|
||||
else if (is_eq(q, "entry"))
|
||||
return WRAP_FUNCTOR(xact_command);
|
||||
else if (is_eq(q, "emacs"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
|
||||
else if (is_eq(q, "echo"))
|
||||
return MAKE_FUNCTOR(report_t::echo_command);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (*(q + 1) == '\0' || is_eq(q, "print"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
||||
HANDLED(raw)), *this, "#print"));
|
||||
else if (is_eq(q, "prices"))
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||
(new format_posts(*this, report_format(HANDLER(prices_format_))),
|
||||
*this, "#prices"));
|
||||
else if (is_eq(q, "pricesdb"))
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||
(new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
|
||||
*this, "#pricesdb"));
|
||||
else if (is_eq(q, "python") && maybe_import("ledger.interp"))
|
||||
return session.lookup(string(CMD_PREFIX) + "python");
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (*(q + 1) == '\0' || is_eq(q, "reg") || is_eq(q, "register"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(register_format_))),
|
||||
*this, "#register"));
|
||||
else if (is_eq(q, "reload"))
|
||||
return MAKE_FUNCTOR(report_t::reload_command);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (is_eq(q, "stats") || is_eq(q, "stat"))
|
||||
return WRAP_FUNCTOR(report_statistics);
|
||||
else
|
||||
if (is_eq(q, "server") && maybe_import("ledger.server"))
|
||||
return session.lookup(string(CMD_PREFIX) + "server");
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
if (is_eq(q, "xact"))
|
||||
return WRAP_FUNCTOR(xact_command);
|
||||
break;
|
||||
case symbol_t::COMMAND:
|
||||
switch (*p) {
|
||||
case 'b':
|
||||
if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) {
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||
(new format_accounts(*this, report_format(HANDLER(balance_format_))),
|
||||
*this, "#balance"));
|
||||
}
|
||||
}
|
||||
else if (is_eq(p, "cyan"))
|
||||
return WRAP_FUNCTOR(fn_cyan);
|
||||
break;
|
||||
else if (is_eq(p, "budget")) {
|
||||
HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
|
||||
|
||||
case 'd':
|
||||
if (is_eq(p, "display_amount"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
||||
else if (is_eq(p, "display_total"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_total);
|
||||
else if (is_eq(p, "date"))
|
||||
return MAKE_FUNCTOR(report_t::fn_now);
|
||||
break;
|
||||
budget_flags |= BUDGET_WRAP_VALUES;
|
||||
if (! (budget_flags & ~BUDGET_WRAP_VALUES))
|
||||
budget_flags |= BUDGET_BUDGETED;
|
||||
|
||||
case 'f':
|
||||
if (is_eq(p, "format_date"))
|
||||
return MAKE_FUNCTOR(report_t::fn_format_date);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
if (is_eq(p, "get_at"))
|
||||
return MAKE_FUNCTOR(report_t::fn_get_at);
|
||||
else if (is_eq(p, "green"))
|
||||
return WRAP_FUNCTOR(fn_green);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
if (is_eq(p, "is_seq"))
|
||||
return MAKE_FUNCTOR(report_t::fn_is_seq);
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
if (is_eq(p, "justify"))
|
||||
return MAKE_FUNCTOR(report_t::fn_justify);
|
||||
else if (is_eq(p, "join"))
|
||||
return MAKE_FUNCTOR(report_t::fn_join);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (is_eq(p, "market"))
|
||||
return MAKE_FUNCTOR(report_t::fn_market);
|
||||
else if (is_eq(p, "magenta"))
|
||||
return WRAP_FUNCTOR(fn_magenta);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (is_eq(p, "null"))
|
||||
return WRAP_FUNCTOR(fn_null);
|
||||
else if (is_eq(p, "now"))
|
||||
return MAKE_FUNCTOR(report_t::fn_now);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN;
|
||||
if (option_t<report_t> * handler = lookup_option(q))
|
||||
return MAKE_OPT_HANDLER(report_t, handler);
|
||||
}
|
||||
else if (is_eq(p, "options")) {
|
||||
return MAKE_FUNCTOR(report_t::fn_options);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
|
||||
switch (*q) {
|
||||
case 'a':
|
||||
if (is_eq(q, "args"))
|
||||
return WRAP_FUNCTOR(args_command);
|
||||
break;
|
||||
case 'e':
|
||||
if (is_eq(q, "eval"))
|
||||
return WRAP_FUNCTOR(eval_command);
|
||||
break;
|
||||
case 'f':
|
||||
if (is_eq(q, "format"))
|
||||
return WRAP_FUNCTOR(format_command);
|
||||
break;
|
||||
case 'g':
|
||||
if (is_eq(q, "generate"))
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::generate_report>
|
||||
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
||||
false), *this, "#generate"));
|
||||
case 'h':
|
||||
if (is_eq(q, "hello") && maybe_import("ledger.hello"))
|
||||
return session.lookup(string(PRECMD_PREFIX) + "hello");
|
||||
break;
|
||||
case 'p':
|
||||
if (is_eq(q, "parse"))
|
||||
return WRAP_FUNCTOR(parse_command);
|
||||
else if (is_eq(q, "period"))
|
||||
return WRAP_FUNCTOR(period_command);
|
||||
break;
|
||||
case 't':
|
||||
if (is_eq(q, "template"))
|
||||
return WRAP_FUNCTOR(template_command);
|
||||
break;
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||
(new format_accounts(*this, report_format(HANDLER(budget_format_))),
|
||||
*this, "#budget"));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (is_eq(p, "csv")) {
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(csv_format_))),
|
||||
*this, "#csv"));
|
||||
}
|
||||
else if (is_eq(p, "cleared")) {
|
||||
HANDLER(amount_).set_expr(string("#cleared"),
|
||||
"(amount, cleared ? amount : 0)");
|
||||
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
|
||||
(new format_accounts(*this, report_format(HANDLER(cleared_format_))),
|
||||
*this, "#cleared"));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
if (is_eq(p, "equity"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(print_format_))),
|
||||
*this, "#equity"));
|
||||
else if (is_eq(p, "entry"))
|
||||
return WRAP_FUNCTOR(xact_command);
|
||||
else if (is_eq(p, "emacs"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
|
||||
else if (is_eq(p, "echo"))
|
||||
return MAKE_FUNCTOR(report_t::echo_command);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (*(p + 1) == '\0' || is_eq(p, "print"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
||||
HANDLED(raw)), *this, "#print"));
|
||||
else if (is_eq(p, "prices"))
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||
(new format_posts(*this, report_format(HANDLER(prices_format_))),
|
||||
*this, "#prices"));
|
||||
else if (is_eq(p, "pricesdb"))
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
|
||||
(new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
|
||||
*this, "#pricesdb"));
|
||||
else if (is_eq(p, "python") && maybe_import("ledger.interp"))
|
||||
return session.lookup(symbol_t::COMMAND, "python");
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register"))
|
||||
return WRAP_FUNCTOR
|
||||
(reporter<>
|
||||
(new format_posts(*this, report_format(HANDLER(register_format_))),
|
||||
*this, "#register"));
|
||||
else if (is_eq(p, "reload"))
|
||||
return MAKE_FUNCTOR(report_t::reload_command);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (is_eq(p, "stats") || is_eq(p, "stat"))
|
||||
return WRAP_FUNCTOR(report_statistics);
|
||||
else
|
||||
if (is_eq(p, "server") && maybe_import("ledger.server"))
|
||||
return session.lookup(symbol_t::COMMAND, "server");
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
if (is_eq(p, "xact"))
|
||||
return WRAP_FUNCTOR(xact_command);
|
||||
break;
|
||||
}
|
||||
else if (is_eq(p, "post"))
|
||||
return WRAP_FUNCTOR(fn_false);
|
||||
else if (is_eq(p, "percent"))
|
||||
return MAKE_FUNCTOR(report_t::fn_percent);
|
||||
else if (is_eq(p, "price"))
|
||||
return MAKE_FUNCTOR(report_t::fn_price);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
if (is_eq(p, "quoted"))
|
||||
return MAKE_FUNCTOR(report_t::fn_quoted);
|
||||
else if (is_eq(p, "quantity"))
|
||||
return MAKE_FUNCTOR(report_t::fn_quantity);
|
||||
case symbol_t::PRECOMMAND:
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
if (is_eq(p, "args"))
|
||||
return WRAP_FUNCTOR(args_command);
|
||||
break;
|
||||
case 'e':
|
||||
if (is_eq(p, "eval"))
|
||||
return WRAP_FUNCTOR(eval_command);
|
||||
break;
|
||||
case 'f':
|
||||
if (is_eq(p, "format"))
|
||||
return WRAP_FUNCTOR(format_command);
|
||||
break;
|
||||
case 'g':
|
||||
if (is_eq(p, "generate"))
|
||||
return expr_t::op_t::wrap_functor
|
||||
(reporter<post_t, post_handler_ptr, &report_t::generate_report>
|
||||
(new format_posts(*this, report_format(HANDLER(print_format_)),
|
||||
false), *this, "#generate"));
|
||||
case 'h':
|
||||
if (is_eq(p, "hello") && maybe_import("ledger.hello"))
|
||||
return session.lookup(symbol_t::PRECOMMAND, "hello");
|
||||
break;
|
||||
case 'p':
|
||||
if (is_eq(p, "parse"))
|
||||
return WRAP_FUNCTOR(parse_command);
|
||||
else if (is_eq(p, "period"))
|
||||
return WRAP_FUNCTOR(period_command);
|
||||
break;
|
||||
case 't':
|
||||
if (is_eq(p, "template"))
|
||||
return WRAP_FUNCTOR(template_command);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (is_eq(p, "rounded"))
|
||||
return MAKE_FUNCTOR(report_t::fn_rounded);
|
||||
else if (is_eq(p, "red"))
|
||||
return WRAP_FUNCTOR(fn_red);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (is_eq(p, "scrub"))
|
||||
return MAKE_FUNCTOR(report_t::fn_scrub);
|
||||
else if (is_eq(p, "strip"))
|
||||
return MAKE_FUNCTOR(report_t::fn_strip);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (is_eq(p, "truncated"))
|
||||
return MAKE_FUNCTOR(report_t::fn_truncated);
|
||||
else if (is_eq(p, "total_expr"))
|
||||
return MAKE_FUNCTOR(report_t::fn_total_expr);
|
||||
else if (is_eq(p, "today"))
|
||||
return MAKE_FUNCTOR(report_t::fn_today);
|
||||
else if (is_eq(p, "t"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_amount);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (is_eq(p, "T"))
|
||||
return MAKE_FUNCTOR(report_t::fn_display_total);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (is_eq(p, "underline"))
|
||||
return WRAP_FUNCTOR(fn_underline);
|
||||
else if (is_eq(p, "unrounded"))
|
||||
return MAKE_FUNCTOR(report_t::fn_unrounded);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (is_eq(p, "white"))
|
||||
return WRAP_FUNCTOR(fn_white);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
if (is_eq(p, "yellow"))
|
||||
return WRAP_FUNCTOR(fn_yellow);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if they are trying to access an option's setting or value.
|
||||
if (option_t<report_t> * handler = lookup_option(p))
|
||||
return MAKE_OPT_FUNCTOR(report_t, handler);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -311,9 +311,11 @@ public:
|
|||
|
||||
option_t<report_t> * lookup_option(const char * p);
|
||||
|
||||
virtual void define(const string& name, expr_t::ptr_op_t def);
|
||||
virtual void define(const symbol_t::kind_t kind, const string& name,
|
||||
expr_t::ptr_op_t def);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
/**
|
||||
* Option handlers
|
||||
|
|
|
|||
23
src/scope.cc
23
src/scope.cc
|
|
@ -35,31 +35,34 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
void symbol_scope_t::define(const string& name, expr_t::ptr_op_t def)
|
||||
void symbol_scope_t::define(const symbol_t::kind_t kind,
|
||||
const string& name, expr_t::ptr_op_t def)
|
||||
{
|
||||
DEBUG("scope.symbols", "Defining '" << name << "' = " << def);
|
||||
|
||||
std::pair<symbol_map::iterator, bool> result
|
||||
= symbols.insert(symbol_map::value_type(name, def));
|
||||
= symbols.insert(symbol_map::value_type(symbol_t(kind, name, def), def));
|
||||
if (! result.second) {
|
||||
symbol_map::iterator i = symbols.find(name);
|
||||
symbol_map::iterator i = symbols.find(symbol_t(kind, name));
|
||||
assert(i != symbols.end());
|
||||
symbols.erase(i);
|
||||
|
||||
std::pair<symbol_map::iterator, bool> result2
|
||||
= symbols.insert(symbol_map::value_type(name, def));
|
||||
if (! result2.second)
|
||||
throw_(compile_error, _("Redefinition of '%1' in same scope") << name);
|
||||
result = symbols.insert(symbol_map::value_type(symbol_t(kind, name, def),
|
||||
def));
|
||||
if (! result.second)
|
||||
throw_(compile_error,
|
||||
_("Redefinition of '%1' in the same scope") << name);
|
||||
}
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t symbol_scope_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t symbol_scope_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
symbol_map::const_iterator i = symbols.find(name);
|
||||
symbol_map::const_iterator i = symbols.find(symbol_t(kind, name));
|
||||
if (i != symbols.end())
|
||||
return (*i).second;
|
||||
|
||||
return child_scope_t::lookup(name);
|
||||
return child_scope_t::lookup(kind, name);
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
93
src/scope.h
93
src/scope.h
|
|
@ -50,6 +50,61 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Long.
|
||||
*/
|
||||
struct symbol_t
|
||||
{
|
||||
enum kind_t {
|
||||
UNKNOWN,
|
||||
FUNCTION,
|
||||
OPTION,
|
||||
PRECOMMAND,
|
||||
COMMAND,
|
||||
DIRECTIVE
|
||||
};
|
||||
|
||||
kind_t kind;
|
||||
string name;
|
||||
expr_t::ptr_op_t definition;
|
||||
|
||||
symbol_t() : kind(UNKNOWN), name(""), definition(NULL) {
|
||||
TRACE_CTOR(symbol_t, "");
|
||||
}
|
||||
symbol_t(kind_t _kind, string _name, expr_t::ptr_op_t _definition = NULL)
|
||||
: kind(_kind), name(_name), definition(_definition) {
|
||||
TRACE_CTOR(symbol_t, "symbol_t::kind_t, string");
|
||||
}
|
||||
symbol_t(const symbol_t& sym)
|
||||
: kind(sym.kind), name(sym.name),
|
||||
definition(sym.definition) {
|
||||
TRACE_CTOR(symbol_t, "copy");
|
||||
}
|
||||
~symbol_t() throw() {
|
||||
TRACE_DTOR(symbol_t);
|
||||
}
|
||||
|
||||
bool operator<(const symbol_t& sym) const {
|
||||
return kind < sym.kind || name < sym.name;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
/** Serialization. */
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& ar, const unsigned int /* version */) {
|
||||
ar & kind;
|
||||
ar & name;
|
||||
ar & definition;
|
||||
}
|
||||
#endif // HAVE_BOOST_SERIALIZATION
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
|
|
@ -65,8 +120,10 @@ public:
|
|||
TRACE_DTOR(scope_t);
|
||||
}
|
||||
|
||||
virtual void define(const string&, expr_t::ptr_op_t) {}
|
||||
virtual expr_t::ptr_op_t lookup(const string& name) = 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,
|
||||
const string& name) = 0;
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
|
|
@ -100,14 +157,16 @@ public:
|
|||
TRACE_DTOR(child_scope_t);
|
||||
}
|
||||
|
||||
virtual void define(const string& name, expr_t::ptr_op_t def) {
|
||||
virtual void define(const symbol_t::kind_t kind,
|
||||
const string& name, expr_t::ptr_op_t def) {
|
||||
if (parent)
|
||||
parent->define(name, def);
|
||||
parent->define(kind, name, def);
|
||||
}
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name) {
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name) {
|
||||
if (parent)
|
||||
return parent->lookup(name);
|
||||
return parent->lookup(kind, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +191,7 @@ private:
|
|||
*/
|
||||
class symbol_scope_t : public child_scope_t
|
||||
{
|
||||
typedef std::map<const string, expr_t::ptr_op_t> symbol_map;
|
||||
typedef std::map<symbol_t, expr_t::ptr_op_t> symbol_map;
|
||||
|
||||
symbol_map symbols;
|
||||
|
||||
|
|
@ -147,9 +206,11 @@ public:
|
|||
TRACE_DTOR(symbol_scope_t);
|
||||
}
|
||||
|
||||
virtual void define(const string& name, expr_t::ptr_op_t def);
|
||||
virtual void define(const symbol_t::kind_t kind, const string& name,
|
||||
expr_t::ptr_op_t def);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
private:
|
||||
|
|
@ -259,15 +320,17 @@ public:
|
|||
TRACE_DTOR(bind_scope_t);
|
||||
}
|
||||
|
||||
virtual void define(const string& name, expr_t::ptr_op_t def) {
|
||||
parent->define(name, def);
|
||||
grandchild.define(name, def);
|
||||
virtual void define(const symbol_t::kind_t kind, const string& name,
|
||||
expr_t::ptr_op_t def) {
|
||||
parent->define(kind, name, def);
|
||||
grandchild.define(kind, name, def);
|
||||
}
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name) {
|
||||
if (expr_t::ptr_op_t def = grandchild.lookup(name))
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name) {
|
||||
if (expr_t::ptr_op_t def = grandchild.lookup(kind, name))
|
||||
return def;
|
||||
return child_scope_t::lookup(name);
|
||||
return child_scope_t::lookup(kind, name);
|
||||
}
|
||||
|
||||
#if defined(HAVE_BOOST_SERIALIZATION)
|
||||
|
|
|
|||
|
|
@ -284,23 +284,26 @@ option_t<session_t> * session_t::lookup_option(const char * p)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t session_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t session_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
const char * p = name.c_str();
|
||||
switch (*p) {
|
||||
case 'o':
|
||||
if (WANT_OPT()) { p += OPT_PREFIX_LEN;
|
||||
if (option_t<session_t> * handler = lookup_option(p))
|
||||
return MAKE_OPT_HANDLER(session_t, handler);
|
||||
}
|
||||
switch (kind) {
|
||||
case symbol_t::FUNCTION:
|
||||
// Check if they are trying to access an option's setting or value.
|
||||
if (option_t<session_t> * handler = lookup_option(name.c_str()))
|
||||
return MAKE_OPT_FUNCTOR(session_t, handler);
|
||||
break;
|
||||
|
||||
case symbol_t::OPTION:
|
||||
if (option_t<session_t> * handler = lookup_option(name.c_str()))
|
||||
return MAKE_OPT_HANDLER(session_t, handler);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if they are trying to access an option's setting or value.
|
||||
if (option_t<session_t> * handler = lookup_option(p))
|
||||
return MAKE_OPT_FUNCTOR(session_t, handler);
|
||||
|
||||
return symbol_scope_t::lookup(name);
|
||||
return symbol_scope_t::lookup(kind, name);
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ public:
|
|||
|
||||
option_t<session_t> * lookup_option(const char * p);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
/**
|
||||
* Option handlers
|
||||
|
|
|
|||
|
|
@ -140,7 +140,8 @@ namespace {
|
|||
std::streamsize len,
|
||||
account_t * account);
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
};
|
||||
|
||||
void parse_amount_expr(scope_t& scope,
|
||||
|
|
@ -749,11 +750,7 @@ void instance_t::general_directive(char * line)
|
|||
break;
|
||||
}
|
||||
|
||||
scoped_array<char> directive(new char[std::strlen(p) + DIR_PREFIX_LEN + 1]);
|
||||
std::strcpy(directive.get(), DIR_PREFIX);
|
||||
std::strcpy(directive.get() + DIR_PREFIX_LEN, p);
|
||||
|
||||
if (expr_t::ptr_op_t op = lookup(directive.get())) {
|
||||
if (expr_t::ptr_op_t op = lookup(symbol_t::DIRECTIVE, p)) {
|
||||
call_scope_t args(*this);
|
||||
args.push_back(string_value(p));
|
||||
op->as_function()(args);
|
||||
|
|
@ -1233,9 +1230,10 @@ xact_t * instance_t::parse_xact(char * line,
|
|||
}
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t instance_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t instance_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
return scope.lookup(name);
|
||||
return scope.lookup(kind, name);
|
||||
}
|
||||
|
||||
std::size_t journal_t::parse(std::istream& in,
|
||||
|
|
|
|||
|
|
@ -422,8 +422,12 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
expr_t::ptr_op_t xact_t::lookup(const string& name)
|
||||
expr_t::ptr_op_t xact_t::lookup(const symbol_t::kind_t kind,
|
||||
const string& name)
|
||||
{
|
||||
if (kind != symbol_t::FUNCTION)
|
||||
return item_t::lookup(kind, name);
|
||||
|
||||
switch (name[0]) {
|
||||
case 'c':
|
||||
if (name == "code")
|
||||
|
|
@ -448,7 +452,7 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
|
|||
break;
|
||||
}
|
||||
|
||||
return item_t::lookup(name);
|
||||
return item_t::lookup(kind, name);
|
||||
}
|
||||
|
||||
bool xact_t::valid() const
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ public:
|
|||
string idstring() const;
|
||||
string id() const;
|
||||
|
||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
|
||||
const string& name);
|
||||
|
||||
virtual bool valid() const;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue