mirror of https://github.com/x64dbg/btparser
Refactor ParseTypes to use a dedicated state class
This commit is contained in:
parent
491057fbfc
commit
3087b56e5b
|
@ -162,5 +162,5 @@ bool RemoveType(const std::string & type);
|
||||||
void EnumTypes(std::vector<Types::TypeManager::Summary> & typeList);
|
void EnumTypes(std::vector<Types::TypeManager::Summary> & typeList);
|
||||||
bool LoadTypesJson(const std::string & json, const std::string & owner);
|
bool LoadTypesJson(const std::string & json, const std::string & owner);
|
||||||
bool LoadTypesFile(const std::string & path, const std::string & owner);
|
bool LoadTypesFile(const std::string & path, const std::string & owner);
|
||||||
bool ParseTypes(const std::string & parse, const std::string & owner, std::vector<std::string> & errors);
|
bool ParseTypes(const std::string & code, const std::string & owner, std::vector<std::string> & errors);
|
||||||
std::string StructUnionPtrType(const std::string & pointto);
|
std::string StructUnionPtrType(const std::string & pointto);
|
|
@ -7,53 +7,61 @@ using namespace Types;
|
||||||
|
|
||||||
void LoadModel(const std::string& owner, Model& model);
|
void LoadModel(const std::string& owner, Model& model);
|
||||||
|
|
||||||
bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<std::string>& errors)
|
struct Parser
|
||||||
{
|
{
|
||||||
Lexer lexer;
|
Lexer lexer;
|
||||||
lexer.SetInputData(parse);
|
std::string owner;
|
||||||
|
std::vector<std::string>& errors;
|
||||||
|
|
||||||
std::vector<Lexer::TokenState> tokens;
|
std::vector<Lexer::TokenState> tokens;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
auto getToken = [&](size_t i) -> Lexer::TokenState&
|
Model model;
|
||||||
|
|
||||||
|
Parser(const std::string& code, const std::string& owner, std::vector<std::string>& errors)
|
||||||
|
: owner(owner), errors(errors)
|
||||||
|
{
|
||||||
|
lexer.SetInputData(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lexer::TokenState& getToken(size_t i)
|
||||||
{
|
{
|
||||||
if (index >= tokens.size() - 1)
|
if (index >= tokens.size() - 1)
|
||||||
i = tokens.size() - 1;
|
i = tokens.size() - 1;
|
||||||
return tokens[i];
|
return tokens[i];
|
||||||
};
|
}
|
||||||
auto curToken = [&]() -> Lexer::TokenState&
|
|
||||||
|
Lexer::TokenState& curToken()
|
||||||
{
|
{
|
||||||
return getToken(index);
|
return getToken(index);
|
||||||
};
|
}
|
||||||
auto isToken = [&](Lexer::Token token)
|
|
||||||
|
bool isToken(Lexer::Token token)
|
||||||
{
|
{
|
||||||
return getToken(index).Token == token;
|
return getToken(index).Token == token;
|
||||||
};
|
}
|
||||||
auto isTokenList = [&](std::initializer_list<Lexer::Token> il)
|
|
||||||
|
bool isTokenList(std::initializer_list<Lexer::Token> il)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto l : il)
|
for (auto l : il)
|
||||||
if (getToken(index + i++).Token != l)
|
if (getToken(index + i++).Token != l)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
|
||||||
std::string error;
|
|
||||||
if (!lexer.DoLexing(tokens, error))
|
|
||||||
{
|
|
||||||
errors.push_back(error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
Model model;
|
|
||||||
|
|
||||||
auto errLine = [&](const Lexer::TokenState& token, const std::string& message)
|
void errLine(const Lexer::TokenState& token, const std::string& message)
|
||||||
{
|
{
|
||||||
auto error = StringUtils::sprintf("[line %zu:%zu] %s", token.CurLine + 1, token.LineIndex, message.c_str());
|
auto error = StringUtils::sprintf("[line %zu:%zu] %s", token.CurLine + 1, token.LineIndex, message.c_str());
|
||||||
errors.push_back(std::move(error));
|
errors.push_back(std::move(error));
|
||||||
};
|
}
|
||||||
auto eatSemic = [&]()
|
|
||||||
|
void eatSemic()
|
||||||
{
|
{
|
||||||
while (curToken().Token == Lexer::tok_semic)
|
while (curToken().Token == Lexer::tok_semic)
|
||||||
index++;
|
index++;
|
||||||
};
|
}
|
||||||
auto parseVariable = [&](const std::vector<Lexer::TokenState>& tlist, std::string& type, bool& isConst, std::string& name)
|
|
||||||
|
bool parseVariable(const std::vector<Lexer::TokenState>& tlist, std::string& type, bool& isConst, std::string& name)
|
||||||
{
|
{
|
||||||
type.clear();
|
type.clear();
|
||||||
isConst = false;
|
isConst = false;
|
||||||
|
@ -134,8 +142,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
if (type.empty())
|
if (type.empty())
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
auto parseFunction = [&](std::vector<Lexer::TokenState>& rettypes, Function& fn, bool ptr)
|
|
||||||
|
bool parseFunction(std::vector<Lexer::TokenState>& rettypes, Function& fn, bool ptr)
|
||||||
{
|
{
|
||||||
if (rettypes.empty())
|
if (rettypes.empty())
|
||||||
{
|
{
|
||||||
|
@ -282,7 +291,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
}
|
}
|
||||||
else if (t.Is(Lexer::tok_paropen))
|
else if (t.Is(Lexer::tok_paropen))
|
||||||
{
|
{
|
||||||
|
errLine(curToken(), "function pointer arguments are not supported");
|
||||||
// TODO: support function pointers (requires recursion)
|
// TODO: support function pointers (requires recursion)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -318,8 +329,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
eatSemic();
|
eatSemic();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
auto parseMember = [&](StructUnion& su)
|
|
||||||
|
bool parseMember(StructUnion& su)
|
||||||
{
|
{
|
||||||
Member m;
|
Member m;
|
||||||
bool sawPointer = false;
|
bool sawPointer = false;
|
||||||
|
@ -473,8 +485,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
auto parseStructUnion = [&]()
|
|
||||||
|
bool parseStructUnion()
|
||||||
{
|
{
|
||||||
if (isToken(Lexer::tok_struct) || isToken(Lexer::tok_union))
|
if (isToken(Lexer::tok_struct) || isToken(Lexer::tok_union))
|
||||||
{
|
{
|
||||||
|
@ -531,8 +544,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
auto parseEnum = [&]()
|
|
||||||
|
bool parseEnum()
|
||||||
{
|
{
|
||||||
if (isToken(Lexer::tok_enum))
|
if (isToken(Lexer::tok_enum))
|
||||||
{
|
{
|
||||||
|
@ -630,8 +644,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
auto parseTypedef = [&]()
|
|
||||||
|
bool parseTypedef()
|
||||||
{
|
{
|
||||||
// TODO: support "typedef struct foo { members... };"
|
// TODO: support "typedef struct foo { members... };"
|
||||||
// TODO: support "typedef enum foo { members... };"
|
// TODO: support "typedef enum foo { members... };"
|
||||||
|
@ -728,8 +743,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
model.types.push_back(tm);
|
model.types.push_back(tm);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
auto parseFunctionTop = [&]()
|
|
||||||
|
bool parseFunctionTop()
|
||||||
{
|
{
|
||||||
bool sawPointer = false;
|
bool sawPointer = false;
|
||||||
std::vector<Lexer::TokenState> tlist;
|
std::vector<Lexer::TokenState> tlist;
|
||||||
|
@ -803,28 +819,42 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
|
||||||
|
|
||||||
while (!isToken(Lexer::tok_eof))
|
|
||||||
{
|
|
||||||
auto curIndex = index;
|
|
||||||
if (!parseTypedef())
|
|
||||||
return false;
|
|
||||||
if (!parseStructUnion())
|
|
||||||
return false;
|
|
||||||
if (!parseEnum())
|
|
||||||
return false;
|
|
||||||
eatSemic();
|
|
||||||
if (curIndex == index)
|
|
||||||
{
|
|
||||||
if (!parseFunctionTop())
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadModel(owner, model);
|
bool operator()()
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
if (!lexer.DoLexing(tokens, error))
|
||||||
|
{
|
||||||
|
errors.push_back(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
while (!isToken(Lexer::tok_eof))
|
||||||
|
{
|
||||||
|
auto curIndex = index;
|
||||||
|
if (!parseTypedef())
|
||||||
|
return false;
|
||||||
|
if (!parseStructUnion())
|
||||||
|
return false;
|
||||||
|
if (!parseEnum())
|
||||||
|
return false;
|
||||||
|
eatSemic();
|
||||||
|
if (curIndex == index)
|
||||||
|
{
|
||||||
|
if (!parseFunctionTop())
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadModel(owner, model);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ParseTypes(const std::string& code, const std::string& owner, std::vector<std::string>& errors)
|
||||||
|
{
|
||||||
|
return Parser(code, owner, errors)();
|
||||||
}
|
}
|
Loading…
Reference in New Issue