First implementation
This commit is contained in:
688
CanDriver/parser/dbc/DbcParser.cpp
Normal file
688
CanDriver/parser/dbc/DbcParser.cpp
Normal file
@@ -0,0 +1,688 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
|
||||
|
||||
This file is part of cangaroo.
|
||||
|
||||
cangaroo is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
cangaroo is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "DbcParser.h"
|
||||
#include <QTextStream>
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
#include <core/Backend.h>
|
||||
#include <core/CanDb.h>
|
||||
|
||||
#include "DbcTokens.h"
|
||||
|
||||
DbcParser::DbcParser()
|
||||
: _errorLine(0), _errorColumn(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool DbcParser::parseFile(QFile *file, CanDb &candb)
|
||||
{
|
||||
DbcTokenList tokens;
|
||||
if (tokenize(file, tokens) != err_ok) {
|
||||
QString msg = QString("error parsing dbc file %1").arg(file->fileName());
|
||||
if (_errorLine) {
|
||||
msg += QString(" at line %1, column %2").arg(_errorLine).arg(_errorColumn);
|
||||
}
|
||||
log_error(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
candb.setPath(file->fileName());
|
||||
return parse(candb, tokens);
|
||||
}
|
||||
|
||||
DbcToken *DbcParser::createNewToken(QChar ch, int line, int column)
|
||||
{
|
||||
static const QString acceptableIdStartChars("ABCDEFGHIKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_");
|
||||
static const QRegExp numberRegExp("^(\\d+(\\.\\d*)?(E[-+]?\\d*)?)$");
|
||||
|
||||
if (ch.isSpace()) {
|
||||
return new DbcWhitespaceToken(line, column);
|
||||
} else if (ch.isDigit()) {
|
||||
return new DbcRegExpToken(line, column, dbc_tok_number, numberRegExp);
|
||||
} else if (ch == '"') {
|
||||
return new DbcStringToken(line, column);
|
||||
} else if (ch == ':') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_colon, ':');
|
||||
} else if (ch == '|') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_pipe, '|');
|
||||
} else if (ch == '@') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_at, '@');
|
||||
} else if (ch == '+') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_plus, '+');
|
||||
} else if (ch == '-') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_minus, '-');
|
||||
} else if (ch == '(') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_parenth_open, '(');
|
||||
} else if (ch == ')') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_parenth_close, ')');
|
||||
} else if (ch == '[') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_bracket_open, '[');
|
||||
} else if (ch == ']') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_bracket_close, ']');
|
||||
} else if (ch == ',') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_comma, ',');
|
||||
} else if (ch == ';') {
|
||||
return new DbcSingleCharToken(line, column, dbc_tok_semicolon, ';');
|
||||
} else if (acceptableIdStartChars.contains(ch)) {
|
||||
return new DbcIdentifierToken(line, column);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DbcParser::error_t DbcParser::tokenize(QFile *file, DbcParser::DbcTokenList &tokens)
|
||||
{
|
||||
|
||||
if (!file->open(QIODevice::ReadOnly)) {
|
||||
// TODO raise cannot open file exception
|
||||
return err_cannot_open_file;
|
||||
}
|
||||
|
||||
DbcToken *currentToken = 0;
|
||||
int line = 1;
|
||||
int column = 0;
|
||||
|
||||
error_t retval = err_ok;
|
||||
|
||||
QTextStream in(file);
|
||||
in.setCodec("ISO 8859-1");
|
||||
|
||||
while (true) {
|
||||
QString s = in.read(1);
|
||||
if (s.isEmpty()) { break; }
|
||||
|
||||
QChar ch = s[0];
|
||||
|
||||
if (ch=='\n') {
|
||||
line++;
|
||||
column=1;
|
||||
} else {
|
||||
column++;
|
||||
}
|
||||
|
||||
if (currentToken) {
|
||||
if (!currentToken->appendChar(ch)) {
|
||||
tokens.append(currentToken);
|
||||
currentToken = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentToken) {
|
||||
currentToken = createNewToken(ch, line, column);
|
||||
if (currentToken) {
|
||||
currentToken->appendChar(ch);
|
||||
} else {
|
||||
retval = err_tokenize_error;
|
||||
_errorColumn = column;
|
||||
_errorLine = line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
file->close();
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool DbcParser::isSectionEnding(DbcToken *token, bool newLineIsSectionEnding)
|
||||
{
|
||||
if (!token) {
|
||||
return true;
|
||||
} else {
|
||||
int numNewLinesForEnding = newLineIsSectionEnding ? 1 : 2;
|
||||
dbc_token_type_t type = token->getType();
|
||||
return ( (type==dbc_tok_semicolon) || ( (type==dbc_tok_whitespace) && (token->countLineBreaks()>=numNewLinesForEnding)));
|
||||
}
|
||||
}
|
||||
|
||||
DbcToken *DbcParser::readToken(DbcParser::DbcTokenList &tokens, int typeMask, bool skipWhitespace, bool skipSectionEnding, bool newLineIsSectionEnding)
|
||||
{
|
||||
while (true) {
|
||||
if (tokens.isEmpty()) { return 0; }
|
||||
|
||||
DbcToken *token = tokens.first();
|
||||
dbc_token_type_t type = token->getType();
|
||||
|
||||
if (type & typeMask) {
|
||||
|
||||
tokens.pop_front();
|
||||
return token;
|
||||
|
||||
} else if (isSectionEnding(token, newLineIsSectionEnding)) {
|
||||
|
||||
if (skipSectionEnding) {
|
||||
tokens.pop_front();
|
||||
free(token);
|
||||
continue;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (skipWhitespace && (type==dbc_tok_whitespace)) {
|
||||
|
||||
tokens.pop_front();
|
||||
free(token);
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DbcParser::expectSectionEnding(DbcTokenList &tokens, bool newLineIsSectionEnding)
|
||||
{
|
||||
if (tokens.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
DbcToken *token = readToken(tokens, dbc_tok_whitespace|dbc_tok_semicolon);
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isSectionEnding(token, newLineIsSectionEnding)) {
|
||||
free(token);
|
||||
return false;
|
||||
} else {
|
||||
free(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool DbcParser::expectLineBreak(DbcParser::DbcTokenList &tokens)
|
||||
{
|
||||
bool found_line_break;
|
||||
|
||||
DbcToken *token = readToken(tokens, dbc_tok_whitespace);
|
||||
if (token) {
|
||||
found_line_break = token->countLineBreaks()>0;
|
||||
free(token);
|
||||
} else {
|
||||
found_line_break = false;
|
||||
}
|
||||
|
||||
return found_line_break;
|
||||
}
|
||||
|
||||
bool DbcParser::expectAndSkipToken(DbcTokenList &tokens, dbc_token_type_t type, bool skipWhitespace, bool skipSectionEnding)
|
||||
{
|
||||
DbcToken *token = readToken(tokens, type, skipWhitespace, skipSectionEnding);
|
||||
if (!token) {
|
||||
return false;
|
||||
} else {
|
||||
free(token);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool DbcParser::expectData(DbcParser::DbcTokenList &tokens, dbc_token_type_t type, QString *data, bool skipWhitespace, bool skipSectionEnding, bool newLineIsSectionEnding)
|
||||
{
|
||||
DbcToken *token;
|
||||
if (!(token = readToken(tokens, type, skipWhitespace, skipSectionEnding, newLineIsSectionEnding))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
data->clear();
|
||||
data->append(token->getData());
|
||||
}
|
||||
|
||||
free(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DbcParser::expectIdentifier(DbcParser::DbcTokenList &tokens, QString *id, bool skipWhitespace, bool skipSectionEnding, bool newLineIsSectionEnding)
|
||||
{
|
||||
return expectData(tokens, dbc_tok_identifier, id, skipWhitespace, skipSectionEnding, newLineIsSectionEnding);
|
||||
}
|
||||
|
||||
bool DbcParser::expectString(DbcParser::DbcTokenList &tokens, QString *str, bool skipWhitespace)
|
||||
{
|
||||
QString quotedStr;
|
||||
bool ok = expectData(tokens, dbc_tok_string, "edStr, skipWhitespace);
|
||||
if (ok && quotedStr.length()>=2) {
|
||||
*str = quotedStr.mid(1, quotedStr.length()-2);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DbcParser::expectNumber(DbcParser::DbcTokenList &tokens, QString *str, bool skipWhitespace)
|
||||
{
|
||||
QString data;
|
||||
if (expectAndSkipToken(tokens, dbc_tok_minus, skipWhitespace)) {
|
||||
*str = "-";
|
||||
} else if (expectAndSkipToken(tokens, dbc_tok_plus, skipWhitespace)) {
|
||||
*str = "+";
|
||||
}
|
||||
|
||||
if (expectData(tokens, dbc_tok_number, &data, skipWhitespace)) {
|
||||
*str += data;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool DbcParser::expectInt(DbcParser::DbcTokenList &tokens, int *i, int base, bool skipWhitespace)
|
||||
{
|
||||
QString data;
|
||||
if (!expectNumber(tokens, &data, skipWhitespace)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool convert_ok;
|
||||
*i = data.toInt(&convert_ok, base);
|
||||
return convert_ok;
|
||||
}
|
||||
|
||||
bool DbcParser::expectLongLong(DbcTokenList &tokens, long long *i, int base, bool skipWhitespace)
|
||||
{
|
||||
QString data;
|
||||
if (!expectNumber(tokens, &data, skipWhitespace)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool convert_ok;
|
||||
*i = data.toLongLong(&convert_ok, base);
|
||||
return convert_ok;
|
||||
}
|
||||
|
||||
bool DbcParser::expectDouble(DbcTokenList &tokens, double *df, bool skipWhitespace)
|
||||
{
|
||||
QString data;
|
||||
if (!expectNumber(tokens, &data, skipWhitespace)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool convert_ok;
|
||||
*df = data.toDouble(&convert_ok);
|
||||
return convert_ok;
|
||||
}
|
||||
|
||||
void DbcParser::skipUntilSectionEnding(DbcTokenList &tokens)
|
||||
{
|
||||
while (!tokens.isEmpty()) {
|
||||
DbcToken *token = readToken(tokens, dbc_tok_ALL, false, false);
|
||||
if (!token) { return; }
|
||||
if (isSectionEnding(token)) {
|
||||
free(token);
|
||||
return;
|
||||
} else {
|
||||
free(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DbcParser::parseIdentifierList(DbcTokenList &tokens, QStringList *list, bool newLineIsSectionEnding)
|
||||
{
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_colon)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString id;
|
||||
while (expectIdentifier(tokens, &id, true, false, newLineIsSectionEnding)) {
|
||||
if (list) {
|
||||
list->append(id);
|
||||
}
|
||||
}
|
||||
|
||||
return expectSectionEnding(tokens, newLineIsSectionEnding);
|
||||
}
|
||||
|
||||
bool DbcParser::parse(CanDb &candb, DbcTokenList &tokens)
|
||||
{
|
||||
_dbcVersion.clear();
|
||||
_nsEntries.clear();
|
||||
_buEntries.clear();
|
||||
|
||||
while (!tokens.isEmpty()) {
|
||||
if (!parseSection(candb, tokens)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DbcParser::parseSection(CanDb &candb, DbcTokenList &tokens) {
|
||||
bool retval = true;
|
||||
|
||||
QString sectionName;
|
||||
QStringList strings;
|
||||
|
||||
while (retval) {
|
||||
|
||||
if (tokens.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (expectIdentifier(tokens, §ionName, true, true)) {
|
||||
if (sectionName == "VERSION") {
|
||||
retval &= parseSectionVersion(candb, tokens);
|
||||
} else if (sectionName == "NS_") {
|
||||
strings.clear();
|
||||
retval &= parseIdentifierList(tokens, &strings);
|
||||
} else if (sectionName == "BS_") {
|
||||
retval &= parseSectionBs(tokens);
|
||||
} else if (sectionName == "BU_") {
|
||||
retval &= parseSectionBu(candb, tokens);
|
||||
} else if (sectionName == "BO_") {
|
||||
retval &= parseSectionBo(candb, tokens);
|
||||
} else if (sectionName == "CM_") {
|
||||
retval &= parseSectionCm(candb, tokens);
|
||||
} else if (sectionName == "VAL_") {
|
||||
retval &= parseSectionVal(candb, tokens);
|
||||
} else {
|
||||
skipUntilSectionEnding(tokens);
|
||||
}
|
||||
|
||||
} else {
|
||||
retval = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!retval) {
|
||||
log_error("dbc parse error");
|
||||
}
|
||||
return retval;
|
||||
|
||||
/*
|
||||
if (sectionName == "BA_") { return tokSectionBa; }
|
||||
if (sectionName == "BA_REL_") { return tokSectionBaRel; }
|
||||
if (sectionName == "BA_DEF_") { return tokSectionBaDef; }
|
||||
if (sectionName == "BA_DEF_DEF_") { return tokSectionBaDefDef; }
|
||||
if (sectionName == "BA_DEF_DEF_REL_") { return tokSectionBaDefDefRel; }
|
||||
*/
|
||||
}
|
||||
|
||||
bool DbcParser::parseSectionVersion(CanDb &candb, DbcTokenList &tokens)
|
||||
{
|
||||
QString version;
|
||||
if (!expectString(tokens, &version)) { return false; }
|
||||
candb.setVersion(version);
|
||||
return expectSectionEnding(tokens);
|
||||
}
|
||||
|
||||
bool DbcParser::parseSectionBs(DbcParser::DbcTokenList &tokens)
|
||||
{
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_colon)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return expectSectionEnding(tokens);
|
||||
}
|
||||
|
||||
bool DbcParser::parseSectionBu(CanDb &candb, DbcParser::DbcTokenList &tokens)
|
||||
{
|
||||
QStringList strings;
|
||||
QString s;
|
||||
|
||||
if (!parseIdentifierList(tokens, &strings, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(s, strings) {
|
||||
candb.getOrCreateNode(s);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DbcParser::parseSectionBo(CanDb &candb, DbcTokenList &tokens)
|
||||
{
|
||||
long long can_id;
|
||||
int dlc;
|
||||
QString msg_name;
|
||||
QString sender;
|
||||
|
||||
if (!expectLongLong(tokens, &can_id)) { return false; }
|
||||
if (!expectIdentifier(tokens, &msg_name)) { return false; }
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_colon)) { return false; }
|
||||
if (!expectInt(tokens, &dlc)) { return false; }
|
||||
if (!expectIdentifier(tokens, &sender)) { return false; }
|
||||
|
||||
CanDbMessage *msg = new CanDbMessage(&candb);
|
||||
msg->setRaw_id(can_id);
|
||||
msg->setName(msg_name);
|
||||
msg->setDlc(dlc);
|
||||
msg->setSender(candb.getOrCreateNode(sender));
|
||||
candb.addMessage(msg);
|
||||
|
||||
QString subsect;
|
||||
while (true) {
|
||||
if (expectSectionEnding(tokens)) {
|
||||
return true;
|
||||
} else {
|
||||
if (!expectIdentifier(tokens, &subsect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subsect!="SG_") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parseSectionBoSg(candb, msg, tokens)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool DbcParser::parseSectionBoSg(CanDb &candb, CanDbMessage *msg, DbcTokenList &tokens)
|
||||
{
|
||||
(void)candb;
|
||||
|
||||
QString signal_name;
|
||||
QString mux_indicator;
|
||||
int start_bit = 0;
|
||||
int length = 0;
|
||||
int byte_order = 0;
|
||||
double factor = 1;
|
||||
double offset = 0;
|
||||
double minimum = 0;
|
||||
double maximum = 0;
|
||||
QString unit;
|
||||
QString receiver;
|
||||
QStringList receivers;
|
||||
|
||||
CanDbSignal *signal = new CanDbSignal(msg);
|
||||
msg->addSignal(signal);
|
||||
|
||||
if (!expectIdentifier(tokens, &signal_name)) { return false; }
|
||||
signal->setName(signal_name);
|
||||
|
||||
|
||||
if (expectIdentifier(tokens, &mux_indicator)) {
|
||||
if (mux_indicator=="M") {
|
||||
signal->setIsMuxer(true);
|
||||
msg->setMuxer(signal);
|
||||
} else if (mux_indicator.startsWith('m')) {
|
||||
signal->setIsMuxed(true);
|
||||
bool ok;
|
||||
signal->setMuxValue(mux_indicator.mid(1).toUInt(&ok));
|
||||
if (!ok) { return false; }
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_colon)) { return false; }
|
||||
if (!expectInt(tokens, &start_bit)) { return false; }
|
||||
|
||||
signal->setStartBit(start_bit);
|
||||
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_pipe)) { return false; }
|
||||
if (!expectInt(tokens, &length)) { return false; }
|
||||
signal->setLength(length);
|
||||
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_at)) { return false; }
|
||||
if (!expectInt(tokens, &byte_order)) { return false; }
|
||||
signal->setIsBigEndian(byte_order==0);
|
||||
|
||||
// If the signal is big endian, convert the start bit to the Intel-style start bit for further parsing
|
||||
if(signal->isBigEndian())
|
||||
{
|
||||
// This will be the number of 8-bit rows above the message
|
||||
uint8_t row_position = signal->startBit() >> 3;
|
||||
|
||||
// Bit position in current row (0-7)
|
||||
uint8_t column_position = signal->startBit() & 0b111;
|
||||
|
||||
// Calcualte the normalized start bit position (bit index starting at 0)
|
||||
uint8_t normalized_position = (row_position * 8) + (7 - column_position);
|
||||
|
||||
signal->setStartBit(normalized_position);
|
||||
}
|
||||
|
||||
if (expectAndSkipToken(tokens, dbc_tok_plus)) {
|
||||
signal->setUnsigned(true);
|
||||
} else {
|
||||
if (expectAndSkipToken(tokens, dbc_tok_minus)) {
|
||||
signal->setUnsigned(false);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_parenth_open)) { return false; }
|
||||
if (!expectDouble(tokens, &factor)) { return false; }
|
||||
signal->setFactor(factor);
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_comma)) { return false; }
|
||||
if (!expectDouble(tokens, &offset)) { return false; }
|
||||
signal->setOffset(offset);
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_parenth_close)) { return false; }
|
||||
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_bracket_open)) { return false; }
|
||||
if (!expectDouble(tokens, &minimum)) { return false; }
|
||||
signal->setMinimumValue(minimum);
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_pipe)) { return false; }
|
||||
if (!expectDouble(tokens, &maximum)) { return false; }
|
||||
signal->setMaximumValue(maximum);
|
||||
if (!expectAndSkipToken(tokens, dbc_tok_bracket_close)) { return false; }
|
||||
|
||||
if (!expectString(tokens, &unit)) { return false; }
|
||||
signal->setUnit(unit);
|
||||
|
||||
if (!expectIdentifier(tokens, &receiver)) { return false; }
|
||||
receivers.append(receiver);
|
||||
|
||||
while (expectAndSkipToken(tokens, dbc_tok_comma, false, false)) {
|
||||
if (!expectIdentifier(tokens, &receiver)) { return false; }
|
||||
receivers.append(receiver);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DbcParser::parseSectionCm(CanDb &candb, DbcParser::DbcTokenList &tokens)
|
||||
{
|
||||
QString s;
|
||||
QString idtype;
|
||||
QString id;
|
||||
long long ll;
|
||||
|
||||
if (expectString(tokens, &s)) { // DBC file comment
|
||||
candb.setComment(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!expectIdentifier(tokens, &idtype)) { return false; }
|
||||
|
||||
if (idtype=="BU_") {
|
||||
|
||||
if (!expectIdentifier(tokens, &id)) { return false; }
|
||||
if (!expectString(tokens, &s)) { return false; }
|
||||
candb.getOrCreateNode(id)->setComment(s);
|
||||
return expectSectionEnding(tokens);
|
||||
|
||||
} else if (idtype=="BO_") {
|
||||
|
||||
if (!expectLongLong(tokens, &ll)) { return false; }
|
||||
if (!expectString(tokens, &s)) { return false; }
|
||||
CanDbMessage *msg = candb.getMessageById(ll);
|
||||
if (!msg) { return false; }
|
||||
msg->setComment(s);
|
||||
return expectSectionEnding(tokens);
|
||||
|
||||
} else if (idtype=="SG_") {
|
||||
|
||||
if (!expectLongLong(tokens, &ll)) { return false; }
|
||||
CanDbMessage *msg = candb.getMessageById(ll);
|
||||
if (!msg) { return false; }
|
||||
|
||||
if (!expectIdentifier(tokens, &id)) { return false; }
|
||||
CanDbSignal *signal = msg->getSignalByName(id);
|
||||
if (!signal) { return false; }
|
||||
|
||||
if (!expectString(tokens, &s)) { return false; }
|
||||
signal->setComment(s);
|
||||
|
||||
return expectSectionEnding(tokens);
|
||||
|
||||
} else {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool DbcParser::parseSectionVal(CanDb &candb, DbcParser::DbcTokenList &tokens)
|
||||
{
|
||||
long long can_id;
|
||||
QString signal_id;
|
||||
long long value;
|
||||
QString name;
|
||||
|
||||
if (!expectLongLong(tokens, &can_id)) { return false; }
|
||||
CanDbMessage *msg = candb.getMessageById(can_id);
|
||||
if (!msg) { return false; }
|
||||
|
||||
if (!expectIdentifier(tokens, &signal_id)) { return false; }
|
||||
CanDbSignal *signal = msg->getSignalByName(signal_id);
|
||||
if (!signal) { return false; }
|
||||
|
||||
while (!expectAndSkipToken(tokens, dbc_tok_semicolon)) {
|
||||
if (!expectLongLong(tokens, &value)) { return false; }
|
||||
if (!expectString(tokens, &name)) { return false; }
|
||||
signal->setValueName(value, name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user