Skip to content

Commit 78629e4

Browse files
committed
refactor(value_parsing): removed the state machine based parsing in favor of regex expressions
1 parent 694a835 commit 78629e4

File tree

2 files changed

+26
-126
lines changed

2 files changed

+26
-126
lines changed

include/libdbc/dbc.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class DbcParser : public Parser {
4343
const std::regex name_space_re;
4444
const std::regex node_re;
4545
const std::regex message_re;
46+
const std::regex value_re;
4647
const std::regex signal_re;
4748

4849
void parse_dbc_header(std::istream& file_stream);

src/dbc.cpp

Lines changed: 25 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <libdbc/utils/utils.hpp>
55

66
#include <regex>
7+
#include <vector>
78

89
namespace libdbc {
910

@@ -52,136 +53,13 @@ struct VALObject {
5253
std::vector<Signal::SignalValueDescriptions> vd;
5354
};
5455

55-
static bool parse_value(const std::string& str, VALObject& obj);
56-
57-
bool parse_value(const std::string& str, VALObject& obj) {
58-
obj.signal_name = "";
59-
obj.vd.clear();
60-
auto state = Identifier;
61-
const char* value_data = str.data();
62-
Signal::SignalValueDescriptions value_description;
63-
for (;;) {
64-
switch (state) {
65-
case Identifier: {
66-
if (*value_data != 'V') {
67-
return false;
68-
}
69-
value_data++;
70-
if (*value_data != 'A') {
71-
return false;
72-
}
73-
value_data++;
74-
if (*value_data != 'L') {
75-
return false;
76-
}
77-
value_data++;
78-
if (*value_data != '_') {
79-
return false;
80-
}
81-
value_data++;
82-
if (*value_data != ' ') {
83-
return false;
84-
}
85-
value_data++; // skip whitespace
86-
state = CANId;
87-
break;
88-
}
89-
case CANId: {
90-
std::string can_id_str;
91-
while (*value_data >= '0' && *value_data <= '9') {
92-
can_id_str += *value_data;
93-
value_data++;
94-
}
95-
if (can_id_str.empty()) {
96-
return false;
97-
}
98-
obj.can_id = static_cast<uint32_t>(std::stoul(can_id_str));
99-
if (*value_data != ' ') {
100-
return false;
101-
}
102-
value_data++; // skip whitespace
103-
state = SignalName;
104-
break;
105-
}
106-
case SignalName: {
107-
if ((*value_data >= 'a' && *value_data <= 'z') || (*value_data >= 'A' && *value_data <= 'Z') || *value_data == '_') {
108-
obj.signal_name += *value_data;
109-
} else {
110-
return false;
111-
}
112-
value_data++;
113-
while ((*value_data >= 'a' && *value_data <= 'z') || (*value_data >= 'A' && *value_data <= 'Z') || *value_data == '_'
114-
|| (*value_data >= '0' && *value_data <= '9')) {
115-
obj.signal_name += *value_data;
116-
value_data++;
117-
}
118-
if (*value_data != ' ') {
119-
return false;
120-
}
121-
value_data++; // skip whitespace
122-
state = Value;
123-
break;
124-
}
125-
case Value: {
126-
std::string value_str;
127-
while (*value_data >= '0' && *value_data <= '9') {
128-
value_str += *value_data;
129-
value_data++;
130-
}
131-
if (*value_data == ';') {
132-
if (value_str.empty()) {
133-
return true;
134-
}
135-
return false;
136-
}
137-
if (value_str.empty()) {
138-
return false;
139-
}
140-
141-
if (*value_data != ' ') {
142-
return false;
143-
}
144-
value_data++; // skip whitespace
145-
value_description.value = (uint32_t)std::stoul(value_str);
146-
state = Description;
147-
break;
148-
}
149-
case Description: {
150-
std::string desc;
151-
if (*value_data != '"') {
152-
return false;
153-
}
154-
value_data++;
155-
while (*value_data != '"' && *value_data != 0) {
156-
desc += *value_data;
157-
value_data++;
158-
}
159-
if (*value_data == 0) {
160-
return false;
161-
}
162-
value_data++;
163-
if (*value_data != ' ') {
164-
return false;
165-
}
166-
value_data++; // skip whitespace
167-
168-
value_description.description = desc;
169-
obj.vd.push_back(value_description);
170-
171-
state = Value;
172-
break;
173-
}
174-
}
175-
}
176-
return false;
177-
}
178-
17956
DbcParser::DbcParser()
18057
: version_re("^(VERSION)\\s\"(.*)\"")
18158
, bit_timing_re("^(BS_:)")
18259
, name_space_re("^(NS_)\\s\\:")
18360
, node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)")
18461
, message_re("^(BO_)\\s(\\d+)\\s(\\w+)\\:\\s(\\d+)\\s(\\w+|Vector__XXX)")
62+
, value_re("^(VAL_)\\s(\\d+)\\s(\\w+)((?:\\s(\\d+)\\s\"([^\"]*)\")+)\\s;$")
18563
,
18664
// NOTE: No multiplex support yet
18765
signal_re(std::string("^") + whiteSpace + signalIdentifierPattern + whiteSpace + namePattern + whiteSpace + "\\:" + whiteSpace + bitStartPattern + "\\|"
@@ -271,7 +149,6 @@ void DbcParser::parse_dbc_messages(const std::vector<std::string>& lines) {
271149

272150
std::vector<VALObject> signal_value;
273151

274-
VALObject obj{};
275152
for (const auto& line : lines) {
276153
if (std::regex_search(line, match, message_re)) {
277154
uint32_t message_id = static_cast<uint32_t>(std::stoul(match.str(MESSAGE_ID_GROUP)));
@@ -308,7 +185,29 @@ void DbcParser::parse_dbc_messages(const std::vector<std::string>& lines) {
308185
continue;
309186
}
310187

311-
if (parse_value(line, obj)) {
188+
if (std::regex_search(line, match, value_re)) {
189+
uint32_t message_id = static_cast<uint32_t>(std::stoul(match.str(2)));
190+
std::string signal_name = match.str(3);
191+
192+
// Loop over the rest of the descriptions
193+
std::string rest_of_descriptions = match.str(4);
194+
std::regex description_re("\\s(\\d+)\\s\"([^\"]*)\"");
195+
196+
std::sregex_iterator desc_iter(rest_of_descriptions.begin(), rest_of_descriptions.end(), description_re);
197+
std::sregex_iterator desc_end;
198+
199+
std::vector<Signal::SignalValueDescriptions> values{};
200+
while (desc_iter != desc_end) {
201+
std::smatch desc_match = *desc_iter;
202+
uint32_t number = static_cast<uint32_t>(std::stoul(desc_match.str(1)));
203+
std::string text = desc_match.str(2);
204+
205+
values.push_back(Signal::SignalValueDescriptions{number, text});
206+
++desc_iter;
207+
}
208+
209+
VALObject obj{message_id, signal_name, values};
210+
312211
signal_value.push_back(obj);
313212
continue;
314213
}

0 commit comments

Comments
 (0)