Go to the documentation of this file.
4 #ifndef LEXY_PARSE_TREE_HPP_INCLUDED
5 #define LEXY_PARSE_TREE_HPP_INCLUDED
16 template <
typename Node>
17 struct parse_tree_input_traits;
23 template <
typename Reader>
25 template <
typename Reader>
27 template <
typename Reader>
30 template <
typename Reader>
41 unsigned type() const noexcept
67 return (
_value & 0b10) >> 1;
86 auto result =
reinterpret_cast<std::uintptr_t
>(ptr);
89 result |= (role & 0b1) << 1;
90 result |= (
type & 0b1);
101 template <
typename Reader>
106 = _detail::is_random_access_iterator<typename Reader::iterator>;
109 = std::conditional_t<_optimize_end, std::uint_least32_t, typename Reader::iterator>;
116 typename Reader::iterator
end) noexcept
122 typename Reader::iterator
end() const noexcept
134 static_assert(!std::is_pointer_v<typename Reader::iterator>
143 static_assert(!std::is_pointer_v<typename Reader::iterator>
151 template <
typename Reader>
152 struct pt_node_production : pt_node<Reader>
156 const char*
const*
id;
171 auto memory =
static_cast<void*
>(
this + 1);
195 template <
typename MemoryResource>
200 static constexpr std::size_t
block_size = 4096 -
sizeof(
void*);
222 unsigned char*
end() noexcept
230 explicit constexpr
pt_buffer(MemoryResource* resource) noexcept
238 other._head = other._cur_block =
nullptr;
239 other._cur_pos =
nullptr;
245 while (cur !=
nullptr)
284 template <
typename T,
typename... Args>
287 static_assert(std::is_trivially_copyable_v<T>);
288 static_assert(
alignof(T) ==
alignof(
void*));
289 constexpr
auto size =
sizeof(T);
295 return ::new (
static_cast<void*
>(memory)) T(
LEXY_FWD(args)...);
305 auto pos =
static_cast<unsigned char*
>(marker);
338 template <
typename Reader,
typename TokenKind>
340 template <
typename Reader,
typename TokenKind>
343 template <
typename Reader,
typename TokenKind =
void,
typename MemoryResource =
void>
346 static_assert(lexy::is_char_encoding<typename Reader::encoding>);
360 return _root ==
nullptr;
363 std::size_t
size() const noexcept
391 class traverse_range;
422 template <
typename Input,
typename TokenKind =
void,
typename MemoryResource =
void>
425 template <
typename Reader,
typename TokenKind,
typename MemoryResource>
452 explicit marker(
void* unwind_pos, std::size_t cur_depth,
454 : unwind_pos(unwind_pos), prod(prod), child_count(0), first_child(nullptr),
455 last_child(nullptr), cur_depth(cur_depth), local_max_depth(cur_depth)
460 first_child =
nullptr;
461 last_child =
nullptr;
467 if (first_child ==
nullptr)
470 first_child = last_child =
child;
488 if (first_child ==
nullptr)
499 child_count += length;
505 if (child_count == 0)
508 if (first_child == parent + 1)
517 auto memory =
static_cast<void*
>(parent + 1);
534 if (cur_depth == local_max_depth && child_count > 0)
538 if (max_depth < local_max_depth)
539 max_depth = local_max_depth;
549 _result._buffer.reset();
554 = _result._buffer.template allocate<_detail::pt_node_production<Reader>>(production);
559 _cur =
marker(_result._buffer.top(), 0, _result._root);
563 [[deprecated(
"Pass the remaining input, or `input.end()` if there is none.")]]
parse_tree&&
570 return LEXY_MOV(*this).finish({end, end});
576 _cur.insert_children_into(_cur.prod);
577 _cur.update_size_depth(_result._size, _result._depth);
580 auto node = _result._buffer
584 _result._root->set_sibling(
node);
603 = _result._buffer.template allocate<_detail::pt_node_production<Reader>>(production);
615 if (m.prod == _cur.prod)
619 _cur.update_size_depth(_result._size, m.local_max_depth);
620 _cur.insert_children_into(_cur.prod);
630 if (_cur.prod == m.prod)
634 _result._buffer.unwind(_cur.unwind_pos);
642 auto unwind_pos = _result._buffer.top();
643 if (_cur.prod && _cur.child_count == 0)
650 _result._buffer.template allocate<_detail::pt_node<Reader>*>(
nullptr);
655 _cur =
marker(unwind_pos, old.cur_depth);
672 = _result._buffer.template allocate<_detail::pt_node_production<Reader>>(production);
673 _result._buffer.template allocate<_detail::pt_node<Reader>*>(
nullptr);
677 auto new_container =
marker(_cur.unwind_pos, _cur.cur_depth);
678 new_container.insert(
node);
681 _cur.insert_children_into(
node);
684 new_container.local_max_depth = [&] {
685 if (_cur.cur_depth == _cur.local_max_depth && _cur.child_count > 0)
687 return _cur.local_max_depth + 1 + 1;
689 return _cur.local_max_depth + 1;
691 _result._size += _cur.child_count;
694 _cur = new_container;
702 m.insert_list(_cur.child_count, _cur.first_child, _cur.last_child);
706 std::size_t
size = 0;
707 _cur.update_size_depth(
size, m.local_max_depth);
718 _result._buffer.unwind(_cur.unwind_pos);
725 typename Reader::iterator
end)
737 _cur.last_child->as_token()->update_end(
end);
744 = _result._buffer.template allocate<_detail::pt_node_token<Reader>>(kind,
begin,
753 return _cur.child_count;
761 template <
typename Reader,
typename TokenKind>
767 return _ptr->as_token() !=
nullptr;
771 return _ptr->as_production() !=
nullptr;
779 return _ptr->next_node()->next_node() ==
nullptr;
786 const char*
name() const noexcept
788 if (
auto prod =
_ptr->as_production())
802 return lhs.
_ptr->as_token()->kind == rhs.
_ptr->as_token()->kind;
804 return lhs.
_ptr->as_production()->id == rhs.
_ptr->as_production()->id;
808 return !(lhs == rhs);
841 return !(nk == info);
845 return !(nk == info);
856 template <
typename Reader,
typename TokenKind>
872 if (
kind().is_root())
879 cur = cur->next_node();
903 return _cur == rhs._cur;
919 std::size_t
size() const noexcept
921 if (
auto prod =
_node->as_production())
922 return prod->child_count;
929 if (
auto prod =
_node->as_production(); prod && prod->first_child())
930 return iterator(prod->first_child());
974 _cur =
_cur->next_node()->as_production()->first_child();
982 return _cur == rhs._cur;
1029 auto position() const noexcept -> typename Reader::iterator
1035 cur = cur->as_production()->first_child();
1039 return cur->as_token()->begin;
1057 auto sibling =
_ptr;
1060 auto next_role = sibling->next_role();
1061 sibling = sibling->next_node();
1083 return lhs._ptr == rhs._ptr;
1087 return lhs._ptr != rhs._ptr;
1109 template <
typename Reader,
typename TokenKind,
typename MemoryResource>
1135 auto child = _cur->as_production()->first_child();
1139 if (
child->as_token())
1159 else if (_cur->next_node()->as_production())
1166 _cur = _cur->next_node();
1172 return _ev == rhs._ev && _cur == rhs._cur;
1184 return _begin == _end;
1201 if (
n.kind().is_token())
1203 _begin._cur =
n._ptr;
1210 _begin._cur =
n._ptr;
1225 #if LEXY_EXPERIMENTAL
1228 template <
typename Reader,
typename TokenKind>
1233 using char_encoding =
typename Reader::encoding;
1235 static bool is_null(_node cur) noexcept
1237 return cur.
_ptr ==
nullptr;
1240 static _node
null() noexcept
1242 return _node(
nullptr);
1245 static _node first_child(_node cur) noexcept
1248 if (
auto prod = cur._ptr->as_production())
1249 return _node(prod->first_child());
1251 return _node(
nullptr);
1254 static _node sibling(_node cur) noexcept
1258 ? _node(cur._ptr->next_node())
1262 template <
typename Kind>
1263 static bool has_kind(_node cur,
const Kind& kind) noexcept
1265 return !is_null(cur) && cur.kind() == kind;
1268 using iterator =
typename Reader::iterator;
1270 static iterator position_begin(_node cur) noexcept
1273 return cur.position();
1275 static iterator position_end(_node cur) noexcept
1278 return cur.covering_lexeme().end();
1281 static auto lexeme(_node cur) noexcept
1284 return cur.lexeme();
1290 #endif // LEXY_PARSE_TREE_HPP_INCLUDED
constexpr auto size(const C &c) -> decltype(c.size())
iterator begin() const noexcept
traverse_range traverse(const node &n) const noexcept
void increment() noexcept
static constexpr auto _optimize_end
friend bool operator==(_pt_node_kind nk, token_kind< TokenKind > tk)
parse_tree && finish() &&
std::conditional_t< std::is_void_v< MemoryResource >, _memory_resource_ptr_empty< default_memory_resource >, std::conditional_t< std::is_empty_v< MemoryResource >, _memory_resource_ptr_empty< MemoryResource >, _memory_resource_ptr< MemoryResource > >> memory_resource_ptr
iterator end() const noexcept
bool equal(iterator rhs) const noexcept
auto token() const noexcept
std::size_t size() const noexcept
pt_node< Reader > * next_node() const noexcept
iterator end() const noexcept
constexpr MemoryResource * get_memory_resource()
auto as_production() noexcept
traverse_range traverse() const noexcept
static constexpr auto role_parent
constexpr bool ignore_if_empty() const noexcept
constexpr parse_tree(MemoryResource *resource)
_detail::pt_node< Reader > * first_child
void set_container_production(production_info production)
@ exit
We're visiting a production node after all its children.
_detail::pt_node_production< Reader > * prod
pt_buffer(pt_buffer &&other) noexcept
static block * allocate(resource_ptr resource)
bool is_token_production() const noexcept
_detail::pt_node< Reader > * _cur
unsigned char memory[block_size]
A parsed token, i.e. its kind and its lexeme.
unsigned char * end() noexcept
void increment() noexcept
friend bool operator!=(_pt_node lhs, _pt_node rhs) noexcept
builder(production_info production)
static constexpr auto type_token
constexpr Iterator next(Iterator iter)
void insert_children_into(_detail::pt_node_production< Reader > *parent)
iterator(_detail::pt_node< Reader > *ptr) noexcept
builder(parse_tree &&tree, production_info production)
bool is_production() const noexcept
bool equal(iterator rhs) const noexcept
friend bool operator==(_pt_node_kind nk, production_info info)
auto position() const noexcept -> typename Reader::iterator
#define LEXY_PRECONDITION(Expr)
auto children() const noexcept
auto siblings() const noexcept
friend bool operator!=(_pt_node_kind nk, token_kind< TokenKind > tk)
bool is_last_child() const noexcept
bool is_token() const noexcept
void reserve(std::size_t size)
constexpr auto end(const C &c) -> decltype(c.end())
iterator(_detail::pt_node< Reader > *ptr) noexcept
auto covering_lexeme() const noexcept
void finish_production(marker &&m)
friend bool operator==(_pt_node_kind lhs, _pt_node_kind rhs)
iterator begin() const noexcept
void increment() noexcept
bool empty() const noexcept
_pt_node_kind(_detail::pt_node< Reader > *ptr)
void update_end(typename Reader::iterator end) noexcept
bool empty() const noexcept
iterator end() const noexcept
void set_parent(pt_node_production< Reader > *parent) noexcept
friend bool operator!=(_pt_node_kind nk, production_info info)
bool equal(iterator rhs) const noexcept
_detail::pt_node< Reader > * last_child
iterator begin() const noexcept
parse_tree && finish(typename Reader::iterator end) &&
constexpr token_kind< TokenKind > kind() const noexcept
static constexpr auto role_sibling
_detail::pt_node_production< Reader > * _root
friend bool operator==(token_kind< TokenKind > tk, _pt_node_kind nk)
void finish_container(marker &&m)
std::conditional_t< _optimize_end, std::uint_least32_t, typename Reader::iterator > _end_t
pt_node_token(std::uint_least16_t kind, typename Reader::iterator begin, typename Reader::iterator end) noexcept
What sort of token it is.
friend bool operator!=(token_kind< TokenKind > tk, _pt_node_kind nk)
auto start_production(production_info production)
std::size_t first_child_adjacent
constexpr void swap(T &lhs, T &rhs)
static std::uintptr_t _make_packed_ptr(pt_node< Reader > *ptr, unsigned type, unsigned role)
auto child(const lexy::parse_tree< Reader, TokenKind, MemoryResource > &tree, typename lexy::parse_tree< Reader, TokenKind, MemoryResource >::node node, Predicate predicate) -> std::optional< typename lexy::parse_tree< Reader, TokenKind, MemoryResource >::node >
Returns the first child that matches predicate, if there is any.
static block * deallocate(resource_ptr resource, block *ptr)
pt_buffer & operator=(pt_buffer &&other) noexcept
static constexpr token_kind< TokenKind > from_raw(std::uint_least16_t kind) noexcept
@ leaf
We're visiting a token.
LEXY_EMPTY_MEMBER resource_ptr _resource
void cancel_production(marker &&m)
void * address() const noexcept
auto kind() const noexcept
static constexpr auto type_production
std::size_t remaining_capacity() const noexcept
constexpr auto n() noexcept
_pt_node(_detail::pt_node< Reader > *ptr) noexcept
friend bool operator==(production_info info, _pt_node_kind nk)
friend bool operator!=(production_info info, _pt_node_kind nk)
constexpr pt_buffer(MemoryResource *resource) noexcept
constexpr auto begin(const C &c) -> decltype(c.begin())
void insert(_detail::pt_node< Reader > *child)
lexy::lexeme< Reader > remaining_input() const noexcept
_detail::pt_node< Reader > * _node
static constexpr std::size_t child_count_bits
const char * name() const noexcept
bool is_root() const noexcept
_detail::memory_resource_ptr< MemoryResource > resource_ptr
static constexpr std::size_t block_size
auto lexeme() const noexcept
void cancel_container(marker &&m)
bool empty() const noexcept
sibling_range(_detail::pt_node< Reader > *node) noexcept
auto deref() const noexcept
std::size_t local_max_depth
void set_sibling(pt_node< Reader > *sibling) noexcept
_value_type deref() const noexcept
auto parent() const noexcept
unsigned type() const noexcept
_detail::pt_buffer< MemoryResource > _buffer
void unwind(void *marker) noexcept
void token(token_kind< TokenKind > _kind, typename Reader::iterator begin, typename Reader::iterator end)
friend bool operator==(_pt_node lhs, _pt_node rhs) noexcept
bool empty() const noexcept
lexeme(const Reader &, typename Reader::iterator) -> lexeme< typename Reader::canonical_reader >
_detail::pt_node< Reader > * _node
_detail::pt_node< Reader > * _ptr
parse_tree && finish(lexy::lexeme< Reader > remaining_input) &&
void update_size_depth(std::size_t &size, std::size_t &max_depth)
Reader::iterator end() const noexcept
marker(void *unwind_pos, std::size_t cur_depth, _detail::pt_node_production< Reader > *prod=nullptr)
pt_node_production(production_info info) noexcept
_detail::pt_node< Reader > * _cur
#define LEXY_EMPTY_MEMBER
void insert_list(std::size_t length, _detail::pt_node< Reader > *first, _detail::pt_node< Reader > *last)
std::size_t size() const noexcept
_detail::pt_node< Reader > * _ptr
_pt_node< Reader, TokenKind > node
auto deref() const noexcept
std::size_t token_production
pt_node< Reader > * first_child()
@ enter
We're visiting a production node before all its children.
T * allocate(Args &&... args)
#define LEXY_ASSERT(Expr, Msg)
node root() const noexcept
std::size_t depth() const noexcept
unsigned next_role() const noexcept
std::size_t current_child_count() const noexcept
static constexpr std::uint_least16_t to_raw(token_kind< TokenKind > kind) noexcept
children_range(_detail::pt_node< Reader > *node)
friend bool operator!=(_pt_node_kind lhs, _pt_node_kind rhs)