Skip to content

Commit 8c4e82f

Browse files
authored
Merge pull request #4 from xatavian/topic-improve-dbc-parsing
Better parsing robustness for DBC file format
2 parents e184960 + 956fa64 commit 8c4e82f

File tree

8 files changed

+705
-385
lines changed

8 files changed

+705
-385
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ set(CPPPARSER_INCLUDE_DIRECTORY
1212
set(CPPPARSER_SRC_FILES
1313
src/models/CANDatabase.cpp
1414
src/models/CANFrame.cpp
15-
src/models/CANSignal.cpp
15+
src/models/CANSignal.cpp
1616
src/parsing/DBCParser.cpp
17+
src/parsing/ParsingUtils.cpp
1718
src/parsing/Tokenizer.cpp
1819
src/analysis/CANFrameAnalysis.cpp)
1920

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ C++ CAN Parser currently is compiled as a static library.
112112

113113
Different uses of `can-parse` are possible, mainly 4 operations are included in `can-parse`:
114114
* Print a summary of the whole database
115-
* Print a detailed view of a single entry of the database (very basic implementation for now)
115+
* Print a detailed view of a single entry of the database
116116
* CAN ID, DLC, Period, Comment
117117
* Signals' description
118118
* Name

include/ParsingUtils.h

Lines changed: 17 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,80 +6,33 @@
66
#include <iostream>
77
#include "CANDatabaseException.h"
88

9-
void throwError(const std::string& category, const std::string& description,
10-
unsigned long long line) {
11-
throw CANDatabaseException(
12-
category + ": " + description + " at line " + std::to_string(line)
13-
);
14-
}
9+
void throw_error(const std::string& category, const std::string& description,
10+
unsigned long long line);
1511

16-
void warning(const std::string& description, unsigned long long line) {
17-
std::cout << "WARNING: "
18-
<< description
19-
<< " at line "
20-
<< line
21-
<< std::endl;
22-
}
12+
void warning(const std::string& description, unsigned long long line) ;
2313

24-
void skipIf(Tokenizer& tokenizer, const std::string& token) {
25-
if(tokenizer.getNextToken().image() == token)
26-
return;
14+
const Token&
15+
assert_token(Tokenizer& tokenizer, const std::string& token);
2716

28-
throwError(
29-
"Syntax error",
30-
"expected \"" + token + "\" but got \"" +
31-
tokenizer.getCurrentToken().image() + "\"",
32-
tokenizer.lineCount()
33-
);
34-
}
17+
const Token&
18+
assert_token(Tokenizer& tokenizer, Token::Type targetType);
3519

36-
void assertToken(const Tokenizer& tokenizer, const std::string& token) {
37-
if(tokenizer.getCurrentToken().image() == token)
38-
return;
20+
const Token&
21+
assert_current_token(const Tokenizer& tokenizer, const std::string& token);
3922

40-
throwError(
41-
"Syntax error",
42-
"expected \"" + token + "\" but got \"" +
43-
tokenizer.getCurrentToken().image() + "\"",
44-
tokenizer.lineCount()
45-
);
46-
}
23+
const Token&
24+
assert_current_token(const Tokenizer& tokenizer, Token::Type type);
4725

26+
bool is_current_token(const Tokenizer& tokenizer, const std::string& token);
4827

49-
Token checkCurrentTokenType(const Token& toCheck, Token::Type targetType,
50-
unsigned long long line) {
51-
if(toCheck.type() == targetType)
52-
return toCheck;
28+
bool is_current_token(const Tokenizer& tokenizer, Token::Type token);
5329

54-
throwError(
55-
"Syntax error",
56-
"unexpected \"" + toCheck.image() + "\"",
57-
line
58-
);
30+
bool is_token(Tokenizer& tokenizer, const std::string& token);
5931

60-
// Removes a compilation warning
61-
return toCheck;
62-
}
32+
bool is_token(Tokenizer& tokenizer, Token::Type token);
6333

64-
Token checkCurrentTokenType(const Token& toCheck,
65-
const std::string& token,
66-
unsigned long long line) {
67-
if(toCheck.image() == token)
68-
return toCheck;
34+
bool peek_token(Tokenizer& tokenizer, Token::Type type);
6935

70-
throwError(
71-
"Syntax error",
72-
"unexpected \"" + toCheck.image() + "\"",
73-
line
74-
);
36+
bool peek_token(Tokenizer& tokenizer, const std::string& token);
7537

76-
// Removes a compilation warning
77-
return toCheck;
78-
}
79-
80-
Token checkTokenType(Tokenizer& tokenizer, Token::Type targetType) {
81-
return checkCurrentTokenType(tokenizer.getNextToken(),
82-
targetType,
83-
tokenizer.lineCount());
84-
}
8538
#endif

include/Token.h

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,120 @@
33

44
#include <string>
55

6-
class Token {
7-
public:
6+
struct Token {
7+
/**
8+
* @brief The different kinds of tokens
9+
* The positive and negative numbers represent different types
10+
* of tokens but a grammar rule that accepts any kind of number
11+
* can use the Number type
12+
*/
813
enum Type {
9-
Literal,
14+
StringLiteral,
1015
Separator,
16+
PositiveNumber,
17+
NegativeNumber,
18+
FloatingPointNumber,
1119
Number,
1220
Identifier,
13-
Sign,
21+
ArithmeticSign,
1422
Eof
1523
};
1624

17-
Token() = default;
18-
Token(Type type, const std::string& image) :
19-
type_(type), image_(image) {}
25+
/**
26+
* @return A Token representing an arithmetic sign
27+
*/
28+
static Token createArithmeticSign(char src);
29+
30+
/**
31+
* @return A Token representing a separator
32+
*/
33+
static Token createSeparator(char src);
34+
35+
/**
36+
* The Token's type returned here depends on is_positive and is_float
37+
* @param number The image of the number
38+
* @param is_positive true if number represents a positive number
39+
* @param is_float true if the number represents a floating-point number
40+
* @return A Token representing a number
41+
*/
42+
static Token createNumber(const std::string& number, bool is_positive, bool is_float);
43+
44+
/**
45+
* @brief Constructs an EOF token.
46+
*/
47+
Token();
48+
49+
/**
50+
* @brief Construct a new token with the given type and image
51+
*/
52+
Token(Type type, const std::string& image = "");
53+
2054
Token(const Token&) = default;
2155
Token& operator=(const Token&) = default;
56+
Token(Token&&) = default;
57+
Token& operator=(Token&&) = default;
2258

23-
Type type() const {
24-
return type_;
25-
}
26-
27-
const std::string& image() const {
28-
return image_;
29-
}
59+
/**
60+
* @brief Equality comparison with another token
61+
* @see operator== with string and Token::Type
62+
*/
63+
bool operator==(const Token&) const;
64+
65+
/**
66+
* @return true if the token's image is equal to other
67+
* @param other String to compare
68+
*/
69+
bool operator==(const std::string&) const;
70+
71+
/**
72+
* If the token's type is Number or if other is Number,
73+
* then it also matches PositiveNumber, NegativeNumber and FloatingPointNumber
74+
*
75+
* @return true if the token's type is equal to other
76+
* @param other Type to compare
77+
*/
78+
bool operator==(Token::Type) const;
3079

31-
unsigned long long toUInt() const {
32-
return std::stoul(image_);
33-
}
80+
/**
81+
* @see operator==
82+
*/
83+
bool operator!=(const Token&) const;
3484

35-
long long toInt() const {
36-
return std::stol(image_);
37-
}
85+
/**
86+
* @see operator==
87+
*/
88+
bool operator!=(const std::string&) const;
89+
90+
/**
91+
* @see operator==
92+
*/
93+
bool operator!=(Token::Type) const;
3894

39-
double toDouble() const {
40-
return std::stod(image_);
41-
}
95+
/**
96+
* Using the standard library's functionnalities, parses the
97+
* image to an unsigned integer
98+
*/
99+
unsigned long long toUInt() const;
100+
101+
/**
102+
* Same as above but outputs a signed integer
103+
*/
104+
long long toInt() const;
105+
106+
/**
107+
* Same as above but outputs a floating-point number
108+
*/
109+
double toDouble() const;
110+
111+
/**
112+
* @brief The token's type
113+
*/
114+
Type type;
42115

43-
private:
44-
Type type_;
45-
std::string image_;
116+
/**
117+
* @brief The token's image, ie. the string that represents it
118+
*/
119+
std::string image;
46120
};
47121

48122
#endif

include/Tokenizer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ class Tokenizer {
1111
Tokenizer();
1212
virtual ~Tokenizer() = default;
1313

14-
Token getNextToken();
15-
Token getCurrentToken() const;
14+
const Token& getNextToken();
15+
const Token& getCurrentToken() const;
1616

1717
void skipLine();
1818
void skipUntil(const std::string& token);
1919
void saveToken(const Token& token);
20+
void saveTokenIfNotEof(const Token& token);
2021

2122
unsigned long long charCount() const;
2223
unsigned long long lineCount() const;
@@ -25,6 +26,8 @@ class Tokenizer {
2526
char getNextChar();
2627
char getCurrentChar() const;
2728

29+
std::string parseNumber(bool& is_float);
30+
2831
private:
2932
virtual char doGetNextChar() = 0;
3033

0 commit comments

Comments
 (0)