diff options
author | John Wiegley <johnw@newartisans.com> | 2012-03-07 10:35:32 -0600 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2012-03-07 10:35:32 -0600 |
commit | c33d7480a60515e4d8b184e01e683e9e74fe7c21 (patch) | |
tree | 3fb5cad9c9838d78dd02ea80d5ad668dc419f0a1 | |
parent | be778e387967e56c711ed66e5aafda2d6d7bbc11 (diff) | |
download | fork-ledger-c33d7480a60515e4d8b184e01e683e9e74fe7c21.tar.gz fork-ledger-c33d7480a60515e4d8b184e01e683e9e74fe7c21.tar.bz2 fork-ledger-c33d7480a60515e4d8b184e01e683e9e74fe7c21.zip |
Created merged_expr_t class for chained expressions
-rw-r--r-- | src/expr.cc | 41 | ||||
-rw-r--r-- | src/expr.h | 62 |
2 files changed, 102 insertions, 1 deletions
diff --git a/src/expr.cc b/src/expr.cc index 74d16ecc..8c8e995a 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -163,6 +163,47 @@ void expr_t::dump(std::ostream& out) const if (ptr) ptr->dump(out, 0); } +bool merged_expr_t::check_for_single_identifier(const string& expr) +{ + bool single_identifier = true; + for (const char * p = expr.c_str(); *p; ++p) + if (! std::isalnum(*p) || *p == '_') { + single_identifier = false; + break; + } + + if (single_identifier) { + set_base_expr(expr); + exprs.clear(); + return true; + } else { + return false; + } +} + +void merged_expr_t::compile(scope_t& scope) +{ + if (exprs.empty()) { + parse(base_expr); + } else { + std::ostringstream buf; + + buf << "__tmp_" << term << "=(" << term << "=(" << base_expr << ")"; + foreach (const string& expr, exprs) { + if (merge_operator == ";") + buf << merge_operator << term << "=" << expr; + else + buf << merge_operator << "(" << expr << ")"; + } + buf << ";" << term << ");__tmp_" << term; + + DEBUG("expr.merged.compile", "Compiled expr: " << buf.str()); + parse(buf.str()); + } + + expr_t::compile(scope); +} + value_t source_command(call_scope_t& args) { std::istream * in = NULL; @@ -172,8 +172,68 @@ inline value_t expr_value(expr_t::ptr_op_t op) { return temp; } -class call_scope_t; +// A merged expression allows one to set an expression term, "foo", and +// a base expression, "bar", and then merge in later expressions that +// utilize foo. For example: +// +// foo: bar +// merge: foo * 10 +// merge: foo + 20 +// +// When this expression is finally compiled, the base and merged +// elements are written into this: +// +// __tmp=(foo=bar; foo=foo*10; foo=foo+20);__tmp +// +// This allows users to select flags like -O, -B or -I at any time, and +// also combine flags such as -V and -A. + +class merged_expr_t : public expr_t +{ +public: + string term; + string base_expr; + string merge_operator; + std::list<string> exprs; + + merged_expr_t(const string& _term, const string& expr, + const string& merge_op = ";") + : expr_t(), term(_term), base_expr(expr), merge_operator(merge_op) { + TRACE_CTOR(merged_expr_t, "string, string, string"); + } + + virtual ~merged_expr_t() { + TRACE_DTOR(merged_expr_t); + } + + void set_term(const string& _term) { + term = _term; + } + void set_base_expr(const string& expr) { + base_expr = expr; + } + void set_merge_operator(const string& merge_op) { + merge_operator = merge_op; + } + + bool check_for_single_identifier(const string& expr); + void prepend(const string& expr) { + if (! check_for_single_identifier(expr)) + exprs.push_front(expr); + } + void append(const string& expr) { + if (! check_for_single_identifier(expr)) + exprs.push_back(expr); + } + void remove(const string& expr) { + exprs.remove(expr); + } + + virtual void compile(scope_t& scope); +}; + +class call_scope_t; value_t source_command(call_scope_t& scope); } // namespace ledger |