Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#81 Empty node list is now supported. Regex refactoring #83

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion DbcParserLib.Tests/NodeLineParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ private static ILineParser CreateParser()
return new NodeLineParser(new SilentFailureObserver());
}

[Test]
public void EmptyNodeListIsAccepted()
{
var dbcBuilderMock = m_repository.Create<IDbcBuilder>();
var nodeLineParser = CreateParser();
var nextLineProviderMock = m_repository.Create<INextLineProvider>();

Assert.That(nodeLineParser.TryParse(" BU_: ", dbcBuilderMock.Object, nextLineProviderMock.Object), Is.True);
}

[Test]
public void EmptyCommentLineIsIgnored()
{
Expand Down Expand Up @@ -95,7 +105,6 @@ public void FullLineIsParsed()

[TestCase("BU_: 0nodeName")]
[TestCase("BU_:nodeName")]
[TestCase("BU_:")]
public void NodeSyntaxErrorIsObserved(string line)
{
var observerMock = m_repository.Create<IParseFailureObserver>();
Expand Down
42 changes: 24 additions & 18 deletions DbcParserLib/Parsers/CommentLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ namespace DbcParserLib.Parsers
{
internal class CommentLineParser : ILineParser
{
private const string CharGroup = "CharString";
private const string NodeNameGroup = "NodeName";
private const string MessageIdGroup = "MessageId";
private const string SignalNameGroup = "SignalName";
private const string EnvVarNameGroup = "EnvVarName";
private const string CommentLineStarter = "CM_ ";
private const string GenericCommentParsingRegex = @"CM_\s+""*([^""]*)""*\s*;";
private const string NodeParsingRegex = @"CM_ BU_\s+([a-zA-Z_][\w]*)\s+""*([^""]*)""*\s*;";
private const string MessageParsingRegex = @"CM_ BO_\s+(\d+)\s+""*([^""]*)""*\s*;";
private const string SignalParsingRegex = @"CM_ SG_\s+(\d+)\s+([a-zA-Z_][\w]*)\s+""*([^""]*)""*\s*;";
private const string EnvironmentVariableParsingRegex = @"CM_ EV_\s+([a-zA-Z_][\w]*)\s+""*([^""]*)""*\s*;";

private readonly string m_genericCommentParsingRegex = $@"CM_\s+""*(?<{CharGroup}>[^""]*)""*\s*;";
private readonly string m_nodeParsingRegex = $@"CM_ BU_\s+(?<{NodeNameGroup}>[a-zA-Z_][\w]*)\s+""*(?<{CharGroup}>[^""]*)""*\s*;";
private readonly string m_messageParsingRegex = $@"CM_ BO_\s+(?<{MessageIdGroup}>\d+)\s+""*(?<{CharGroup}>[^""]*)""*\s*;";
private readonly string m_signalParsingRegex = $@"CM_ SG_\s+(?<{MessageIdGroup}>\d+)\s+(?<{SignalNameGroup}>[a-zA-Z_][\w]*)\s+""*(?<{CharGroup}>[^""]*)""*\s*;";
private readonly string m_environmentVariableParsingRegex = $@"CM_ EV_\s+(?<{EnvVarNameGroup}>[a-zA-Z_][\w]*)\s+""*(?<{CharGroup}>[^""]*)""*\s*;";

private readonly IParseFailureObserver m_observer;

Expand Down Expand Up @@ -54,50 +60,50 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin
return true;
}

var match = Regex.Match(cleanLine, GenericCommentParsingRegex);
var match = Regex.Match(cleanLine, m_genericCommentParsingRegex);
if (match.Success)
return true;

m_observer.CommentSyntaxError();
return true;
}

private static void SetSignalComment(string sigCommentStr, IParseFailureObserver observer, IDbcBuilder builder, INextLineProvider nextLineProvider)
private void SetSignalComment(string sigCommentStr, IParseFailureObserver observer, IDbcBuilder builder, INextLineProvider nextLineProvider)
{
var match = Regex.Match(sigCommentStr, SignalParsingRegex);
var match = Regex.Match(sigCommentStr, m_signalParsingRegex);

if (match.Success)
builder.AddSignalComment(uint.Parse(match.Groups[1].Value), match.Groups[2].Value, match.Groups[3].Value);
builder.AddSignalComment(uint.Parse(match.Groups[MessageIdGroup].Value), match.Groups[SignalNameGroup].Value, match.Groups[CharGroup].Value);
else
observer.CommentSyntaxError();
}

private static void SetNodeComment(string sigCommentStr, IParseFailureObserver observer, IDbcBuilder builder, INextLineProvider nextLineProvider)
private void SetNodeComment(string sigCommentStr, IParseFailureObserver observer, IDbcBuilder builder, INextLineProvider nextLineProvider)
{
var match = Regex.Match(sigCommentStr, NodeParsingRegex);
var match = Regex.Match(sigCommentStr, m_nodeParsingRegex);

if (match.Success)
builder.AddNodeComment(match.Groups[1].Value, match.Groups[2].Value);
builder.AddNodeComment(match.Groups[NodeNameGroup].Value, match.Groups[CharGroup].Value);
else
observer.CommentSyntaxError();
}

private static void SetMessageComment(string sigCommentStr, IParseFailureObserver observer, IDbcBuilder builder, INextLineProvider nextLineProvider)
private void SetMessageComment(string sigCommentStr, IParseFailureObserver observer, IDbcBuilder builder, INextLineProvider nextLineProvider)
{
var match = Regex.Match(sigCommentStr, MessageParsingRegex);
var match = Regex.Match(sigCommentStr, m_messageParsingRegex);

if (match.Success)
builder.AddMessageComment(uint.Parse(match.Groups[1].Value), match.Groups[2].Value);
builder.AddMessageComment(uint.Parse(match.Groups[MessageIdGroup].Value), match.Groups[CharGroup].Value);
else
observer.CommentSyntaxError();
}

private static void SetEnvironmentVariableComment(string envCommentStr, IParseFailureObserver observer, IDbcBuilder builder)
private void SetEnvironmentVariableComment(string envCommentStr, IParseFailureObserver observer, IDbcBuilder builder)
{
var match = Regex.Match(envCommentStr, EnvironmentVariableParsingRegex);
var match = Regex.Match(envCommentStr, m_environmentVariableParsingRegex);

if (match.Success)
builder.AddEnvironmentVariableComment(match.Groups[1].Value, match.Groups[2].Value);
builder.AddEnvironmentVariableComment(match.Groups[EnvVarNameGroup].Value, match.Groups[CharGroup].Value);
else
observer.CommentSyntaxError();
}
Expand Down
11 changes: 7 additions & 4 deletions DbcParserLib/Parsers/EnvironmentDataVariableLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ namespace DbcParserLib.Parsers
{
internal class EnvironmentDataVariableLineParser : ILineParser
{
private const string NameGroup = "Name";
private const string DataSizeGroup = "DataSize";
private const string EnvironmentDataVariableLineStarter = "ENVVAR_DATA_ ";
private const string EnvironmentDataVariableParsingRegex = @"ENVVAR_DATA_\s+([a-zA-Z_][\w]*)\s*:\s+(\d+)\s*;";

private readonly string m_environmentDataVariableParsingRegex = $@"ENVVAR_DATA_\s+(?<{NameGroup}>[a-zA-Z_][\w]*)\s*:\s+(?<{DataSizeGroup}>\d+)\s*;";

private readonly IParseFailureObserver m_observer;

Expand All @@ -22,12 +25,12 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin
if (cleanLine.StartsWith(EnvironmentDataVariableLineStarter) == false)
return false;

var match = Regex.Match(cleanLine, EnvironmentDataVariableParsingRegex);
var match = Regex.Match(cleanLine, m_environmentDataVariableParsingRegex);
if (match.Success)
builder.AddEnvironmentDataVariable(match.Groups[1].Value, uint.Parse(match.Groups[2].Value));
builder.AddEnvironmentDataVariable(match.Groups[NameGroup].Value, uint.Parse(match.Groups[DataSizeGroup].Value));
else
m_observer.EnvironmentDataVariableSyntaxError();

return true;
}
}
Expand Down
47 changes: 30 additions & 17 deletions DbcParserLib/Parsers/EnvironmentVariableLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,21 @@ namespace DbcParserLib.Parsers
{
internal class EnvironmentVariableLineParser : ILineParser
{
private const string NameGroup = "Name";
private const string VarTypeGroup = "VarType";
private const string MinGroup = "Min";
private const string MaxGroup = "Max";
private const string UnitGroup = "Unit";
private const string InitialValueGroup = "InitialValue";
private const string VarId = "VarId";
private const string StringDataTypeGroup = "StringDataType";
private const string AccessibilityGroup = "Accessibility2";
private const string NodeGroup = "Node";
private const string EnvironmentVariableLineStarter = "EV_ ";
private const string EnvironmentVariableParsingRegex = @"EV_\s+([a-zA-Z_][\w]*)\s*:\s+([012])\s+\[([\d\+\-eE.]+)\|([\d\+\-eE.]+)\]\s+""([^""]*)""\s+([\d\+\-eE.]+)\s+(\d+)\s+DUMMY_NODE_VECTOR(800){0,1}([0123])\s+((?:[a-zA-Z_][\w]*)(?:,[a-zA-Z_][\w]*)*)\s*;";

private readonly string m_environmentVariableParsingRegex = $@"EV_\s+(?<{NameGroup}>[a-zA-Z_][\w]*)\s*:\s+(?<{VarTypeGroup}>[012])\s+\[(?<{MinGroup}>[\d\+\-eE.]+)\|(?<{MaxGroup}>[\d\+\-eE.]+)\]" +
$@"\s+""(?<{UnitGroup}>[^""]*)""\s+(?<{InitialValueGroup}>[\d\+\-eE.]+)\s+(?<{VarId}>\d+)\s+DUMMY_NODE_VECTOR(?<{StringDataTypeGroup}>800){{0,1}}" +
$@"(?<{AccessibilityGroup}>[0123])\s+(?<{NodeGroup}>(?:[a-zA-Z_][\w]*)(?:,[a-zA-Z_][\w]*)*)\s*;";

private readonly IParseFailureObserver m_observer;

Expand All @@ -23,16 +36,16 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin
if (cleanLine.StartsWith(EnvironmentVariableLineStarter) == false)
return false;

var match = Regex.Match(cleanLine, EnvironmentVariableParsingRegex);
var match = Regex.Match(cleanLine, m_environmentVariableParsingRegex);
if (match.Success)
{
var environmentVariable = new EnvironmentVariable()
{
Name = match.Groups[1].Value,
Unit = match.Groups[5].Value,
Name = match.Groups[NameGroup].Value,
Unit = match.Groups[UnitGroup].Value,
};

switch (uint.Parse(match.Groups[9].Value))
switch (uint.Parse(match.Groups[AccessibilityGroup].Value))
{
case 0:
environmentVariable.Access = EnvAccessibility.Unrestricted;
Expand All @@ -48,30 +61,30 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin
break;
}

if (match.Groups[8].Value == "800")
if (match.Groups[StringDataTypeGroup].Value == "800")
{
environmentVariable.Type = EnvDataType.String;
}
else
{
switch (uint.Parse(match.Groups[2].Value))
switch (uint.Parse(match.Groups[VarTypeGroup].Value))
{
case 0:
environmentVariable.Type = EnvDataType.Integer;
environmentVariable.IntegerEnvironmentVariable = new NumericEnvironmentVariable<int>()
{
Minimum = int.Parse(match.Groups[3].Value),
Maximum = int.Parse(match.Groups[4].Value),
Default = int.Parse(match.Groups[6].Value)
Minimum = int.Parse(match.Groups[MinGroup].Value),
Maximum = int.Parse(match.Groups[MaxGroup].Value),
Default = int.Parse(match.Groups[InitialValueGroup].Value)
};
break;
case 1:
environmentVariable.Type = EnvDataType.Float;
environmentVariable.FloatEnvironmentVariable = new NumericEnvironmentVariable<double>()
{
Minimum = double.Parse(match.Groups[3].Value),
Maximum = double.Parse(match.Groups[4].Value),
Default = double.Parse(match.Groups[6].Value)
Minimum = double.Parse(match.Groups[MinGroup].Value),
Maximum = double.Parse(match.Groups[MaxGroup].Value),
Default = double.Parse(match.Groups[InitialValueGroup].Value)
};
break;
case 2:
Expand All @@ -80,17 +93,17 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin
}
}

builder.AddEnvironmentVariable(match.Groups[1].Value, environmentVariable);
builder.AddEnvironmentVariable(match.Groups[NameGroup].Value, environmentVariable);

var nodes = match.Groups[10].Value.Split(',');
var nodes = match.Groups[NodeGroup].Value.Split(',');
foreach (var node in nodes)
{
builder.AddNodeEnvironmentVariable(node, match.Groups[1].Value);
builder.AddNodeEnvironmentVariable(node, match.Groups[NameGroup].Value);
}
}
else
m_observer.EnvironmentVariableSyntaxError();

return true;
}
}
Expand Down
27 changes: 16 additions & 11 deletions DbcParserLib/Parsers/MessageLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ namespace DbcParserLib.Parsers
{
internal class MessageLineParser : ILineParser
{
private const string IdGroup = "Id";
private const string NameGroup = "Name";
private const string SizeGroup = "Size";
private const string TransmitterGroup = "Transmitter";
private const string MessageLineStarter = "BO_ ";
private const string MessageRegex = @"BO_ (\d+)\s+([a-zA-Z_][\w]*)\s*:\s*(\d+)\s+([a-zA-Z_][\w]*)";

private readonly string m_messageRegex = $@"BO_ (?<{IdGroup}>\d+)\s+(?<{NameGroup}>[a-zA-Z_][\w]*)\s*:\s*(?<{SizeGroup}>\d+)\s+(?<{TransmitterGroup}>[a-zA-Z_][\w]*)";

private readonly IParseFailureObserver m_observer;

Expand All @@ -19,25 +24,25 @@ public MessageLineParser(IParseFailureObserver observer)

public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLineProvider)
{
if(line.Trim().StartsWith(MessageLineStarter) == false)
if (line.Trim().StartsWith(MessageLineStarter) == false)
return false;
var match = Regex.Match(line, MessageRegex);
if(match.Success)

var match = Regex.Match(line, m_messageRegex);
if (match.Success)
{
var msg = new Message()
{
Name = match.Groups[2].Value,
DLC = ushort.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture),
Transmitter = match.Groups[4].Value,
ID = uint.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture)
Name = match.Groups[NameGroup].Value,
DLC = ushort.Parse(match.Groups[SizeGroup].Value, CultureInfo.InvariantCulture),
Transmitter = match.Groups[TransmitterGroup].Value,
ID = uint.Parse(match.Groups[IdGroup].Value, CultureInfo.InvariantCulture)
};

builder.AddMessage(msg);
}
else
m_observer.MessageSyntaxError();

return true;
}
}
Expand Down
14 changes: 11 additions & 3 deletions DbcParserLib/Parsers/NodeLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,33 @@ namespace DbcParserLib.Parsers
{
internal class NodeLineParser : ILineParser
{
private const string NameGroup = "Name";
private const string NodeLineStarter = "BU_:";
private const string NodeLineParsingRegex = @"BU_:((?:\s+(?:[a-zA-Z_][\w]*))+)";

private readonly string m_nodeLineParsingRegex = $@"BU_:(?<{NameGroup}>(?:\s+(?:[a-zA-Z_][\w]*))+)";

private readonly IParseFailureObserver m_observer;
private readonly Regex m_regex;

public NodeLineParser(IParseFailureObserver observer)
{
m_observer = observer;
m_regex = new Regex(m_nodeLineParsingRegex);
}

public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLineProvider)
{
if (line.TrimStart().StartsWith(NodeLineStarter) == false)
return false;

var match = Regex.Match(line, NodeLineParsingRegex);
// Empty node list
if (line.Trim().Equals(NodeLineStarter))
return true;

var match = m_regex.Match(line);
if (match.Success)
{
foreach (var nodeName in match.Groups[1].Value.TrimStart().SplitBySpace())
foreach (var nodeName in match.Groups[NameGroup].Value.TrimStart().SplitBySpace())
{
var node = new Node()
{
Expand Down
Loading
Loading