diff --git a/btparser/types.h b/btparser/types.h index 5e014d8..29d3137 100644 --- a/btparser/types.h +++ b/btparser/types.h @@ -162,5 +162,5 @@ bool RemoveType(const std::string & type); void EnumTypes(std::vector & typeList); bool LoadTypesJson(const std::string & json, 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 & errors); +bool ParseTypes(const std::string & code, const std::string & owner, std::vector & errors); std::string StructUnionPtrType(const std::string & pointto); \ No newline at end of file diff --git a/btparser/typesparser.cpp b/btparser/typesparser.cpp index 0956a7c..4535319 100644 --- a/btparser/typesparser.cpp +++ b/btparser/typesparser.cpp @@ -7,53 +7,61 @@ using namespace Types; void LoadModel(const std::string& owner, Model& model); -bool ParseTypes(const std::string& parse, const std::string& owner, std::vector& errors) +struct Parser { Lexer lexer; - lexer.SetInputData(parse); + std::string owner; + std::vector& errors; + std::vector tokens; size_t index = 0; - auto getToken = [&](size_t i) -> Lexer::TokenState& + Model model; + + Parser(const std::string& code, const std::string& owner, std::vector& errors) + : owner(owner), errors(errors) + { + lexer.SetInputData(code); + } + + Lexer::TokenState& getToken(size_t i) { if (index >= tokens.size() - 1) i = tokens.size() - 1; return tokens[i]; - }; - auto curToken = [&]() -> Lexer::TokenState& + } + + Lexer::TokenState& curToken() { return getToken(index); - }; - auto isToken = [&](Lexer::Token token) + } + + bool isToken(Lexer::Token token) { return getToken(index).Token == token; - }; - auto isTokenList = [&](std::initializer_list il) + } + + bool isTokenList(std::initializer_list il) { size_t i = 0; for (auto l : il) if (getToken(index + i++).Token != l) return false; 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()); errors.push_back(std::move(error)); - }; - auto eatSemic = [&]() + } + + void eatSemic() { while (curToken().Token == Lexer::tok_semic) index++; - }; - auto parseVariable = [&](const std::vector& tlist, std::string& type, bool& isConst, std::string& name) + } + + bool parseVariable(const std::vector& tlist, std::string& type, bool& isConst, std::string& name) { type.clear(); isConst = false; @@ -134,8 +142,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector< if (type.empty()) __debugbreak(); return true; - }; - auto parseFunction = [&](std::vector& rettypes, Function& fn, bool ptr) + } + + bool parseFunction(std::vector& rettypes, Function& fn, bool ptr) { 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)) { + errLine(curToken(), "function pointer arguments are not supported"); // TODO: support function pointers (requires recursion) + return false; } else { @@ -318,8 +329,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector< eatSemic(); return true; - }; - auto parseMember = [&](StructUnion& su) + } + + bool parseMember(StructUnion& su) { Member m; bool sawPointer = false; @@ -473,8 +485,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector< return false; return true; - }; - auto parseStructUnion = [&]() + } + + bool parseStructUnion() { 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; - }; - auto parseEnum = [&]() + } + + bool parseEnum() { if (isToken(Lexer::tok_enum)) { @@ -630,8 +644,9 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector< __debugbreak(); } return true; - }; - auto parseTypedef = [&]() + } + + bool parseTypedef() { // TODO: support "typedef struct 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); } return true; - }; - auto parseFunctionTop = [&]() + } + + bool parseFunctionTop() { bool sawPointer = false; std::vector tlist; @@ -803,28 +819,42 @@ bool ParseTypes(const std::string& parse, const std::string& owner, std::vector< } } 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& errors) +{ + return Parser(code, owner, errors)(); } \ No newline at end of file