Added operators: .+ .- .* ./ for formula language

This commit is contained in:
Bartek Waresiak 2009-07-04 21:16:39 +00:00
parent 897a733e92
commit 5a720bcb1d
4 changed files with 95 additions and 2 deletions

View File

@ -276,6 +276,14 @@ public:
op_ = AND;
} else if(op == "or") {
op_ = OR;
} else if(op == ".+") {
op_ = ADDL;
} else if(op == ".-") {
op_ = SUBL;
} else if(op == ".*") {
op_ = MULL;
} else if(op == "./") {
op_ = DIVL;
}
}
@ -298,6 +306,14 @@ private:
return left / right;
case POW:
return left ^ right;
case ADDL:
return left.list_elements_add(right);
case SUBL:
return left.list_elements_sub(right);
case MULL:
return left.list_elements_mul(right);
case DIVL:
return left.list_elements_div(right);
case EQ:
return left == right ? variant(1) : variant(0);
case NEQ:
@ -327,7 +343,7 @@ private:
}
enum OP { AND, OR, NEQ, LTE, GTE, GT='>', LT='<', EQ='=',
ADD='+', SUB='-', MUL='*', DIV='/', DICE='d', POW='^', MOD='%' };
ADD='+', SUB='-', MUL='*', DIV='/', ADDL, SUBL, MULL, DIVL, DICE='d', POW='^', MOD='%' };
OP op_;
expression_ptr left_, right_;

View File

@ -31,7 +31,7 @@ struct token_type {
};
//create the array with list of possible tokens
token_type token_types[] = { { regex("^(not\\b|and\\b|or\\b|where\\b|d(?=[^a-zA-Z])|\\*|\\+|-(?=[^>])|\\^|%|/|<=|>=|<|>|!=|=|\\.)"), TOKEN_OPERATOR },
token_type token_types[] = { { regex("^(not\\b|and\\b|or\\b|where\\b|d(?=[^a-zA-Z])|\\*|\\+|-(?=[^>])|\\^|%|/|<=|>=|<|>|!=|=|\\.\\+|\\.-|\\.\\*|\\./|\\.)"), TOKEN_OPERATOR },
{ regex("^functions\\b"), TOKEN_KEYWORD },
{ regex("^def\\b"), TOKEN_KEYWORD },
{ regex("^fai\\b"), TOKEN_KEYWORD },

View File

@ -643,6 +643,78 @@ bool variant::operator>(const variant& v) const
return !(*this <= v);
}
variant variant::list_elements_add(const variant& v) const
{
must_be(TYPE_LIST);
v.must_be(TYPE_LIST);
if( num_elements() != v.num_elements() )
throw type_error("Operator '.+' requires two lists of the same length");
std::vector< variant > res;
res.reserve(num_elements());
for(size_t i = 0; i < num_elements(); ++i) {
res.push_back( (*this)[i] + v[i] );
}
return variant( &res );
}
variant variant::list_elements_sub(const variant& v) const
{
must_be(TYPE_LIST);
v.must_be(TYPE_LIST);
if( num_elements() != v.num_elements() )
throw type_error("Operator '.-' requires two lists of the same length");
std::vector< variant > res;
res.reserve(num_elements());
for(size_t i = 0; i < num_elements(); ++i) {
res.push_back( (*this)[i] - v[i] );
}
return variant( &res );
}
variant variant::list_elements_mul(const variant& v) const
{
must_be(TYPE_LIST);
v.must_be(TYPE_LIST);
if( num_elements() != v.num_elements() )
throw type_error("Operator '.*' requires two lists of the same length");
std::vector< variant > res;
res.reserve(num_elements());
for(size_t i = 0; i < num_elements(); ++i) {
res.push_back( (*this)[i] * v[i] );
}
return variant( &res );
}
variant variant::list_elements_div(const variant& v) const
{
must_be(TYPE_LIST);
v.must_be(TYPE_LIST);
if( num_elements() != v.num_elements() )
throw type_error("Operator './' requires two lists of the same length");
std::vector< variant > res;
res.reserve(num_elements());
for(size_t i = 0; i < num_elements(); ++i) {
res.push_back( (*this)[i] / v[i] );
}
return variant( &res );
}
void variant::must_be(variant::TYPE t) const
{
if(type_ != t) {

View File

@ -105,6 +105,11 @@ public:
bool operator<=(const variant&) const;
bool operator>=(const variant&) const;
variant list_elements_add(const variant& v) const;
variant list_elements_sub(const variant& v) const;
variant list_elements_mul(const variant& v) const;
variant list_elements_div(const variant& v) const;
variant get_keys() const;
variant get_values() const;