This commit is contained in:
deeaitch committed 2026-10-23 20:10:39 -04:00
1 parent c43222939f
commit a258abf7be
7 files changed
+148 -5

No files matched your search

+8 -4
View File
@@ -11,12 +11,16 @@ namespace {
bool quoted = false;
};
bool IsWhitespace(char character) {
return character == ' ' || character == '\t' || character == '\n' || character == '\r';
}
std::vector<Token> Tokenize(const std::string &text) {
std::vector<Token> tokens;
std::size_t index = 0U;
while (index < text.size()) {
const char character = text[index++];
if (character == ' ' || character == '\t')
if (IsWhitespace(character))
continue;
Token token;
if (character == '"') {
@@ -39,14 +43,14 @@ namespace {
}
if (!closed)
throw std::runtime_error("Unterminated attribute string.");
if (index < text.size() && text[index] != ' ' && text[index] != '\t' &&
if (index < text.size() && !IsWhitespace(text[index]) &&
text[index] != ',' && text[index] != ';')
throw std::runtime_error("Missing separator after attribute string.");
} else if (character == ';' || character == ',') {
token.text = character;
} else {
token.text = character;
while (index < text.size() && text[index] != ' ' && text[index] != '\t' &&
while (index < text.size() && !IsWhitespace(text[index]) &&
text[index] != ';' && text[index] != ',') {
if (text[index] == '"')
throw std::runtime_error("Missing separator before attribute string.");
@@ -259,7 +263,7 @@ void DbcParseContext::ResolveAttributes(const std::string &filePath, std::vector
const char *keywords[] = {"BA_DEF_", "BA_DEF_DEF_", "BA_"};
for (const char *phase: keywords) {
for (const PendingAttribute &pending: pendingAttributes) {
const std::string keyword = pending.statement.substr(0U, pending.statement.find_first_of(" \t"));
const std::string keyword = pending.statement.substr(0U, pending.statement.find_first_of(" \t\r\n"));
if (keyword != phase) continue;
try {
AttributeTokens tokens(pending.statement);
+32
View File
@@ -19,6 +19,35 @@
#include <utility>
namespace {
// Attribute statements end at a semicolon outside quoted text.
void ReadAttributeLines(std::ifstream &input, std::string &statement,
std::size_t &lineNumber) {
bool inQuote = false;
bool escaped = false;
std::string part = statement;
for (;;) {
for (const char character: part) {
if (escaped) {
escaped = false;
} else if (inQuote && character == '\\') {
escaped = true;
} else if (character == '"') {
inQuote = !inQuote;
} else if (!inQuote && character == ';') {
return;
}
}
if (!std::getline(input, part))
return;
++lineNumber;
if (!part.empty() && part.back() == '\r')
part.pop_back();
statement += '\n';
statement += part;
escaped = false;
}
}
// Read through the closing unescaped quote, preserving comment whitespace.
void ReadCommentLines(std::ifstream &input, std::string &statement,
std::size_t &lineNumber) {
@@ -112,6 +141,9 @@ DbcParseResult DbcParser::ParseFileWithDiagnostics(const std::string &filePath)
if (keyword == "CM_") {
line = rawLine;
ReadCommentLines(input, line, lineNumber);
} else if (keyword == "BA_DEF_" || keyword == "BA_DEF_DEF_" || keyword == "BA_") {
line = rawLine.substr(rawLine.find(keyword));
ReadAttributeLines(input, line, lineNumber);
}
try {
+2
View File
@@ -34,6 +34,8 @@ struct DbcParserOptions {
* - BA_DEF_, BA_DEF_DEF_, BA_ typed attributes, frame format and cycle time
*
* Frame/signal comments support multiline quoted text and deferred references.
* Attribute statements support multiline fields and quoted strings, ending at
* a semicolon outside quoted text. Diagnostics use the first physical line.
*
* Reports unsupported statements as warnings, except SG_MUL_VAL_ which is
* an error. VERSION, NS_, BS_, BU_ and NS_ symbol declarations stay quiet.