From 3d4dd4abef193f4b6033c840dfdb2c0cbd243953 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 7 Jan 2018 19:07:49 -0800 Subject: [PATCH] Introduce tnode --- src/parse_grammar.h | 5 ++++- src/parse_tree.h | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/parse_grammar.h b/src/parse_grammar.h index 243f77355..18def39cd 100644 --- a/src/parse_grammar.h +++ b/src/parse_grammar.h @@ -82,6 +82,9 @@ template struct seq { static constexpr production_t<1 + sizeof...(Ts)> production = { {element(), element()..., token_type_invalid}}; + + using type_tuple = std::tuple; + static const production_element_t *resolve(const parse_token_t &, const parse_token_t &, parse_node_tag_t *) { return production_for(); @@ -103,7 +106,7 @@ struct alternative { }; // Following are the grammar productions. -#define BODY(T) +#define BODY(T) static constexpr parse_token_type_t symbol = symbol_##T; #define DEF(T) struct T : public #define DEF_ALT(T) struct T : public alternative diff --git a/src/parse_tree.h b/src/parse_tree.h index e08cf1364..b92f34914 100644 --- a/src/parse_tree.h +++ b/src/parse_tree.h @@ -11,6 +11,7 @@ #include "common.h" #include "parse_constants.h" +#include "parse_grammar.h" #include "tokenizer.h" class parse_node_tree_t; @@ -227,6 +228,44 @@ class parse_node_tree_t : public std::vector { bool job_should_be_backgrounded(const parse_node_t &job) const; }; +/// A helper for type-safe manipulation of parse nodes. +/// This is a lightweight value-type class. +template +class tnode_t { + /// The tree containing our node. + const parse_node_tree_t *tree = nullptr; + + /// The node in the tree + const parse_node_t *nodeptr = nullptr; + + // Helper to get a child type at a given index. + template + using child_at = typename std::tuple_element::type; + + public: + tnode_t() = default; + + tnode_t(const parse_node_tree_t *t, const parse_node_t *n) : tree(t), nodeptr(n) { + assert(t && "tree cannot be null in this constructor"); + assert((!n || n->type == Type::symbol) && "node has wrong type"); + } + + /// Return the underlying (type-erased) node. + const parse_node_t *node() const { return nodeptr; } + + /// Check whether we're populated. + explicit operator bool() const { return nodeptr != nullptr; } + + /// Type-safe access to a child at the given index. + template + tnode_t> child() const { + using child_type = child_at; + const parse_node_t *child = nullptr; + if (nodeptr) child = tree->get_child(*nodeptr, Index, child_type::symbol); + return tnode_t{tree, child}; + } +}; + /// The big entry point. Parse a string, attempting to produce a tree for the given goal type. bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse_node_tree_t *output, parse_error_list_t *errors,