OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESTokenizer.cc
Go to the documentation of this file.
1 // BESTokenizer.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <cstring>
34 #include <iostream>
35 
36 using std::cout ;
37 using std::endl ;
38 
39 #include "BESTokenizer.h"
40 #include "BESSyntaxUserError.h"
41 
43 : _counter( -1 ) {}
44 
46 
59 void
60 BESTokenizer::parse_error( const string &s ) {
61  string error = "Parse error." ;
62  string where = "" ;
63  if( _counter >= 0 ) {
64  for( int w = 0; w < _counter+1; w++ )
65  where += tokens[w] + " " ;
66  where += "<----HERE IS THE ERROR" ;
67  error += "\n" + where ;
68  }
69  if( s != "" )
70  error += "\n" + s ;
71  throw BESSyntaxUserError( error, __FILE__, __LINE__ ) ;
72 }
73 
82 string &
84  _counter = 0 ;
85  return tokens[_counter] ;
86 }
87 
97 string &
99  if( _counter == -1 ) {
100  parse_error( "incomplete expression!" ) ;
101  }
102 
103  if( _counter > _number_tokens-1 ) {
104  parse_error( "incomplete expression!" ) ;
105  }
106 
107  return tokens[_counter] ;
108 }
109 
119 string &
121  if( _counter == -1 ) {
122  parse_error( "incomplete expression!" ) ;
123  }
124 
125  if( _counter >= _number_tokens-1 ) {
126  parse_error( "incomplete expression!" ) ;
127  }
128 
129  return tokens[++_counter] ;
130 }
131 
158 void
159 BESTokenizer::tokenize( const char *p ) {
160  size_t len = strlen( p ) ;
161  string s = "" ;
162  bool passing_raw = false ;
163  bool escaped = false ;
164 
165 
166 
167  for( unsigned int j = 0; j < len; j++ ) {
168 
169 
170  if( !escaped && p[j] == '\"') {
171 
172  if( s != "" ) {
173  if( passing_raw ) {
174  s += "\"" ;
175  tokens.push_back( s ) ;
176  s = "" ;
177  } else {
178  tokens.push_back( s ) ;
179  s = "\"" ;
180  }
181  } else {
182  s += "\"" ;
183  }
184  passing_raw =! passing_raw ;
185 
186  } else if( passing_raw ) {
187 
188  if(!escaped && p[j] == '\\' ){
189  escaped = true;
190  } else {
191  s += p[j] ;
192 
193  if(escaped)
194  escaped = false;
195  }
196 
197  } else {
198  if( ( p[j] == ' ' ) ||
199  ( p[j] == '\n' ) ||
200  ( p[j] == 0x0D ) ||
201  ( p[j] == 0x0A ) ) {
202  if( s != "" ) {
203  tokens.push_back( s ) ;
204  s = "" ;
205  }
206  } else if( ( p[j] == ',' ) || ( p[j] == ';' ) ) {
207  if( s!= "" ) {
208  tokens.push_back( s ) ;
209  s = "" ;
210  }
211  switch( p[j] ) {
212  case ',':
213  tokens.push_back( "," ) ;
214  break;
215  case ';':
216  tokens.push_back( ";" ) ;
217  break;
218  }
219  } else
220  s += p[j] ;
221  }
222  }
223 
224 
225  if( s != "" )
226  tokens.push_back( s ) ;
227  _number_tokens = tokens.size() ;
228  if( passing_raw )
229  parse_error( "Unclose quote found.(\")" ) ;
230  if( _number_tokens < 1 )
231  parse_error( "Unknown command: '" + (string)p + (string)"'") ;
232  if( tokens[_number_tokens - 1] != ";" )
233  parse_error( "The request must be terminated by a semicolon (;)" ) ;
234 }
235 
256 string
257 BESTokenizer::parse_container_name( const string &s, unsigned int &type ) {
258  string::size_type where = s.rfind( ".constraint=", s.size() ) ;
259  if( where == string::npos ) {
260  where = s.rfind( ".attributes=", s.size() ) ;
261  if( where == string::npos ) {
262  parse_error( "Expected property declaration." ) ;
263  } else {
264  type = 2 ;
265  }
266  } else {
267  type = 1 ;
268  }
269  string valid = s.substr( where, s.size() ) ;
270  if( (valid != ".constraint=") && (valid != ".attributes=") ) {
271  string err = (string)"Invalid container property "
272  + valid
273  + " for container "
274  + s.substr( 0, where )
275  + ". constraint expressions and attribute lists "
276  + "must be wrapped in quotes" ;
277  parse_error( err ) ;
278  }
279  return s.substr( 0, where ) ;
280 }
281 
293 string
294 BESTokenizer::remove_quotes( const string &s ) {
295  if( (s[0] != '"' ) || (s[s.size() - 1] != '"' ) ) {
296  parse_error( "item " + s + " must be enclosed by quotes" ) ;
297  }
298  return s.substr( 1, s.size() - 2 ) ;
299 }
300 
309 void
311  tokens_citerator i = tokens.begin() ;
312  tokens_citerator ie = tokens.end() ;
313  for( ; i != ie; i++ ) {
314  cout << "\"" << (*i) << "\"" << endl ;
315  }
316 }
317 
324 void
325 BESTokenizer::dump( ostream &strm ) const {
326  strm << BESIndent::LMarg << "BESTokenizer::dump - ("
327  << (void *)this << ")" << endl ;
329  tokens_citerator i = tokens.begin() ;
330  tokens_citerator ie = tokens.end() ;
331  for( ; i != ie; i++ ) {
332  strm << BESIndent::LMarg << "\"" << (*i) << "\"" << endl ;
333  }
335 }
336 
string & get_next_token()
returns the next token from the token list
static void Indent()
Definition: BESIndent.cc:38
error thrown if there is a user syntax error in the request or any other user error ...
string & get_first_token()
returns the first token from the token list
Definition: BESTokenizer.cc:83
string remove_quotes(const string &s)
removes quotes from a quoted token
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
string parse_container_name(const string &s, unsigned int &type)
parses a container name for constraint and attributes
void parse_error(const string &s="")
throws an exception giving the tokens up to the point of the problem
Definition: BESTokenizer.cc:60
void tokenize(const char *p)
tokenize the BES request/command string
static void UnIndent()
Definition: BESIndent.cc:44
virtual void dump(ostream &strm) const
dumps information about this object
string & get_current_token()
returns the current token from the token list
Definition: BESTokenizer.cc:98
void dump_tokens()
dump the tokens that have been tokenized in the order in which they are parsed.