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 }