Refactor ParseTypes to use a dedicated state class

This commit is contained in:
Duncan Ogilvie 2023-02-06 04:40:17 +01:00
parent 491057fbfc
commit 3087b56e5b
2 changed files with 85 additions and 55 deletions

View File

@ -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);

View File

@ -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,7 +819,16 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
} }
} }
return false; return false;
}; }
bool operator()()
{
std::string error;
if (!lexer.DoLexing(tokens, error))
{
errors.push_back(error);
return false;
}
while (!isToken(Lexer::tok_eof)) while (!isToken(Lexer::tok_eof))
{ {
@ -825,6 +850,11 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector<
} }
LoadModel(owner, model); LoadModel(owner, model);
return true; return true;
} }
};
bool ParseTypes(const std::string& code, const std::string& owner, std::vector<std::string>& errors)
{
return Parser(code, owner, errors)();
}