mirror of https://github.com/x64dbg/btparser
better error reporting
This commit is contained in:
parent
382da6b367
commit
9dfa58daef
|
@ -60,11 +60,13 @@ struct Lexer
|
||||||
//lexer state
|
//lexer state
|
||||||
string IdentifierStr;
|
string IdentifierStr;
|
||||||
uint64_t NumberVal = 0;
|
uint64_t NumberVal = 0;
|
||||||
|
bool IsHexNumberVal = false;
|
||||||
string StringLit;
|
string StringLit;
|
||||||
string NumStr;
|
string NumStr;
|
||||||
char CharLit = '\0';
|
char CharLit = '\0';
|
||||||
int LastChar = ' ';
|
int LastChar = ' ';
|
||||||
int CurLine = 0;
|
int CurLine = 0;
|
||||||
|
int LineIndex = 0;
|
||||||
|
|
||||||
static void clearReserve(string & str, size_t reserve = DEFAULT_STRING_BUFFER)
|
static void clearReserve(string & str, size_t reserve = DEFAULT_STRING_BUFFER)
|
||||||
{
|
{
|
||||||
|
@ -87,11 +89,13 @@ struct Lexer
|
||||||
Warnings.clear();
|
Warnings.clear();
|
||||||
clearReserve(IdentifierStr);
|
clearReserve(IdentifierStr);
|
||||||
NumberVal = 0;
|
NumberVal = 0;
|
||||||
|
IsHexNumberVal = false;
|
||||||
clearReserve(StringLit);
|
clearReserve(StringLit);
|
||||||
clearReserve(NumStr, 16);
|
clearReserve(NumStr, 16);
|
||||||
CharLit = '\0';
|
CharLit = '\0';
|
||||||
LastChar = ' ';
|
LastChar = ' ';
|
||||||
CurLine = 0;
|
CurLine = 0;
|
||||||
|
LineIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unordered_map<string, Token> KeywordMap;
|
unordered_map<string, Token> KeywordMap;
|
||||||
|
@ -146,15 +150,15 @@ struct Lexer
|
||||||
switch (Token(tok))
|
switch (Token(tok))
|
||||||
{
|
{
|
||||||
case tok_eof: return "tok_eof";
|
case tok_eof: return "tok_eof";
|
||||||
case tok_error: return StringUtils::sprintf("error(\"%s\")", Error.c_str());
|
case tok_error: return StringUtils::sprintf("error(line %d, col %d, \"%s\")", CurLine + 1, LineIndex, Error.c_str());
|
||||||
case tok_identifier: return StringUtils::sprintf("id(\"%s\")", IdentifierStr.c_str());
|
case tok_identifier: return IdentifierStr.c_str();
|
||||||
case tok_number: return StringUtils::sprintf("num(%llu, 0x%llX)", NumberVal, NumberVal);
|
case tok_number: return StringUtils::sprintf(IsHexNumberVal ? "0x%llX" : "%llu", NumberVal);
|
||||||
case tok_stringlit: return StringUtils::sprintf("\"%s\"", StringUtils::Escape(StringLit).c_str());
|
case tok_stringlit: return StringUtils::sprintf("\"%s\"", StringUtils::Escape(StringLit).c_str());
|
||||||
case tok_charlit:
|
case tok_charlit:
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
s = CharLit;
|
s = CharLit;
|
||||||
return StringUtils::sprintf("\'%s\'", StringUtils::Escape(s).c_str());
|
return StringUtils::sprintf("'%s'", StringUtils::Escape(s).c_str());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -184,6 +188,7 @@ struct Lexer
|
||||||
if (Index == Input.size())
|
if (Index == Input.size())
|
||||||
return EOF;
|
return EOF;
|
||||||
auto ch = Input[Index++];
|
auto ch = Input[Index++];
|
||||||
|
LineIndex++;
|
||||||
if (ch == '\0')
|
if (ch == '\0')
|
||||||
{
|
{
|
||||||
ReportWarning(StringUtils::sprintf("\\0 character in file data"));
|
ReportWarning(StringUtils::sprintf("\\0 character in file data"));
|
||||||
|
@ -211,6 +216,12 @@ struct Lexer
|
||||||
return LastChar = ReadChar();
|
return LastChar = ReadChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SignalNextLine()
|
||||||
|
{
|
||||||
|
CurLine++;
|
||||||
|
LineIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* ConvertNumber(const char* str, uint64_t & result, int radix)
|
static const char* ConvertNumber(const char* str, uint64_t & result, int radix)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -231,7 +242,7 @@ struct Lexer
|
||||||
while (isspace(LastChar))
|
while (isspace(LastChar))
|
||||||
{
|
{
|
||||||
if (LastChar == '\n')
|
if (LastChar == '\n')
|
||||||
CurLine++;
|
SignalNextLine();
|
||||||
NextChar();
|
NextChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +266,9 @@ struct Lexer
|
||||||
return ReportError("unexpected newline in character literal (1)");
|
return ReportError("unexpected newline in character literal (1)");
|
||||||
if (LastChar == '\'') //end of character literal
|
if (LastChar == '\'') //end of character literal
|
||||||
{
|
{
|
||||||
|
if (charLit.length() != 1)
|
||||||
|
return ReportError(StringUtils::sprintf("invalid character literal '%s'", charLit.c_str()));
|
||||||
|
CharLit = charLit[0];
|
||||||
NextChar();
|
NextChar();
|
||||||
return tok_charlit;
|
return tok_charlit;
|
||||||
}
|
}
|
||||||
|
@ -396,7 +410,7 @@ struct Lexer
|
||||||
//hex numbers
|
//hex numbers
|
||||||
if (LastChar == '0' && PeekChar() == 'x') //0x
|
if (LastChar == '0' && PeekChar() == 'x') //0x
|
||||||
{
|
{
|
||||||
ReadChar(); //consume the 'x'
|
NextChar(); //consume the 'x'
|
||||||
NumStr.clear();
|
NumStr.clear();
|
||||||
|
|
||||||
while (isxdigit(NextChar())) //[0-9a-fA-F]*
|
while (isxdigit(NextChar())) //[0-9a-fA-F]*
|
||||||
|
@ -408,6 +422,7 @@ struct Lexer
|
||||||
auto error = ConvertNumber(NumStr.c_str(), NumberVal, 16);
|
auto error = ConvertNumber(NumStr.c_str(), NumberVal, 16);
|
||||||
if (error)
|
if (error)
|
||||||
return ReportError(StringUtils::sprintf("ConvertNumber failed (%s) on hexadecimal number", error));
|
return ReportError(StringUtils::sprintf("ConvertNumber failed (%s) on hexadecimal number", error));
|
||||||
|
IsHexNumberVal = true;
|
||||||
return tok_number;
|
return tok_number;
|
||||||
}
|
}
|
||||||
if (isdigit(LastChar)) //[0-9]
|
if (isdigit(LastChar)) //[0-9]
|
||||||
|
@ -420,6 +435,7 @@ struct Lexer
|
||||||
auto error = ConvertNumber(NumStr.c_str(), NumberVal, 10);
|
auto error = ConvertNumber(NumStr.c_str(), NumberVal, 10);
|
||||||
if (error)
|
if (error)
|
||||||
return ReportError(StringUtils::sprintf("ConvertNumber failed (%s) on decimal number", error));
|
return ReportError(StringUtils::sprintf("ConvertNumber failed (%s) on decimal number", error));
|
||||||
|
IsHexNumberVal = false;
|
||||||
return tok_number;
|
return tok_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,25 +444,27 @@ struct Lexer
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
NextChar();
|
|
||||||
if (LastChar == '\n')
|
if (LastChar == '\n')
|
||||||
CurLine++;
|
SignalNextLine();
|
||||||
|
NextChar();
|
||||||
} while (!(LastChar == EOF || LastChar == '\n'));
|
} while (!(LastChar == EOF || LastChar == '\n'));
|
||||||
|
|
||||||
NextChar();
|
|
||||||
return GetToken(); //interpret the next line
|
return GetToken(); //interpret the next line
|
||||||
}
|
}
|
||||||
if (LastChar == '/' && PeekChar() == '*') //block comment
|
if (LastChar == '/' && PeekChar() == '*') //block comment
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
NextChar();
|
|
||||||
if (LastChar == '\n')
|
if (LastChar == '\n')
|
||||||
CurLine++;
|
SignalNextLine();
|
||||||
|
NextChar();
|
||||||
} while (!(LastChar == EOF || LastChar == '*' && PeekChar() == '/'));
|
} while (!(LastChar == EOF || LastChar == '*' && PeekChar() == '/'));
|
||||||
|
|
||||||
if (LastChar == EOF) //unexpected end of file
|
if (LastChar == EOF) //unexpected end of file
|
||||||
|
{
|
||||||
|
LineIndex++;
|
||||||
return ReportError("unexpected end of file in block comment");
|
return ReportError("unexpected end of file in block comment");
|
||||||
|
}
|
||||||
|
|
||||||
NextChar();
|
NextChar();
|
||||||
NextChar();
|
NextChar();
|
||||||
|
|
|
@ -40,8 +40,8 @@ DEF_OP_SINGLE(subopen, '[')
|
||||||
DEF_OP_SINGLE(subclose, ']')
|
DEF_OP_SINGLE(subclose, ']')
|
||||||
DEF_OP_SINGLE(member, '.')
|
DEF_OP_SINGLE(member, '.')
|
||||||
DEF_OP_SINGLE(comma, ',')
|
DEF_OP_SINGLE(comma, ',')
|
||||||
DEF_OP_SINGLE(tenary1, '?')
|
DEF_OP_SINGLE(tenary, '?')
|
||||||
DEF_OP_SINGLE(tenary2, ':')
|
DEF_OP_SINGLE(colon, ':')
|
||||||
DEF_OP_SINGLE(assign, '=')
|
DEF_OP_SINGLE(assign, '=')
|
||||||
DEF_OP_SINGLE(semic, ';')
|
DEF_OP_SINGLE(semic, ';')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue