DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

TokenParser.cpp (7855B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code 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
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #include "../idlib/precompiled.h"
     30 #pragma hdrstop
     31 
     32 void idTokenParser::LoadFromParser( idParser &parser, const char *guiName ) {
     33 	idToken tok;
     34 	idTokenIndexes tokIdxs;
     35 	tokIdxs.SetName( guiName );
     36 	while ( parser.ReadToken( &tok ) ) {
     37 		tokIdxs.Append( tokens.AddUnique( idBinaryToken( tok ) ) );
     38 	}
     39 	guiTokenIndexes.Append( tokIdxs );
     40 	currentToken = 0;
     41 }
     42 
     43 void idTokenParser::LoadFromFile( const char *filename ) {
     44 	Clear();
     45 	idFile *inFile = fileSystem->OpenFileReadMemory( filename );
     46 	if ( inFile != NULL ) {
     47 		int num;
     48 		inFile->ReadBig( num );
     49 		guiTokenIndexes.SetNum( num );
     50 		for ( int i = 0; i < num; i++ ) {
     51 			guiTokenIndexes[ i ].Read( inFile );
     52 		}
     53 		inFile->ReadBig( num );
     54 		tokens.SetNum( num );
     55 		for ( int i = 0; i < num; i++ ) {
     56 			tokens[ i ].Read( inFile );
     57 		}
     58 	}
     59 	delete inFile;
     60 	preloaded = ( tokens.Num() > 0 );
     61 }
     62 
     63 void idTokenParser::WriteToFile ( const char *filename ) {
     64 	if ( preloaded ) {
     65 		return;
     66 	}
     67 	idFile *outFile = fileSystem->OpenFileWrite( filename, "fs_basepath" );
     68 	if ( outFile != NULL ) {
     69 		outFile->WriteBig( ( int )guiTokenIndexes.Num() );
     70 		for ( int i = 0; i < guiTokenIndexes.Num(); i++ ) {
     71 			guiTokenIndexes[ i ].Write( outFile );
     72 		}
     73 		outFile->WriteBig( ( int )tokens.Num() );
     74 		for ( int i = 0; i < tokens.Num(); i++ ) {
     75 			tokens[ i ].Write( outFile );
     76 		}
     77 	}
     78 	delete outFile;
     79 }
     80 
     81 bool idTokenParser::StartParsing( const char * filename ) {
     82 	currentTokenList = -1;
     83 	for ( int i = 0; i < guiTokenIndexes.Num(); i++ ) {
     84 		if ( idStr::Icmp( filename, guiTokenIndexes[ i ].GetName() ) == 0 ) {
     85 			currentTokenList = i;
     86 			break;
     87 		}
     88 	}
     89 	currentToken = 0;
     90 	return ( currentTokenList != -1 );
     91 }
     92 
     93 bool idTokenParser::ReadToken( idToken * tok ) {
     94 	if ( currentToken >= 0 && currentToken < guiTokenIndexes[ currentTokenList ].Num() ) {
     95 		tok->Clear();
     96 		idBinaryToken &btok = tokens[ guiTokenIndexes[ currentTokenList ][ currentToken ] ];
     97 		*tok = btok.token;
     98 		tok->type = btok.tokenType;
     99 		tok->subtype = btok.tokenSubType;
    100 		currentToken++;
    101 		return true;
    102 	}
    103 	return false;
    104 }
    105 int	idTokenParser::ExpectTokenString( const char *string ) {
    106 	idToken token;
    107 	if ( !ReadToken( &token ) ) {
    108 		Error( "couldn't find expected '%s'", string );
    109 		return 0;
    110 	}
    111 	if ( token != string ) {
    112 		Error( "expected '%s' but found '%s'", string, token.c_str() );
    113 		return 0;
    114 	}
    115 	return 1;
    116 }
    117 // expect a certain token type
    118 int	idTokenParser::ExpectTokenType( int type, int subtype, idToken *token ) {
    119 	idStr str;
    120 
    121 	if ( !ReadToken( token ) ) {
    122 		Error( "couldn't read expected token" );
    123 		return 0;
    124 	}
    125 
    126 	if ( token->type != type ) {
    127 		switch( type ) {
    128 		case TT_STRING: str = "string"; break;
    129 		case TT_LITERAL: str = "literal"; break;
    130 		case TT_NUMBER: str = "number"; break;
    131 		case TT_NAME: str = "name"; break;
    132 		case TT_PUNCTUATION: str = "punctuation"; break;
    133 		default: str = "unknown type"; break;
    134 		}
    135 		Error( "expected a %s but found '%s'", str.c_str(), token->c_str() );
    136 		return 0;
    137 	}
    138 	if ( token->type == TT_NUMBER ) {
    139 		if ( (token->subtype & subtype) != subtype ) {
    140 			str.Clear();
    141 			if ( subtype & TT_DECIMAL ) str = "decimal ";
    142 			if ( subtype & TT_HEX ) str = "hex ";
    143 			if ( subtype & TT_OCTAL ) str = "octal ";
    144 			if ( subtype & TT_BINARY ) str = "binary ";
    145 			if ( subtype & TT_UNSIGNED ) str += "unsigned ";
    146 			if ( subtype & TT_LONG ) str += "long ";
    147 			if ( subtype & TT_FLOAT ) str += "float ";
    148 			if ( subtype & TT_INTEGER ) str += "integer ";
    149 			str.StripTrailing( ' ' );
    150 			Error( "expected %s but found '%s'", str.c_str(), token->c_str() );
    151 			return 0;
    152 		}
    153 	}
    154 	else if ( token->type == TT_PUNCTUATION ) {
    155 		if ( subtype < 0 ) {
    156 			Error( "BUG: wrong punctuation subtype" );
    157 			return 0;
    158 		}
    159 		if ( token->subtype != subtype ) {
    160 			//Error( "expected '%s' but found '%s'", idLexer::GetPunctuationFromId( subtype ), token->c_str() );
    161 			return 0;
    162 		}
    163 	}
    164 	return 1;
    165 }
    166 // expect a token
    167 int idTokenParser::ExpectAnyToken( idToken *token ) {
    168 	if (!ReadToken( token )) {
    169 		Error( "couldn't read expected token" );
    170 		return 0;
    171 	}
    172 	return 1;
    173 }
    174 
    175 void idTokenParser::UnreadToken( const idToken *token ) {
    176 	if ( currentToken == 0 || currentToken >=  guiTokenIndexes[ currentTokenList ].Num() ) {
    177 		idLib::common->FatalError( "idTokenParser::unreadToken, unread token twice\n" );
    178 	}
    179 	currentToken--;
    180 }
    181 void idTokenParser::Error( VERIFY_FORMAT_STRING const char *str, ... ) {
    182 	char text[MAX_STRING_CHARS];
    183 	va_list ap;
    184 
    185 	va_start(ap, str);
    186 	vsprintf(text, str, ap);
    187 	va_end(ap);
    188 
    189 	idLib::common->Warning( text );
    190 }
    191 void idTokenParser::Warning( VERIFY_FORMAT_STRING const char *str, ... ) {
    192 	char text[MAX_STRING_CHARS];
    193 	va_list ap;
    194 
    195 	va_start(ap, str);
    196 	vsprintf(text, str, ap);
    197 	va_end(ap);
    198 
    199 	idLib::common->Warning( text );
    200 }
    201 int idTokenParser::ParseInt() { 
    202 	idToken token;
    203 	if ( !ReadToken( &token ) ) {
    204 		Error( "couldn't read expected integer" );
    205 		return 0;
    206 	}
    207 	if ( token.type == TT_PUNCTUATION && token == "-" ) {
    208 		ExpectTokenType( TT_NUMBER, TT_INTEGER, &token );
    209 		return -((signed int) token.GetIntValue());
    210 	}
    211 	else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
    212 		Error( "expected integer value, found '%s'", token.c_str() );
    213 	}
    214 	return token.GetIntValue();
    215 }
    216 // read a boolean
    217 bool idTokenParser::ParseBool() { 
    218 	idToken token;
    219 	if ( !ExpectTokenType( TT_NUMBER, 0, &token ) ) {
    220 		Error( "couldn't read expected boolean" );
    221 		return false;
    222 	}
    223 	return ( token.GetIntValue() != 0 );
    224 }
    225 // read a floating point number.  If errorFlag is NULL, a non-numeric token will
    226 // issue an Error().  If it isn't NULL, it will issue a Warning() and set *errorFlag = true
    227 float idTokenParser::ParseFloat( bool *errorFlag ) {
    228 	idToken token;
    229 	if ( errorFlag ) {
    230 		*errorFlag = false;
    231 	}
    232 	if ( !ReadToken( &token ) ) {
    233 		if ( errorFlag ) {
    234 			Warning( "couldn't read expected floating point number" );
    235 			*errorFlag = true;
    236 		} else {
    237 			Error( "couldn't read expected floating point number" );
    238 		}
    239 		return 0;
    240 	}
    241 	if ( token.type == TT_PUNCTUATION && token == "-" ) {
    242 		ExpectTokenType( TT_NUMBER, 0, &token );
    243 		return -token.GetFloatValue();
    244 	}
    245 	else if ( token.type != TT_NUMBER ) {
    246 		if ( errorFlag ) {
    247 			Warning( "expected float value, found '%s'", token.c_str() );
    248 			*errorFlag = true;
    249 		} else {
    250 			Error( "expected float value, found '%s'", token.c_str() );
    251 		}
    252 	}
    253 	return token.GetFloatValue();
    254 }