diff --git a/src/frontend/window/watch_window.cpp b/src/frontend/window/watch_window.cpp index 125b322..b295cb2 100644 --- a/src/frontend/window/watch_window.cpp +++ b/src/frontend/window/watch_window.cpp @@ -694,6 +694,9 @@ namespace Frontend *frontend; std::string_view buf; std::vector literal_buf; + + std::optional peek_token; + std::string path_buf{}; std::vector nodes{}; }; @@ -742,6 +745,13 @@ namespace std::optional 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(WatchToken::literal_bit) | static_cast(idx)}; @@ -791,6 +801,24 @@ namespace } } + std::optional 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; + } + + // = . | | | std::optional 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 + // = $ 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; } + + // , and 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 , and end of + 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 + // consume the token + next_token(state); + return parse_data_desc(state); + } + + if (peek_token == WatchToken::bracket_open) + { + // TODO: parse + assert(0); + return {}; + } + } + + spdlog::trace("Parsing data_desc: creating variable source with path {}", + state.path_buf); + // something else, end of + 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; }