diff --git a/DbcParserLib.Tests/ValueTableLineParserTests.cs b/DbcParserLib.Tests/ValueTableLineParserTests.cs index d79ae14..efc44c3 100644 --- a/DbcParserLib.Tests/ValueTableLineParserTests.cs +++ b/DbcParserLib.Tests/ValueTableLineParserTests.cs @@ -320,11 +320,11 @@ public void ValueTableEnvironmentNameNotFoundErrorIsObserved() lineParser.TryParse(line, dbcBuilder, nextLineProviderMock.Object); } - [TestCase("VAL_TABLE_ tableName 0 \"Running\" 1 \"Idle\";")] [TestCase("VAL_TABLE_ tableName 0 \"Running\" 1 \"Idle\"")] [TestCase("VAL_TABLE_ tableName 0 \"Running\" 1 Idle;")] [TestCase("VAL_TABLE_ \"tableName\" 0 \"Running\" 1 \"Idle\" ;")] [TestCase("VAL_TABLE_ tableName 0 \"Running\" 1.5 \"Idle\" ;")] + [TestCase("VAL_TABLE_ tableName 0 \"Running\"1 \"Idle\";")] public void ValueTableDefinitionSyntaxErrorIsObserved(string line) { var observerMock = m_repository.Create(); @@ -368,5 +368,20 @@ public void ValueTableDefinitionContainsAdditionalSpacesBeforeSemicolon() Assert.That(lineParser.TryParse(line, dbcBuilder, nextLineProviderMock.Object), Is.True); } + + [Test] + public void ValueTableDefinitionContainsNoSpacesBeforeSemicolon() + { + var tableName = "tableName"; + var line = $"VAL_TABLE_ {tableName} 0 \"Running\" 1 \"Idle\";"; + + var observerMock = m_repository.Create(); + var nextLineProviderMock = m_repository.Create(); + var dbcBuilder = new DbcBuilder(observerMock.Object); + + var lineParser = new ValueTableDefinitionLineParser(observerMock.Object); + + Assert.That(lineParser.TryParse(line, dbcBuilder, nextLineProviderMock.Object), Is.True); + } } } \ No newline at end of file diff --git a/DbcParserLib/Parsers/ValueTableDefinitionLineParser.cs b/DbcParserLib/Parsers/ValueTableDefinitionLineParser.cs index 1e823bf..b14df12 100644 --- a/DbcParserLib/Parsers/ValueTableDefinitionLineParser.cs +++ b/DbcParserLib/Parsers/ValueTableDefinitionLineParser.cs @@ -7,9 +7,11 @@ internal class ValueTableDefinitionLineParser : ILineParser { private const string ValTableGroup = "ValTableName"; private const string ValueDescriptionGroup = "ValueDescription"; + private const string EndValeDescriptionGroup = "ValueDescriptionEnd"; private const string ValueTableDefinitionLineStarter = "VAL_TABLE_ "; - private readonly string m_valueTableDefinitionParsingRegex = $@"VAL_TABLE_\s+(?<{ValTableGroup}>[a-zA-Z_][\w]*)\s+(?<{ValueDescriptionGroup}>(?:\d+\s+(?:""[^""]*"")\s+)*)\s*;"; + private readonly string m_valueTableDefinitionParsingRegex = $@"VAL_TABLE_\s+(?<{ValTableGroup}>[a-zA-Z_][\w]*)\s+" + + $@"(?<{ValueDescriptionGroup}>(?:\d+\s+(?:""[^""]*"")\s+)*)(?<{EndValeDescriptionGroup}>(?:\d+\s+(?:""[^""]*"")\s*));"; private readonly IParseFailureObserver m_observer; @@ -23,19 +25,31 @@ public bool TryParse(string line, IDbcBuilder builder, INextLineProvider nextLin var cleanLine = line.Trim(' '); if (cleanLine.StartsWith(ValueTableDefinitionLineStarter) == false) + { return false; + } var match = Regex.Match(cleanLine, m_valueTableDefinitionParsingRegex); if (match.Success) { - if (match.Groups[ValueDescriptionGroup].Value.TryParseToDict(out var valueTableDictionary)) + var dictionary = string.IsNullOrEmpty(match.Groups[ValueDescriptionGroup].Value) + ? match.Groups[EndValeDescriptionGroup].Value + : string.Concat(match.Groups[ValueDescriptionGroup].Value, match.Groups[EndValeDescriptionGroup].Value); + + if (!string.IsNullOrEmpty(dictionary) && dictionary.TryParseToDict(out var valueTableDictionary)) + { builder.AddNamedValueTable(match.Groups[ValTableGroup].Value, valueTableDictionary); + } else + { m_observer.ValueTableDefinitionSyntaxError(); + } } else + { m_observer.ValueTableDefinitionSyntaxError(); - + } + return true; } }