Files
tompzf 6ed4b1534e Precommit (#1)
* first commit

* cleanup
2025-11-04 13:28:06 +01:00

237 lines
9.8 KiB
C++

#ifndef PARSER_H
#define PARSER_H
#include "lexer.h"
#include "preproc.h"
#include "source.h"
#include "environment.h"
#include <stack>
#include <thread>
#include <vector>
#include <map>
#include <set>
#include <filesystem>
#include "entities/root_entity.h"
#include "parsecontext.h"
enum class EEntityType : uint32_t
{
entity_comment,
entity_include,
entity_module,
entity_interface, // Part of a module
entity_valuetype, // Part of an interface
entity_function, // part of an interface
entity_typedef, // Part of an interface
entity_eof
};
/**
* @brief SDV IDL lexer class
*/
class CParser : public CPreprocessor, public ILexerCallback, public sdv::idl::ICompilerInfo, public sdv::IInterfaceAccess
{
public:
/**
* @brief Constructor used to inject code directly into the parser (mainly for unit tests).
* @param[in] szCode Zero terminated string containing the IDL code. Must not be NULL.
* @param[in] renv Reference to the environment to start using as a base for search dirs and macros.
* @attention The pointer to the source file code needs to stay valid during the duration of the processing.
* @throws Throws CCompileException on parse error.
*/
CParser(const char* szCode, const CIdlCompilerEnvironment& renv = CIdlCompilerEnvironment());
/**
* @brief Constructor
* @param[in] rpath Reference to the source file path. Must be a valid path.
* @param[in] renv Reference to the environment to start using as a base for search dirs and macros.
* @throws Throws CCompileException on parse error.
*/
CParser(const std::filesystem::path& rpath, const CIdlCompilerEnvironment& renv = CIdlCompilerEnvironment());
/**
* @brief Default destructor
*/
virtual ~CParser() = default;
/**
* @brief Get access to another interface. Overload of IInterfaceAccess::GetInterface.
*
* @param[in] idInterface The interface id to get access to.
* @return Returns a pointer to the interface or NULL when the interface is not supported.
*/
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
/**
* @brief Get the path of the processed file. Overload of sdv::idl::ICompilerInfo::GetFilePath.
* @return The path string.
*/
virtual sdv::u8string GetFilePath() const override;
/**
* @brief Return the path to the output directory. Overload of sdv::idl::ICompilerInfo::GetOutputDir.
* @return The directory string.
*/
virtual sdv::u8string GetOutputDir() const override;
/**
* @brief Get access to the underlying lexer.
* @return Reference to the lexer.
*/
const CLexer& GetLexer() const;
/**
* @brief Include a file. Overload of CPreprocessor::IncludeFile.
* @param[in] rpath Reference to the source file path. Must be a valid path.
* @param[in] bLocal When set, the include file is a local include. Otherwise it represents a global include.
*/
virtual void IncludeFile(const std::filesystem::path& rpath, bool bLocal) override;
/**
* @brief Get the environment. Overload of CPreprocessor::GetEnvironment.
* @return Reference to the environment.
*/
virtual CIdlCompilerEnvironment& GetEnvironment() override;
/**
* @brief Get a token from the lexer with moving the current position.
* @details Check the token cache for any unprocessed tokens. If empty, get a token from the lexer for the currently open
* file. Preprocessor directives are automatically executed causing conditionally parsing the file, defining and undefining
* macros and opening include files.
* @throws Throws CCompileException on parse error.
* @return Returns the token if there is any or an empty token when there is no token any more.
*/
CToken GetToken();
/**
* @brief Get the last valid token.
* @return Returns the last read token or an empty token when no token was read before.
*/
CToken GetLastValidToken() const;
/**
* @brief Get a token from the parser without moving the current position.
* @param[in] nIndex The amount of tokens to skip before returning the token.
* @return Returns the token if there is any or an empty token when there is no token any more.
*/
CToken PeekToken(size_t nIndex = 0);
/**
* @brief Get the comment list gathered until the next token.
* @return Token list with comments.
*/
CTokenList GetComments();
/**
* @brief Insert a token in from of the current token cache.
* @details This function prepends the current token at the current position.
* @param[in] rToken Reference to token object containing the code to insert.
*/
void PrependToken(const CToken& rToken);
/**
* @brief Skip adjacent comments - this prevents succeeding comments to be interpreted as preceding comments for the next
* token.
*/
void SkipAdjacentComments();
/**
* @brief Lexical check.
* @details Parse through the file and belonging include files without interpretation to check for lexical errors.
* @throws Throws CCompileException on parse error.
* @return Returns a reference to this parser.
*/
CParser& LexicalCheck();
/**
* @brief Parse the code.
* @details Parse through the file and belonging include files and build a parse tree.
* @throws Throws CCompileException on parse error.
* @return Returns a reference to this parser.
*/
CParser& Parse();
/**
* @brief Get the root entity (after parsing).
* @return Pointer to the root entity or NULL when there is no root entity.
*/
const CRootEntity* Root() const;
/**
* @brief Generate a name for anonymous entities (structs, unions and enums with declarations can be anonymous; unions within
* structs can be transparent - having an anonymous declaration).
* @param[in] rssPrefix The prefix to use to generate an automatic name.
* @return Returns the name of the anonymous entity consisting of a name part "prefix_" with a unique number.
*/
std::string GenerateAnonymousEntityName(const std::string& rssPrefix);
/**
* @brief Structure containing the meta data token
*/
struct SMetaToken
{
CToken tokenMeta; ///< Meta data token
CTokenList lstComments; ///< If available list of preceding comments.
};
/**
* @brief Get and remove the meta data collected until this point.
* @return List of meta tokens.
*/
std::list<SMetaToken> GetAndRemoveMeta();
private:
/**
* @brief Prepare the parsing
* @param[in] rptrContext Reference to the smart pointer to the source code context.
*/
void ParserPrepare(CContextPtr& rptrContext);
/**
* @brief Insert whitespace. Overload of ILexerCallback::InsertWhitespace.
* @param[in] rtoken Reference to the token structure pointing to the whitespace.
*/
virtual void InsertWhitespace(const CToken &rtoken) override;
/**
* @brief Insert a comment, either standalone, belonging to the last statement or belonging to the next statement. Overload
* of ILexerCallback::InsertComment.
* @param[in] rtoken Reference to the token structure pointing to the comment.
*/
virtual void InsertComment(const CToken& rtoken) override;
/**
* @brief Process a preprocessor directive. Overload of ILexerCallback::ProcessPreprocDirective.
* @param[in] rCode Reference to the code.
*/
virtual void ProcessPreprocDirective(CCodePos& rCode) override;
/**
* @brief Get a token from the lexer with moving the current position.
* @details Get a token from the lexer for the currently open file. Preprocessor directives are automatically executed causing
* conditionally parsing the file, defining and undefining macros and opening include files.
* @throws Throws CCompileException on parse error.
* @param[in] bPeekOnly When set, the function doesn't throw an error, but only returns an empty token when no code is
* available any more.
* @return Returns the token if there is any or an empty token when there is no token any more.
*/
CToken GetTokenFromLexer(bool bPeekOnly);
CLexer m_lexer; ///< The lexer.
std::stack<CContextPtr> m_stackCode; ///< Stack with source code.
std::set<std::filesystem::path> m_setProcessedFiles; ///< Set with processed files to prevent recurrency.
std::vector<std::filesystem::path> m_vecSearchDirs; ///< Global search directories.
const size_t m_nMaxDepth = 48; ///< At the most 48 files can be nested.
CIdlCompilerEnvironment m_environment; ///< The environment that is used.
CEntityPtr m_ptrRoot; ///< Root entity pointer.
std::map<std::string, size_t> m_mapAutoNameCount; ///< Automatic name generator counter (for a specific
///< prefix).
CTokenList m_lstCacheTokenList; ///< Token list with pre-inserted tokens before the
///< current position.
std::filesystem::path m_pathFile; ///< Path to the file.
CTokenList m_lstComments; ///< Comments are collected. Collection starts newly
///< after each token.
std::list<SMetaToken> m_lstMeta; ///< List of meta tokens and preceding comments.
};
#endif // !defined PARSER_H