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; Frontend *frontend;
std::string_view buf; std::string_view buf;
std::vector<char> literal_buf; std::vector<char> literal_buf;
std::optional<WatchToken> peek_token;
std::string path_buf{}; std::string path_buf{};
std::vector<data::source::Node> nodes{}; std::vector<data::source::Node> nodes{};
}; };
@@ -742,6 +745,13 @@ namespace
std::optional<WatchToken> next_token(ParseState &state) 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()) if (state.buf.empty())
{ {
spdlog::trace("Token buffer empty"); spdlog::trace("Token buffer empty");
@@ -783,7 +793,7 @@ namespace
state.literal_buf.insert(state.literal_buf.end(), state.buf.begin(), state.literal_buf.insert(state.literal_buf.end(), state.buf.begin(),
literal_end); literal_end);
state.literal_buf.push_back('\0'); 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) return WatchToken{static_cast<uint32_t>(WatchToken::literal_bit)
| static_cast<uint32_t>(idx)}; | 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) std::optional<size_t> parse_data_desc(ParseState &state)
{ {
const auto token_opt = next_token(state); const auto token_opt = next_token(state);
@@ -803,6 +831,7 @@ namespace
spdlog::trace("Parsing data_desc: Token {}", token_to_str(state, token)); spdlog::trace("Parsing data_desc: Token {}", token_to_str(state, token));
// check for register // check for register
// <reg> = $<ident>
if (token == WatchToken::dollar) if (token == WatchToken::dollar)
{ {
spdlog::trace("Parsing register"); spdlog::trace("Parsing register");
@@ -870,13 +899,73 @@ namespace
spdlog::trace("Created register node with id {}", node_id); spdlog::trace("Created register node with id {}", node_id);
return 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 } // namespace
void WatchWindow::create_node_for_extra_slot(Frontend &frontend, void WatchWindow::create_node_for_extra_slot(Frontend &frontend,
const size_t slot_idx) const size_t slot_idx)
{ {
const auto &slot = extra_slots[slot_idx]; auto &slot = extra_slots[slot_idx];
auto parse_state = ParseState{ auto parse_state = ParseState{
.frontend = &frontend, .frontend = &frontend,
@@ -884,13 +973,29 @@ void WatchWindow::create_node_for_extra_slot(Frontend &frontend,
.literal_buf = {}, .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; if (!parse_state.buf.empty())
frontend.target->backend->add_data_node(Node{ {
.id = slot.id, spdlog::warn(
.type = Node::Type::source, "Error parsing expression path '{}' for slot {}: trailing data '{}'",
.data = Source{.type = Source::Type::variable, slot.buf, slot_idx, parse_state.buf);
.data = Source::Variable{.expr_path = slot.buf, return;
.address_of_or_pointer = false}}}); }
// 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;
} }