#pragma once #include "token.h" #include struct punctuation_t { char* p; int n; }; // Recovered from the lexer PDB enums and the subtype tests in lexer.cpp. enum lexerTokenType_t : int { TT_STRING = 1, TT_LITERAL = 2, TT_NUMBER = 3, TT_NAME = 4, TT_PUNCTUATION = 5 }; enum lexerNumberSubtype_t : int { TT_INTEGER = 0x0001, TT_DECIMAL = 0x0002, TT_HEX = 0x0004, TT_OCTAL = 0x0008, TT_BINARY = 0x0010, TT_LONG = 0x0020, TT_UNSIGNED = 0x0040, TT_FLOAT = 0x0080, TT_IPADDRESS = 0x0100, TT_IPPORT = 0x0200, TT_VALUESVALID = 0x0400, TT_INFINITE = 0x0800, TT_INDEFINITE = 0x1000, TT_NAN = 0x2000 }; enum lexerPunctuation_t : int { P_RSHIFT_ASSIGN = 0, P_LSHIFT_ASSIGN, P_PARMS, P_PRECOMPMERGE, P_LOGIC_AND, P_LOGIC_OR, P_LOGIC_GEQ, P_LOGIC_LEQ, P_LOGIC_EQ, P_LOGIC_UNEQ, P_MUL_ASSIGN, P_DIV_ASSIGN, P_MOD_ASSIGN, P_ADD_ASSIGN, P_SUB_ASSIGN, P_INC, P_DEC, P_BIN_AND_ASSIGN, P_BIN_OR_ASSIGN, P_BIN_XOR_ASSIGN, P_RSHIFT, P_LSHIFT, P_SCOPE_RESOLUTION, P_MEMBER_SELECTION_OBJECT, P_MEMBER_SELECTION_POINTER, P_POINTER_TO_MEMBER_OBJECT, P_POINTER_TO_MEMBER_POINTER, P_MUL, P_DIV, P_MOD, P_ADD, P_SUB, P_ASSIGN, P_BIN_AND, P_BIN_OR, P_BIN_XOR, P_BIN_NOT, P_LOGIC_NOT, P_LOGIC_GREATER, P_LOGIC_LESS, P_COMMA, P_SEMICOLON, P_COLON, P_QUESTIONMARK, P_PARENTHESESOPEN, P_PARENTHESESCLOSE, P_BRACEOPEN, P_BRACECLOSE, P_SQBRACKETOPEN, P_SQBRACKETCLOSE, P_BACKSLASH, P_PRECOMP, P_DOLLAR, P_APOSTROPHE, P_QUOTE, P_AT }; enum lexerFlags_t : int { LEXFL_NOERRORS = 0x1, LEXFL_NOWARNINGS = 0x2, LEXFL_NOFATALERRORS = 0x4, LEXFL_VCSTYLEREPORTS = 0x8, LEXFL_NOSTRINGCONCAT = 0x10, LEXFL_NOSTRINGESCAPECHARS = 0x20, LEXFL_NODOLLARPRECOMPILE = 0x40, LEXFL_NOBASEINCLUDES = 0x80, LEXFL_NOGLOBALDEFINES = 0x100, LEXFL_ALLOWPATHNAMES = 0x200, LEXFL_ALLOWNUMBERNAMES = 0x400, LEXFL_ALLOWIPADDRESSES = 0x800, LEXFL_ALLOWFLOATEXCEPTIONS = 0x1000, LEXFL_ALLOWMULTICHARLITERALS = 0x2000, LEXFL_ALLOWBACKSLASHSTRINGCONCAT = 0x4000, LEXFL_ONLYSTRINGS = 0x8000, LEXFL_NOEMITSTRINGESCAPECHARS = 0x10000, LEXFL_ALLOWRAWSTRINGBLOCKS = 0x20000, LEXFL_THROWFATAL = 0x40000, LEXFL_NOSTRINGS = 0x80000, LEXFL_ALLOWWILDCARD = 0x100000, LEXFL_REPORT_MULTIPLE_ERRORS = 0x200000 }; class alignas(4) idLexer { public: explicit idLexer(int flags = 0); ~idLexer(); bool LoadFile(const char* fileName, bool OSPath = false); bool LoadFilePartial(const char* fileName, bool OSPath, int length); bool LoadMemory(const char* pointer, unsigned int length, const char* name); void FreeSource(); void Reset(); bool SetScriptP(const char* pointer); void SetPunctuations(const punctuation_t* punctuation); bool ReadToken(idToken& token); bool ReadTokenOnLine(idToken& token); void UnreadToken(); bool ExpectTokenString(const char* string); bool ExpectTokenType(int type, int subtype, idToken& token); bool ExpectAnyToken(idToken& token); bool CheckTokenString(const char* string); bool CheckTokenType(int type, int subtype, idToken& token); bool PeekTokenString(const char* string); bool PeekTokenType(int type, int subtype, idToken& token); bool SkipUntilString(const char* string); bool SkipRestOfLine(); bool SkipBracedSection(bool parseFirstBrace = true); bool SkipWhiteSpace(bool currentLine); bool ParseBracedSectionExact(idStr& out, bool parseFirstBrace, char openBrace = '{', char closeBrace = '}'); const char* ParseRestOfLine(idStr& out); const char* ParseCompleteLine(idStr& out); int ParseInt(); unsigned int ParseUnsignedInt(); bool ParseBool(); float ParseFloat(bool* errorFlag = nullptr); bool Parse1DMatrix(int x, float* matrix, bool expectCommas = false); bool Parse2DMatrix(int y, int x, float* matrix); int GetLastWhiteSpace(idStr& whiteSpace) const; int GetNextWhiteSpace(idStr& whiteSpace, bool currentLine); bool GetWhiteSpaceBeforeToken(const idToken& token, idStr& whiteSpace) const; const char* GetPunctuationFromId(int id) const; int GetPunctuationId(const char* punctuation) const; bool EndOfFile() const; bool HadError() const; bool HadWarning() const; const char* GetFileName() const { return filename.c_str(); } int GetFileOffset() const { return script_p == nullptr || buffer == nullptr ? 0 : static_cast(script_p - buffer); } int GetLineNum() const { return line; } void Error(const char* format, ...); void Warning(const char* format, ...); bool loaded; idStr filename; int allocated; const char* buffer; const char* script_p; const char* end_p; const char* lastScript_p; const char* whiteSpaceStart_p; const char* whiteSpaceEnd_p; unsigned int fileTime; unsigned int length; int line; int lastline; int flags; const punctuation_t* punctuations; int* punctuationtable; int* nextpunctuation; idLexer* next; idStr errorMsg; bool hadError; bool hadWarning; private: bool CheckString(const char* string) const; void CreatePunctuationTable(const punctuation_t* punctuation); bool ReadEscapeCharacter(char* character); bool ReadName(idToken& token); bool ReadNumber(idToken& token); bool ReadPunctuation(idToken& token); bool ReadRawStringBlock(idToken& token); bool ReadString(idToken& token, int quote); }; #if INTPTR_MAX == INT32_MAX static_assert(sizeof(punctuation_t) == 8, "Recovered punctuation_t ABI changed"); static_assert(sizeof(idLexer) == 136, "Recovered idLexer ABI changed"); #endif