2012-11-26 18:58:24 +00:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
2012-11-28 15:47:07 +00:00
|
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
2012-11-26 18:58:24 +00:00
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
2012-11-26 18:58:24 +00:00
|
|
|
|
|
|
|
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __LEXER_H__
|
|
|
|
#define __LEXER_H__
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============================================================================
|
|
|
|
|
|
|
|
Lexicographical parser
|
|
|
|
|
|
|
|
Does not use memory allocation during parsing. The lexer uses no
|
|
|
|
memory allocation if a source is loaded with LoadMemory().
|
|
|
|
However, idToken may still allocate memory for large strings.
|
2012-11-28 15:47:07 +00:00
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
A number directly following the escape character '\' in a string is
|
|
|
|
assumed to be in decimal format instead of octal. Binary numbers of
|
|
|
|
the form 0b.. or 0B.. can also be used.
|
|
|
|
|
|
|
|
===============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// lexer flags
|
2012-11-28 15:47:07 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
LEXFL_NOERRORS = BIT( 0 ), // don't print any errors
|
|
|
|
LEXFL_NOWARNINGS = BIT( 1 ), // don't print any warnings
|
|
|
|
LEXFL_NOFATALERRORS = BIT( 2 ), // errors aren't fatal
|
2013-12-31 01:23:16 +00:00
|
|
|
LEXFL_NOSTRINGCONCAT = BIT( 3 ), // multiple strings separated by whitespaces are not concatenated
|
2012-11-28 15:47:07 +00:00
|
|
|
LEXFL_NOSTRINGESCAPECHARS = BIT( 4 ), // no escape characters inside strings
|
|
|
|
LEXFL_NODOLLARPRECOMPILE = BIT( 5 ), // don't use the $ sign for precompilation
|
|
|
|
LEXFL_NOBASEINCLUDES = BIT( 6 ), // don't include files embraced with < >
|
|
|
|
LEXFL_ALLOWPATHNAMES = BIT( 7 ), // allow path seperators in names
|
|
|
|
LEXFL_ALLOWNUMBERNAMES = BIT( 8 ), // allow names to start with a number
|
|
|
|
LEXFL_ALLOWIPADDRESSES = BIT( 9 ), // allow ip addresses to be parsed as numbers
|
|
|
|
LEXFL_ALLOWFLOATEXCEPTIONS = BIT( 10 ), // allow float exceptions like 1.#INF or 1.#IND to be parsed
|
|
|
|
LEXFL_ALLOWMULTICHARLITERALS = BIT( 11 ), // allow multi character literals
|
2013-12-31 01:23:16 +00:00
|
|
|
LEXFL_ALLOWBACKSLASHSTRINGCONCAT = BIT( 12 ), // allow multiple strings separated by '\' to be concatenated
|
2012-11-28 15:47:07 +00:00
|
|
|
LEXFL_ONLYSTRINGS = BIT( 13 ) // parse as whitespace deliminated strings (quoted strings keep quotes)
|
2012-11-26 18:58:24 +00:00
|
|
|
} lexerFlags_t;
|
|
|
|
|
|
|
|
// punctuation ids
|
|
|
|
#define P_RSHIFT_ASSIGN 1
|
|
|
|
#define P_LSHIFT_ASSIGN 2
|
|
|
|
#define P_PARMS 3
|
|
|
|
#define P_PRECOMPMERGE 4
|
|
|
|
|
|
|
|
#define P_LOGIC_AND 5
|
|
|
|
#define P_LOGIC_OR 6
|
|
|
|
#define P_LOGIC_GEQ 7
|
|
|
|
#define P_LOGIC_LEQ 8
|
|
|
|
#define P_LOGIC_EQ 9
|
|
|
|
#define P_LOGIC_UNEQ 10
|
|
|
|
|
|
|
|
#define P_MUL_ASSIGN 11
|
|
|
|
#define P_DIV_ASSIGN 12
|
|
|
|
#define P_MOD_ASSIGN 13
|
|
|
|
#define P_ADD_ASSIGN 14
|
|
|
|
#define P_SUB_ASSIGN 15
|
|
|
|
#define P_INC 16
|
|
|
|
#define P_DEC 17
|
|
|
|
|
|
|
|
#define P_BIN_AND_ASSIGN 18
|
|
|
|
#define P_BIN_OR_ASSIGN 19
|
|
|
|
#define P_BIN_XOR_ASSIGN 20
|
|
|
|
#define P_RSHIFT 21
|
|
|
|
#define P_LSHIFT 22
|
|
|
|
|
|
|
|
#define P_POINTERREF 23
|
|
|
|
#define P_CPP1 24
|
|
|
|
#define P_CPP2 25
|
|
|
|
#define P_MUL 26
|
|
|
|
#define P_DIV 27
|
|
|
|
#define P_MOD 28
|
|
|
|
#define P_ADD 29
|
|
|
|
#define P_SUB 30
|
|
|
|
#define P_ASSIGN 31
|
|
|
|
|
|
|
|
#define P_BIN_AND 32
|
|
|
|
#define P_BIN_OR 33
|
|
|
|
#define P_BIN_XOR 34
|
|
|
|
#define P_BIN_NOT 35
|
|
|
|
|
|
|
|
#define P_LOGIC_NOT 36
|
|
|
|
#define P_LOGIC_GREATER 37
|
|
|
|
#define P_LOGIC_LESS 38
|
|
|
|
|
|
|
|
#define P_REF 39
|
|
|
|
#define P_COMMA 40
|
|
|
|
#define P_SEMICOLON 41
|
|
|
|
#define P_COLON 42
|
|
|
|
#define P_QUESTIONMARK 43
|
|
|
|
|
|
|
|
#define P_PARENTHESESOPEN 44
|
|
|
|
#define P_PARENTHESESCLOSE 45
|
|
|
|
#define P_BRACEOPEN 46
|
|
|
|
#define P_BRACECLOSE 47
|
|
|
|
#define P_SQBRACKETOPEN 48
|
|
|
|
#define P_SQBRACKETCLOSE 49
|
|
|
|
#define P_BACKSLASH 50
|
|
|
|
|
|
|
|
#define P_PRECOMP 51
|
|
|
|
#define P_DOLLAR 52
|
|
|
|
|
|
|
|
// punctuation
|
|
|
|
typedef struct punctuation_s
|
|
|
|
{
|
2012-12-11 22:48:55 +00:00
|
|
|
const char* p; // punctuation character(s)
|
2012-11-26 18:58:24 +00:00
|
|
|
int n; // punctuation id
|
|
|
|
} punctuation_t;
|
|
|
|
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
class idLexer
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
|
|
|
friend class idParser;
|
2012-11-28 15:47:07 +00:00
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
public:
|
2012-11-28 15:47:07 +00:00
|
|
|
// constructor
|
|
|
|
idLexer();
|
|
|
|
idLexer( int flags );
|
|
|
|
idLexer( const char* filename, int flags = 0, bool OSPath = false );
|
|
|
|
idLexer( const char* ptr, int length, const char* name, int flags = 0 );
|
|
|
|
// destructor
|
|
|
|
~idLexer();
|
|
|
|
// load a script from the given file at the given offset with the given length
|
|
|
|
int LoadFile( const char* filename, bool OSPath = false );
|
|
|
|
// load a script from the given memory with the given length and a specified line offset,
|
|
|
|
// so source strings extracted from a file can still refer to proper line numbers in the file
|
|
|
|
// NOTE: the ptr is expected to point at a valid C string: ptr[length] == '\0'
|
|
|
|
int LoadMemory( const char* ptr, int length, const char* name, int startLine = 1 );
|
|
|
|
// free the script
|
2012-11-26 18:58:24 +00:00
|
|
|
void FreeSource();
|
2012-11-28 15:47:07 +00:00
|
|
|
// returns true if a script is loaded
|
|
|
|
int IsLoaded()
|
|
|
|
{
|
|
|
|
return idLexer::loaded;
|
|
|
|
};
|
|
|
|
// read a token
|
|
|
|
int ReadToken( idToken* token );
|
|
|
|
// expect a certain token, reads the token when available
|
|
|
|
int ExpectTokenString( const char* string );
|
|
|
|
// expect a certain token type
|
|
|
|
int ExpectTokenType( int type, int subtype, idToken* token );
|
|
|
|
// expect a token
|
|
|
|
int ExpectAnyToken( idToken* token );
|
|
|
|
// returns true when the token is available
|
|
|
|
int CheckTokenString( const char* string );
|
|
|
|
// returns true an reads the token when a token with the given type is available
|
|
|
|
int CheckTokenType( int type, int subtype, idToken* token );
|
|
|
|
// returns true if the next token equals the given string but does not remove the token from the source
|
|
|
|
int PeekTokenString( const char* string );
|
|
|
|
// returns true if the next token equals the given type but does not remove the token from the source
|
|
|
|
int PeekTokenType( int type, int subtype, idToken* token );
|
|
|
|
// skip tokens until the given token string is read
|
|
|
|
int SkipUntilString( const char* string );
|
|
|
|
// skip the rest of the current line
|
2012-11-26 18:58:24 +00:00
|
|
|
int SkipRestOfLine();
|
2012-11-28 15:47:07 +00:00
|
|
|
// skip the braced section
|
2012-11-26 18:58:24 +00:00
|
|
|
int SkipBracedSection( bool parseFirstBrace = true );
|
|
|
|
// skips spaces, tabs, C-like comments etc. Returns false if there is no token left to read.
|
|
|
|
bool SkipWhiteSpace( bool currentLine );
|
2012-11-28 15:47:07 +00:00
|
|
|
// unread the given token
|
|
|
|
void UnreadToken( const idToken* token );
|
|
|
|
// read a token only if on the same line
|
|
|
|
int ReadTokenOnLine( idToken* token );
|
|
|
|
|
|
|
|
//Returns the rest of the current line
|
|
|
|
const char* ReadRestOfLine( idStr& out );
|
|
|
|
|
|
|
|
// read a signed integer
|
2012-11-26 18:58:24 +00:00
|
|
|
int ParseInt();
|
2012-11-28 15:47:07 +00:00
|
|
|
// read a boolean
|
2012-11-26 18:58:24 +00:00
|
|
|
bool ParseBool();
|
2012-11-28 15:47:07 +00:00
|
|
|
// read a floating point number. If errorFlag is NULL, a non-numeric token will
|
|
|
|
// issue an Error(). If it isn't NULL, it will issue a Warning() and set *errorFlag = true
|
|
|
|
float ParseFloat( bool* errorFlag = NULL );
|
|
|
|
// parse matrices with floats
|
|
|
|
int Parse1DMatrix( int x, float* m );
|
|
|
|
int Parse2DMatrix( int y, int x, float* m );
|
|
|
|
int Parse3DMatrix( int z, int y, int x, float* m );
|
|
|
|
// parse a braced section into a string
|
|
|
|
const char* ParseBracedSection( idStr& out );
|
|
|
|
// parse a braced section into a string, maintaining indents and newlines
|
|
|
|
const char* ParseBracedSectionExact( idStr& out, int tabs = -1 );
|
|
|
|
// parse the rest of the line
|
|
|
|
const char* ParseRestOfLine( idStr& out );
|
|
|
|
// pulls the entire line, including the \n at the end
|
|
|
|
const char* ParseCompleteLine( idStr& out );
|
|
|
|
// retrieves the white space characters before the last read token
|
|
|
|
int GetLastWhiteSpace( idStr& whiteSpace ) const;
|
|
|
|
// returns start index into text buffer of last white space
|
2012-11-26 18:58:24 +00:00
|
|
|
int GetLastWhiteSpaceStart() const;
|
2012-11-28 15:47:07 +00:00
|
|
|
// returns end index into text buffer of last white space
|
2012-11-26 18:58:24 +00:00
|
|
|
int GetLastWhiteSpaceEnd() const;
|
2012-11-28 15:47:07 +00:00
|
|
|
// set an array with punctuations, NULL restores default C/C++ set, see default_punctuations for an example
|
|
|
|
void SetPunctuations( const punctuation_t* p );
|
|
|
|
// returns a pointer to the punctuation with the given id
|
|
|
|
const char* GetPunctuationFromId( int id );
|
|
|
|
// get the id for the given punctuation
|
|
|
|
int GetPunctuationId( const char* p );
|
|
|
|
// set lexer flags
|
2012-11-26 18:58:24 +00:00
|
|
|
void SetFlags( int flags );
|
2012-11-28 15:47:07 +00:00
|
|
|
// get lexer flags
|
2012-11-26 18:58:24 +00:00
|
|
|
int GetFlags();
|
2012-11-28 15:47:07 +00:00
|
|
|
// reset the lexer
|
2012-11-26 18:58:24 +00:00
|
|
|
void Reset();
|
2012-11-28 15:47:07 +00:00
|
|
|
// returns true if at the end of the file
|
2012-11-26 18:58:24 +00:00
|
|
|
bool EndOfFile();
|
2012-11-28 15:47:07 +00:00
|
|
|
// returns the current filename
|
|
|
|
const char* GetFileName();
|
|
|
|
// get offset in script
|
2012-11-26 18:58:24 +00:00
|
|
|
const int GetFileOffset();
|
2012-11-28 15:47:07 +00:00
|
|
|
// get file time
|
2012-11-26 18:58:24 +00:00
|
|
|
const ID_TIME_T GetFileTime();
|
2012-11-28 15:47:07 +00:00
|
|
|
// returns the current line number
|
2012-11-26 18:58:24 +00:00
|
|
|
const int GetLineNum();
|
2012-11-28 15:47:07 +00:00
|
|
|
// print an error message
|
|
|
|
void Error( VERIFY_FORMAT_STRING const char* str, ... );
|
|
|
|
// print a warning message
|
|
|
|
void Warning( VERIFY_FORMAT_STRING const char* str, ... );
|
|
|
|
// returns true if Error() was called with LEXFL_NOFATALERRORS or LEXFL_NOERRORS set
|
2012-11-26 18:58:24 +00:00
|
|
|
bool HadError() const;
|
2012-11-28 15:47:07 +00:00
|
|
|
|
|
|
|
// set the base folder to load files from
|
|
|
|
static void SetBaseFolder( const char* path );
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
private:
|
|
|
|
int loaded; // set when a script file is loaded from file or memory
|
|
|
|
idStr filename; // file name of the script
|
|
|
|
int allocated; // true if buffer memory was allocated
|
2012-11-28 15:47:07 +00:00
|
|
|
const char* buffer; // buffer containing the script
|
|
|
|
const char* script_p; // current pointer in the script
|
|
|
|
const char* end_p; // pointer to the end of the script
|
|
|
|
const char* lastScript_p; // script pointer before reading token
|
|
|
|
const char* whiteSpaceStart_p; // start of last white space
|
|
|
|
const char* whiteSpaceEnd_p; // end of last white space
|
2012-11-26 18:58:24 +00:00
|
|
|
ID_TIME_T fileTime; // file time
|
|
|
|
int length; // length of the script in bytes
|
|
|
|
int line; // current line in script
|
|
|
|
int lastline; // line before reading token
|
|
|
|
int tokenavailable; // set by unreadToken
|
|
|
|
int flags; // several script flags
|
2012-11-28 15:47:07 +00:00
|
|
|
const punctuation_t* punctuations; // the punctuations used in the script
|
|
|
|
int* punctuationtable; // ASCII table with punctuations
|
|
|
|
int* nextpunctuation; // next punctuation in chain
|
2012-11-26 18:58:24 +00:00
|
|
|
idToken token; // available token
|
2012-11-28 15:47:07 +00:00
|
|
|
idLexer* next; // next script in a chain
|
2012-11-26 18:58:24 +00:00
|
|
|
bool hadError; // set by idLexer::Error, even if the error is supressed
|
2012-11-28 15:47:07 +00:00
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
static char baseFolder[ 256 ]; // base folder to load files from
|
2012-11-28 15:47:07 +00:00
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
private:
|
2012-11-28 15:47:07 +00:00
|
|
|
void CreatePunctuationTable( const punctuation_t* punctuations );
|
2012-11-26 18:58:24 +00:00
|
|
|
int ReadWhiteSpace();
|
2012-11-28 15:47:07 +00:00
|
|
|
int ReadEscapeCharacter( char* ch );
|
|
|
|
int ReadString( idToken* token, int quote );
|
|
|
|
int ReadName( idToken* token );
|
|
|
|
int ReadNumber( idToken* token );
|
|
|
|
int ReadPunctuation( idToken* token );
|
|
|
|
int ReadPrimitive( idToken* token );
|
|
|
|
int CheckString( const char* str ) const;
|
2012-11-26 18:58:24 +00:00
|
|
|
int NumLinesCrossed();
|
|
|
|
};
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
ID_INLINE const char* idLexer::GetFileName()
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return idLexer::filename;
|
|
|
|
}
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
ID_INLINE const int idLexer::GetFileOffset()
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return idLexer::script_p - idLexer::buffer;
|
|
|
|
}
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
ID_INLINE const ID_TIME_T idLexer::GetFileTime()
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return idLexer::fileTime;
|
|
|
|
}
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
ID_INLINE const int idLexer::GetLineNum()
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return idLexer::line;
|
|
|
|
}
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
ID_INLINE void idLexer::SetFlags( int flags )
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
idLexer::flags = flags;
|
|
|
|
}
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
ID_INLINE int idLexer::GetFlags()
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
return idLexer::flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* !__LEXER_H__ */
|
|
|
|
|