allow nested data desc with dots and create the nodes
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user