31 #include "D4CEScanner.h"
32 #include "D4ConstraintEvaluator.h"
33 #include "d4_ce_parser.tab.hh"
37 #include "D4Dimensions.h"
41 #include "Constructor.h"
42 #include "D4Sequence.h"
45 #include "D4FilterClause.h"
53 bool D4ConstraintEvaluator::parse(
const std::string &expr)
57 std::istringstream iss(expr);
58 D4CEScanner scanner(iss);
59 D4CEParser parser(scanner, *
this );
61 if (trace_parsing()) {
62 parser.set_debug_level(1);
63 parser.set_debug_stream(std::cerr);
66 return parser.parse() == 0;
70 D4ConstraintEvaluator::throw_not_found(
const string &
id,
const string &ident)
72 throw Error(no_such_variable, d_expr +
": The variable " +
id +
" was not found in the dataset (" + ident +
").");
76 D4ConstraintEvaluator::throw_not_array(
const string &
id,
const string &ident)
78 throw Error(no_such_variable, d_expr +
": The variable '" +
id +
"' is not an Array variable (" + ident +
").");
82 D4ConstraintEvaluator::search_for_and_mark_arrays(BaseType *btp)
84 DBG(cerr <<
"Entering D4ConstraintEvaluator::search_for_and_mark_arrays...(" << btp->name() <<
")" << endl);
86 assert(btp->is_constructor_type());
88 Constructor *ctor =
static_cast<Constructor*
>(btp);
89 for (Constructor::Vars_iter i = ctor->var_begin(), e = ctor->var_end(); i != e; ++i) {
90 switch ((*i)->type()) {
92 DBG(cerr <<
"Found an array: " << (*i)->name() << endl);
93 mark_array_variable(*i);
95 case dods_structure_c:
97 DBG(cerr <<
"Found a ctor: " << (*i)->name() << endl);
98 search_for_and_mark_arrays(*i);
116 D4ConstraintEvaluator::mark_variable(BaseType *btp)
120 DBG(cerr <<
"In D4ConstraintEvaluator::mark_variable... (" << btp->name() <<
"; " << btp->type_name() <<
")" << endl);
122 btp->set_send_p(
true);
124 if (btp->type() == dods_array_c ) {
125 mark_array_variable(btp);
129 if (btp->is_constructor_type()) {
130 search_for_and_mark_arrays(btp);
132 else if (btp->type() == dods_array_c && btp->var() && btp->var()->is_constructor_type()) {
133 search_for_and_mark_arrays(btp->var());
137 BaseType *parent = btp->get_parent();
139 parent->BaseType::set_send_p(
true);
140 parent = parent->get_parent();
147 array_uses_shared_dimension(Array *map, D4Dimension *source_dim)
149 for (
Array::Dim_iter d = map->dim_begin(), e = map->dim_end(); d != e; ++d) {
150 if (source_dim->name() == (*d).name)
173 D4ConstraintEvaluator::mark_array_variable(BaseType *btp)
175 assert(btp->type() == dods_array_c);
177 Array *a =
static_cast<Array*
>(btp);
182 if (d_indexes.empty()) {
183 for (
Array::Dim_iter d = a->dim_begin(), de = a->dim_end(); d != de; ++d) {
184 D4Dimension *dim = a->dimension_D4dim(d);
186 a->add_constraint(d, dim);
192 if (d_indexes.size() != a->dimensions())
193 throw Error(malformed_expr,
"The index constraint for '" + btp->name() +
"' does not match its rank.");
196 for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
197 if ((*i).stride > (
unsigned long long) (a->dimension_stop(d,
false) - a->dimension_start(d,
false)) + 1)
198 throw Error(malformed_expr,
"For '" + btp->name() +
"', the index stride value is greater than the number of elements in the Array");
199 if (!(*i).rest && ((*i).stop) > (
unsigned long long) (a->dimension_stop(d,
false) - a->dimension_start(d,
false)) + 1)
200 throw Error(malformed_expr,
"For '" + btp->name() +
"', the index stop value is greater than the number of elements in the Array");
202 D4Dimension *dim = a->dimension_D4dim(d);
209 if (dim && (*i).empty) {
213 a->add_constraint(d, dim);
223 a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
234 if (!a->maps()->empty()) {
235 for(D4Maps::D4MapsIter m = a->maps()->map_begin(), e = a->maps()->map_end(); m != e; ++m) {
236 if ((*m)->array() == 0)
237 throw Error(malformed_expr,
"An array with Maps was found, but one of the Maps was not defined correctly.");
239 Array *map =
const_cast<Array*
>((*m)->array());
242 if (dim && array_uses_shared_dimension(map, dim)) {
243 D4Map *map_to_be_removed = *m;
244 a->maps()->remove_map(map_to_be_removed);
245 delete map_to_be_removed;
270 D4ConstraintEvaluator::slice_dimension(
const std::string &
id,
const index &i)
274 if (i.stride > dim->size())
275 throw Error(malformed_expr,
"For '" +
id +
"', the index stride value is greater than the size of the dimension");
276 if (!i.rest && (i.stop > dim->size() - 1))
277 throw Error(malformed_expr,
"For '" +
id +
"', the index stop value is greater than the size of the dimension");
279 dim->set_constraint(i.start, i.stride, i.rest ? dim->size() - 1: i.stop);
284 D4ConstraintEvaluator::index
285 D4ConstraintEvaluator::make_index(
const std::string &i)
287 unsigned long long v = get_int64(i.c_str());
288 return index(v, 1, v,
false,
false ,
"");
291 D4ConstraintEvaluator::index
292 D4ConstraintEvaluator::make_index(
const std::string &i,
const std::string &s,
const std::string &e)
294 return index(get_int64(i.c_str()), get_int64(s.c_str()), get_int64(e.c_str()),
false,
false ,
"");
297 D4ConstraintEvaluator::index
298 D4ConstraintEvaluator::make_index(
const std::string &i,
unsigned long long s,
const std::string &e)
300 return index(get_int64(i.c_str()), s, get_int64(e.c_str()),
false,
false ,
"");
303 D4ConstraintEvaluator::index
304 D4ConstraintEvaluator::make_index(
const std::string &i,
const std::string &s)
306 return index(get_int64(i.c_str()), get_int64(s.c_str()), 0,
true,
false ,
"");
309 D4ConstraintEvaluator::index
310 D4ConstraintEvaluator::make_index(
const std::string &i,
unsigned long long s)
312 return index(get_uint64(i.c_str()), s, 0,
true,
false ,
"");
316 expr_msg(
const std::string &op,
const std::string &arg1,
const std::string &arg2)
318 return "(" + arg1 +
" " + op +
" " + arg2 +
").";
338 static D4FilterClause::ops
339 get_op_code(
const std::string &op)
341 DBGN(cerr <<
"Entering " << __PRETTY_FUNCTION__ << endl <<
"op: " << op << endl);
344 return D4FilterClause::less;
346 return D4FilterClause::greater;
348 return D4FilterClause::less_equal;
350 return D4FilterClause::greater_equal;
352 return D4FilterClause::equal;
354 return D4FilterClause::not_equal;
356 return D4FilterClause::match;
358 throw Error(malformed_expr,
"The opertator '" + op +
"' is not supported.");
383 D4ConstraintEvaluator::add_filter_clause(
const std::string &op,
const std::string &arg1,
const std::string &arg2)
385 DBG(cerr <<
"Entering: " << __PRETTY_FUNCTION__ << endl);
388 D4Sequence *s =
dynamic_cast<D4Sequence*
>(top_basetype());
390 throw Error(malformed_expr,
391 "When a filter expression is used, it must be bound to a Sequence variable: " + expr_msg(op, arg1, arg2));
393 DBG(cerr <<
"s->name(): " << s->name() << endl);
396 BaseType *a1 = s->var(arg1);
397 BaseType *a2 = s->var(arg2);
398 DBG(cerr <<
"a1: " << a1 <<
", a2: " << a2 << endl);
401 throw Error(malformed_expr,
402 "One of the arguments in a filter expression must be a constant: " + expr_msg(op, arg1, arg2));
404 throw Error(malformed_expr,
405 "One of the arguments in a filter expression must be a variable in a Sequence: " + expr_msg(op, arg1, arg2));
409 s->clauses().add_clause(
new D4FilterClause(get_op_code(op),
new D4RValue(a1),
D4RValueFactory(arg2)));
412 s->clauses().add_clause(
new D4FilterClause(get_op_code(op),
D4RValueFactory(arg1),
new D4RValue(a2)));
423 D4ConstraintEvaluator::remove_quotes(
string &s)
425 if (*s.begin() ==
'\"' && *(s.end() - 1) ==
'\"') {
427 s.erase(s.end() - 1);
437 D4ConstraintEvaluator::error(
const libdap::location &l,
const std::string &m)
440 oss << l <<
": " << m << ends;
441 throw Error(malformed_expr, oss.str());