176 lines
5.6 KiB
C++
176 lines
5.6 KiB
C++
#pragma once
|
|
|
|
#include "token.h"
|
|
|
|
#include <cstdarg>
|
|
|
|
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<int>(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
|