Skip to content

Commit

Permalink
PmtYaml: Fix parsing of maps in lists
Browse files Browse the repository at this point in the history
Make sure block-style maps in block-style lists are parsed correctly.
This is needed to parse our existing GRC files.

Signed-off-by: Frank Osterfeld <frank.osterfeld@kdab.com>
  • Loading branch information
frankosterfeld committed Dec 3, 2024
1 parent 4829478 commit 7496797
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
26 changes: 21 additions & 5 deletions core/include/gnuradio-4.0/YamlPmt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ struct ParseContext {

bool atEndOfDocument() const { return lineIdx == lines.size(); }

std::size_t currentIndent() const { return lines[lineIdx].find_first_not_of(' '); }
std::size_t currentIndent(std::string_view indentChars = " ") const { return lines[lineIdx].find_first_not_of(indentChars); }

ParseError makeError(std::string message) const { return {.line = lineIdx + 1, .column = columnIdx + 1, .message = std::move(message)}; }

Expand Down Expand Up @@ -950,7 +950,7 @@ inline std::expected<pmtv::map_t, ParseError> parseMap(ParseContext& ctx, int pa
continue;
}

const auto line_indent = ctx.currentIndent();
const auto line_indent = ctx.currentIndent(" -"); // Ignore "-" if map is in a list

if (parentIndentLevel >= 0 && line_indent <= static_cast<std::size_t>(parentIndentLevel)) {
// indentation decreased; end of current map
Expand Down Expand Up @@ -1042,7 +1042,23 @@ inline std::expected<pmtv::pmt, ParseError> parseList(ParseContext& ctx, std::st

ctx.consumeSpaces();

const auto tagPos = ctx.columnIdx;
const auto itemIndent = ctx.columnIdx;

auto hasKey = [](const ParseContext& context) {
auto tmpCtx = context;
return parseKey(tmpCtx).has_value();
};

if (hasKey(ctx)) {
// block-style map as list item
auto value = parseMap(ctx, static_cast<int>(itemIndent) - 1);
if (!value.has_value()) {
return std::unexpected(value.error());
}
list.push_back(value.value());
continue;
}

const auto maybeLocalTag = parseTag(ctx);
if (!maybeLocalTag.has_value()) {
return std::unexpected(maybeLocalTag.error());
Expand All @@ -1060,7 +1076,7 @@ inline std::expected<pmtv::pmt, ParseError> parseList(ParseContext& ctx, std::st
switch (peekedType) {
case ValueType::List: {
if (!typeTag.empty()) {
return std::unexpected(ctx.makeErrorAtColumn("Cannot have type tag for list containing lists", tagPos));
return std::unexpected(ctx.makeErrorAtColumn("Cannot have type tag for list containing lists", itemIndent));
}
auto parsedValue = parseList(ctx, tag, static_cast<int>(line_indent));
if (!parsedValue.has_value()) {
Expand All @@ -1071,7 +1087,7 @@ inline std::expected<pmtv::pmt, ParseError> parseList(ParseContext& ctx, std::st
}
case ValueType::Map: {
if (!localTag.empty()) {
return std::unexpected(ctx.makeErrorAtColumn("Cannot have type tag for maps", tagPos));
return std::unexpected(ctx.makeErrorAtColumn("Cannot have type tag for maps", itemIndent));
}
auto parsedValue = parseMap(ctx, static_cast<int>(line_indent));
if (!parsedValue.has_value()) {
Expand Down
6 changes: 6 additions & 0 deletions core/test/qa_YamlPmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,11 @@ flowMultiline: !!str [ "Hello, " , #]
- !!str [3, 4]
- { key: !!str [5, 6] }
nestedFlow: [ !!str [1, 2], [3, 4] ]
vectorWithBlockMap:
- name: ArraySink<double>
id: ArraySink
parameters:
name: Block
)";

pmtv::map_t expected;
Expand All @@ -498,6 +503,7 @@ nestedFlow: [ !!str [1, 2], [3, 4] ]
expected["nestedVector"] = std::vector<pmtv::pmt>{std::vector<std::string>{"1", "2"}, std::vector<pmtv::pmt>{static_cast<int64_t>(3), static_cast<int64_t>(4)}};
expected["nestedFlow"] = std::vector<pmtv::pmt>{std::vector<std::string>{"1", "2"}, std::vector<pmtv::pmt>{static_cast<int64_t>(3), static_cast<int64_t>(4)}};
expected["nestedVector2"] = std::vector<pmtv::pmt>{static_cast<int64_t>(42), std::vector<std::string>{"1", "2"}, std::vector<std::string>{"3", "4"}, pmtv::map_t{{"key", std::vector<std::string>{"5", "6"}}}};
expected["vectorWithBlockMap"] = std::vector<pmtv::pmt>{pmtv::map_t{{"name", "ArraySink<double>"}, {"id", "ArraySink"}, {"parameters", pmtv::map_t{{"name", "Block"}}}}};

testYAML(src1, expected);

Expand Down

0 comments on commit 7496797

Please sign in to comment.