2
// -*- mode: c++; c-basic-offset:4 -*-
4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
7
// Copyright (c) 2002,2003 OPeNDAP, Inc.
8
// Author: James Gallagher <jgallagher@opendap.org>
10
// This library is free software; you can redistribute it and/or
11
// modify it under the terms of the GNU Lesser General Public
12
// License as published by the Free Software Foundation; either
13
// version 2.1 of the License, or (at your option) any later version.
15
// This library is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
// Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public
21
// License along with this library; if not, write to the Free Software
22
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
// (c) COPYRIGHT URI/MIT 1994-1999
27
// Please read the full copyright statement in the file COPYRIGHT_URI.
30
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
33
Grammar for the DDS. This grammar can be used with the bison parser
34
generator to build a parser for the DDS. It assumes that a scanner called
35
`ddslex()' exists and returns several token types (see das.tab.h)
36
in addition to several single character token types. The matched lexeme
37
for an ID is stored by the scanner in a global char * `ddslval'.
38
Because the scanner returns a value via this global and because the parser
39
stores ddslval (not the information pointed to), the values of rule
40
components must be stored as they are parsed and used once accumulated at
41
or near the end of a rule. If ddslval returned a value (instead of a
42
pointer to a value) this would not be necessary.
49
#include "config_dap.h"
67
#include "Structure.h"
77
using namespace libdap;
79
// These macros are used to access the `arguments' passed to the parser. A
80
// pointer to an error object and a pointer to an integer status variable are
81
// passed in to the parser within a structure (which itself is passed as a
82
// pointer). Note that the ERROR macro explicitly casts OBJ to an ERROR *.
83
// ERROR is no longer used. These parsers now signal problems by throwing
84
// exceptions. 5/22/2002 jhrg
85
#define DDS_OBJ(arg) ((DDS *)((parser_arg *)(arg))->_object)
87
// #define YYPARSE_PARAM arg
89
extern int dds_line_num; /* defined in dds.lex */
95
// No global static objects in the dap library! 1/24/2000 jhrg
96
static stack<BaseType *> *ctor;
97
static BaseType *current;
99
static Part part = nil; /* Part is defined in BaseType */
101
static const char *NO_DDS_MSG =
102
"The descriptor object returned from the dataset was null.\n\
103
Check that the URL is correct.";
105
static const char *BAD_DECLARATION =
106
"In the dataset descriptor object: Expected a variable declaration\n\
107
(e.g., Int32 i;). Make sure that the variable name is not the name\n\
108
of a datatype and that the Array: and Maps: sections of a Grid are\n\
112
void ddserror(parser_arg *arg, const string &s /*char *s*/);
113
void error_exit_cleanup();
114
void add_entry(DDS &table, stack<BaseType *> **ctor, BaseType **current,
116
void invalid_declaration(parser_arg *arg, string semantic_err_msg,
117
char *type, char *name);
123
%parse-param {parser_arg *arg}
136
%token <word> SCAN_WORD
137
%token <word> SCAN_DATASET
138
%token <word> SCAN_LIST
139
%token <word> SCAN_SEQUENCE
140
%token <word> SCAN_STRUCTURE
141
%token <word> SCAN_FUNCTION
142
%token <word> SCAN_GRID
143
%token <word> SCAN_BYTE
144
%token <word> SCAN_INT16
145
%token <word> SCAN_UINT16
146
%token <word> SCAN_INT32
147
%token <word> SCAN_UINT32
148
%token <word> SCAN_FLOAT32
149
%token <word> SCAN_FLOAT64
150
%token <word> SCAN_STRING
151
%token <word> SCAN_URL
153
%type <boolean> datasets dataset declarations array_decl
155
%type <word> declaration base_type structure sequence grid var var_name name
161
/* On entry to the parser, make the BaseType stack. */
162
ctor = new stack<BaseType *>;
166
delete ctor; ctor = 0;
174
dataset: SCAN_DATASET '{' declarations '}' name ';'
180
parse_error((parser_arg *)arg, NO_DDS_MSG,
181
dds_line_num, $<word>1);
182
error_exit_cleanup();
187
declarations: /* empty */
192
| declaration { $$ = true; }
193
| declarations declaration { $$ = true; }
196
/* This non-terminal is here only to keep types like `List List Int32' from
197
parsing. DODS does not allow Lists of Lists. Those types make translation
198
to/from arrays too hard. */
200
declaration: base_type var ';'
203
if (current->check_semantics(smsg)) {
204
/* BaseType *current_save = current ; */
205
add_entry(*DDS_OBJ(arg), &ctor, ¤t, part);
207
if( current_save == current )
214
invalid_declaration((parser_arg *)arg, smsg, $1, $2);
215
error_exit_cleanup();
218
strncpy($$,$2,ID_MAX);
222
| structure '{' declarations '}'
224
if( current ) delete current ;
225
current = ctor->top();
231
if (current->check_semantics(smsg))
232
add_entry(*DDS_OBJ(arg), &ctor, ¤t, part);
234
invalid_declaration((parser_arg *)arg, smsg, $1, $6);
235
error_exit_cleanup();
238
strncpy($$,$6,ID_MAX);
242
| sequence '{' declarations '}'
244
if( current ) delete current ;
245
current = ctor->top();
251
if (current->check_semantics(smsg))
252
add_entry(*DDS_OBJ(arg), &ctor, ¤t, part);
254
invalid_declaration((parser_arg *)arg, smsg, $1, $6);
255
error_exit_cleanup();
258
strncpy($$,$6,ID_MAX);
262
| grid '{' SCAN_WORD ':'
264
if (is_keyword(string($3), "array"))
268
msg << BAD_DECLARATION;
269
parse_error((parser_arg *)arg, msg.str().c_str(),
274
declaration SCAN_WORD ':'
276
if (is_keyword(string($7), "maps"))
280
msg << BAD_DECLARATION;
281
parse_error((parser_arg *)arg, msg.str().c_str(),
288
if( current ) delete current ;
289
current = ctor->top();
295
if (current->check_semantics(smsg)) {
297
add_entry(*DDS_OBJ(arg), &ctor, ¤t, part);
300
invalid_declaration((parser_arg *)arg, smsg, $1, $13);
301
error_exit_cleanup();
304
strncpy($$,$13,ID_MAX);
311
msg << BAD_DECLARATION;
312
parse_error((parser_arg *)arg, msg.str().c_str(),
313
dds_line_num, $<word>1);
319
structure: SCAN_STRUCTURE
321
ctor->push(DDS_OBJ(arg)->get_factory()->NewStructure());
325
sequence: SCAN_SEQUENCE
327
ctor->push(DDS_OBJ(arg)->get_factory()->NewSequence());
333
ctor->push(DDS_OBJ(arg)->get_factory()->NewGrid());
337
base_type: SCAN_BYTE { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewByte(); }
338
| SCAN_INT16 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewInt16(); }
339
| SCAN_UINT16 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewUInt16(); }
340
| SCAN_INT32 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewInt32(); }
341
| SCAN_UINT32 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewUInt32(); }
342
| SCAN_FLOAT32 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewFloat32(); }
343
| SCAN_FLOAT64 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewFloat64(); }
344
| SCAN_STRING { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewStr(); }
345
| SCAN_URL { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewUrl(); }
348
var: var_name { current->set_name($1); }
352
var_name: SCAN_WORD | SCAN_BYTE | SCAN_INT16 | SCAN_INT32 | SCAN_UINT16
353
| SCAN_UINT32 | SCAN_FLOAT32 | SCAN_FLOAT64 | SCAN_STRING
354
| SCAN_URL | SCAN_STRUCTURE | SCAN_SEQUENCE | SCAN_GRID
358
array_decl: '[' SCAN_WORD ']'
360
if (!check_int32($2)) {
361
string msg = "In the dataset descriptor object:\n";
362
msg += "Expected an array subscript.\n";
363
parse_error((parser_arg *)arg, msg.c_str(),
366
if (current->type() == dods_array_c
367
&& check_int32($2)) {
368
((Array *)current)->append_dim(atoi($2));
371
Array *a = DDS_OBJ(arg)->get_factory()->NewArray();
373
a->append_dim(atoi($2));
374
if( current ) delete current ;
387
if (!check_int32($5)) {
388
string msg = "In the dataset descriptor object:\n";
389
msg += "Expected an array subscript.\n";
390
parse_error((parser_arg *)arg, msg.c_str(),
392
error_exit_cleanup();
395
if (current->type() == dods_array_c) {
396
((Array *)current)->append_dim(atoi($5), *id);
399
Array *a = DDS_OBJ(arg)->get_factory()->NewArray();
401
a->append_dim(atoi($5), *id);
402
if( current ) delete current ;
416
msg << "In the dataset descriptor object:" << endl
417
<< "Expected an array subscript." << endl;
418
parse_error((parser_arg *)arg, msg.str().c_str(),
419
dds_line_num, $<word>1);
424
name: var_name { (*DDS_OBJ(arg)).set_dataset_name($1); }
425
| SCAN_DATASET { (*DDS_OBJ(arg)).set_dataset_name($1); }
429
msg << "Error parsing the dataset name." << endl
430
<< "The name may be missing or may contain an illegal character." << endl;
431
parse_error((parser_arg *)arg, msg.str().c_str(),
432
dds_line_num, $<word>1);
440
This function must be defined. However, use the error reporting code in
445
ddserror(parser_arg *, const string &)
450
Error clean up. Call this before calling YYBORT. Don't call this on a
454
void error_exit_cleanup()
465
Invalid declaration message.
468
void invalid_declaration(parser_arg *arg, string semantic_err_msg, char *type, char *name)
471
msg << "In the dataset descriptor object: `" << type << " " << name << "'" << endl << "is not a valid declaration."
472
<< endl << semantic_err_msg;
473
parse_error((parser_arg *) arg, msg.str().c_str(), dds_line_num);
477
Add the variable pointed to by CURRENT to either the topmost ctor object on
478
the stack CTOR or to the dataset variable table TABLE if CTOR is empty. If
479
it exists, the current ctor object is popped off the stack and assigned to
482
NB: the ctor stack is popped for arrays because they are ctors which
483
contain only a single variable. For other ctor types, several variables may
484
be members and the parse rule (see `declaration' above) determines when to
490
void add_entry(DDS &table, stack<BaseType *> **ctor, BaseType **current, Part part)
493
*ctor = new stack<BaseType *> ;
495
if (!(*ctor)->empty()) { /* must be parsing a ctor type */
496
(*ctor)->top()->add_var(*current, part);
498
const Type &ctor_type = (*ctor)->top()->type();
500
if (ctor_type == dods_array_c) {
503
*current = (*ctor)->top();
506
// Return here to avoid deleting the new value of 'current.'
511
table.add_var(*current);