Created merged_expr_t class for chained expressions

This commit is contained in:
John Wiegley 2012-03-07 10:35:32 -06:00
parent be778e3879
commit c33d7480a6
2 changed files with 102 additions and 1 deletions

View file

@ -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;

View file

@ -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