// SPDX-License-Identifier: MIT #ifndef DBC_STATEMENT_HANDLER_H #define DBC_STATEMENT_HANDLER_H #include "dbc_database.h" #include "dbc_diagnostic.h" #include "typefactory.h" #include #include #include /** @brief Deferred raw value descriptions and their target. */ struct PendingValueDescriptions { std::uint32_t canId; /**< Normalized target frame identifier. */ bool isExtended; /**< Target frame type. */ std::string signalName; /**< Target signal name. */ ValueDescriptions descriptions; /**< Raw integer descriptions to merge. */ std::size_t lineNumber; /**< One-based physical statement line. */ }; /** @brief Deferred frame or signal comment and its source location. */ struct PendingComment { std::uint32_t canId; /**< Normalized target frame identifier. */ bool isExtended; /**< Target frame type. */ bool isSignal; /**< Whether the target is a signal rather than a frame. */ std::string signalName; /**< Target signal name. */ std::string comment; /**< Unescaped comment text. */ std::size_t lineNumber; /**< One-based physical statement line. */ }; /** Carries deferred validation locations without parsing exception text. */ class DbcDiagnosticError : public std::runtime_error { public: /** @brief Create an exception with a structured source diagnostic. */ DbcDiagnosticError(DbcDiagnosticCode code, const std::string &filePath, std::size_t lineNumber, const std::string &message) : std::runtime_error(filePath + ":" + std::to_string(lineNumber) + ": " + message), diagnostic{DbcDiagnosticSeverity::Error, code, filePath, lineNumber, message} {} DbcDiagnostic diagnostic; /**< Structured error accompanying the exception message. */ }; /** @brief Attribute statement retained for ordered resolution. */ struct PendingAttribute { std::string statement; /**< Complete attribute statement. */ std::size_t lineNumber; /**< One-based physical statement line. */ }; /** Mutable state belonging to one file parse. Handlers do not retain it. */ struct DbcParseContext { DbcDatabase &database; /**< Parsed metadata under construction. */ FrameInfo *currentFrame = nullptr; /**< Current frame for following signal definitions. */ bool enableJ1939 = false; /**< Explicit interpretation option for extended frames. */ std::size_t lineNumber = 0U; /**< Physical line of the current statement. */ std::vector pendingValues = {}; /**< Unresolved raw value descriptions. */ std::vector> signalLines = {}; /**< Signal definition lines grouped by frame. */ /** @brief Validate selectors, branch ranges, and signal overlap. */ void ValidateMultiplexing(const std::string &filePath) const; std::vector pendingComments = {}; /**< Unresolved comments in source order. */ /** @brief Resolve deferred comments after all definitions are known. */ void ResolveComments(const std::string &filePath); std::vector pendingAttributes = {}; /**< Unresolved attributes in source order. */ /** @brief Resolve definitions, defaults, then assignments; append format warnings. */ void ResolveAttributes(const std::string &filePath, std::vector &diagnostics); /** @brief Resolve deferred raw descriptions against unique targets. */ void ResolveValueDescriptions(const std::string &filePath); }; /** @brief Interface for processing a registered DBC statement. */ class DbcStatementHandler { public: virtual ~DbcStatementHandler() = default; /** @brief Process a trimmed statement using state belonging to this parse. */ virtual void Handle(const std::string &line, DbcParseContext &context) const = 0; }; /** @brief Parse and append frame definitions. */ class DbcFrameHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; private: static FrameInfo ParseFrameLine(const std::string &line); }; /** @brief Parse and append signals to the current frame. */ class DbcSignalHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; private: static SignalInfo ParseSignalLine(const std::string &line); }; /** @brief Defer frame and signal comments for target resolution. */ class DbcCommentHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; }; /** @brief Defer typed attribute statements for resolution. */ class DbcAttributeHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; }; /** @brief Defer raw value descriptions for target resolution. */ class DbcValueDescriptionHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; }; /** @brief Reject unsupported extended multiplexing statements. */ class DbcUnsupportedMultiplexingHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; }; /** Common header metadata does not change the supported decode definitions. */ class DbcHeaderHandler : public DbcStatementHandler { public: void Handle(const std::string &line, DbcParseContext &context) const override; }; /** Exact-key dispatch to handlers created once per registration via TypeFactory. */ class DbcStatementDispatcher { public: /** @brief Register supported statement handlers through TypeFactory. */ DbcStatementDispatcher(); /** @brief Register or replace a handler and create its reusable instance. */ template void RegisterType(const std::string &keyword) { m_factory.registerType(keyword); m_handlers.insert_or_assign(keyword, m_factory.create(keyword)); } /** Returns false for an unregistered keyword; input must be trimmed. */ bool Dispatch(const std::string &line, DbcParseContext &context) const; private: using HandlerMap = std::unordered_map>; TypeFactory m_factory; HandlerMap m_handlers; }; #endif /* DBC_STATEMENT_HANDLER_H */