Blame dds.yy

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 1994-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
   Grammar for the DDS. This grammar can be used with the bison parser
Packit a4aae4
   generator to build a parser for the DDS. It assumes that a scanner called
Packit a4aae4
   `ddslex()' exists and returns several token types (see das.tab.h)
Packit a4aae4
   in addition to several single character token types. The matched lexeme
Packit a4aae4
   for an ID is stored by the scanner in a global char * `ddslval'.
Packit a4aae4
   Because the scanner returns a value via this global and because the parser
Packit a4aae4
   stores ddslval (not the information pointed to), the values of rule
Packit a4aae4
   components must be stored as they are parsed and used once accumulated at
Packit a4aae4
   or near the end of a rule. If ddslval returned a value (instead of a
Packit a4aae4
   pointer to a value) this would not be necessary.
Packit a4aae4
Packit a4aae4
   jhrg 8/29/94 
Packit a4aae4
*/
Packit a4aae4
Packit a4aae4
%code requires {
Packit a4aae4
Packit a4aae4
#include "config_dap.h"
Packit a4aae4
Packit a4aae4
#include <cstring>
Packit a4aae4
#include <cassert>
Packit a4aae4
#include <iostream>
Packit a4aae4
#include <stack>
Packit a4aae4
#include <sstream>
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 "DDS.h"
Packit a4aae4
#include "Error.h"
Packit a4aae4
#include "parser.h"
Packit a4aae4
#include "util.h"
Packit a4aae4
Packit a4aae4
using namespace std;
Packit a4aae4
using namespace libdap;
Packit a4aae4
Packit a4aae4
// These macros are used to access the `arguments' passed to the parser. A
Packit a4aae4
// pointer to an error object and a pointer to an integer status variable are
Packit a4aae4
// passed in to the parser within a structure (which itself is passed as a
Packit a4aae4
// pointer). Note that the ERROR macro explicitly casts OBJ to an ERROR *. 
Packit a4aae4
// ERROR is no longer used. These parsers now signal problems by throwing
Packit a4aae4
// exceptions. 5/22/2002 jhrg
Packit a4aae4
#define DDS_OBJ(arg) ((DDS *)((parser_arg *)(arg))->_object)
Packit a4aae4
Packit a4aae4
// #define YYPARSE_PARAM arg
Packit a4aae4
Packit a4aae4
extern int dds_line_num;	/* defined in dds.lex */
Packit a4aae4
Packit a4aae4
} // code requires
Packit a4aae4
Packit a4aae4
%code {
Packit a4aae4
Packit a4aae4
// No global static objects in the dap library! 1/24/2000 jhrg
Packit a4aae4
static stack<BaseType *> *ctor;
Packit a4aae4
static BaseType *current;
Packit a4aae4
static string *id;
Packit a4aae4
static Part part = nil;		/* Part is defined in BaseType */
Packit a4aae4
Packit a4aae4
static const char *NO_DDS_MSG =
Packit a4aae4
"The descriptor object returned from the dataset was null.\n\
Packit a4aae4
Check that the URL is correct.";
Packit a4aae4
Packit a4aae4
static const char *BAD_DECLARATION =
Packit a4aae4
"In the dataset descriptor object: Expected a variable declaration\n\
Packit a4aae4
(e.g., Int32 i;). Make sure that the variable name is not the name\n\
Packit a4aae4
of a datatype and that the Array: and Maps: sections of a Grid are\n\
Packit a4aae4
labeled properly.";
Packit a4aae4
Packit a4aae4
int ddslex();
Packit a4aae4
void ddserror(parser_arg *arg, const string &s /*char *s*/);
Packit a4aae4
void error_exit_cleanup();
Packit a4aae4
void add_entry(DDS &table, stack<BaseType *> **ctor, BaseType **current, 
Packit a4aae4
	       Part p);
Packit a4aae4
void invalid_declaration(parser_arg *arg, string semantic_err_msg, 
Packit a4aae4
			 char *type, char *name);
Packit a4aae4
Packit a4aae4
} // code
Packit a4aae4
Packit a4aae4
%require "2.4"
Packit a4aae4
Packit a4aae4
%parse-param {parser_arg *arg}
Packit a4aae4
%name-prefix "dds"
Packit a4aae4
%defines
Packit a4aae4
%debug
Packit a4aae4
%verbose
Packit a4aae4
Packit a4aae4
%expect 52
Packit a4aae4
Packit a4aae4
%union {
Packit a4aae4
    bool boolean;
Packit a4aae4
    char word[ID_MAX];
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
%token <word> SCAN_WORD
Packit a4aae4
%token <word> SCAN_DATASET
Packit a4aae4
%token <word> SCAN_LIST
Packit a4aae4
%token <word> SCAN_SEQUENCE
Packit a4aae4
%token <word> SCAN_STRUCTURE
Packit a4aae4
%token <word> SCAN_FUNCTION
Packit a4aae4
%token <word> SCAN_GRID
Packit a4aae4
%token <word> SCAN_BYTE
Packit a4aae4
%token <word> SCAN_INT16
Packit a4aae4
%token <word> SCAN_UINT16
Packit a4aae4
%token <word> SCAN_INT32
Packit a4aae4
%token <word> SCAN_UINT32
Packit a4aae4
%token <word> SCAN_FLOAT32
Packit a4aae4
%token <word> SCAN_FLOAT64
Packit a4aae4
%token <word> SCAN_STRING
Packit a4aae4
%token <word> SCAN_URL 
Packit a4aae4
Packit a4aae4
%type <boolean> datasets dataset declarations array_decl name
Packit a4aae4
Packit a4aae4
%type <word> declaration base_type structure sequence grid var var_name
Packit a4aae4
Packit a4aae4
%%
Packit a4aae4
Packit a4aae4
start:
Packit a4aae4
        {
Packit a4aae4
		    /* On entry to the parser, make the BaseType stack. 
Packit a4aae4
		       I use if (!ctor) here because in the tab.cc file,
Packit a4aae4
		       this is a case block in a switch, so it could be
Packit a4aae4
		       run more than once, causing the storage to be
Packit a4aae4
		       overwritten. jhrg 6/26/15 */
Packit a4aae4
		       
Packit a4aae4
		    if (!ctor)
Packit a4aae4
		    	ctor = new stack<BaseType *>;
Packit a4aae4
        }
Packit a4aae4
        datasets
Packit a4aae4
        {
Packit a4aae4
		    delete ctor; ctor = 0;
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
datasets:	dataset
Packit a4aae4
		| datasets dataset
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
dataset:	SCAN_DATASET '{' declarations '}' name ';'
Packit a4aae4
        {
Packit a4aae4
		    $$ = $3 && $5;
Packit a4aae4
		}
Packit a4aae4
        | error
Packit a4aae4
        {
Packit a4aae4
		    parse_error((parser_arg *)arg, NO_DDS_MSG, dds_line_num, $<word>1);
Packit a4aae4
		    error_exit_cleanup();
Packit a4aae4
		    YYABORT;
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
declarations:	/* empty */
Packit a4aae4
        {
Packit a4aae4
		    $$ = true;
Packit a4aae4
		}
Packit a4aae4
        | declaration { $$ = true; }
Packit a4aae4
        | declarations declaration { $$ = true; }
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
/* This non-terminal is here only to keep types like `List List Int32' from
Packit a4aae4
   parsing. DODS does not allow Lists of Lists. Those types make translation
Packit a4aae4
   to/from arrays too hard. 
Packit a4aae4
   
Packit a4aae4
   NB: I removed the List type from DAP years ago. jhrg 6/26/15 */
Packit a4aae4
Packit a4aae4
declaration:  base_type var ';' 
Packit a4aae4
        { 
Packit a4aae4
		    string smsg;
Packit a4aae4
		    if (current->check_semantics(smsg)) {
Packit a4aae4
			    add_entry(*DDS_OBJ(arg), &ctor, &current, part); 
Packit a4aae4
		    } else {
Packit a4aae4
		      invalid_declaration((parser_arg *)arg, smsg, $1, $2);
Packit a4aae4
		      error_exit_cleanup();
Packit a4aae4
		      YYABORT;
Packit a4aae4
		    }
Packit a4aae4
            strncpy($$,$2,ID_MAX);
Packit a4aae4
            $$[ID_MAX-1] = '\0';
Packit a4aae4
		}
Packit a4aae4
Packit a4aae4
		| structure  '{' declarations '}' 
Packit a4aae4
		{ 
Packit a4aae4
		    if( current ) delete current ;
Packit a4aae4
		    current = ctor->top(); 
Packit a4aae4
		    ctor->pop();
Packit a4aae4
		} 
Packit a4aae4
        var ';' 
Packit a4aae4
        { 
Packit a4aae4
		    string smsg;
Packit a4aae4
		    if (current->check_semantics(smsg)) {
Packit a4aae4
			    add_entry(*DDS_OBJ(arg), &ctor, &current, part); 
Packit a4aae4
			}
Packit a4aae4
		    else {
Packit a4aae4
		        invalid_declaration((parser_arg *)arg, smsg, $1, $6);
Packit a4aae4
		        error_exit_cleanup();
Packit a4aae4
		        YYABORT;
Packit a4aae4
		    }
Packit a4aae4
            strncpy($$,$6,ID_MAX);
Packit a4aae4
            $$[ID_MAX-1] = '\0';
Packit a4aae4
		}
Packit a4aae4
Packit a4aae4
		| sequence '{' declarations '}' 
Packit a4aae4
        { 
Packit a4aae4
		    if( current ) delete current ;
Packit a4aae4
		    current = ctor->top(); 
Packit a4aae4
		    ctor->pop();
Packit a4aae4
		} 
Packit a4aae4
        var ';' 
Packit a4aae4
        { 
Packit a4aae4
		    string smsg;
Packit a4aae4
		    if (current->check_semantics(smsg)) {
Packit a4aae4
			    add_entry(*DDS_OBJ(arg), &ctor, &current, part); 
Packit a4aae4
			}
Packit a4aae4
		    else {
Packit a4aae4
		      invalid_declaration((parser_arg *)arg, smsg, $1, $6);
Packit a4aae4
		      error_exit_cleanup();
Packit a4aae4
		      YYABORT;
Packit a4aae4
		    }
Packit a4aae4
            strncpy($$,$6,ID_MAX);
Packit a4aae4
            $$[ID_MAX-1] = '\0';
Packit a4aae4
		}
Packit a4aae4
Packit a4aae4
		| grid '{' SCAN_WORD ':'
Packit a4aae4
		{ 
Packit a4aae4
		    if (is_keyword(string($3), "array")) {
Packit a4aae4
			    part = libdap::array;
Packit a4aae4
			}
Packit a4aae4
		    else {
Packit a4aae4
			    ostringstream msg;
Packit a4aae4
			    msg << BAD_DECLARATION;
Packit a4aae4
			    parse_error((parser_arg *)arg, msg.str().c_str(), dds_line_num, $3);
Packit a4aae4
			    YYABORT;
Packit a4aae4
		    }
Packit a4aae4
        }
Packit a4aae4
        declaration SCAN_WORD ':'
Packit a4aae4
		{ 
Packit a4aae4
		    if (is_keyword(string($7), "maps")) {
Packit a4aae4
			    part = maps; 
Packit a4aae4
			}
Packit a4aae4
		    else {
Packit a4aae4
			    ostringstream msg;
Packit a4aae4
			    msg << BAD_DECLARATION;
Packit a4aae4
			    parse_error((parser_arg *)arg, msg.str().c_str(), dds_line_num, $7);
Packit a4aae4
			    YYABORT;
Packit a4aae4
		    }
Packit a4aae4
        }
Packit a4aae4
        declarations '}' 
Packit a4aae4
		{
Packit a4aae4
		    if( current ) delete current ;
Packit a4aae4
		    current = ctor->top(); 
Packit a4aae4
		    ctor->pop();
Packit a4aae4
		}
Packit a4aae4
        var ';' 
Packit a4aae4
        {
Packit a4aae4
		    string smsg;
Packit a4aae4
		    if (current->check_semantics(smsg)) {
Packit a4aae4
			    part = nil; 
Packit a4aae4
			    add_entry(*DDS_OBJ(arg), &ctor, &current, part); 
Packit a4aae4
		    }
Packit a4aae4
		    else {
Packit a4aae4
		      invalid_declaration((parser_arg *)arg, smsg, $1, $13);
Packit a4aae4
		      error_exit_cleanup();
Packit a4aae4
		      YYABORT;
Packit a4aae4
		    }
Packit a4aae4
        strncpy($$,$13,ID_MAX);
Packit a4aae4
        $$[ID_MAX-1] = '\0';
Packit a4aae4
		}
Packit a4aae4
Packit a4aae4
        | error 
Packit a4aae4
        {
Packit a4aae4
		    ostringstream msg;
Packit a4aae4
		    msg << BAD_DECLARATION;
Packit a4aae4
		    parse_error((parser_arg *)arg, msg.str().c_str(), dds_line_num, $<word>1);
Packit a4aae4
		    YYABORT;
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
 
Packit a4aae4
Packit a4aae4
structure:	SCAN_STRUCTURE
Packit a4aae4
		{ 
Packit a4aae4
		    ctor->push(DDS_OBJ(arg)->get_factory()->NewStructure()); 
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
sequence:	SCAN_SEQUENCE 
Packit a4aae4
		{ 
Packit a4aae4
		    ctor->push(DDS_OBJ(arg)->get_factory()->NewSequence()); 
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
grid:		SCAN_GRID 
Packit a4aae4
		{ 
Packit a4aae4
		    ctor->push(DDS_OBJ(arg)->get_factory()->NewGrid()); 
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
base_type:	SCAN_BYTE { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewByte(); }
Packit a4aae4
		| SCAN_INT16 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewInt16(); }
Packit a4aae4
		| SCAN_UINT16 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewUInt16(); }
Packit a4aae4
		| SCAN_INT32 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewInt32(); }
Packit a4aae4
		| SCAN_UINT32 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewUInt32(); }
Packit a4aae4
		| SCAN_FLOAT32 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewFloat32(); }
Packit a4aae4
		| SCAN_FLOAT64 { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewFloat64(); }
Packit a4aae4
		| SCAN_STRING { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewStr(); }
Packit a4aae4
		| SCAN_URL { if( current ) delete current ;current = DDS_OBJ(arg)->get_factory()->NewUrl(); }
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
var:		var_name { current->set_name($1); }
Packit a4aae4
 		| var array_decl
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
var_name:       SCAN_WORD | SCAN_BYTE | SCAN_INT16 | SCAN_INT32 | SCAN_UINT16
Packit a4aae4
        | SCAN_UINT32 | SCAN_FLOAT32 | SCAN_FLOAT64 | SCAN_STRING
Packit a4aae4
        | SCAN_URL | SCAN_STRUCTURE | SCAN_SEQUENCE | SCAN_GRID
Packit a4aae4
        | SCAN_LIST
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
array_decl:	'[' SCAN_WORD ']'
Packit a4aae4
        { 
Packit a4aae4
		    if (!check_int32($2)) {
Packit a4aae4
			    string msg = "In the dataset descriptor object:\n";
Packit a4aae4
			    msg += "Expected an array subscript.\n";
Packit a4aae4
			    parse_error((parser_arg *)arg, msg.c_str(), dds_line_num, $2);
Packit a4aae4
		    }
Packit a4aae4
		    if (current->type() == dods_array_c && check_int32($2)) {
Packit a4aae4
			    ((Array *)current)->append_dim(atoi($2));
Packit a4aae4
		    }
Packit a4aae4
		    else {
Packit a4aae4
			    Array *a = DDS_OBJ(arg)->get_factory()->NewArray(); 
Packit a4aae4
			    a->add_var(current); 
Packit a4aae4
			    a->append_dim(atoi($2));
Packit a4aae4
			    if( current ) delete current ;
Packit a4aae4
			    current = a;
Packit a4aae4
		    }
Packit a4aae4
Packit a4aae4
		    $$ = true;
Packit a4aae4
		 }
Packit a4aae4
Packit a4aae4
		 | '[' SCAN_WORD 
Packit a4aae4
		 {
Packit a4aae4
		     if (!id) id = new string($2);
Packit a4aae4
		 } 
Packit a4aae4
         '=' SCAN_WORD 
Packit a4aae4
         { 
Packit a4aae4
		     if (!check_int32($5)) {
Packit a4aae4
			     string msg = "In the dataset descriptor object:\n";
Packit a4aae4
			     msg += "Expected an array subscript.\n";
Packit a4aae4
			     parse_error((parser_arg *)arg, msg.c_str(), dds_line_num, $5);
Packit a4aae4
			     error_exit_cleanup();
Packit a4aae4
			     YYABORT;
Packit a4aae4
		     }
Packit a4aae4
		     if (current->type() == dods_array_c) {
Packit a4aae4
			     ((Array *)current)->append_dim(atoi($5), *id);
Packit a4aae4
		     }
Packit a4aae4
		     else {
Packit a4aae4
			     Array *a = DDS_OBJ(arg)->get_factory()->NewArray(); 
Packit a4aae4
			     a->add_var(current); 
Packit a4aae4
			     a->append_dim(atoi($5), *id);
Packit a4aae4
			     if( current ) delete current ;
Packit a4aae4
			     current = a;
Packit a4aae4
		     }
Packit a4aae4
Packit a4aae4
		     delete id; id = 0;
Packit a4aae4
		 }
Packit a4aae4
		 ']'
Packit a4aae4
         {
Packit a4aae4
		     $$ = true;
Packit a4aae4
		 }
Packit a4aae4
Packit a4aae4
		 | error
Packit a4aae4
         {
Packit a4aae4
		     ostringstream msg;
Packit a4aae4
		     msg << "In the dataset descriptor object:" << endl
Packit a4aae4
			     << "Expected an array subscript." << endl;
Packit a4aae4
		     parse_error((parser_arg *)arg, msg.str().c_str(), dds_line_num, $<word>1);
Packit a4aae4
		     YYABORT;
Packit a4aae4
		 }
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
name:		var_name { (*DDS_OBJ(arg)).set_dataset_name($1); $$ = true;}
Packit a4aae4
		| SCAN_DATASET { (*DDS_OBJ(arg)).set_dataset_name($1); $$ = true; }
Packit a4aae4
        | error 
Packit a4aae4
        {
Packit a4aae4
		    ostringstream msg;
Packit a4aae4
		    msg << "Error parsing the dataset name." << endl
Packit a4aae4
		        << "The name may be missing or may contain an illegal character." << endl;
Packit a4aae4
		    parse_error((parser_arg *)arg, msg.str().c_str(), dds_line_num, $<word>1);
Packit a4aae4
		    YYABORT;
Packit a4aae4
		}
Packit a4aae4
;
Packit a4aae4
Packit a4aae4
%%
Packit a4aae4
Packit a4aae4
/* 
Packit a4aae4
 This function must be defined. However, use the error reporting code in
Packit a4aae4
 parser-utils.cc.
Packit a4aae4
 */
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
ddserror(parser_arg *, const string &)
Packit a4aae4
{
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/*
Packit a4aae4
 Error clean up. Call this before calling YYBORT. Don't call this on a
Packit a4aae4
 normal exit.
Packit a4aae4
 */
Packit a4aae4
Packit a4aae4
void error_exit_cleanup()
Packit a4aae4
{
Packit a4aae4
    delete id;
Packit a4aae4
    id = 0;
Packit a4aae4
    delete current;
Packit a4aae4
    current = 0;
Packit a4aae4
    delete ctor;
Packit a4aae4
    ctor = 0;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/*
Packit a4aae4
 Invalid declaration message.
Packit a4aae4
 */
Packit a4aae4
Packit a4aae4
void invalid_declaration(parser_arg *arg, string semantic_err_msg, char *type, char *name)
Packit a4aae4
{
Packit a4aae4
    ostringstream msg;
Packit a4aae4
    msg << "In the dataset descriptor object: `" << type << " " << name << "'" << endl << "is not a valid declaration."
Packit a4aae4
            << endl << semantic_err_msg;
Packit a4aae4
    parse_error((parser_arg *) arg, msg.str().c_str(), dds_line_num);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/*
Packit a4aae4
 Add the variable pointed to by CURRENT to either the topmost ctor object on
Packit a4aae4
 the stack CTOR or to the dataset variable table TABLE if CTOR is empty.  If
Packit a4aae4
 it exists, the current ctor object is popped off the stack and assigned to
Packit a4aae4
 CURRENT.
Packit a4aae4
Packit a4aae4
 NB: the ctor stack is popped for arrays because they are ctors which
Packit a4aae4
 contain only a single variable. For other ctor types, several variables may
Packit a4aae4
 be members and the parse rule (see `declaration' above) determines when to
Packit a4aae4
 pop the stack.
Packit a4aae4
Packit a4aae4
 Returns: void 
Packit a4aae4
 */
Packit a4aae4
Packit a4aae4
void add_entry(DDS &table, stack<BaseType *> **ctor, BaseType **current, Part part)
Packit a4aae4
{
Packit a4aae4
    if (!*ctor)
Packit a4aae4
        *ctor = new stack<BaseType *> ;
Packit a4aae4
Packit a4aae4
    if (!(*ctor)->empty()) { /* must be parsing a ctor type */
Packit a4aae4
        (*ctor)->top()->add_var(*current, part);
Packit a4aae4
Packit a4aae4
        const Type &ctor_type = (*ctor)->top()->type();
Packit a4aae4
Packit a4aae4
        if (ctor_type == dods_array_c) {
Packit a4aae4
            if (*current)
Packit a4aae4
                delete *current;
Packit a4aae4
            *current = (*ctor)->top();
Packit a4aae4
            (*ctor)->pop();
Packit a4aae4
Packit a4aae4
            // Return here to avoid deleting the new value of 'current.'
Packit a4aae4
            return;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        table.add_var(*current);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    if (*current)
Packit a4aae4
        delete *current;
Packit a4aae4
    *current = 0;
Packit a4aae4
}
Packit a4aae4