Added new formula functions: keys() and values()
Added support for [] operator, examples: [1, 2, 3][0] returns 1, {'elf' -> 1, 'orc' -> 2}['orc'] returns 2
This commit is contained in:
parent
ffafdb2056
commit
43a4d8a62a
4 changed files with 93 additions and 7 deletions
|
@ -217,6 +217,26 @@ private:
|
|||
expression_ptr left_, right_;
|
||||
};
|
||||
|
||||
class square_bracket_expression : public formula_expression { //TODO
|
||||
public:
|
||||
square_bracket_expression(expression_ptr left, expression_ptr key)
|
||||
: left_(left), key_(key)
|
||||
{}
|
||||
private:
|
||||
variant execute(const formula_callable& variables) const {
|
||||
const variant left = left_->evaluate(variables);
|
||||
const variant key = key_->evaluate(variables);
|
||||
if(left.is_list() || left.is_map()) {
|
||||
return left[ key ];
|
||||
} else {
|
||||
std::cerr << "illegal usage of operator []'\n";
|
||||
throw formula_error();
|
||||
}
|
||||
}
|
||||
|
||||
expression_ptr left_, key_;
|
||||
};
|
||||
|
||||
class operator_expression : public formula_expression {
|
||||
public:
|
||||
operator_expression(const std::string& op, expression_ptr left,
|
||||
|
@ -491,9 +511,9 @@ void parse_args(const token* i1, const token* i2,
|
|||
int parens = 0;
|
||||
const token* beg = i1;
|
||||
while(i1 != i2) {
|
||||
if(i1->type == TOKEN_LPARENS || i1->type == TOKEN_LSQUARE) {
|
||||
if(i1->type == TOKEN_LPARENS || i1->type == TOKEN_LSQUARE || i1->type == TOKEN_LBRACKET ) {
|
||||
++parens;
|
||||
} else if(i1->type == TOKEN_RPARENS || i1->type == TOKEN_RSQUARE) {
|
||||
} else if(i1->type == TOKEN_RPARENS || i1->type == TOKEN_RSQUARE || i1->type == TOKEN_RBRACKET) {
|
||||
--parens;
|
||||
} else if(i1->type == TOKEN_COMMA && !parens) {
|
||||
res->push_back(parse_expression(beg,i1, symbols));
|
||||
|
@ -653,11 +673,24 @@ expression_ptr parse_expression(const token* i1, const token* i2, function_symbo
|
|||
if(op == NULL) {
|
||||
if(i1->type == TOKEN_LPARENS && (i2-1)->type == TOKEN_RPARENS) {
|
||||
return parse_expression(i1+1,i2-1,symbols);
|
||||
} else if(i1->type == TOKEN_LSQUARE && (i2-1)->type == TOKEN_RSQUARE) {
|
||||
//create a list
|
||||
std::vector<expression_ptr> args;
|
||||
parse_args(i1+1,i2-1,&args,symbols);
|
||||
return expression_ptr(new list_expression(args));
|
||||
} else if( (i2-1)->type == TOKEN_RSQUARE) { //check if there is [ ] : either a list definition, or a operator
|
||||
const token* tok = i2-2;
|
||||
while (tok->type != TOKEN_LSQUARE && tok != i1) {
|
||||
--tok;
|
||||
}
|
||||
if (tok->type == TOKEN_LSQUARE) {
|
||||
if (tok == i1) {
|
||||
//create a list
|
||||
std::vector<expression_ptr> args;
|
||||
parse_args(i1+1,i2-1,&args,symbols);
|
||||
return expression_ptr(new list_expression(args));
|
||||
} else {
|
||||
//execute operator [ ]
|
||||
return expression_ptr(new square_bracket_expression(
|
||||
parse_expression(i1,tok,symbols),
|
||||
parse_expression(tok+1,i2-1,symbols)));
|
||||
}
|
||||
}
|
||||
} else if(i1->type == TOKEN_LBRACKET && (i2-1)->type == TOKEN_RBRACKET) {
|
||||
//create a map TODO: add support for a set
|
||||
std::vector<expression_ptr> args;
|
||||
|
|
|
@ -259,6 +259,32 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class keys_function : public function_expression {
|
||||
public:
|
||||
explicit keys_function(const args_list& args)
|
||||
: function_expression("keys", args, 1, 1)
|
||||
{}
|
||||
|
||||
private:
|
||||
variant execute(const formula_callable& variables) const {
|
||||
const variant map = args()[0]->evaluate(variables);
|
||||
return map.get_keys();
|
||||
}
|
||||
};
|
||||
|
||||
class values_function : public function_expression {
|
||||
public:
|
||||
explicit values_function(const args_list& args)
|
||||
: function_expression("values", args, 1, 1)
|
||||
{}
|
||||
|
||||
private:
|
||||
variant execute(const formula_callable& variables) const {
|
||||
const variant map = args()[0]->evaluate(variables);
|
||||
return map.get_values();
|
||||
}
|
||||
};
|
||||
|
||||
class choose_function : public function_expression {
|
||||
public:
|
||||
explicit choose_function(const args_list& args)
|
||||
|
@ -648,6 +674,8 @@ functions_map& get_functions_map() {
|
|||
FUNCTION(null);
|
||||
FUNCTION(refcount);
|
||||
FUNCTION(loc);
|
||||
FUNCTION(keys);
|
||||
FUNCTION(values);
|
||||
#undef FUNCTION
|
||||
}
|
||||
|
||||
|
|
|
@ -240,6 +240,28 @@ const variant& variant::operator[](const variant v) const
|
|||
}
|
||||
}
|
||||
|
||||
variant variant::get_keys() const
|
||||
{
|
||||
must_be(TYPE_MAP);
|
||||
assert(map_);
|
||||
std::vector<variant> tmp;
|
||||
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
|
||||
tmp.push_back(i->first);
|
||||
}
|
||||
return variant(&tmp);
|
||||
}
|
||||
|
||||
variant variant::get_values() const
|
||||
{
|
||||
must_be(TYPE_MAP);
|
||||
assert(map_);
|
||||
std::vector<variant> tmp;
|
||||
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
|
||||
tmp.push_back(i->second);
|
||||
}
|
||||
return variant(&tmp);
|
||||
}
|
||||
|
||||
size_t variant::num_elements() const
|
||||
{
|
||||
if(type_ == TYPE_CALLABLE) {
|
||||
|
|
|
@ -102,6 +102,9 @@ public:
|
|||
bool operator<=(const variant&) const;
|
||||
bool operator>=(const variant&) const;
|
||||
|
||||
variant get_keys() const;
|
||||
variant get_values() const;
|
||||
|
||||
void serialize_to_string(std::string& str) const;
|
||||
void serialize_from_string(const std::string& str);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue