allow nested data desc with dots and create the nodes

This commit is contained in:
T0b1
2024-05-13 03:46:04 +02:00
parent aa80d690d9
commit 894ff6a408

View File

@@ -694,6 +694,9 @@ namespace
Frontend *frontend;
std::string_view buf;
std::vector<char> literal_buf;
std::optional<WatchToken> peek_token;
std::string path_buf{};
std::vector<data::source::Node> nodes{};
};
@@ -742,6 +745,13 @@ namespace
std::optional<WatchToken> next_token(ParseState &state)
{
if (state.peek_token)
{
const auto token = *state.peek_token;
state.peek_token.reset();
return token;
}
if (state.buf.empty())
{
spdlog::trace("Token buffer empty");
@@ -783,7 +793,7 @@ namespace
state.literal_buf.insert(state.literal_buf.end(), state.buf.begin(),
literal_end);
state.literal_buf.push_back('\0');
state.buf.remove_prefix(literal_end - state.buf.begin() + 1);
state.buf.remove_prefix(literal_end - state.buf.begin());
return WatchToken{static_cast<uint32_t>(WatchToken::literal_bit)
| static_cast<uint32_t>(idx)};
@@ -791,6 +801,24 @@ namespace
}
}
std::optional<WatchToken> peek_token(ParseState &state)
{
if (state.peek_token)
{
return *state.peek_token;
}
const auto token = next_token(state);
if (!token)
{
return {};
}
state.peek_token = token;
return token;
}
// <data desc> = <data desc>.<data desc> | <array desc> | <ident> | <reg>
std::optional<size_t> parse_data_desc(ParseState &state)
{
const auto token_opt = next_token(state);
@@ -803,6 +831,7 @@ namespace
spdlog::trace("Parsing data_desc: Token {}", token_to_str(state, token));
// check for register
// <reg> = $<ident>
if (token == WatchToken::dollar)
{
spdlog::trace("Parsing register");
@@ -870,13 +899,73 @@ namespace
spdlog::trace("Created register node with id {}", node_id);
return node_id;
}
// <data desc>, <array desc> and <ident> expect an identifier now
if (!token_is_literal(token))
{
spdlog::trace("Failed to parse data_desc: expected identifier, got {}",
token_to_str(state, token));
return {};
}
const auto ident = token_literal(state, token);
spdlog::trace("Parsing data_desc: got ident {}", ident);
if (!state.path_buf.empty())
{
state.path_buf.push_back('.');
}
state.path_buf.append(ident);
// differentiate between <data desc>, <array desc> and end of <data desc>
const auto peek_token_opt = peek_token(state);
if (peek_token_opt)
{
const auto peek_token = *peek_token_opt;
spdlog::trace("Parsing data_desc: peek token {}",
token_to_str(state, peek_token));
if (peek_token == WatchToken::dot)
{
// nested <data desc>
// consume the token
next_token(state);
return parse_data_desc(state);
}
if (peek_token == WatchToken::bracket_open)
{
// TODO: parse <array desc>
assert(0);
return {};
}
}
spdlog::trace("Parsing data_desc: creating variable source with path {}",
state.path_buf);
// something else, end of <data desc>
auto node_id = state.frontend->target->data_node_id++;
state.nodes.push_back(data::source::Node{
.id = node_id,
.type = data::source::Node::Type::source,
.data =
data::source::Source{
.type = data::source::Source::Type::variable,
.data =
data::source::Source::Variable{
.expr_path = state.path_buf,
.address_of_or_pointer = false,
},
},
});
return node_id;
}
} // namespace
void WatchWindow::create_node_for_extra_slot(Frontend &frontend,
const size_t slot_idx)
{
const auto &slot = extra_slots[slot_idx];
auto &slot = extra_slots[slot_idx];
auto parse_state = ParseState{
.frontend = &frontend,
@@ -884,13 +973,29 @@ void WatchWindow::create_node_for_extra_slot(Frontend &frontend,
.literal_buf = {},
};
assert(0);
const auto top_node_id = parse_data_desc(parse_state);
if (!top_node_id)
{
spdlog::warn("Error parsing expression path '{}' for slot {}", slot.buf,
slot_idx);
return;
}
using namespace data::source;
frontend.target->backend->add_data_node(Node{
.id = slot.id,
.type = Node::Type::source,
.data = Source{.type = Source::Type::variable,
.data = Source::Variable{.expr_path = slot.buf,
.address_of_or_pointer = false}}});
if (!parse_state.buf.empty())
{
spdlog::warn(
"Error parsing expression path '{}' for slot {}: trailing data '{}'",
slot.buf, slot_idx, parse_state.buf);
return;
}
// TODO: assert node ordering
for (auto idx = 0; idx < parse_state.nodes.size(); ++idx)
{
const auto &node = parse_state.nodes[idx];
frontend.target->backend->add_data_node(node);
}
slot.id = *top_node_id;
}