Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT
2 : : #ifndef DBC_STATEMENT_HANDLER_H
3 : : #define DBC_STATEMENT_HANDLER_H
4 : :
5 : : #include "dbc_database.h"
6 : : #include "dbc_diagnostic.h"
7 : : #include "typefactory.h"
8 : : #include <stdexcept>
9 : : #include <string>
10 : : #include <unordered_map>
11 : :
12 : : /** @brief Deferred raw value descriptions and their target. */
13 : : struct PendingValueDescriptions {
14 : : std::uint32_t canId; /**< Normalized target frame identifier. */
15 : : bool isExtended; /**< Target frame type. */
16 : : std::string signalName; /**< Target signal name. */
17 : : ValueDescriptions descriptions; /**< Raw integer descriptions to merge. */
18 : : std::size_t lineNumber; /**< One-based physical statement line. */
19 : : };
20 : :
21 : : /** @brief Deferred frame or signal comment and its source location. */
22 : : struct PendingComment {
23 : : std::uint32_t canId; /**< Normalized target frame identifier. */
24 : : bool isExtended; /**< Target frame type. */
25 : : bool isSignal; /**< Whether the target is a signal rather than a frame. */
26 : : std::string signalName; /**< Target signal name. */
27 : : std::string comment; /**< Unescaped comment text. */
28 : : std::size_t lineNumber; /**< One-based physical statement line. */
29 : : };
30 : :
31 : : /** Carries deferred validation locations without parsing exception text. */
32 : : class DbcDiagnosticError : public std::runtime_error {
33 : : public:
34 : : /** @brief Create an exception with a structured source diagnostic. */
35 : 438 : DbcDiagnosticError(DbcDiagnosticCode code, const std::string &filePath,
36 : : std::size_t lineNumber, const std::string &message)
37 [ + - + - : 876 : : std::runtime_error(filePath + ":" + std::to_string(lineNumber) + ": " + message),
+ - + - ]
38 [ + - + - : 1314 : diagnostic{DbcDiagnosticSeverity::Error, code, filePath, lineNumber, message} {}
+ - + - -
- ]
39 : :
40 : : DbcDiagnostic diagnostic; /**< Structured error accompanying the exception message. */
41 : : };
42 : :
43 : : /** @brief Attribute statement retained for ordered resolution. */
44 : : struct PendingAttribute {
45 : : std::string statement; /**< Complete attribute statement. */
46 : : std::size_t lineNumber; /**< One-based physical statement line. */
47 : : };
48 : :
49 : : /** Mutable state belonging to one file parse. Handlers do not retain it. */
50 : : struct DbcParseContext {
51 : : DbcDatabase &database; /**< Parsed metadata under construction. */
52 : : FrameInfo *currentFrame = nullptr; /**< Current frame for following signal definitions. */
53 : : bool enableJ1939 = false; /**< Explicit interpretation option for extended frames. */
54 : : std::size_t lineNumber = 0U; /**< Physical line of the current statement. */
55 : : std::vector<PendingValueDescriptions> pendingValues = {}; /**< Unresolved raw value descriptions. */
56 : :
57 : : std::vector<std::vector<std::size_t>> signalLines = {}; /**< Signal definition lines grouped by frame. */
58 : : /** @brief Validate selectors, branch ranges, and signal overlap. */
59 : : void ValidateMultiplexing(const std::string &filePath) const;
60 : :
61 : : std::vector<PendingComment> pendingComments = {}; /**< Unresolved comments in source order. */
62 : : /** @brief Resolve deferred comments after all definitions are known. */
63 : : void ResolveComments(const std::string &filePath);
64 : :
65 : : std::vector<PendingAttribute> pendingAttributes = {}; /**< Unresolved attributes in source order. */
66 : : /** @brief Resolve definitions, defaults, then assignments; append format warnings. */
67 : : void ResolveAttributes(const std::string &filePath, std::vector<DbcDiagnostic> &diagnostics);
68 : :
69 : : /** @brief Resolve deferred raw descriptions against unique targets. */
70 : : void ResolveValueDescriptions(const std::string &filePath);
71 : : };
72 : :
73 : : /** @brief Interface for processing a registered DBC statement. */
74 : : class DbcStatementHandler {
75 : : public:
76 : 14250 : virtual ~DbcStatementHandler() = default;
77 : : /** @brief Process a trimmed statement using state belonging to this parse. */
78 : : virtual void Handle(const std::string &line, DbcParseContext &context) const = 0;
79 : : };
80 : :
81 : : /** @brief Parse and append frame definitions. */
82 : : class DbcFrameHandler : public DbcStatementHandler {
83 : : public:
84 : : void Handle(const std::string &line, DbcParseContext &context) const override;
85 : :
86 : : private:
87 : : static FrameInfo ParseFrameLine(const std::string &line);
88 : : };
89 : :
90 : : /** @brief Parse and append signals to the current frame. */
91 : : class DbcSignalHandler : public DbcStatementHandler {
92 : : public:
93 : : void Handle(const std::string &line, DbcParseContext &context) const override;
94 : :
95 : : private:
96 : : static SignalInfo ParseSignalLine(const std::string &line);
97 : : };
98 : :
99 : : /** @brief Defer frame and signal comments for target resolution. */
100 : : class DbcCommentHandler : public DbcStatementHandler {
101 : : public:
102 : : void Handle(const std::string &line, DbcParseContext &context) const override;
103 : : };
104 : :
105 : : /** @brief Defer typed attribute statements for resolution. */
106 : : class DbcAttributeHandler : public DbcStatementHandler {
107 : : public:
108 : : void Handle(const std::string &line, DbcParseContext &context) const override;
109 : : };
110 : :
111 : : /** @brief Defer raw value descriptions for target resolution. */
112 : : class DbcValueDescriptionHandler : public DbcStatementHandler {
113 : : public:
114 : : void Handle(const std::string &line, DbcParseContext &context) const override;
115 : : };
116 : :
117 : : /** @brief Reject unsupported extended multiplexing statements. */
118 : : class DbcUnsupportedMultiplexingHandler : public DbcStatementHandler {
119 : : public:
120 : : void Handle(const std::string &line, DbcParseContext &context) const override;
121 : : };
122 : :
123 : : /** Common header metadata does not change the supported decode definitions. */
124 : : class DbcHeaderHandler : public DbcStatementHandler {
125 : : public:
126 : : void Handle(const std::string &line, DbcParseContext &context) const override;
127 : : };
128 : :
129 : : /** Exact-key dispatch to handlers created once per registration via TypeFactory. */
130 : : class DbcStatementDispatcher {
131 : : public:
132 : : /** @brief Register supported statement handlers through TypeFactory. */
133 : : DbcStatementDispatcher();
134 : :
135 : : /** @brief Register or replace a handler and create its reusable instance. */
136 : : template<class Handler>
137 : 14236 : void RegisterType(const std::string &keyword) {
138 : 14236 : m_factory.registerType<Handler>(keyword);
139 [ + - + - ]: 14236 : m_handlers.insert_or_assign(keyword, m_factory.create(keyword));
140 : 14236 : }
141 : :
142 : : /** Returns false for an unregistered keyword; input must be trimmed. */
143 : : bool Dispatch(const std::string &line, DbcParseContext &context) const;
144 : :
145 : : private:
146 : : using HandlerMap = std::unordered_map<std::string, std::shared_ptr<DbcStatementHandler>>;
147 : : TypeFactory<std::string, DbcStatementHandler> m_factory;
148 : : HandlerMap m_handlers;
149 : : };
150 : :
151 : : #endif /* DBC_STATEMENT_HANDLER_H */
|