|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2002,2003 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// (c) COPYRIGHT URI/MIT 1995-1999
|
|
Packit |
a4aae4 |
// Please read the full copyright statement in the file COPYRIGHT_URI.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Authors:
|
|
Packit |
a4aae4 |
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
This is the parser for the DODS constraint expression grammar. The parser
|
|
Packit |
a4aae4 |
calls various `helper' functions defined by the DAP classes which either
|
|
Packit |
a4aae4 |
implement the operations (in the case of relational ops) or store
|
|
Packit |
a4aae4 |
information (in the case of selection operations).
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
jhrg 9/5/95
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%code requires {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cassert>
|
|
Packit |
a4aae4 |
#include <cstdlib>
|
|
Packit |
a4aae4 |
#include <cstring>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
#include <iterator>
|
|
Packit |
a4aae4 |
#include <string>
|
|
Packit |
a4aae4 |
#include <stack>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "DDS.h"
|
|
Packit |
a4aae4 |
#include "ConstraintEvaluator.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "BaseType.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Byte.h"
|
|
Packit |
a4aae4 |
#include "Int16.h"
|
|
Packit |
a4aae4 |
#include "UInt16.h"
|
|
Packit |
a4aae4 |
#include "Int32.h"
|
|
Packit |
a4aae4 |
#include "UInt32.h"
|
|
Packit |
a4aae4 |
#include "Float32.h"
|
|
Packit |
a4aae4 |
#include "Float64.h"
|
|
Packit |
a4aae4 |
#include "Str.h"
|
|
Packit |
a4aae4 |
#include "Url.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
#include "Structure.h"
|
|
Packit |
a4aae4 |
#include "Sequence.h"
|
|
Packit |
a4aae4 |
#include "Grid.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Error.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
#include "parser.h"
|
|
Packit |
a4aae4 |
#include "ce_parser.h"
|
|
Packit |
a4aae4 |
#include "expr.h"
|
|
Packit |
a4aae4 |
#include "RValue.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using std::cerr;
|
|
Packit |
a4aae4 |
using std::endl;
|
|
Packit |
a4aae4 |
using namespace libdap ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#define EVALUATOR(arg) (static_cast<ce_parser_arg*>(arg)->get_eval())
|
|
Packit |
a4aae4 |
#define DDS(arg) (static_cast<ce_parser_arg*>(arg)->get_dds())
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// #define YYPARSE_PARAM arg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int ce_exprlex(void); /* the scanner; see expr.lex */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void ce_exprerror(ce_parser_arg *arg, const string &s);
|
|
Packit |
a4aae4 |
void ce_exprerror(ce_parser_arg *arg, const string &s, const string &s2;;
|
|
Packit |
a4aae4 |
void no_such_func(ce_parser_arg *arg, const string &name);
|
|
Packit |
a4aae4 |
void no_such_ident(ce_parser_arg *arg, const string &name, const string &word);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *make_array_index(value &i1, value &i2, value &i3;;
|
|
Packit |
a4aae4 |
int_list *make_array_index(value &i1, value &i2;;
|
|
Packit |
a4aae4 |
int_list *make_array_index(value &i1;;
|
|
Packit |
a4aae4 |
int_list_list *make_array_indices(int_list *index);
|
|
Packit |
a4aae4 |
int_list_list *append_array_index(int_list_list *indices, int_list *index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void delete_array_indices(int_list_list *indices);
|
|
Packit |
a4aae4 |
bool bracket_projection(DDS &table, const char *name, int_list_list *indices);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void process_array_indices(BaseType *variable, int_list_list *indices);
|
|
Packit |
a4aae4 |
void process_grid_indices(BaseType *variable, int_list_list *indices);
|
|
Packit |
a4aae4 |
void process_sequence_indices(BaseType *variable, int_list_list *indices);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Replace these with method calls. jhrg 8/31/06 */
|
|
Packit |
a4aae4 |
bool is_array_t(BaseType *variable);
|
|
Packit |
a4aae4 |
bool is_grid_t(BaseType *variable);
|
|
Packit |
a4aae4 |
bool is_sequence_t(BaseType *variable);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *make_variable(ConstraintEvaluator &eval, const value &val;;
|
|
Packit |
a4aae4 |
bool_func get_function(const ConstraintEvaluator &eval, const char *name);
|
|
Packit |
a4aae4 |
btp_func get_btp_function(const ConstraintEvaluator &eval, const char *name);
|
|
Packit |
a4aae4 |
proj_func get_proj_function(const ConstraintEvaluator &eval, const char *name);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<class arg_list, class arg_type>
|
|
Packit |
a4aae4 |
arg_list make_fast_arg_list(unsigned long vector_size_hint, arg_type arg_value);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<class arg_list, class arg_type>
|
|
Packit |
a4aae4 |
arg_list make_fast_arg_list(arg_list int_values, arg_type arg_value);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<class t, class T>
|
|
Packit |
a4aae4 |
rvalue *build_constant_array(vector<t> *values, DDS *dds);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%require "2.4"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%parse-param {ce_parser_arg *arg}
|
|
Packit |
a4aae4 |
%name-prefix "ce_expr"
|
|
Packit |
a4aae4 |
%defines
|
|
Packit |
a4aae4 |
%debug
|
|
Packit |
a4aae4 |
%verbose
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%union {
|
|
Packit |
a4aae4 |
bool boolean;
|
|
Packit |
a4aae4 |
int op;
|
|
Packit |
a4aae4 |
char id[ID_MAX];
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
libdap::dods_byte byte_value;
|
|
Packit |
a4aae4 |
libdap::dods_int16 int16_value;
|
|
Packit |
a4aae4 |
libdap::dods_uint16 uint16_value;
|
|
Packit |
a4aae4 |
libdap::dods_int32 int32_value;
|
|
Packit |
a4aae4 |
libdap::dods_uint32 uint32_value;
|
|
Packit |
a4aae4 |
libdap::dods_float32 float32_value;
|
|
Packit |
a4aae4 |
libdap::dods_float64 float64_value;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
libdap::byte_arg_list byte_values;
|
|
Packit |
a4aae4 |
libdap::int16_arg_list int16_values;
|
|
Packit |
a4aae4 |
libdap::uint16_arg_list uint16_values;
|
|
Packit |
a4aae4 |
libdap::int32_arg_list int32_values;
|
|
Packit |
a4aae4 |
libdap::uint32_arg_list uint32_values;
|
|
Packit |
a4aae4 |
libdap::float32_arg_list float32_values;
|
|
Packit |
a4aae4 |
libdap::float64_arg_list float64_values;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
libdap::value val; // value is defined in expr.h
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
libdap::bool_func b_func;
|
|
Packit |
a4aae4 |
libdap::btp_func bt_func;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
libdap::int_list *int_l_ptr;
|
|
Packit |
a4aae4 |
libdap::int_list_list *int_ll_ptr;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
libdap::rvalue *rval_ptr;
|
|
Packit |
a4aae4 |
libdap::rvalue_list *r_val_l_ptr;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%token <val> SCAN_STR
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%token <id> SCAN_WORD
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%token <op> SCAN_EQUAL
|
|
Packit |
a4aae4 |
%token <op> SCAN_NOT_EQUAL
|
|
Packit |
a4aae4 |
%token <op> SCAN_GREATER
|
|
Packit |
a4aae4 |
%token <op> SCAN_GREATER_EQL
|
|
Packit |
a4aae4 |
%token <op> SCAN_LESS
|
|
Packit |
a4aae4 |
%token <op> SCAN_LESS_EQL
|
|
Packit |
a4aae4 |
%token <op> SCAN_REGEXP
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%token <op> SCAN_STAR
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_BYTE
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_INT16
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_UINT16
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_INT32
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_UINT32
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_FLOAT32
|
|
Packit |
a4aae4 |
%token <op> SCAN_HASH_FLOAT64
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <boolean> constraint_expr projection proj_clause proj_function
|
|
Packit |
a4aae4 |
%type <boolean> array_projection selection clause bool_function arg_length_hint
|
|
Packit |
a4aae4 |
%type <id> array_proj_clause name
|
|
Packit |
a4aae4 |
%type <op> rel_op
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <int_l_ptr> array_index
|
|
Packit |
a4aae4 |
%type <int_ll_ptr> array_indices
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <rval_ptr> r_value id_or_const array_const_special_form array_projection_rvalue
|
|
Packit |
a4aae4 |
%type <r_val_l_ptr> r_value_list arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <byte_value> fast_byte_arg
|
|
Packit |
a4aae4 |
%type <byte_values> fast_byte_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <int16_value> fast_int16_arg
|
|
Packit |
a4aae4 |
%type <int16_values> fast_int16_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <uint16_value> fast_uint16_arg
|
|
Packit |
a4aae4 |
%type <uint16_values> fast_uint16_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <int32_value> fast_int32_arg
|
|
Packit |
a4aae4 |
%type <int32_values> fast_int32_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <uint32_value> fast_uint32_arg
|
|
Packit |
a4aae4 |
%type <uint32_values> fast_uint32_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <float32_value> fast_float32_arg
|
|
Packit |
a4aae4 |
%type <float32_values> fast_float32_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%type <float64_value> fast_float64_arg
|
|
Packit |
a4aae4 |
%type <float64_values> fast_float64_arg_list
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%code {
|
|
Packit |
a4aae4 |
/* This global is used by the rule 'arg_length_hint' so that the hint can
|
|
Packit |
a4aae4 |
be used during the paraent rule's parse. See fast_int32_arg_list. */
|
|
Packit |
a4aae4 |
unsigned long arg_length_hint_value = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%%
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
constraint_expr: /* empty constraint --> send all */
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Mark all variables" << endl);
|
|
Packit |
a4aae4 |
DDS(arg)->mark_all(true);
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
/* projection only */
|
|
Packit |
a4aae4 |
| projection
|
|
Packit |
a4aae4 |
/* selection only --> project everything */
|
|
Packit |
a4aae4 |
| '&' { DDS(arg)->mark_all(true); } selection
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $3;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| projection '&' selection
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1 && $3;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
projection: proj_clause
|
|
Packit |
a4aae4 |
| proj_clause ',' projection
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1 && $3;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
proj_clause: name
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *var = DDS(arg)->var($1);
|
|
Packit |
a4aae4 |
if (var) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Marking " << $1 << endl);
|
|
Packit |
a4aae4 |
$$ = DDS(arg)->mark($1, true);
|
|
Packit |
a4aae4 |
DBG(cerr << "result: " << $$ << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
no_such_ident(arg, $1, "identifier");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| proj_function
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_projection
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_const_special_form
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Array *array = dynamic_cast<Array*>($1->bvalue(*DDS(arg)));
|
|
Packit |
a4aae4 |
if (array) {
|
|
Packit |
a4aae4 |
/* When the special form appears here (not as a function argument)
|
|
Packit |
a4aae4 |
set send_p so the data will be sent and add it to the DDS. This
|
|
Packit |
a4aae4 |
streamlines testing (and is likely what is intended). */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array->set_send_p(true);
|
|
Packit |
a4aae4 |
DDS(arg)->add_var_nocopy(array);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
ce_exprerror(arg, "Could not create the anonymous vector using the # special form");
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* The value parsed by arg_length_hint is stored in a global variable by that rule
|
|
Packit |
a4aae4 |
so that it can be used during the parse of fast_byte_arg_list. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return a rvalue */
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_BYTE '(' arg_length_hint ':' fast_byte_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_byte, Byte>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_INT16 '(' arg_length_hint ':' fast_int16_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_int16, Int16>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_UINT16 '(' arg_length_hint ':' fast_uint16_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_uint16, UInt16>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_INT32 '(' arg_length_hint ':' fast_int32_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_int32, Int32>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_UINT32 '(' arg_length_hint ':' fast_uint32_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_uint32, UInt32>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_FLOAT32 '(' arg_length_hint ':' fast_float32_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_float32, Float32>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_const_special_form: SCAN_HASH_FLOAT64 '(' arg_length_hint ':' fast_float64_arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = build_constant_array<dods_float64, Float64>($5, DDS(arg));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Here the arg length hint is stored in a global so it can be used by the
|
|
Packit |
a4aae4 |
function that allocates the vector. The value is passed to vector::reserve(). */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
arg_length_hint: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!check_int32($1))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "$<type>(hint, value, ...) special form expected hint to be an integer");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
arg_length_hint_value = atoi($1);
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_byte_arg_list: fast_byte_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<byte_arg_list, dods_byte>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_byte_arg_list ',' fast_byte_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<byte_arg_list, dods_byte>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_byte_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtol($1, 0, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_int16_arg_list: fast_int16_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<int16_arg_list, dods_int16>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_int16_arg_list ',' fast_int16_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<int16_arg_list, dods_int16>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_int16_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtol($1, 0, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_uint16_arg_list: fast_uint16_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<uint16_arg_list, dods_uint16>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_uint16_arg_list ',' fast_uint16_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<uint16_arg_list, dods_uint16>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_uint16_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtoul($1, 0, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_int32_arg_list: fast_int32_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<int32_arg_list, dods_int32>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_int32_arg_list ',' fast_int32_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<int32_arg_list, dods_int32>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_int32_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtol($1, 0, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_uint32_arg_list: fast_uint32_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<uint32_arg_list, dods_uint32>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_uint32_arg_list ',' fast_uint32_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<uint32_arg_list, dods_uint32>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_uint32_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtoul($1, 0, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_float32_arg_list: fast_float32_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<float32_arg_list, dods_float32>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_float32_arg_list ',' fast_float32_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<float32_arg_list, dods_float32>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_float32_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtof($1, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* return an int_arg_list (a std::vector<int>*) */
|
|
Packit |
a4aae4 |
fast_float64_arg_list: fast_float64_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<float64_arg_list, dods_float64>(arg_length_hint_value, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| fast_float64_arg_list ',' fast_float64_arg
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_fast_arg_list<float64_arg_list, dods_float64>($1, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
fast_float64_arg: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = strtod($1, 0);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
proj_function: SCAN_WORD '(' arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
proj_func p_f = 0;
|
|
Packit |
a4aae4 |
btp_func f = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((f = get_btp_function(*(EVALUATOR(arg)), $1))) {
|
|
Packit |
a4aae4 |
EVALUATOR(arg)->append_clause(f, $3);
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if ((p_f = get_proj_function(*(EVALUATOR(arg)), $1))) {
|
|
Packit |
a4aae4 |
DDS &dds = dynamic_cast<DDS&>(*(DDS(arg)));
|
|
Packit |
a4aae4 |
BaseType **args = build_btp_args( $3, dds );
|
|
Packit |
a4aae4 |
(*p_f)(($3) ? $3->size():0, args, dds, *(EVALUATOR(arg)));
|
|
Packit |
a4aae4 |
delete[] args;
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
no_such_func(arg, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
selection: clause
|
|
Packit |
a4aae4 |
| selection '&' clause
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1 && $3;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
clause: r_value rel_op '{' r_value_list '}'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ($1) {
|
|
Packit |
a4aae4 |
EVALUATOR(arg)->append_clause($2, $1, $4);
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
$$ = false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| r_value rel_op r_value
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ($1) {
|
|
Packit |
a4aae4 |
rvalue_list *rv = new rvalue_list;
|
|
Packit |
a4aae4 |
rv->push_back($3);
|
|
Packit |
a4aae4 |
EVALUATOR(arg)->append_clause($2, $1, rv);
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
$$ = false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| bool_function
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
bool_function: SCAN_WORD '(' arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
bool_func b_func = get_function((*EVALUATOR(arg)), $1);
|
|
Packit |
a4aae4 |
if (!b_func) {
|
|
Packit |
a4aae4 |
no_such_func(arg, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
EVALUATOR(arg)->append_clause(b_func, $3);
|
|
Packit |
a4aae4 |
$$ = true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* This rule does not check SCAN_WORD nor does it perform www escaping */
|
|
Packit |
a4aae4 |
r_value: id_or_const
|
|
Packit |
a4aae4 |
| SCAN_WORD '(' arg_list ')'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
btp_func func = get_btp_function((*EVALUATOR(arg)), $1);
|
|
Packit |
a4aae4 |
if (func) {
|
|
Packit |
a4aae4 |
$$ = new rvalue(func, $3);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
no_such_func(arg, $1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_const_special_form
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_projection_rvalue
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
r_value_list: r_value
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ($1)
|
|
Packit |
a4aae4 |
$$ = make_rvalue_list($1);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
$$ = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| r_value_list ',' r_value
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ($1 && $3)
|
|
Packit |
a4aae4 |
$$ = append_rvalue_list($1, $3);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
$$ = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
arg_list: r_value_list
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = $1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| /* Null, argument lists may be empty */
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
id_or_const: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *btp = DDS(arg)->var(www2id($1));
|
|
Packit |
a4aae4 |
if (btp) {
|
|
Packit |
a4aae4 |
btp->set_in_selection(true);
|
|
Packit |
a4aae4 |
$$ = new rvalue(btp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
value new_val;
|
|
Packit |
a4aae4 |
string name_tmp;
|
|
Packit |
a4aae4 |
if (check_int32($1)) {
|
|
Packit |
a4aae4 |
new_val.type = dods_int32_c;
|
|
Packit |
a4aae4 |
new_val.v.i = atoi($1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (check_uint32($1)) {
|
|
Packit |
a4aae4 |
new_val.type = dods_uint32_c;
|
|
Packit |
a4aae4 |
new_val.v.ui = atoi($1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (check_float64($1)) {
|
|
Packit |
a4aae4 |
new_val.type = dods_float64_c;
|
|
Packit |
a4aae4 |
new_val.v.f = atof($1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
new_val.type = dods_str_c;
|
|
Packit |
a4aae4 |
// The 'new' here was used because www2id() modifies the
|
|
Packit |
a4aae4 |
// std::string arg in place but 'value' holds a string*.
|
|
Packit |
a4aae4 |
// new_val.v.s = new string(www2id($1));
|
|
Packit |
a4aae4 |
// I replcaed this with a local tmp to avoid the dynamic
|
|
Packit |
a4aae4 |
// allocation and the need to call delete. This was part of
|
|
Packit |
a4aae4 |
// the fix for ticket 2240. jhrg 7/30/14
|
|
Packit |
a4aae4 |
name_tmp = $1;
|
|
Packit |
a4aae4 |
name_tmp = www2id(name_tmp);
|
|
Packit |
a4aae4 |
new_val.v.s = &name_tmp;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
BaseType *btp = make_variable((*EVALUATOR(arg)), new_val);
|
|
Packit |
a4aae4 |
$$ = new rvalue(btp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| SCAN_STR
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ($1.type != dods_str_c || $1.v.s == 0 || $1.v.s->empty())
|
|
Packit |
a4aae4 |
ce_exprerror(arg, "Malformed string", "");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *var = DDS(arg)->var(www2id(*($1.v.s)));
|
|
Packit |
a4aae4 |
if (var) {
|
|
Packit |
a4aae4 |
$$ = new rvalue(var);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
var = make_variable((*EVALUATOR(arg)), $1);
|
|
Packit |
a4aae4 |
$$ = new rvalue(var);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// When the scanner (ce_expr.lex) returns the SCAN_STR token type
|
|
Packit |
a4aae4 |
// it makes a local copy of the string in a new std::string object
|
|
Packit |
a4aae4 |
// that we must delete. Fix for a bug report by Aron.Bartle@mechdyne.com
|
|
Packit |
a4aae4 |
// See ticket 2240. jhrg 7/30/14
|
|
Packit |
a4aae4 |
delete $1.v.s;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* this must return an rvalue. It should run bracket_projection()
|
|
Packit |
a4aae4 |
and then return the BaseType of the Array wrapped in a RValue
|
|
Packit |
a4aae4 |
object. */
|
|
Packit |
a4aae4 |
array_projection_rvalue : name array_indices
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!bracket_projection((*DDS(arg)), $1, $2))
|
|
Packit |
a4aae4 |
no_such_ident(arg, $1, "array, grid or sequence");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// strncpy($$, $1, ID_MAX-1);
|
|
Packit |
a4aae4 |
// $$[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DDS(arg)->mark($1, true);
|
|
Packit |
a4aae4 |
$$ = new rvalue(DDS(arg)->var($1));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_projection : array_proj_clause
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = (*DDS(arg)).mark($1, true);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_proj_clause: name array_indices
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
//string name = www2id($1);
|
|
Packit |
a4aae4 |
if (!bracket_projection((*DDS(arg)), $1, $2))
|
|
Packit |
a4aae4 |
no_such_ident(arg, $1, "array, grid or sequence");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
strncpy($$, $1, ID_MAX-1);
|
|
Packit |
a4aae4 |
$$[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_proj_clause name
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = string($1) + string($2);
|
|
Packit |
a4aae4 |
strncpy($$, name.c_str(), ID_MAX-1);
|
|
Packit |
a4aae4 |
$$[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_proj_clause name array_indices
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = string($1) + string($2);
|
|
Packit |
a4aae4 |
if (!bracket_projection((*DDS(arg)), name.c_str(), $3))
|
|
Packit |
a4aae4 |
no_such_ident(arg, name.c_str(), "array, grid or sequence");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
strncpy($$, name.c_str(), ID_MAX-1);
|
|
Packit |
a4aae4 |
$$[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name: SCAN_WORD
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strncpy($$, www2id($1).c_str(), ID_MAX-1);
|
|
Packit |
a4aae4 |
$$[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| SCAN_STR
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ($1.type != dods_str_c || $1.v.s == 0 || $1.v.s->empty())
|
|
Packit |
a4aae4 |
ce_exprerror(arg, "Malformed string", "");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
strncpy($$, www2id(*($1.v.s)).c_str(), ID_MAX-1);
|
|
Packit |
a4aae4 |
// See comment about regarding the scanner's behavior WRT SCAN_STR.
|
|
Packit |
a4aae4 |
// jhrg 7/30/14
|
|
Packit |
a4aae4 |
delete $1.v.s;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
$$[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array_indices: array_index
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = make_array_indices($1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| array_indices array_index
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
$$ = append_array_index($1, $2);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
* We added [*], [n:*] and [n:m:*] to the syntax for array projections.
|
|
Packit |
a4aae4 |
* These mean, resp., all the elements, elements from n to the end, and
|
|
Packit |
a4aae4 |
* from n to the end with a stride of m. To encode this with as little
|
|
Packit |
a4aae4 |
* disruption as possible, we represent the star with -1. jhrg 12/20/12
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
array_index:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
'[' SCAN_WORD ']'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!check_uint32($2))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($2) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
value i;
|
|
Packit |
a4aae4 |
i.type = dods_uint32_c;
|
|
Packit |
a4aae4 |
i.v.i = atoi($2);
|
|
Packit |
a4aae4 |
$$ = make_array_index(i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| '[' SCAN_STAR ']'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
value i;
|
|
Packit |
a4aae4 |
i.type = dods_int32_c;
|
|
Packit |
a4aae4 |
i.v.i =-1;
|
|
Packit |
a4aae4 |
$$ = make_array_index(i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|'[' SCAN_WORD ':' SCAN_WORD ']'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!check_uint32($2))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($2) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
if (!check_uint32($4))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($4) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
value i,j;
|
|
Packit |
a4aae4 |
i.type = j.type = dods_uint32_c;
|
|
Packit |
a4aae4 |
i.v.i = atoi($2);
|
|
Packit |
a4aae4 |
j.v.i = atoi($4);
|
|
Packit |
a4aae4 |
$$ = make_array_index(i, j);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|'[' SCAN_WORD ':' SCAN_STAR ']'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!check_uint32($2))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($2) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
value i,j;
|
|
Packit |
a4aae4 |
i.type = dods_uint32_c;
|
|
Packit |
a4aae4 |
j.type = dods_int32_c; /* signed */
|
|
Packit |
a4aae4 |
i.v.i = atoi($2);
|
|
Packit |
a4aae4 |
j.v.i = -1;
|
|
Packit |
a4aae4 |
$$ = make_array_index(i, j);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| '[' SCAN_WORD ':' SCAN_WORD ':' SCAN_WORD ']'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!check_uint32($2))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($2) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
if (!check_uint32($4))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($4) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
if (!check_uint32($6))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($6) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
value i, j, k;
|
|
Packit |
a4aae4 |
i.type = j.type = k.type = dods_uint32_c;
|
|
Packit |
a4aae4 |
i.v.i = atoi($2);
|
|
Packit |
a4aae4 |
j.v.i = atoi($4);
|
|
Packit |
a4aae4 |
k.v.i = atoi($6);
|
|
Packit |
a4aae4 |
$$ = make_array_index(i, j, k);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
| '[' SCAN_WORD ':' SCAN_WORD ':' SCAN_STAR ']'
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!check_uint32($2))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($2) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
if (!check_uint32($4))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "The word `" + string($4) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
value i, j, k;
|
|
Packit |
a4aae4 |
i.type = j.type = dods_uint32_c;
|
|
Packit |
a4aae4 |
k.type = dods_int32_c;
|
|
Packit |
a4aae4 |
i.v.i = atoi($2);
|
|
Packit |
a4aae4 |
j.v.i = atoi($4);
|
|
Packit |
a4aae4 |
k.v.i = -1;
|
|
Packit |
a4aae4 |
$$ = make_array_index(i, j, k);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
rel_op: SCAN_EQUAL
|
|
Packit |
a4aae4 |
| SCAN_NOT_EQUAL
|
|
Packit |
a4aae4 |
| SCAN_GREATER
|
|
Packit |
a4aae4 |
| SCAN_GREATER_EQL
|
|
Packit |
a4aae4 |
| SCAN_LESS
|
|
Packit |
a4aae4 |
| SCAN_LESS_EQL
|
|
Packit |
a4aae4 |
| SCAN_REGEXP
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%%
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// All these error reporting function now throw instances of Error. The expr
|
|
Packit |
a4aae4 |
// parser no longer returns an error code to indicate and error. 2/16/2000
|
|
Packit |
a4aae4 |
// jhrg.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
ce_exprerror(ce_parser_arg *, const string &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string msg = "Constraint expression parse error: " +s;
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, msg);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void ce_exprerror(ce_parser_arg *, const string &s, const string &s2)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string msg = "Constraint expression parse error: " + s + ": " + s2;
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, msg);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void no_such_ident(ce_parser_arg *arg, const string &name, const string &word)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
string msg = "No such " + word + " in dataset";
|
|
Packit |
a4aae4 |
ce_exprerror(arg, msg , name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
string msg = "Constraint expression parse error: No such " + word + " in dataset: " + name;
|
|
Packit |
a4aae4 |
throw Error(no_such_variable, msg);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void no_such_func(ce_parser_arg *arg, const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ce_exprerror(arg, "Not a registered function", name);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* If we're calling this, assume var is not a Sequence. But assume that the
|
|
Packit |
a4aae4 |
name contains a dot and it's a separator. Look for the rightmost dot and
|
|
Packit |
a4aae4 |
then look to see if the name to the left is a sequence. Return a pointer
|
|
Packit |
a4aae4 |
to the sequence if it is otherwise return null. Uses tail-recursion to
|
|
Packit |
a4aae4 |
'walk' back from right to left looking at each dot. This way the sequence
|
|
Packit |
a4aae4 |
will be found even if there are structures between the field and the
|
|
Packit |
a4aae4 |
Sequence. */
|
|
Packit |
a4aae4 |
static Sequence *
|
|
Packit |
a4aae4 |
parent_is_sequence(DDS &table, const string &n)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string::size_type dotpos = n.find_last_of('.');
|
|
Packit |
a4aae4 |
if (dotpos == string::npos)
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string s = n.substr(0, dotpos);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If the thing returned by table.var is not a Sequence, this cast
|
|
Packit |
a4aae4 |
// will yield null.
|
|
Packit |
a4aae4 |
Sequence *seq = dynamic_cast<Sequence*> (table.var(s));
|
|
Packit |
a4aae4 |
if (seq)
|
|
Packit |
a4aae4 |
return seq;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return parent_is_sequence(table, s);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool bracket_projection(DDS &table, const char *name, int_list_list *indices)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *var = table.var(name);
|
|
Packit |
a4aae4 |
Sequence *seq; // used in last else-if clause
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!var)
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (is_array_t(var)) {
|
|
Packit |
a4aae4 |
/* calls to set_send_p should be replaced with
|
|
Packit |
a4aae4 |
calls to DDS::mark so that arrays of Structures,
|
|
Packit |
a4aae4 |
etc. will be processed correctly when individual
|
|
Packit |
a4aae4 |
elements are projected using short names.
|
|
Packit |
a4aae4 |
9/1/98 jhrg */
|
|
Packit |
a4aae4 |
/* var->set_send_p(true); */
|
|
Packit |
a4aae4 |
//table.mark(name, true);
|
|
Packit |
a4aae4 |
// We don't call mark() here for an array. Instead it is called from
|
|
Packit |
a4aae4 |
// within the parser. jhrg 10/10/08
|
|
Packit |
a4aae4 |
process_array_indices(var, indices); // throws on error
|
|
Packit |
a4aae4 |
delete_array_indices(indices);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (is_grid_t(var)) {
|
|
Packit |
a4aae4 |
process_grid_indices(var, indices);
|
|
Packit |
a4aae4 |
table.mark(name, true);
|
|
Packit |
a4aae4 |
delete_array_indices(indices);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (is_sequence_t(var)) {
|
|
Packit |
a4aae4 |
table.mark(name, true);
|
|
Packit |
a4aae4 |
process_sequence_indices(var, indices);
|
|
Packit |
a4aae4 |
delete_array_indices(indices);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if ((seq = parent_is_sequence(table, name))) {
|
|
Packit |
a4aae4 |
process_sequence_indices(seq, indices);
|
|
Packit |
a4aae4 |
table.mark(name, true);
|
|
Packit |
a4aae4 |
delete_array_indices(indices);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Given three values (I1, I2, I3), all of which must be integers, build an
|
|
Packit |
a4aae4 |
// int_list which contains those values.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Note that we added support for * in the rightmost position of an index
|
|
Packit |
a4aae4 |
// (i.e., [*], [n:*], [n:m:*]) and indicate that star using -1 as an index value.
|
|
Packit |
a4aae4 |
// Bescause of this change, the test for the type of the rightmost value in
|
|
Packit |
a4aae4 |
// the index subexpr was changed to include signed int.
|
|
Packit |
a4aae4 |
// jhrg 12/20/12
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Returns: A pointer to an int_list of three integers or NULL if any of the
|
|
Packit |
a4aae4 |
// values are not integers.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *
|
|
Packit |
a4aae4 |
make_array_index(value &i1, value &i2, value &i3)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (i1.type != dods_uint32_c || i2.type != dods_uint32_c || (i3.type != dods_uint32_c && i3.type != dods_int32_c))
|
|
Packit |
a4aae4 |
return (int_list *) 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *index = new int_list;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
index->push_back((int) i1.v.i);
|
|
Packit |
a4aae4 |
index->push_back((int) i2.v.i);
|
|
Packit |
a4aae4 |
index->push_back((int) i3.v.i);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cout << "index: ");
|
|
Packit |
a4aae4 |
DBG(copy(index->begin(), index->end(), ostream_iterator<int>(cerr, " ")));
|
|
Packit |
a4aae4 |
DBG(cerr << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return index;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *
|
|
Packit |
a4aae4 |
make_array_index(value &i1, value &i2)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (i1.type != dods_uint32_c || (i2.type != dods_uint32_c && i2.type != dods_int32_c))
|
|
Packit |
a4aae4 |
return (int_list *) 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *index = new int_list;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
index->push_back((int) i1.v.i);
|
|
Packit |
a4aae4 |
index->push_back(1);
|
|
Packit |
a4aae4 |
index->push_back((int) i2.v.i);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cout << "index: ");
|
|
Packit |
a4aae4 |
DBG(copy(index->begin(), index->end(), ostream_iterator<int>(cerr, " ")));
|
|
Packit |
a4aae4 |
DBG(cerr << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return index;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *
|
|
Packit |
a4aae4 |
make_array_index(value &i1)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (i1.type != dods_uint32_c && i1.type != dods_int32_c)
|
|
Packit |
a4aae4 |
return (int_list *) 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list *index = new int_list;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// When the CE is Array[*] that means all of the elements, but the value
|
|
Packit |
a4aae4 |
// of i1 will be -1. Make the projection triple be 0:1:-1 which is a
|
|
Packit |
a4aae4 |
// pattern that libdap::Array will recognize.
|
|
Packit |
a4aae4 |
if (i1.v.i == -1)
|
|
Packit |
a4aae4 |
index->push_back(0);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
index->push_back((int) i1.v.i);
|
|
Packit |
a4aae4 |
index->push_back(1);
|
|
Packit |
a4aae4 |
index->push_back((int) i1.v.i);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cout << "index: ");
|
|
Packit |
a4aae4 |
DBG(copy(index->begin(), index->end(), ostream_iterator<int>(cerr, " ")));
|
|
Packit |
a4aae4 |
DBG(cerr << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return index;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list_list *
|
|
Packit |
a4aae4 |
make_array_indices(int_list *index)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
int_list_list *indices = new int_list_list;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cout << "index: ");
|
|
Packit |
a4aae4 |
DBG(copy(index->begin(), index->end(), ostream_iterator<int>(cerr, " ")));
|
|
Packit |
a4aae4 |
DBG(cerr << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
assert(index);
|
|
Packit |
a4aae4 |
indices->push_back(index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return indices;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list_list *
|
|
Packit |
a4aae4 |
append_array_index(int_list_list *indices, int_list *index)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(indices);
|
|
Packit |
a4aae4 |
assert(index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
indices->push_back(index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return indices;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Delete an array indices list.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void delete_array_indices(int_list_list *indices)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(indices);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (int_list_citer i = indices->begin(); i != indices->end(); i++) {
|
|
Packit |
a4aae4 |
int_list *il = *i;
|
|
Packit |
a4aae4 |
assert(il);
|
|
Packit |
a4aae4 |
delete il;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete indices;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool is_array_t(BaseType *variable)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(variable);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (variable->type() != dods_array_c)
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool is_grid_t(BaseType *variable)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(variable);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (variable->type() != dods_grid_c)
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool is_sequence_t(BaseType *variable)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(variable);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (variable->type() != dods_sequence_c)
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void process_array_indices(BaseType *variable, int_list_list *indices)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(variable);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Array *a = dynamic_cast<Array *>(variable); // replace with dynamic cast
|
|
Packit |
a4aae4 |
if (!a)
|
|
Packit |
a4aae4 |
throw Error(malformed_expr,
|
|
Packit |
a4aae4 |
string("The constraint expression evaluator expected an array; ") + variable->name() + " is not an array.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (a->dimensions(true) != (unsigned) indices->size())
|
|
Packit |
a4aae4 |
throw Error(malformed_expr,
|
|
Packit |
a4aae4 |
string("Error: The number of dimensions in the constraint for ") + variable->name()
|
|
Packit |
a4aae4 |
+ " must match the number in the array.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Before applying projection to array:" << endl);
|
|
Packit |
a4aae4 |
DBG(a->print_decl(cerr, "", true, false, true));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
assert(indices);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_list_citer p = indices->begin();
|
|
Packit |
a4aae4 |
Array::Dim_iter r = a->dim_begin();
|
|
Packit |
a4aae4 |
for (; p != indices->end() && r != a->dim_end(); p++, r++) {
|
|
Packit |
a4aae4 |
int_list *index = *p;
|
|
Packit |
a4aae4 |
assert(index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_citer q = index->begin();
|
|
Packit |
a4aae4 |
assert(q != index->end());
|
|
Packit |
a4aae4 |
int start = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
int stride = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
int stop = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
if (q != index->end())
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, string("Too many values in index list for ") + a->name() + ".");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "process_array_indices: Setting constraint on "
|
|
Packit |
a4aae4 |
<< a->name() << "[" << start << ":" << stop << "]"
|
|
Packit |
a4aae4 |
<< endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// It's possible that an array will appear more than once in a CE
|
|
Packit |
a4aae4 |
// (for example, if an array of structures is constrained so that
|
|
Packit |
a4aae4 |
// only two fields are projected and there's an associated hyperslab).
|
|
Packit |
a4aae4 |
// However, in this case the two hyperslabs must be equal; test for
|
|
Packit |
a4aae4 |
// that here.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// We added '*' to mean 'the last element' in the array and use an index of -1
|
|
Packit |
a4aae4 |
// to indicate that. If 'stop' is -1, don't test it here because dimension_stop()
|
|
Packit |
a4aae4 |
// won't be -1 but the actual ending index of the array. jhrg 12/20/12
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (a->send_p() && (a->dimension_start(r, true) != start || (a->dimension_stop(r, true) != stop && stop != -1)
|
|
Packit |
a4aae4 |
|| a->dimension_stride(r, true) != stride))
|
|
Packit |
a4aae4 |
throw Error(malformed_expr,
|
|
Packit |
a4aae4 |
string("The Array was already projected differently in the constraint expression: ") + a->name() + ".");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
a->add_constraint(r, start, stride, stop);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Set Constraint: " << a->dimension_size(r, true) << endl);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "After applying projection to array:" << endl);
|
|
Packit |
a4aae4 |
DBG(a->print_decl(cerr, "", true, false, true));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (p != indices->end() && r == a->dim_end())
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, string("Too many indices in constraint for ") + a->name() + ".");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void process_grid_indices(BaseType *variable, int_list_list *indices)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(variable);
|
|
Packit |
a4aae4 |
assert(variable->type() == dods_grid_c);
|
|
Packit |
a4aae4 |
Grid *g = dynamic_cast<Grid *>(variable);
|
|
Packit |
a4aae4 |
if (!g)
|
|
Packit |
a4aae4 |
throw Error(unknown_error, "Expected a Grid variable");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Array *a = g->get_array();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (a->dimensions(true) != (unsigned) indices->size())
|
|
Packit |
a4aae4 |
throw Error(malformed_expr,
|
|
Packit |
a4aae4 |
string("Error: The number of dimensions in the constraint for ") + variable->name()
|
|
Packit |
a4aae4 |
+ " must match the number in the grid.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// First do the constraints on the ARRAY in the grid.
|
|
Packit |
a4aae4 |
process_array_indices(g->array_var(), indices);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Now process the maps.
|
|
Packit |
a4aae4 |
Grid::Map_iter r = g->map_begin();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Suppress all maps by default.
|
|
Packit |
a4aae4 |
for (; r != g->map_end(); r++) {
|
|
Packit |
a4aae4 |
(*r)->set_send_p(false);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Add specified maps to the current projection.
|
|
Packit |
a4aae4 |
assert(indices);
|
|
Packit |
a4aae4 |
int_list_citer p = indices->begin();
|
|
Packit |
a4aae4 |
r = g->map_begin();
|
|
Packit |
a4aae4 |
for (; p != indices->end() && r != g->map_end(); p++, r++) {
|
|
Packit |
a4aae4 |
int_list *index = *p;
|
|
Packit |
a4aae4 |
assert(index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_citer q = index->begin();
|
|
Packit |
a4aae4 |
assert(q != index->end());
|
|
Packit |
a4aae4 |
int start = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
int stride = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
int stop = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *btp = *r;
|
|
Packit |
a4aae4 |
assert(btp);
|
|
Packit |
a4aae4 |
assert(btp->type() == dods_array_c);
|
|
Packit |
a4aae4 |
Array *a = (Array *) btp;
|
|
Packit |
a4aae4 |
a->set_send_p(true);
|
|
Packit |
a4aae4 |
a->reset_constraint();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
if (q != index->end()) {
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, string("Too many values in index list for ") + a->name() + ".");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "process_grid_indices: Setting constraint on "
|
|
Packit |
a4aae4 |
<< a->name() << "[" << start << ":"
|
|
Packit |
a4aae4 |
<< stop << "]" << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Array::Dim_iter si = a->dim_begin();
|
|
Packit |
a4aae4 |
a->add_constraint(si, start, stride, stop);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cout << "Grid Constraint: ";
|
|
Packit |
a4aae4 |
for (Array::Dim_iter dp = ((Array *) g->array_var())->dim_begin();
|
|
Packit |
a4aae4 |
dp != ((Array *) g->array_var())->dim_end(); dp++)
|
|
Packit |
a4aae4 |
cout << ((Array *) g->array_var())->dimension_size(dp, true) << " ";
|
|
Packit |
a4aae4 |
cout << endl
|
|
Packit |
a4aae4 |
);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (p != indices->end() && r == g->map_end()) {
|
|
Packit |
a4aae4 |
throw Error(malformed_expr,
|
|
Packit |
a4aae4 |
string("Too many indices in constraint for ") + (*r)->name() + ".");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void process_sequence_indices(BaseType *variable, int_list_list *indices)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(variable);
|
|
Packit |
a4aae4 |
assert(variable->type() == dods_sequence_c);
|
|
Packit |
a4aae4 |
Sequence *s = dynamic_cast<Sequence *> (variable);
|
|
Packit |
a4aae4 |
if (!s)
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "Expected a Sequence variable");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Add specified maps to the current projection.
|
|
Packit |
a4aae4 |
assert(indices);
|
|
Packit |
a4aae4 |
for (int_list_citer p = indices->begin(); p != indices->end(); p++) {
|
|
Packit |
a4aae4 |
int_list *index = *p;
|
|
Packit |
a4aae4 |
assert(index);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int_citer q = index->begin();
|
|
Packit |
a4aae4 |
assert(q != index->end());
|
|
Packit |
a4aae4 |
int start = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
int stride = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
int stop = *q;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
q++;
|
|
Packit |
a4aae4 |
if (q != index->end()) {
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, string("Too many values in index list for ") + s->name() + ".");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
s->set_row_number_constraint(start, stop, stride);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Given a value, wrap it up in a BaseType and return a pointer to the same.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
make_variable(ConstraintEvaluator &eval, const value &val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
BaseType *var;
|
|
Packit |
a4aae4 |
switch (val.type) {
|
|
Packit |
a4aae4 |
case dods_int32_c: {
|
|
Packit |
a4aae4 |
var = new Int32("dummy");
|
|
Packit |
a4aae4 |
var->val2buf((void *) &val.v.i);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_uint32_c: {
|
|
Packit |
a4aae4 |
var = new UInt32("dummy");
|
|
Packit |
a4aae4 |
var->val2buf((void *) &val.v.i);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_float64_c: {
|
|
Packit |
a4aae4 |
var = new Float64("dummy");
|
|
Packit |
a4aae4 |
var->val2buf((void *) &val.v.f);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case dods_str_c: {
|
|
Packit |
a4aae4 |
var = new Str("dummy");
|
|
Packit |
a4aae4 |
var->val2buf((void *) val.v.s);
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
var = (BaseType *) 0;
|
|
Packit |
a4aae4 |
return var;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
var->set_read_p(true); // ...so the evaluator will know it has data
|
|
Packit |
a4aae4 |
eval.append_constant(var);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return var;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Given a string (passed in VAL), consult the DDS CE function lookup table
|
|
Packit |
a4aae4 |
// to see if a function by that name exists.
|
|
Packit |
a4aae4 |
// NB: function arguments are type-checked at run-time.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Returns: A pointer to the function or NULL if not such function exists.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool_func get_function(const ConstraintEvaluator &eval, const char *name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
bool_func f;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (eval.find_function(name, &f))
|
|
Packit |
a4aae4 |
return f;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
btp_func get_btp_function(const ConstraintEvaluator &eval, const char *name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
btp_func f;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (eval.find_function(name, &f))
|
|
Packit |
a4aae4 |
return f;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
proj_func get_proj_function(const ConstraintEvaluator &eval, const char *name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
proj_func f;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (eval.find_function(name, &f))
|
|
Packit |
a4aae4 |
return f;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<class arg_type_list, class arg_type>
|
|
Packit |
a4aae4 |
arg_type_list
|
|
Packit |
a4aae4 |
make_fast_arg_list(unsigned long vector_size_hint, arg_type value)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
arg_type_list args = new std::vector<arg_type>;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (vector_size_hint > 0) args->reserve(vector_size_hint);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
args->push_back(value);
|
|
Packit |
a4aae4 |
return args;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<class arg_type_list, class arg_type>
|
|
Packit |
a4aae4 |
arg_type_list
|
|
Packit |
a4aae4 |
make_fast_arg_list(arg_type_list values, arg_type value)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
values->push_back(value);
|
|
Packit |
a4aae4 |
return values;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<class t, class T>
|
|
Packit |
a4aae4 |
rvalue *build_constant_array(vector<t> *values, DDS *dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
//vector<t> *values = $5;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
T i("");
|
|
Packit |
a4aae4 |
Array *array = new Array("", &i);
|
|
Packit |
a4aae4 |
array->append_dim(values->size());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// TODO Make set_value_nocopy() methods so that values' pointers can be copied
|
|
Packit |
a4aae4 |
// instead of allocating memory twice. jhrg 7/5/13
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array->set_value(*values, values->size());
|
|
Packit |
a4aae4 |
delete values;
|
|
Packit |
a4aae4 |
array->set_read_p(true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static unsigned long counter = 1;
|
|
Packit |
a4aae4 |
string name;
|
|
Packit |
a4aae4 |
do {
|
|
Packit |
a4aae4 |
name = "g" + long_to_string(counter++);
|
|
Packit |
a4aae4 |
} while (dds->var(name));
|
|
Packit |
a4aae4 |
array->set_name(name);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return new rvalue(array);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|