00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "RioMMIndexParser.h"
00019 #include "RioError.h"
00020
00021 #include <ctype.h>
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <limits.h>
00026 #include <iostream>
00027 using namespace std;
00028
00029 CRioMMIndexParser::TokenType CRioMMIndexParser::token_type;
00030 char CRioMMIndexParser::token_string[ 256 ];
00031 int CRioMMIndexParser::token_offset;
00032
00033 CRioMMIndex * CRioMMIndexParser::index;
00034
00035 FILE * CRioMMIndexParser::file;
00036 int CRioMMIndexParser::line_number;
00037
00038 RioBlock CRioMMIndexParser::command_index;
00039
00040 int CRioMMIndexParser::integer_value;
00041 RioBlock CRioMMIndexParser::index_value;
00042
00043 bool CRioMMIndexParser::quit_on_errors;
00044
00045
00046 const char * CRioMMIndexParser::token_name[] =
00047 {
00048 "an invalid token",
00049 "the end of the file",
00050
00051 "an integer",
00052 "a string",
00053
00054 "'{'",
00055 "'}'",
00056
00057 "'['",
00058 "']'",
00059
00060 "'('",
00061 "')'",
00062
00063 "','",
00064 "';'",
00065
00066 "'Version'",
00067 "'Archive'",
00068 "'File'",
00069 "'Slide'",
00070 "'OpenURL'",
00071 "a command"
00072 };
00073
00074 void CRioMMIndexParser::InitVars( void )
00075 {
00076 token_type = TK_INVALID;
00077 token_string[ 0 ] = '\0';
00078 index = NULL;
00079 file = NULL;
00080 line_number = 0;
00081 command_index = 0;
00082 integer_value = 0;
00083 token_offset = -1;
00084 }
00085
00086 void CRioMMIndexParser::ReportError( const char * message )
00087 {
00088 RioErr << "Error at line " << line_number << ": " << message << endl;
00089 if( index )
00090 delete index;
00091 if( quit_on_errors )
00092 exit( -1 );
00093 }
00094
00095 void CRioMMIndexParser::Match( TokenType type )
00096 {
00097 if( token_type == type )
00098 {
00099 if( GetToken( ) == TK_INVALID )
00100 {
00101 ReportError( "Invalid token found in the input" );
00102 }
00103 }
00104 else
00105 {
00106 RioErr << "Found " << token_name[ token_type ]
00107 << " while expecting " << token_name[ type ]
00108 << endl;
00109 ReportError( "Syntax error matching token" );
00110 }
00111 }
00112
00113 CRioMMIndexParser::TokenType CRioMMIndexParser::GetToken( void )
00114 {
00115 int i;
00116 char ch;
00117
00118
00119 do
00120 {
00121 ch = fgetc( file );
00122 if( ch == '\n' )
00123 line_number++;
00124 } while( isspace( ch ) );
00125
00126 token_offset = ftell( file ) - 1;
00127
00128 if( ch == EOF )
00129 {
00130
00131 token_type = TK_EOF;
00132 }
00133 else if( ch == '#' )
00134 {
00135 do
00136 {
00137 ch = fgetc( file );
00138 }
00139 while( ch != '\n' && ch != EOF );
00140
00141 if( ch == EOF )
00142 {
00143 token_offset = ftell( file ) - 1;
00144 token_type = TK_EOF;
00145 }
00146 else
00147 {
00148 line_number++;
00149 token_type = GetToken( );
00150 }
00151 }
00152 else if( isdigit( ch ) )
00153 {
00154
00155
00156 i = 0;
00157 do
00158 {
00159 token_string[ i++ ] = ch;
00160 ch = fgetc( file );
00161 }
00162 while( isdigit( ch ) );
00163
00164 ungetc( ch, file );
00165 token_string[ i ] = '\0';
00166 integer_value = atoi( token_string );
00167 index_value = strtoul( token_string, NULL, 10 );
00168 token_type = TK_INTEGER;
00169 }
00170 else if( ch == '"' )
00171 {
00172 i = 0;
00173 ch = fgetc( file );
00174 while( ch != '"' && ch != EOF )
00175 {
00176 token_string[ i++ ] = ch;
00177 ch = fgetc( file );
00178 }
00179 if( ch == '"' )
00180 {
00181 token_string[ i ] = '\0';
00182 token_type = TK_STRING;
00183 }
00184 else
00185 {
00186 token_type = TK_INVALID;
00187 }
00188 }
00189 else if( isalpha( ch ) )
00190 {
00191
00192
00193 i = 0;
00194 while( isalpha( ch ) || ch == '_' || isdigit( ch ) )
00195 {
00196 token_string[ i++ ] = ch;
00197 ch = fgetc( file );
00198 }
00199 ungetc( ch, file );
00200 token_string[ i ] = '\0';
00201
00202
00203 if( strcmp( token_string, "Version" ) == 0 )
00204 {
00205 token_type = TK_VERSION;
00206 }
00207 else if( strcmp( token_string, "Archive" ) == 0 )
00208 {
00209 token_type = TK_ARCHIVE;
00210 }
00211 else if( strcmp( token_string, "File" ) == 0 )
00212 {
00213 token_type = TK_FILE;
00214 }
00215 else if( strcmp( token_string, "Slide" ) == 0 )
00216 {
00217 token_type = TK_SLIDE;
00218 }
00219 else if( strcmp( token_string, "OpenURL" ) == 0 )
00220 {
00221 token_type = TK_OPENURL;
00222 }
00223 else
00224 {
00225 token_type = TK_COMMAND;
00226 }
00227 }
00228 else
00229 {
00230 switch( ch )
00231 {
00232 case '(':
00233 token_type = TK_LPAR;
00234 break;
00235 case ')':
00236 token_type = TK_RPAR;
00237 break;
00238 case '{':
00239 token_type = TK_LCBRAC;
00240 break;
00241 case '}':
00242 token_type = TK_RCBRAC;
00243 break;
00244 case '[':
00245 token_type = TK_LBRAC;
00246 break;
00247 case ']':
00248 token_type = TK_RBRAC;
00249 break;
00250 case ',':
00251 token_type = TK_COMMA;
00252 break;
00253 case ';':
00254 token_type = TK_SEMICOL;
00255 break;
00256 default:
00257 token_type = TK_INVALID;
00258 break;
00259 }
00260 }
00261
00262 return token_type;
00263 }
00264
00265 void CRioMMIndexParser::FilesDeclaration( void )
00266 {
00267 if( token_type == TK_LBRAC )
00268 {
00269 FileDeclaration( );
00270 FilesDeclaration( );
00271 }
00272 else ;
00273 }
00274
00275 void CRioMMIndexParser::FileDeclaration( void )
00276 {
00277 TString filename;
00278 RioBlock position;
00279
00280 Match( TK_LBRAC );
00281 position = index_value;
00282 Match( TK_INTEGER );
00283 Match( TK_RBRAC );
00284
00285 if( token_type == TK_OPENURL )
00286 {
00287 Match( TK_OPENURL );
00288 Match( TK_LPAR );
00289 filename = token_string;
00290 Match( TK_STRING );
00291 Match( TK_RPAR );
00292 Match( TK_SEMICOL );
00293
00294 #ifdef RIO_DEBUG2
00295 RioErr << "Inserting URL " << (const char *)filename << " at position "
00296 << position << endl;
00297 #endif
00298
00299 if( !index->InsertFile( (const char *)filename, position ) )
00300 {
00301 ReportError( "Error trying to insert a new file" );
00302 }
00303 if( !index->InsertSlide( 1, -1,
00304 0, position ) )
00305 {
00306 ReportError( "Error trying to insert a new slide" );
00307 }
00308 }
00309 else
00310 {
00311 Match( TK_FILE );
00312 Match( TK_LPAR );
00313 filename = token_string;
00314 Match( TK_STRING );
00315 Match( TK_RPAR );
00316 Match( TK_LCBRAC );
00317
00318 #ifdef RIO_DEBUG2
00319 RioErr << "Inserting file " << (const char *)filename << " at position "
00320 << position << endl;
00321 #endif
00322
00323 if( !index->InsertFile( (const char *)filename, position ) )
00324 {
00325 ReportError( "Error trying to insert a new file" );
00326 }
00327
00328 SlideDeclaration( );
00329 SlidesDeclaration( );
00330
00331 Match( TK_RCBRAC );
00332 }
00333 }
00334
00335 void CRioMMIndexParser::SlidesDeclaration( void )
00336 {
00337 if( token_type == TK_LBRAC )
00338 {
00339 SlideDeclaration( );
00340 SlidesDeclaration( );
00341 }
00342 else ;
00343 }
00344
00345 void CRioMMIndexParser::SlideDeclaration( void )
00346 {
00347 int slide_number;
00348 int commands_offset = -1;
00349 RioBlock first_command_index = 0,
00350 position;
00351
00352 Match( TK_LBRAC );
00353 position = index_value;
00354 Match( TK_INTEGER );
00355 Match( TK_RBRAC );
00356
00357 Match( TK_SLIDE );
00358 Match( TK_LPAR );
00359 slide_number = integer_value;
00360 Match( TK_INTEGER );
00361 Match( TK_RPAR );
00362 if( token_type == TK_LCBRAC )
00363 {
00364 Match( TK_LCBRAC );
00365 commands_offset = token_offset;
00366 CommandDeclaration( );
00367 first_command_index = command_index;
00368 CommandsDeclaration( );
00369 Match( TK_RCBRAC );
00370 }
00371 else
00372 Match( TK_SEMICOL );
00373
00374 #ifdef RIO_DEBUG2
00375 RioErr << "Inserting slide " << slide_number << " at position "
00376 << position << endl;
00377 #endif
00378
00379 if( !index->InsertSlide( slide_number, commands_offset,
00380 first_command_index, position ) )
00381 {
00382 ReportError( "Error trying to insert a new slide" );
00383 }
00384 }
00385
00386 void CRioMMIndexParser::CommandsDeclaration( void )
00387 {
00388 if( token_type == TK_LBRAC )
00389 {
00390 CommandDeclaration( );
00391 CommandsDeclaration( );
00392 }
00393 else ;
00394 }
00395
00396 void CRioMMIndexParser::CommandDeclaration( void )
00397 {
00398 Match( TK_LBRAC );
00399 command_index = integer_value;
00400 Match( TK_INTEGER );
00401 Match( TK_RBRAC );
00402
00403 Match( TK_COMMAND );
00404 Match( TK_LPAR );
00405 ArgumentsDeclaration( );
00406 Match( TK_RPAR );
00407 Match( TK_SEMICOL );
00408 }
00409
00410 void CRioMMIndexParser::ArgumentsDeclaration( void )
00411 {
00412 if( token_type == TK_INTEGER || token_type == TK_STRING )
00413 Match( token_type );
00414 else
00415 {
00416
00417 return;
00418 }
00419
00420 while( token_type == TK_COMMA )
00421 {
00422 Match( TK_COMMA );
00423 if( token_type == TK_INTEGER )
00424 Match( TK_INTEGER );
00425 else
00426 Match( TK_STRING );
00427 }
00428 }
00429
00430 CRioMMIndex * CRioMMIndexParser::ParseIndex( FILE * fp, RioBlock idcs )
00431 {
00432 int major, minor;
00433 TString archive_name;
00434
00435 #ifdef RIO_DEBUG2
00436 RioErr << "[RioMMIndexParser]: Entrei na ParseIndex: fp=" << fp
00437 << ", idcs=" << idcs << endl;
00438 #endif
00439
00440 InitVars( );
00441
00442
00443 quit_on_errors = true;
00444
00445
00446 line_number = 1;
00447
00448
00449 file = fp;
00450 if( file == NULL )
00451 ReportError( "Invalid file" );
00452 rewind( file );
00453
00454
00455 if( GetToken( ) == TK_INVALID )
00456 ReportError( "Invalid token at the begining of input" );
00457
00458
00459 Match( TK_VERSION );
00460 Match( TK_LPAR );
00461 major = integer_value;
00462 Match( TK_INTEGER );
00463 Match( TK_COMMA );
00464 minor = integer_value;
00465 Match( TK_INTEGER );
00466 Match( TK_RPAR );
00467 Match( TK_SEMICOL );
00468
00469
00470 Match( TK_ARCHIVE );
00471 Match( TK_LPAR );
00472 archive_name = token_string;
00473 Match( TK_STRING );
00474 Match( TK_RPAR );
00475 Match( TK_SEMICOL );
00476
00477 index = new CRioMMIndex( idcs, major, minor, (const char *)archive_name );
00478
00479 FilesDeclaration( );
00480
00481 Match( TK_EOF );
00482
00483
00484 if( !index->IsValid( ) )
00485 ReportError( "Invalid index declaration" );
00486
00487 rewind( file );
00488
00489 return index;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498 bool CRioMMIndexParser::ParseCommand( FILE * fp, RioMMCommand * command,
00499 TQueue & args_queue, RioBlock * idx, int * offset )
00500 {
00501 #ifdef RIO_DEBUG2
00502 RioErr << "[RioMMIndexParser]: Entrou na ParseCommand (file="
00503 << fp << ",command=" << command << ",queue_size="
00504 << args_queue.GetSize( ) << ",*idx=" << *idx << ",*offset="
00505 << *offset << ")" << endl;
00506 #endif
00507
00508 InitVars( );
00509
00510
00511 quit_on_errors = false;
00512
00513
00514 line_number = 1;
00515
00516
00517 file = fp;
00518 if( file == NULL )
00519 ReportError( "Invalid file" );
00520 fseek( file, *offset, SEEK_SET );
00521
00522
00523 if( GetToken( ) == TK_INVALID )
00524 {
00525 ReportError( "Found invalid token at the beginning of stream" );
00526 return false;
00527 }
00528
00529
00530 Match( TK_LBRAC );
00531 *idx = integer_value;
00532 Match( TK_INTEGER );
00533 Match( TK_RBRAC );
00534
00535 command->name = token_string;
00536 Match( TK_COMMAND );
00537 Match( TK_LPAR );
00538
00539
00540 command->arg_types = 0;
00541 if( token_type == TK_INTEGER || token_type == TK_STRING )
00542 {
00543 if( token_type == TK_INTEGER )
00544 {
00545 command->arg_types |= ARG_INT( 0 );
00546 args_queue.Add( (void *)integer_value );
00547 Match( TK_INTEGER );
00548 }
00549 else
00550 {
00551 command->arg_types |= ARG_STRING( 0 );
00552 args_queue.Add( new TString( token_string ) );
00553 Match( TK_STRING );
00554 }
00555
00556 while( token_type == TK_COMMA )
00557 {
00558 Match( TK_COMMA );
00559 if( token_type == TK_INTEGER )
00560 {
00561 command->arg_types |= ARG_INT( args_queue.GetSize( ) );
00562 args_queue.Add( (void *)integer_value );
00563 Match( TK_INTEGER );
00564 }
00565 else
00566 {
00567 command->arg_types |= ARG_STRING( args_queue.GetSize( ) );
00568 args_queue.Add( new TString( token_string ) );
00569 Match( TK_STRING );
00570 }
00571 }
00572 }
00573
00574 command->n_args = args_queue.GetSize( );
00575
00576 Match( TK_RPAR );
00577 Match( TK_SEMICOL );
00578
00579 if( token_type == TK_LBRAC )
00580 {
00581 *offset = token_offset;
00582 Match( TK_LBRAC );
00583 *idx = integer_value;
00584 Match( TK_INTEGER );
00585 Match( TK_RBRAC );
00586 }
00587 else
00588 {
00589 *offset = -1;
00590 *idx = UINT_MAX;
00591
00592 #ifdef RIO_DEBUG2
00593 RioErr << "[RioMMIndexParser]: End of commands section found!\n"
00594 << " Expecting to change context next" << endl;
00595 #endif
00596 }
00597
00598 #ifdef RIO_DEBUG2
00599 RioErr << "[RioMMIndexParser]: Saindo da ParseCommand" << endl;
00600 #endif
00601 return true;
00602 }