BESTokenizer.cc

Go to the documentation of this file.
00001 // BESTokenizer.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025 
00026 // (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <iostream>
00034 
00035 using std::cout ;
00036 using std::endl ;
00037 
00038 #include "BESTokenizer.h"
00039 #include "BESParserException.h"
00040 
00041 BESTokenizer::BESTokenizer( )
00042 : _counter( -1 ) {}
00043 
00044 BESTokenizer::~BESTokenizer() {}
00045 
00058 void
00059 BESTokenizer::parse_error( const string &s ) {
00060     string error = "Parse error." ;
00061     string where = "" ;
00062     if( _counter >= 0 ) {
00063         for( int w = 0; w < _counter+1; w++ )
00064             where += tokens[w] + " " ;
00065         where += "<----HERE IS THE ERROR" ;
00066         error += "\n" + where ;
00067     }
00068     if( s != "" )
00069         error += "\n" + s ;
00070     throw BESParserException( error, __FILE__, __LINE__ ) ;
00071 }
00072 
00081 string &
00082 BESTokenizer::get_first_token() {
00083     _counter = 0 ;
00084     return tokens[_counter] ;
00085 }
00086 
00096 string &
00097 BESTokenizer::get_current_token() {
00098     if( _counter == -1 ) {
00099         parse_error( "incomplete expression!" ) ;
00100     }
00101 
00102     if( _counter > _number_tokens-1 ) {
00103         parse_error( "incomplete expression!" ) ;
00104     }
00105 
00106     return tokens[_counter] ;
00107 }
00108 
00118 string &
00119 BESTokenizer::get_next_token() {
00120     if( _counter == -1 ) {
00121         parse_error( "incomplete expression!" ) ;
00122     }
00123 
00124     if( _counter >= _number_tokens-1 ) {
00125         parse_error( "incomplete expression!" ) ;
00126     }
00127 
00128     return tokens[++_counter] ;
00129 }
00130 
00157 void
00158 BESTokenizer::tokenize( const char *p ) {
00159     size_t len = strlen( p ) ;
00160     string s = "" ;
00161     bool passing_raw = false ;
00162     bool escaped = false ;
00163     
00164 
00165     
00166     for( unsigned int j = 0; j < len; j++ ) {
00167         
00168         
00169         if( !escaped && p[j] == '\"') {
00170 
00171             if( s != "" ) {
00172                 if( passing_raw ) {
00173                     s += "\"" ;
00174                     tokens.push_back( s ) ;
00175                     s = "" ;
00176                 } else {
00177                     tokens.push_back( s ) ;
00178                     s = "\"" ;
00179                 }
00180             } else {
00181                 s += "\"" ;
00182             }
00183             passing_raw =! passing_raw ;
00184             
00185         } else if( passing_raw ) {
00186              
00187                 if(!escaped && p[j] == '\\' ){
00188                     escaped = true;
00189                 } else {          
00190                 s += p[j] ;
00191                                
00192                 if(escaped)
00193                     escaped = false;     
00194                 }  
00195            
00196         } else {
00197             if( ( p[j] == ' ' ) ||
00198                     ( p[j] == '\n' ) ||
00199                     ( p[j] == 0x0D ) ||
00200                     ( p[j] == 0x0A ) ) {
00201                 if( s != "" ) {
00202                     tokens.push_back( s ) ;
00203                     s = "" ;
00204                 }
00205             } else if( ( p[j] == ',' ) || ( p[j] == ';' ) ) {
00206                 if( s!= "" ) {
00207                     tokens.push_back( s ) ;
00208                     s = "" ;
00209                 }
00210                 switch( p[j] ) {
00211                 case ',':
00212                     tokens.push_back( "," ) ;
00213                     break;
00214                 case ';':
00215                     tokens.push_back( ";" ) ;
00216                     break;
00217                 }
00218             } else
00219                 s += p[j] ;
00220         }
00221     }
00222 
00223 
00224     if( s != "" )
00225         tokens.push_back( s ) ;
00226     _number_tokens = tokens.size() ;
00227     if( passing_raw )
00228         parse_error( "Unclose quote found.(\")" ) ;
00229     if( _number_tokens < 2 )
00230         parse_error( "Unknown command: '" + (string)p + (string)"'") ;
00231     if( tokens[_number_tokens - 1] != ";" )
00232         parse_error( "The request must be terminated by a semicolon (;)" ) ;
00233 }
00234 
00255 string
00256 BESTokenizer::parse_container_name( const string &s, unsigned int &type ) {
00257     string::size_type where = s.rfind( ".constraint=", s.size() ) ;
00258     if( where == string::npos ) {
00259         where = s.rfind( ".attributes=", s.size() ) ;
00260         if( where == string::npos ) {
00261             parse_error( "Expected property declaration." ) ;
00262         } else {
00263             type = 2 ;
00264         }
00265     } else {
00266         type = 1 ;
00267     }
00268     string valid = s.substr( where, s.size() ) ;
00269     if( (valid != ".constraint=") && (valid != ".attributes=") ) {
00270         string err = (string)"Invalid container property "
00271                      + valid
00272                      + " for container "
00273                      + s.substr( 0, where )
00274                      + ". constraint expressions and attribute lists "
00275                      + "must be wrapped in quotes"  ;
00276         parse_error( err ) ;
00277     }
00278     return s.substr( 0, where ) ;
00279 }
00280 
00292 string
00293 BESTokenizer::remove_quotes( const string &s ) {
00294     if( (s[0] != '"' ) || (s[s.size() - 1] != '"' ) ) {
00295         parse_error( "item " + s + " must be enclosed by quotes" ) ;
00296     }
00297     return s.substr( 1, s.size() - 2 ) ;
00298 }
00299 
00308 void
00309 BESTokenizer::dump_tokens() {
00310     tokens_citerator i = tokens.begin() ;
00311     tokens_citerator ie = tokens.end() ;
00312     for( ; i != ie; i++ ) {
00313         cout << "\"" << (*i) << "\"" << endl ;
00314     }
00315 }
00316 
00323 void
00324 BESTokenizer::dump( ostream &strm ) const {
00325     strm << BESIndent::LMarg << "BESTokenizer::dump - ("
00326     << (void *)this << ")" << endl ;
00327     BESIndent::Indent() ;
00328     tokens_citerator i = tokens.begin() ;
00329     tokens_citerator ie = tokens.end() ;
00330     for( ; i != ie; i++ ) {
00331     strm << BESIndent::LMarg << "\"" << (*i) << "\"" << endl ;
00332     }
00333     BESIndent::UnIndent() ;
00334 }
00335 

Generated on Wed Aug 29 03:14:16 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2