parse_tree.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2024 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_PARSE_TREE_HPP_INCLUDED
5 #define LEXY_PARSE_TREE_HPP_INCLUDED
6 
11 #include <lexy/grammar.hpp>
12 #include <lexy/token.hpp>
13 
14 namespace lexy
15 {
16 template <typename Node>
17 struct parse_tree_input_traits;
18 }
19 
20 //=== internal: pt_node ===//
21 namespace lexy::_detail
22 {
23 template <typename Reader>
24 class pt_node;
25 template <typename Reader>
27 template <typename Reader>
29 
30 template <typename Reader>
31 class pt_node
32 {
33 public:
34  static constexpr auto type_token = 0b0u;
35  static constexpr auto type_production = 0b1u;
36 
37  static constexpr auto role_sibling = 0b0u;
38  static constexpr auto role_parent = 0b1u;
39 
40  //=== information about the current node ===//
41  unsigned type() const noexcept
42  {
43  return _value & 0b1;
44  }
45 
46  auto as_token() noexcept
47  {
48  return type() == type_token ? static_cast<pt_node_token<Reader>*>(this) : nullptr;
49  }
50  auto as_production() noexcept
51  {
52  return type() == type_production ? static_cast<pt_node_production<Reader>*>(this) : nullptr;
53  }
54 
55  //=== information about the next node ===//
56  void set_sibling(pt_node<Reader>* sibling) noexcept
57  {
59  }
60  void set_parent(pt_node_production<Reader>* parent) noexcept
61  {
63  }
64 
65  unsigned next_role() const noexcept
66  {
67  return (_value & 0b10) >> 1;
68  }
69 
70  pt_node<Reader>* next_node() const noexcept
71  {
72  // NOLINTNEXTLINE: We need pointer conversion.
73  return reinterpret_cast<pt_node<Reader>*>(_value & ~std::uintptr_t(0b11));
74  }
75 
76 protected:
77  explicit pt_node(unsigned type)
78  // We initializy it to a null parent pointer.
79  // This means it is automatically an empty child range.
81  {}
82 
83 private:
84  static std::uintptr_t _make_packed_ptr(pt_node<Reader>* ptr, unsigned type, unsigned role)
85  {
86  auto result = reinterpret_cast<std::uintptr_t>(ptr);
87  LEXY_PRECONDITION((result & 0b11) == 0);
88 
89  result |= (role & 0b1) << 1;
90  result |= (type & 0b1);
91 
92  return result;
93  }
94 
95  // Stores an address of the "next" node in the tree.
96  // Stores a bit that remembers whether the next node is a sibling or parent (the role).
97  // Stores a bit that remembers whether *this* node is a token or production.
98  std::uintptr_t _value;
99 };
100 
101 template <typename Reader>
102 struct pt_node_token : pt_node<Reader>
103 {
104  // If it's random access, we store size instead of end.
105  static constexpr auto _optimize_end
106  = _detail::is_random_access_iterator<typename Reader::iterator>;
107  using _end_t
108  // If we can optimize it, we store the size as a uint32_t, otherwise the iterator.
109  = std::conditional_t<_optimize_end, std::uint_least32_t, typename Reader::iterator>;
110 
111  typename Reader::iterator begin;
113  ::uint_least16_t kind;
114 
115  explicit pt_node_token(std::uint_least16_t kind, typename Reader::iterator begin,
116  typename Reader::iterator end) noexcept
118  {
119  update_end(end);
120  }
121 
122  typename Reader::iterator end() const noexcept
123  {
124  if constexpr (_optimize_end)
125  return begin + end_impl;
126  else
127  return end_impl;
128  }
129 
130  void update_end(typename Reader::iterator end) noexcept
131  {
132  if constexpr (_optimize_end)
133  {
134  static_assert(!std::is_pointer_v<typename Reader::iterator>
135  || sizeof(pt_node_token) == 3 * sizeof(void*));
136 
137  auto size = std::size_t(end - begin);
138  LEXY_PRECONDITION(size <= UINT_LEAST32_MAX);
139  end_impl = std::uint_least32_t(size);
140  }
141  else
142  {
143  static_assert(!std::is_pointer_v<typename Reader::iterator>
144  || sizeof(pt_node_token) <= 4 * sizeof(void*));
145 
146  end_impl = end;
147  }
148  }
149 };
150 
151 template <typename Reader>
152 struct pt_node_production : pt_node<Reader>
153 {
154  static constexpr std::size_t child_count_bits = sizeof(std::size_t) * CHAR_BIT - 2;
155 
156  const char* const* id;
158  std::size_t token_production : 1;
159  std::size_t first_child_adjacent : 1;
160 
161  explicit pt_node_production(production_info info) noexcept
163  token_production(info.is_token), first_child_adjacent(true)
164  {
165  static_assert(sizeof(pt_node_production) == 3 * sizeof(void*));
166  LEXY_PRECONDITION(!info.is_transparent);
167  }
168 
170  {
171  auto memory = static_cast<void*>(this + 1);
172  if (child_count == 0)
173  {
174  // We don't have a child at all.
175  return nullptr;
176  }
177  else if (first_child_adjacent)
178  {
179  // The first child is stored immediately afterwards.
180  return static_cast<pt_node<Reader>*>(memory);
181  }
182  else
183  {
184  // We're only storing a pointer to the first child immediately afterwards.
185  return *static_cast<pt_node<Reader>**>(memory);
186  }
187  }
188 };
189 } // namespace lexy::_detail
190 
191 //=== internal: pt_buffer ===//
192 namespace lexy::_detail
193 {
194 // Basic stack allocator to store all the nodes of a tree.
195 template <typename MemoryResource>
197 {
199 
200  static constexpr std::size_t block_size = 4096 - sizeof(void*);
201 
202  struct block
203  {
205  unsigned char memory[block_size];
206 
207  static block* allocate(resource_ptr resource)
208  {
209  auto memory = resource->allocate(sizeof(block), alignof(block));
210  auto ptr = ::new (memory) block; // Don't initialize array!
211  ptr->next = nullptr;
212  return ptr;
213  }
214 
215  static block* deallocate(resource_ptr resource, block* ptr)
216  {
217  auto next = ptr->next;
218  resource->deallocate(ptr, sizeof(block), alignof(block));
219  return next;
220  }
221 
222  unsigned char* end() noexcept
223  {
224  return &memory[block_size];
225  }
226  };
227 
228 public:
229  //=== constructors/destructors/assignment ===//
230  explicit constexpr pt_buffer(MemoryResource* resource) noexcept
231  : _resource(resource), _head(nullptr), _cur_block(nullptr), _cur_pos(nullptr)
232  {}
233 
234  pt_buffer(pt_buffer&& other) noexcept
235  : _resource(other._resource), _head(other._head), _cur_block(other._cur_block),
236  _cur_pos(other._cur_pos)
237  {
238  other._head = other._cur_block = nullptr;
239  other._cur_pos = nullptr;
240  }
241 
242  ~pt_buffer() noexcept
243  {
244  auto cur = _head;
245  while (cur != nullptr)
246  cur = block::deallocate(_resource, cur);
247  }
248 
249  pt_buffer& operator=(pt_buffer&& other) noexcept
250  {
251  lexy::_detail::swap(_resource, other._resource);
252  lexy::_detail::swap(_head, other._head);
253  lexy::_detail::swap(_cur_block, other._cur_block);
254  lexy::_detail::swap(_cur_pos, other._cur_pos);
255  return *this;
256  }
257 
258  //=== allocation ===//
259  // Allocates the first block for the buffer.
260  // Must be called before everything else.
261  // (If done in the constructor, it would require a move that does allocation which we don't
262  // want).
263  // If called after being initialized, destroys all nodes without releasing memory.
264  void reset()
265  {
266  if (!_head)
268 
269  _cur_block = _head;
270  _cur_pos = &_cur_block->memory[0];
271  }
272 
273  void reserve(std::size_t size)
274  {
275  if (remaining_capacity() < size)
276  {
278  _cur_block->next = next;
279  _cur_block = next;
280  _cur_pos = &_cur_block->memory[0];
281  }
282  }
283 
284  template <typename T, typename... Args>
285  T* allocate(Args&&... args)
286  {
287  static_assert(std::is_trivially_copyable_v<T>);
288  static_assert(alignof(T) == alignof(void*));
289  constexpr auto size = sizeof(T); // NOLINT: It's fine, we want to allocate for a pointer.
290  LEXY_PRECONDITION(_cur_block); // Forgot to call .init().
291  LEXY_PRECONDITION(remaining_capacity() >= size); // Forgot to call .reserve().
292 
293  auto memory = _cur_pos;
294  _cur_pos += size;
295  return ::new (static_cast<void*>(memory)) T(LEXY_FWD(args)...);
296  }
297 
298  void* top()
299  {
300  return _cur_pos;
301  }
302 
303  void unwind(void* marker) noexcept
304  {
305  auto pos = static_cast<unsigned char*>(marker);
306 
307  // Note: this is not guaranteed to work by the standard;
308  // We'd have to go through std::less instead.
309  // However, on all implementations I care about, std::less just does < anyway.
310  if (_cur_block->memory <= pos && pos < _cur_block->end())
311  // We're still in the same block, just reset position.
312  _cur_pos = pos;
313  else
314  // Reset to the beginning of the current block only.
315  // This can waste memory, but this is not a problem here:
316  // unwind() is only used to backtrack a production, which happens after a couple of
317  // tokens only; the memory waste is directly proportional to the lookahead length.
319  }
320 
321 private:
322  std::size_t remaining_capacity() const noexcept
323  {
324  return std::size_t(_cur_block->end() - _cur_pos);
325  }
326 
328  block* _head;
329 
330  block* _cur_block;
331  unsigned char* _cur_pos;
332 };
333 } // namespace lexy::_detail
334 
335 //=== parse_tree ===//
336 namespace lexy
337 {
338 template <typename Reader, typename TokenKind>
340 template <typename Reader, typename TokenKind>
341 class _pt_node;
342 
343 template <typename Reader, typename TokenKind = void, typename MemoryResource = void>
345 {
346  static_assert(lexy::is_char_encoding<typename Reader::encoding>);
347 
348 public:
349  //=== construction ===//
350  class builder;
351 
352  constexpr parse_tree() : parse_tree(_detail::get_memory_resource<MemoryResource>()) {}
353  constexpr explicit parse_tree(MemoryResource* resource)
354  : _buffer(resource), _root(nullptr), _size(0), _depth(0)
355  {}
356 
357  //=== container access ===//
358  bool empty() const noexcept
359  {
360  return _root == nullptr;
361  }
362 
363  std::size_t size() const noexcept
364  {
365  return _size;
366  }
367 
368  std::size_t depth() const noexcept
369  {
371  return _depth;
372  }
373 
374  void clear() noexcept
375  {
376  _buffer.reset();
377  _root = nullptr;
378  }
379 
380  //=== node access ===//
383 
384  node root() const noexcept
385  {
387  return node(_root);
388  }
389 
390  //=== traverse ===//
391  class traverse_range;
392 
393  traverse_range traverse(const node& n) const noexcept
394  {
395  return traverse_range(n);
396  }
397  traverse_range traverse() const noexcept
398  {
399  if (empty())
400  return traverse_range();
401  else
402  return traverse_range(root());
403  }
404 
405  //=== remaining input ===//
407  {
408  if (empty())
409  return {};
410 
411  auto token = _root->next_node()->as_token();
412  return {token->begin, token->end()};
413  }
414 
415 private:
418  std::size_t _size;
419  std::size_t _depth;
420 };
421 
422 template <typename Input, typename TokenKind = void, typename MemoryResource = void>
423 using parse_tree_for = lexy::parse_tree<lexy::input_reader<Input>, TokenKind, MemoryResource>;
424 
425 template <typename Reader, typename TokenKind, typename MemoryResource>
426 class parse_tree<Reader, TokenKind, MemoryResource>::builder
427 {
428 public:
429  class marker
430  {
431  public:
432  marker() : marker(nullptr, 0) {}
433 
434  private:
435  // Where to unwind when done.
436  void* unwind_pos;
437  // The current production node.
438  // nullptr if using the container API.
440  // The number of children we've already added.
441  std::size_t child_count;
442  // The first and last child of the container.
445 
446  // For a production node, depth of the production node.
447  // For a container node, depth of the children.
448  std::size_t cur_depth;
449  // The maximum local depth seen in the subtree beginning at the marker.
450  std::size_t local_max_depth;
451 
452  explicit marker(void* unwind_pos, std::size_t cur_depth,
453  _detail::pt_node_production<Reader>* prod = nullptr)
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)
456  {}
457 
458  void clear()
459  {
460  first_child = nullptr;
461  last_child = nullptr;
462  child_count = 0;
463  }
464 
466  {
467  if (first_child == nullptr)
468  {
469  // Initialize the pointers.
470  first_child = last_child = child;
471  }
472  else
473  {
474  // last_child gets a sibling pointer.
475  last_child->set_sibling(child);
476  // child is now the last child.
477  last_child = child;
478  }
479 
480  ++child_count;
481  }
482  void insert_list(std::size_t length, _detail::pt_node<Reader>* first,
484  {
485  if (length == 0)
486  return;
487 
488  if (first_child == nullptr)
489  {
490  first_child = first;
491  last_child = last;
492  }
493  else
494  {
495  last_child->set_sibling(first);
496  last_child = last;
497  }
498 
499  child_count += length;
500  }
501 
503  {
504  LEXY_PRECONDITION(parent->child_count == 0);
505  if (child_count == 0)
506  return;
507 
508  if (first_child == parent + 1)
509  {
510  parent->first_child_adjacent = true;
511  }
512  else
513  {
514  // This case happens either if the first child is in a new block or if we're
515  // dealing with a container node. In either case, we've already reserved memory
516  // for a pointer.
517  auto memory = static_cast<void*>(parent + 1);
518  ::new (memory) _detail::pt_node<Reader>*(first_child);
519  parent->first_child_adjacent = false;
520  }
521 
522  // last_child needs a pointer to the production.
523  last_child->set_parent(parent);
524 
525  constexpr auto mask
526  = ((std::size_t(1) << _detail::pt_node_production<Reader>::child_count_bits) - 1);
527  parent->child_count = child_count & mask;
528  }
529 
530  void update_size_depth(std::size_t& size, std::size_t& max_depth)
531  {
532  size += child_count;
533 
534  if (cur_depth == local_max_depth && child_count > 0)
535  // We have children we haven't yet accounted for.
536  ++local_max_depth;
537 
538  if (max_depth < local_max_depth)
539  max_depth = local_max_depth;
540  }
541 
542  friend builder;
543  };
544 
545  //=== root node ===//
546  explicit builder(parse_tree&& tree, production_info production) : _result(LEXY_MOV(tree))
547  {
548  // Empty the initial parse tree.
549  _result._buffer.reset();
550 
551  // Allocate a new root node.
552  // No need to reserve for the initial node.
553  _result._root
554  = _result._buffer.template allocate<_detail::pt_node_production<Reader>>(production);
555  _result._size = 1;
556  _result._depth = 0;
557 
558  // Begin construction at the root.
559  _cur = marker(_result._buffer.top(), 0, _result._root);
560  }
561  explicit builder(production_info production) : builder(parse_tree(), production) {}
562 
563  [[deprecated("Pass the remaining input, or `input.end()` if there is none.")]] parse_tree&&
564  finish() &&
565  {
566  return LEXY_MOV(*this).finish(lexy::lexeme<Reader>());
567  }
568  parse_tree&& finish(typename Reader::iterator end) &&
569  {
570  return LEXY_MOV(*this).finish({end, end});
571  }
573  {
574  LEXY_PRECONDITION(_cur.prod == _result._root);
575 
576  _cur.insert_children_into(_cur.prod);
577  _cur.update_size_depth(_result._size, _result._depth);
578 
579  _result._buffer.reserve(sizeof(_detail::pt_node_token<Reader>));
580  auto node = _result._buffer
581  .template allocate<_detail::pt_node_token<Reader>>(lexy::eof_token_kind,
582  remaining_input.begin(),
583  remaining_input.end());
584  _result._root->set_sibling(node);
585 
586  return LEXY_MOV(_result);
587  }
588 
589  //=== production nodes ===//
591  {
592  if (production.is_transparent)
593  // Don't need to add a new node for a transparent production.
594  return _cur;
595 
596  // Allocate a node for the production and append it to the current child list.
597  // We reserve enough memory to allow for a trailing pointer.
598  // This is only necessary if the first child is in a new block,
599  // in which case we won't overwrite it.
600  _result._buffer.reserve(sizeof(_detail::pt_node_production<Reader>)
601  + sizeof(_detail::pt_node<Reader>*));
602  auto node
603  = _result._buffer.template allocate<_detail::pt_node_production<Reader>>(production);
604  // Note: don't append the node yet, we might still backtrack.
605 
606  // Subsequent insertions are to the new node, so update marker and return old one.
607  auto old = LEXY_MOV(_cur);
608  _cur = marker(node, old.cur_depth + 1, node);
609  return old;
610  }
611 
613  {
614  LEXY_PRECONDITION(_cur.prod || m.prod == _cur.prod);
615  if (m.prod == _cur.prod)
616  // We're finishing with a transparent production, do nothing.
617  return;
618 
619  _cur.update_size_depth(_result._size, m.local_max_depth);
620  _cur.insert_children_into(_cur.prod);
621 
622  // Insert the production node into the parent and continue with it.
623  m.insert(_cur.prod);
624  _cur = LEXY_MOV(m);
625  }
626 
628  {
629  LEXY_PRECONDITION(_cur.prod || m.prod == _cur.prod);
630  if (_cur.prod == m.prod)
631  // We're backtracking a transparent production, do nothing.
632  return;
633 
634  _result._buffer.unwind(_cur.unwind_pos);
635  // Continue with parent.
636  _cur = LEXY_MOV(m);
637  }
638 
639  //=== container nodes ===//
641  {
642  auto unwind_pos = _result._buffer.top();
643  if (_cur.prod && _cur.child_count == 0)
644  {
645  // If our parent production doesn't have any children,
646  // we might need space for a first child pointer.
647  //
648  // If our parent is another container, its start_container() function took care of it.
649  // If our parent already has a child, the first_child pointer is taken care of.
650  _result._buffer.template allocate<_detail::pt_node<Reader>*>(nullptr);
651  }
652 
653  // Create a new container marker and activate it.
654  auto old = LEXY_MOV(_cur);
655  _cur = marker(unwind_pos, old.cur_depth);
656  return old;
657  }
658 
660  {
661  LEXY_PRECONDITION(!_cur.prod);
662  if (production.is_transparent)
663  // If the production is transparent, we do nothing.
664  return;
665 
666  // Allocate a new node for the production.
667  // We definitely need space for node pointer at this point,
668  // as the first child precedes it.
669  _result._buffer.reserve(sizeof(_detail::pt_node_production<Reader>)
670  + sizeof(_detail::pt_node<Reader>*));
671  auto node
672  = _result._buffer.template allocate<_detail::pt_node_production<Reader>>(production);
673  _result._buffer.template allocate<_detail::pt_node<Reader>*>(nullptr);
674 
675  // Create a new container that will contain the production as its only child.
676  // As such, it logically starts at the same position and depth as the current container.
677  auto new_container = marker(_cur.unwind_pos, _cur.cur_depth);
678  new_container.insert(node);
679 
680  // The production contains all the children.
681  _cur.insert_children_into(node);
682 
683  // The local_max_depth of the new container is determined by the old maximum depth + 1.
684  new_container.local_max_depth = [&] {
685  if (_cur.cur_depth == _cur.local_max_depth && _cur.child_count > 0)
686  // There are children we haven't yet accounted for.
687  return _cur.local_max_depth + 1 + 1;
688  else
689  return _cur.local_max_depth + 1;
690  }();
691  _result._size += _cur.child_count;
692 
693  // And we continue with the current container.
694  _cur = new_container;
695  }
696 
698  {
699  LEXY_PRECONDITION(!_cur.prod);
700 
701  // Insert the children of our container into the parent.
702  m.insert_list(_cur.child_count, _cur.first_child, _cur.last_child);
703 
704  // We can't update size yet, it would be double counted.
705  // We do need to update the max depth if necessary, however.
706  std::size_t size = 0;
707  _cur.update_size_depth(size, m.local_max_depth);
708 
709  // Continue with the parent.
710  _cur = LEXY_MOV(m);
711  }
712 
714  {
715  LEXY_PRECONDITION(!_cur.prod);
716 
717  // Deallocate everything we've inserted.
718  _result._buffer.unwind(_cur.unwind_pos);
719  // Continue with parent.
720  _cur = LEXY_MOV(m);
721  }
722 
723  //=== token nodes ===//
724  void token(token_kind<TokenKind> _kind, typename Reader::iterator begin,
725  typename Reader::iterator end)
726  {
727  if (_kind.ignore_if_empty() && begin == end)
728  return;
729 
730  auto kind = token_kind<TokenKind>::to_raw(_kind);
731 
732  // We merge error tokens.
733  if (kind == lexy::error_token_kind && _cur.last_child && _cur.last_child->as_token()
734  && _cur.last_child->as_token()->kind == lexy::error_token_kind)
735  {
736  // No need to allocate a new node, just extend the previous node.
737  _cur.last_child->as_token()->update_end(end);
738  }
739  else
740  {
741  // Allocate and append.
742  _result._buffer.reserve(sizeof(_detail::pt_node_token<Reader>));
743  auto node
744  = _result._buffer.template allocate<_detail::pt_node_token<Reader>>(kind, begin,
745  end);
746  _cur.insert(node);
747  }
748  }
749 
750  //=== accessors ===//
751  std::size_t current_child_count() const noexcept
752  {
753  return _cur.child_count;
754  }
755 
756 private:
759 };
760 
761 template <typename Reader, typename TokenKind>
762 class _pt_node_kind
763 {
764 public:
765  bool is_token() const noexcept
766  {
767  return _ptr->as_token() != nullptr;
768  }
769  bool is_production() const noexcept
770  {
771  return _ptr->as_production() != nullptr;
772  }
773 
774  bool is_root() const noexcept
775  {
776  // Root node has a next node (the remaining input node) which has no next node.
777  // We assume that _ptr is never the remaining input node, so we know that we have a next
778  // node.
779  return _ptr->next_node()->next_node() == nullptr;
780  }
781  bool is_token_production() const noexcept
782  {
783  return is_production() && _ptr->as_production()->token_production;
784  }
785 
786  const char* name() const noexcept
787  {
788  if (auto prod = _ptr->as_production())
789  return *prod->id;
790  else if (auto token = _ptr->as_token())
792  else
793  {
794  LEXY_ASSERT(false, "unreachable");
795  return nullptr;
796  }
797  }
798 
799  friend bool operator==(_pt_node_kind lhs, _pt_node_kind rhs)
800  {
801  if (lhs.is_token() && rhs.is_token())
802  return lhs._ptr->as_token()->kind == rhs._ptr->as_token()->kind;
803  else
804  return lhs._ptr->as_production()->id == rhs._ptr->as_production()->id;
805  }
806  friend bool operator!=(_pt_node_kind lhs, _pt_node_kind rhs)
807  {
808  return !(lhs == rhs);
809  }
810 
812  {
813  if (auto token = nk._ptr->as_token())
815  else
816  return false;
817  }
819  {
820  return nk == tk;
821  }
823  {
824  return !(nk == tk);
825  }
827  {
828  return !(nk == tk);
829  }
830 
832  {
833  return nk.is_production() && nk._ptr->as_production()->id == info.id;
834  }
836  {
837  return nk == info;
838  }
840  {
841  return !(nk == info);
842  }
844  {
845  return !(nk == info);
846  }
847 
848 private:
849  explicit _pt_node_kind(_detail::pt_node<Reader>* ptr) : _ptr(ptr) {}
850 
852 
854 };
855 
856 template <typename Reader, typename TokenKind>
857 class _pt_node
858 {
859 public:
860  void* address() const noexcept
861  {
862  return _ptr;
863  }
864 
865  auto kind() const noexcept
866  {
868  }
869 
870  auto parent() const noexcept
871  {
872  if (kind().is_root())
873  // The root has itself as parent.
874  return *this;
875 
876  // If we follow the sibling pointer, we reach a parent pointer.
877  auto cur = _ptr;
878  while (cur->next_role() == _detail::pt_node<Reader>::role_sibling)
879  cur = cur->next_node();
880  return _pt_node(cur->next_node());
881  }
882 
884  {
885  public:
886  class iterator : public _detail::forward_iterator_base<iterator, _pt_node, _pt_node, void>
887  {
888  public:
889  iterator() noexcept : _cur(nullptr) {}
890 
891  auto deref() const noexcept
892  {
893  return _pt_node(_cur);
894  }
895 
896  void increment() noexcept
897  {
898  _cur = _cur->next_node();
899  }
900 
901  bool equal(iterator rhs) const noexcept
902  {
903  return _cur == rhs._cur;
904  }
905 
906  private:
907  explicit iterator(_detail::pt_node<Reader>* ptr) noexcept : _cur(ptr) {}
908 
910 
912  };
913 
914  bool empty() const noexcept
915  {
916  return size() == 0;
917  }
918 
919  std::size_t size() const noexcept
920  {
921  if (auto prod = _node->as_production())
922  return prod->child_count;
923  else
924  return 0;
925  }
926 
927  iterator begin() const noexcept
928  {
929  if (auto prod = _node->as_production(); prod && prod->first_child())
930  return iterator(prod->first_child());
931  else
932  return end();
933  }
934  iterator end() const noexcept
935  {
936  // The last child has a next pointer back to the parent,
937  // so if we keep following it, we'll end up here.
938  return iterator(_node);
939  }
940 
941  private:
943  {
944  LEXY_PRECONDITION(node);
945  }
946 
948 
949  friend _pt_node;
950  };
951 
952  auto children() const noexcept
953  {
954  return children_range(_ptr);
955  }
956 
958  {
959  public:
960  class iterator : public _detail::forward_iterator_base<iterator, _pt_node, _pt_node, void>
961  {
962  public:
963  iterator() noexcept : _cur() {}
964 
965  auto deref() const noexcept
966  {
967  return _pt_node(_cur);
968  }
969 
970  void increment() noexcept
971  {
972  if (_cur->next_role() == _detail::pt_node<Reader>::role_parent)
973  // We're pointing to the parent, go to first child instead.
974  _cur = _cur->next_node()->as_production()->first_child();
975  else
976  // We're pointing to a sibling, go there.
977  _cur = _cur->next_node();
978  }
979 
980  bool equal(iterator rhs) const noexcept
981  {
982  return _cur == rhs._cur;
983  }
984 
985  private:
986  explicit iterator(_detail::pt_node<Reader>* ptr) noexcept : _cur(ptr) {}
987 
989 
991  };
992 
993  bool empty() const noexcept
994  {
995  return begin() == end();
996  }
997 
998  iterator begin() const noexcept
999  {
1000  // We begin with the next node after ours.
1001  // If we don't have siblings, this is our node itself.
1002  return ++iterator(_node);
1003  }
1004  iterator end() const noexcept
1005  {
1006  // We end when we're back at the node.
1007  return iterator(_node);
1008  }
1009 
1010  private:
1011  explicit sibling_range(_detail::pt_node<Reader>* node) noexcept : _node(node) {}
1012 
1014 
1015  friend _pt_node;
1016  };
1017 
1018  auto siblings() const noexcept
1019  {
1020  return sibling_range(_ptr);
1021  }
1022 
1023  bool is_last_child() const noexcept
1024  {
1025  // We're the last child if our pointer points to the parent.
1026  return _ptr->next_role() == _detail::pt_node<Reader>::role_parent;
1027  }
1028 
1029  auto position() const noexcept -> typename Reader::iterator
1030  {
1031  // Find the first descendant that is a token.
1032  auto cur = _ptr;
1033  while (cur->type() == _detail::pt_node<Reader>::type_production)
1034  {
1035  cur = cur->as_production()->first_child();
1036  LEXY_PRECONDITION(cur);
1037  }
1038 
1039  return cur->as_token()->begin;
1040  }
1041 
1042  auto lexeme() const noexcept
1043  {
1044  if (auto token = _ptr->as_token())
1045  return lexy::lexeme<Reader>(token->begin, token->end());
1046  else
1047  return lexy::lexeme<Reader>();
1048  }
1049 
1050  auto covering_lexeme() const noexcept
1051  {
1052  if (auto token = _ptr->as_token())
1053  return lexy::lexeme<Reader>(token->begin, token->end());
1054 
1055  auto begin = position();
1056 
1057  auto sibling = _ptr;
1058  while (true)
1059  {
1060  auto next_role = sibling->next_role();
1061  sibling = sibling->next_node();
1062  // If we went to parent, we need to continue finding siblings.
1063  if (next_role == _detail::pt_node<Reader>::role_sibling)
1064  break;
1065  }
1066  auto end = _pt_node(sibling).position();
1067 
1068  LEXY_PRECONDITION(begin == end || end != typename Reader::iterator());
1069  return lexy::lexeme<Reader>(begin, end);
1070  }
1071 
1072  auto token() const noexcept
1073  {
1074  LEXY_PRECONDITION(kind().is_token());
1075 
1076  auto token = _ptr->as_token();
1078  return lexy::token<Reader, TokenKind>(kind, token->begin, token->end());
1079  }
1080 
1081  friend bool operator==(_pt_node lhs, _pt_node rhs) noexcept
1082  {
1083  return lhs._ptr == rhs._ptr;
1084  }
1085  friend bool operator!=(_pt_node lhs, _pt_node rhs) noexcept
1086  {
1087  return lhs._ptr != rhs._ptr;
1088  }
1089 
1090 private:
1091  explicit _pt_node(_detail::pt_node<Reader>* ptr) noexcept : _ptr(ptr) {}
1092 
1094 
1097 };
1098 
1099 enum class traverse_event
1100 {
1102  enter,
1104  exit,
1106  leaf,
1107 };
1108 
1109 template <typename Reader, typename TokenKind, typename MemoryResource>
1110 class parse_tree<Reader, TokenKind, MemoryResource>::traverse_range
1111 {
1112 public:
1113  using event = traverse_event;
1114 
1116  {
1119  };
1120 
1121  class iterator : public _detail::forward_iterator_base<iterator, _value_type, _value_type, void>
1122  {
1123  public:
1124  iterator() noexcept = default;
1125 
1126  _value_type deref() const noexcept
1127  {
1128  return {_ev, node(_cur)};
1129  }
1130 
1131  void increment() noexcept
1132  {
1133  if (_ev == traverse_event::enter)
1134  {
1135  auto child = _cur->as_production()->first_child();
1136  if (child)
1137  {
1138  // We go to the first child next.
1139  if (child->as_token())
1141  else
1143 
1144  _cur = child;
1145  }
1146  else
1147  {
1148  // Don't have children, exit.
1150  }
1151  }
1152  else
1153  {
1154  // We follow the next pointer.
1155 
1156  if (_cur->next_role() == _detail::pt_node<Reader>::role_parent)
1157  // We go back to a production for the second time.
1159  else if (_cur->next_node()->as_production())
1160  // We're having a production as sibling.
1162  else
1163  // Token as sibling.
1165 
1166  _cur = _cur->next_node();
1167  }
1168  }
1169 
1170  bool equal(iterator rhs) const noexcept
1171  {
1172  return _ev == rhs._ev && _cur == rhs._cur;
1173  }
1174 
1175  private:
1176  _detail::pt_node<Reader>* _cur = nullptr;
1178 
1180  };
1181 
1182  bool empty() const noexcept
1183  {
1184  return _begin == _end;
1185  }
1186 
1187  iterator begin() const noexcept
1188  {
1189  return _begin;
1190  }
1191 
1192  iterator end() const noexcept
1193  {
1194  return _end;
1195  }
1196 
1197 private:
1198  traverse_range() noexcept = default;
1200  {
1201  if (n.kind().is_token())
1202  {
1203  _begin._cur = n._ptr;
1204  _begin._ev = traverse_event::leaf;
1205 
1206  _end = _detail::next(_begin);
1207  }
1208  else
1209  {
1210  _begin._cur = n._ptr;
1211  _begin._ev = traverse_event::enter;
1212 
1213  _end._cur = n._ptr;
1214  _end._ev = traverse_event::exit;
1215  ++_end; // half-open range
1216  }
1217  }
1218 
1219  iterator _begin, _end;
1220 
1221  friend parse_tree;
1222 };
1223 } // namespace lexy
1224 
1225 #if LEXY_EXPERIMENTAL
1226 namespace lexy
1227 {
1228 template <typename Reader, typename TokenKind>
1229 struct parse_tree_input_traits<_pt_node<Reader, TokenKind>>
1230 {
1231  using _node = _pt_node<Reader, TokenKind>;
1232 
1233  using char_encoding = typename Reader::encoding;
1234 
1235  static bool is_null(_node cur) noexcept
1236  {
1237  return cur._ptr == nullptr;
1238  }
1239 
1240  static _node null() noexcept
1241  {
1242  return _node(nullptr);
1243  }
1244 
1245  static _node first_child(_node cur) noexcept
1246  {
1247  LEXY_PRECONDITION(!is_null(cur));
1248  if (auto prod = cur._ptr->as_production())
1249  return _node(prod->first_child());
1250  else
1251  return _node(nullptr);
1252  }
1253 
1254  static _node sibling(_node cur) noexcept
1255  {
1256  LEXY_PRECONDITION(!is_null(cur));
1257  return cur._ptr->next_role() == _detail::pt_node<Reader>::role_sibling
1258  ? _node(cur._ptr->next_node())
1259  : _node(nullptr);
1260  }
1261 
1262  template <typename Kind>
1263  static bool has_kind(_node cur, const Kind& kind) noexcept
1264  {
1265  return !is_null(cur) && cur.kind() == kind;
1266  }
1267 
1268  using iterator = typename Reader::iterator;
1269 
1270  static iterator position_begin(_node cur) noexcept
1271  {
1272  LEXY_PRECONDITION(!is_null(cur));
1273  return cur.position();
1274  }
1275  static iterator position_end(_node cur) noexcept
1276  {
1277  LEXY_PRECONDITION(!is_null(cur));
1278  return cur.covering_lexeme().end();
1279  }
1280 
1281  static auto lexeme(_node cur) noexcept
1282  {
1283  LEXY_PRECONDITION(!is_null(cur));
1284  return cur.lexeme();
1285  }
1286 };
1287 } // namespace lexy
1288 #endif
1289 
1290 #endif // LEXY_PARSE_TREE_HPP_INCLUDED
1291 
cx::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: wildcards.hpp:636
lexy::_pt_node::sibling_range::begin
iterator begin() const noexcept
Definition: parse_tree.hpp:998
lexy::parse_tree::traverse
traverse_range traverse(const node &n) const noexcept
Definition: parse_tree.hpp:393
LEXY_MOV
#define LEXY_MOV(...)
Definition: config.hpp:29
lexy::_detail::pt_node
Definition: parse_tree.hpp:24
lexy::_pt_node::children_range::iterator::increment
void increment() noexcept
Definition: parse_tree.hpp:896
lexy::eof_token_kind
@ eof_token_kind
Definition: grammar.hpp:92
lexy::_detail::pt_node_token::_optimize_end
static constexpr auto _optimize_end
Definition: parse_tree.hpp:106
lexy::_detail::pt_node::pt_node
pt_node(unsigned type)
Definition: parse_tree.hpp:77
lexy::_pt_node_kind::operator==
friend bool operator==(_pt_node_kind nk, token_kind< TokenKind > tk)
Definition: parse_tree.hpp:811
lexy::parse_tree::traverse_range::_value_type::event
traverse_event event
Definition: parse_tree.hpp:1117
lexy::parse_tree::_depth
std::size_t _depth
Definition: parse_tree.hpp:419
lexy::parse_tree::builder::finish
parse_tree && finish() &&
Definition: parse_tree.hpp:564
lexy::parse_tree::traverse_range
Definition: parse_tree.hpp:1110
lexy::parse_tree::builder::marker
Definition: parse_tree.hpp:429
lexy::parse_tree::builder::_result
parse_tree _result
Definition: parse_tree.hpp:757
lexy::_detail::pt_buffer::block
Definition: parse_tree.hpp:202
lexy::_pt_node::sibling_range::iterator::iterator
iterator() noexcept
Definition: parse_tree.hpp:963
lexy::_detail::pt_buffer::_cur_block
block * _cur_block
Definition: parse_tree.hpp:330
lexy::_pt_node::children_range::iterator
Definition: parse_tree.hpp:886
lexy::_detail::memory_resource_ptr
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
Definition: memory_resource.hpp:140
lexy::_pt_node::sibling_range::end
iterator end() const noexcept
Definition: parse_tree.hpp:1004
lexy::parse_tree::traverse_range::iterator::equal
bool equal(iterator rhs) const noexcept
Definition: parse_tree.hpp:1170
lexy::_pt_node::token
auto token() const noexcept
Definition: parse_tree.hpp:1072
iterator.hpp
lexy::_detail::pt_buffer::~pt_buffer
~pt_buffer() noexcept
Definition: parse_tree.hpp:242
lexy::parse_tree::builder::marker::unwind_pos
void * unwind_pos
Definition: parse_tree.hpp:436
config.hpp
lexy::_detail::pt_buffer::_cur_pos
unsigned char * _cur_pos
Definition: parse_tree.hpp:331
lexy::_pt_node::children_range::size
std::size_t size() const noexcept
Definition: parse_tree.hpp:919
lexy::_detail::pt_node::next_node
pt_node< Reader > * next_node() const noexcept
Definition: parse_tree.hpp:70
lexy::_pt_node::children_range::end
iterator end() const noexcept
Definition: parse_tree.hpp:934
lexy::parse_events
Definition: trace.hpp:14
lexy::_detail::get_memory_resource
constexpr MemoryResource * get_memory_resource()
Definition: memory_resource.hpp:145
lexy::_detail::pt_node::as_token
auto as_token() noexcept
Definition: parse_tree.hpp:46
lexy::_detail::pt_node::as_production
auto as_production() noexcept
Definition: parse_tree.hpp:50
lexy::_pt_node::children_range::iterator::children_range
friend children_range
Definition: parse_tree.hpp:911
lexy::parse_tree::traverse
traverse_range traverse() const noexcept
Definition: parse_tree.hpp:397
lexy::_detail::pt_node::role_parent
static constexpr auto role_parent
Definition: parse_tree.hpp:38
lexy::token_kind::ignore_if_empty
constexpr bool ignore_if_empty() const noexcept
Definition: token.hpp:165
lexy::parse_tree::parse_tree
constexpr parse_tree(MemoryResource *resource)
Definition: parse_tree.hpp:353
lexy::parse_tree::builder::marker::first_child
_detail::pt_node< Reader > * first_child
Definition: parse_tree.hpp:443
lexy::parse_tree::builder::_cur
marker _cur
Definition: parse_tree.hpp:758
lexy::parse_tree::builder::set_container_production
void set_container_production(production_info production)
Definition: parse_tree.hpp:659
lexy::traverse_event::exit
@ exit
We're visiting a production node after all its children.
lexy::parse_tree::builder::marker::prod
_detail::pt_node_production< Reader > * prod
Definition: parse_tree.hpp:439
lexy::_detail::pt_buffer::pt_buffer
pt_buffer(pt_buffer &&other) noexcept
Definition: parse_tree.hpp:234
lexy::_detail::pt_buffer::block::allocate
static block * allocate(resource_ptr resource)
Definition: parse_tree.hpp:207
lexy::_pt_node_kind::is_token_production
bool is_token_production() const noexcept
Definition: parse_tree.hpp:781
lexy::_pt_node::children_range::iterator::_cur
_detail::pt_node< Reader > * _cur
Definition: parse_tree.hpp:909
lexy::_detail::pt_buffer::block::memory
unsigned char memory[block_size]
Definition: parse_tree.hpp:205
lexy::token
A parsed token, i.e. its kind and its lexeme.
Definition: token.hpp:226
lexy::_detail::pt_buffer::block::end
unsigned char * end() noexcept
Definition: parse_tree.hpp:222
lexy::parse_tree::traverse_range::iterator::increment
void increment() noexcept
Definition: parse_tree.hpp:1131
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:30
lexy::_detail::pt_node::_value
std::uintptr_t _value
Definition: parse_tree.hpp:98
lexy::_pt_node::operator!=
friend bool operator!=(_pt_node lhs, _pt_node rhs) noexcept
Definition: parse_tree.hpp:1085
token.hpp
lexy::parse_tree::builder::builder
builder(production_info production)
Definition: parse_tree.hpp:561
lexy::_detail::pt_node::type_token
static constexpr auto type_token
Definition: parse_tree.hpp:34
lexy::parse_tree_input_traits
Definition: parse_tree_input.hpp:19
lexy::_detail::next
constexpr Iterator next(Iterator iter)
Definition: iterator.hpp:38
lexy::parse_tree::builder::marker::insert_children_into
void insert_children_into(_detail::pt_node_production< Reader > *parent)
Definition: parse_tree.hpp:502
lexy::_pt_node::children_range::iterator::iterator
iterator(_detail::pt_node< Reader > *ptr) noexcept
Definition: parse_tree.hpp:907
lexy::parse_tree::builder::builder
builder(parse_tree &&tree, production_info production)
Definition: parse_tree.hpp:546
lexy::_pt_node_kind::is_production
bool is_production() const noexcept
Definition: parse_tree.hpp:769
lexy::_pt_node::children_range::iterator::equal
bool equal(iterator rhs) const noexcept
Definition: parse_tree.hpp:901
lexy::_pt_node_kind::operator==
friend bool operator==(_pt_node_kind nk, production_info info)
Definition: parse_tree.hpp:831
lexy::_pt_node::position
auto position() const noexcept -> typename Reader::iterator
Definition: parse_tree.hpp:1029
lexy::_pt_node::sibling_range::iterator::sibling_range
friend sibling_range
Definition: parse_tree.hpp:990
lexy::parse_tree::builder::marker::child_count
std::size_t child_count
Definition: parse_tree.hpp:441
lexy
Definition: any_ref.hpp:12
lexy::_pt_node::children_range::iterator::iterator
iterator() noexcept
Definition: parse_tree.hpp:889
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
lexy::_pt_node::children
auto children() const noexcept
Definition: parse_tree.hpp:952
lexy::_pt_node::siblings
auto siblings() const noexcept
Definition: parse_tree.hpp:1018
lexy::_pt_node_kind::operator!=
friend bool operator!=(_pt_node_kind nk, token_kind< TokenKind > tk)
Definition: parse_tree.hpp:822
lexy::_pt_node::is_last_child
bool is_last_child() const noexcept
Definition: parse_tree.hpp:1023
lexy::_pt_node_kind::is_token
bool is_token() const noexcept
Definition: parse_tree.hpp:765
lexy::_detail::pt_node_token::begin
Reader::iterator begin
Definition: parse_tree.hpp:111
lexy::_detail::pt_buffer::reserve
void reserve(std::size_t size)
Definition: parse_tree.hpp:273
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
lexy::_pt_node::sibling_range::iterator::iterator
iterator(_detail::pt_node< Reader > *ptr) noexcept
Definition: parse_tree.hpp:986
lexy::_pt_node::covering_lexeme
auto covering_lexeme() const noexcept
Definition: parse_tree.hpp:1050
lexy::parse_tree::builder::finish_production
void finish_production(marker &&m)
Definition: parse_tree.hpp:612
lexy::_pt_node_kind::operator==
friend bool operator==(_pt_node_kind lhs, _pt_node_kind rhs)
Definition: parse_tree.hpp:799
lexy::_detail::pt_buffer::_head
block * _head
Definition: parse_tree.hpp:328
grammar.hpp
lexy::parse_tree::traverse_range::begin
iterator begin() const noexcept
Definition: parse_tree.hpp:1187
lexy::_pt_node::sibling_range::iterator::increment
void increment() noexcept
Definition: parse_tree.hpp:970
lexy::_pt_node::children_range::empty
bool empty() const noexcept
Definition: parse_tree.hpp:914
lexy::_pt_node_kind::_pt_node_kind
_pt_node_kind(_detail::pt_node< Reader > *ptr)
Definition: parse_tree.hpp:849
lexy::_detail::pt_node_token::update_end
void update_end(typename Reader::iterator end) noexcept
Definition: parse_tree.hpp:130
lexy::_pt_node::sibling_range::empty
bool empty() const noexcept
Definition: parse_tree.hpp:993
lexy::parse_tree::traverse_range::end
iterator end() const noexcept
Definition: parse_tree.hpp:1192
lexy::_detail::pt_node::set_parent
void set_parent(pt_node_production< Reader > *parent) noexcept
Definition: parse_tree.hpp:60
lexy::_pt_node_kind::operator!=
friend bool operator!=(_pt_node_kind nk, production_info info)
Definition: parse_tree.hpp:839
lexy::_pt_node::sibling_range::iterator::equal
bool equal(iterator rhs) const noexcept
Definition: parse_tree.hpp:980
lexy::parse_tree::builder::marker::last_child
_detail::pt_node< Reader > * last_child
Definition: parse_tree.hpp:444
lexy::_pt_node::children_range::begin
iterator begin() const noexcept
Definition: parse_tree.hpp:927
lexy::_pt_node::children_range::_pt_node
friend _pt_node
Definition: parse_tree.hpp:949
lexy::parse_tree::builder::finish
parse_tree && finish(typename Reader::iterator end) &&
Definition: parse_tree.hpp:568
lexy::token::kind
constexpr token_kind< TokenKind > kind() const noexcept
Definition: token.hpp:242
lexy::_detail::pt_node::role_sibling
static constexpr auto role_sibling
Definition: parse_tree.hpp:37
lexy::parse_tree::traverse_range::parse_tree
friend parse_tree
Definition: parse_tree.hpp:1221
lexy::parse_tree::_root
_detail::pt_node_production< Reader > * _root
Definition: parse_tree.hpp:417
lexy::_pt_node_kind::operator==
friend bool operator==(token_kind< TokenKind > tk, _pt_node_kind nk)
Definition: parse_tree.hpp:818
lexy::parse_tree::builder::finish_container
void finish_container(marker &&m)
Definition: parse_tree.hpp:697
lexy::_detail::pt_node_token::_end_t
std::conditional_t< _optimize_end, std::uint_least32_t, typename Reader::iterator > _end_t
Definition: parse_tree.hpp:109
lexy::parse_tree::clear
void clear() noexcept
Definition: parse_tree.hpp:374
lexy::_detail::pt_node_token::pt_node_token
pt_node_token(std::uint_least16_t kind, typename Reader::iterator begin, typename Reader::iterator end) noexcept
Definition: parse_tree.hpp:115
lexy::token_kind
What sort of token it is.
Definition: token.hpp:99
lexy::_pt_node_kind::operator!=
friend bool operator!=(token_kind< TokenKind > tk, _pt_node_kind nk)
Definition: parse_tree.hpp:826
lexy::parse_tree::builder::start_production
auto start_production(production_info production)
Definition: parse_tree.hpp:590
lexy::_detail::pt_node_production::first_child_adjacent
std::size_t first_child_adjacent
Definition: parse_tree.hpp:159
lexy::_detail::swap
constexpr void swap(T &lhs, T &rhs)
Definition: config.hpp:53
lexy::_detail::pt_node::_make_packed_ptr
static std::uintptr_t _make_packed_ptr(pt_node< Reader > *ptr, unsigned type, unsigned role)
Definition: parse_tree.hpp:84
lexy::_detail::pt_node_token::end_impl
_end_t end_impl
Definition: parse_tree.hpp:112
lexy::_detail::pt_node_production::id
const char *const * id
Definition: parse_tree.hpp:156
lexy_ext::child
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.
Definition: parse_tree_algorithm.hpp:244
lexy::parse_tree::builder::marker::cur_depth
std::size_t cur_depth
Definition: parse_tree.hpp:448
lexy::_detail::pt_buffer::block::deallocate
static block * deallocate(resource_ptr resource, block *ptr)
Definition: parse_tree.hpp:215
lexy::_detail::pt_buffer::operator=
pt_buffer & operator=(pt_buffer &&other) noexcept
Definition: parse_tree.hpp:249
lexy::token_kind::from_raw
static constexpr token_kind< TokenKind > from_raw(std::uint_least16_t kind) noexcept
Definition: token.hpp:203
lexy::production_info::is_transparent
bool is_transparent
Definition: grammar.hpp:197
lexy::parse_tree::builder
Definition: parse_tree.hpp:426
lexy::parse_tree::builder::marker::builder
friend builder
Definition: parse_tree.hpp:542
lexy::traverse_event::leaf
@ leaf
We're visiting a token.
lexy::_detail::pt_buffer::_resource
LEXY_EMPTY_MEMBER resource_ptr _resource
Definition: parse_tree.hpp:327
lexy::parse_tree
Definition: parse_tree.hpp:344
lexy::_pt_node::sibling_range
Definition: parse_tree.hpp:957
lexy::parse_tree::builder::cancel_production
void cancel_production(marker &&m)
Definition: parse_tree.hpp:627
lexy::_pt_node::address
void * address() const noexcept
Definition: parse_tree.hpp:860
assert.hpp
lexy::parse_tree::_size
std::size_t _size
Definition: parse_tree.hpp:418
lexy::_pt_node::kind
auto kind() const noexcept
Definition: parse_tree.hpp:865
lexy::_detail::pt_node::type_production
static constexpr auto type_production
Definition: parse_tree.hpp:35
lexy::_detail::pt_node_production
Definition: parse_tree.hpp:28
lexy::_detail::pt_buffer::remaining_capacity
std::size_t remaining_capacity() const noexcept
Definition: parse_tree.hpp:322
lexy::error_token_kind
@ error_token_kind
Definition: grammar.hpp:86
lexy::_pt_node::children_range
Definition: parse_tree.hpp:883
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:417
lexy::_pt_node::_pt_node
_pt_node(_detail::pt_node< Reader > *ptr) noexcept
Definition: parse_tree.hpp:1091
lexy::_detail::pt_buffer::top
void * top()
Definition: parse_tree.hpp:298
lexy::_detail::pt_buffer
Definition: parse_tree.hpp:196
lexy::_pt_node_kind::operator==
friend bool operator==(production_info info, _pt_node_kind nk)
Definition: parse_tree.hpp:835
lexy::_pt_node_kind::operator!=
friend bool operator!=(production_info info, _pt_node_kind nk)
Definition: parse_tree.hpp:843
lexy::_pt_node_kind
Definition: parse_tree.hpp:339
lexy::_detail::pt_buffer::pt_buffer
constexpr pt_buffer(MemoryResource *resource) noexcept
Definition: parse_tree.hpp:230
lexy::traverse_event
traverse_event
Definition: parse_tree.hpp:1099
lexy::parse_tree::builder::start_container
marker start_container()
Definition: parse_tree.hpp:640
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
lexy::parse_tree::builder::marker::insert
void insert(_detail::pt_node< Reader > *child)
Definition: parse_tree.hpp:465
lexy::parse_tree::remaining_input
lexy::lexeme< Reader > remaining_input() const noexcept
Definition: parse_tree.hpp:406
lexy::_pt_node::sibling_range::_pt_node
friend _pt_node
Definition: parse_tree.hpp:1015
lexy::_pt_node::children_range::_node
_detail::pt_node< Reader > * _node
Definition: parse_tree.hpp:947
lexy::_detail::pt_node_production::child_count_bits
static constexpr std::size_t child_count_bits
Definition: parse_tree.hpp:154
lexy::_pt_node_kind::name
const char * name() const noexcept
Definition: parse_tree.hpp:786
lexy::_pt_node_kind::is_root
bool is_root() const noexcept
Definition: parse_tree.hpp:774
lexy::_detail::pt_buffer::resource_ptr
_detail::memory_resource_ptr< MemoryResource > resource_ptr
Definition: parse_tree.hpp:198
lexy::_pt_node
Definition: parse_tree.hpp:341
lexy::_detail::pt_node_token::kind
::uint_least16_t kind
Definition: parse_tree.hpp:113
lexy::_detail
Definition: any_ref.hpp:12
lexy::_detail::pt_buffer::block_size
static constexpr std::size_t block_size
Definition: parse_tree.hpp:200
lexy::_pt_node::lexeme
auto lexeme() const noexcept
Definition: parse_tree.hpp:1042
lexy::parse_tree::builder::cancel_container
void cancel_container(marker &&m)
Definition: parse_tree.hpp:713
lexy::parse_tree::traverse_range::iterator
Definition: parse_tree.hpp:1121
lexy::parse_tree::traverse_range::empty
bool empty() const noexcept
Definition: parse_tree.hpp:1182
lexy::_pt_node::sibling_range::sibling_range
sibling_range(_detail::pt_node< Reader > *node) noexcept
Definition: parse_tree.hpp:1011
lexy::_pt_node::sibling_range::iterator::deref
auto deref() const noexcept
Definition: parse_tree.hpp:965
lexy::parse_tree::builder::marker::local_max_depth
std::size_t local_max_depth
Definition: parse_tree.hpp:450
std
Definition: std.hpp:31
lexy::_detail::pt_node::set_sibling
void set_sibling(pt_node< Reader > *sibling) noexcept
Definition: parse_tree.hpp:56
lexy::lexeme
Definition: lexeme.hpp:16
lexy::parse_tree::traverse_range::iterator::deref
_value_type deref() const noexcept
Definition: parse_tree.hpp:1126
lexy::_pt_node::parent
auto parent() const noexcept
Definition: parse_tree.hpp:870
lexy::_detail::pt_node::type
unsigned type() const noexcept
Definition: parse_tree.hpp:41
lexy::parse_tree::_buffer
_detail::pt_buffer< MemoryResource > _buffer
Definition: parse_tree.hpp:416
lexy::_detail::pt_buffer::unwind
void unwind(void *marker) noexcept
Definition: parse_tree.hpp:303
lexy::parse_tree::builder::token
void token(token_kind< TokenKind > _kind, typename Reader::iterator begin, typename Reader::iterator end)
Definition: parse_tree.hpp:724
lexy::parse_tree::traverse_range::_value_type::node
parse_tree::node node
Definition: parse_tree.hpp:1118
lexy::parse_tree::parse_tree
constexpr parse_tree()
Definition: parse_tree.hpp:352
lexy::_detail::pt_buffer::reset
void reset()
Definition: parse_tree.hpp:264
lexy::_pt_node::operator==
friend bool operator==(_pt_node lhs, _pt_node rhs) noexcept
Definition: parse_tree.hpp:1081
lexy::parse_tree::empty
bool empty() const noexcept
Definition: parse_tree.hpp:358
lexy::lexeme
lexeme(const Reader &, typename Reader::iterator) -> lexeme< typename Reader::canonical_reader >
lexy::_pt_node::sibling_range::_node
_detail::pt_node< Reader > * _node
Definition: parse_tree.hpp:1013
lexy::_pt_node_kind::_ptr
_detail::pt_node< Reader > * _ptr
Definition: parse_tree.hpp:851
lexy::parse_tree::builder::finish
parse_tree && finish(lexy::lexeme< Reader > remaining_input) &&
Definition: parse_tree.hpp:572
lexy::production_info
Definition: grammar.hpp:192
lexy::parse_tree::builder::marker::update_size_depth
void update_size_depth(std::size_t &size, std::size_t &max_depth)
Definition: parse_tree.hpp:530
lexy::_detail::pt_node_token::end
Reader::iterator end() const noexcept
Definition: parse_tree.hpp:122
lexy::parse_tree::builder::marker::marker
marker()
Definition: parse_tree.hpp:432
lexy::_detail::pt_node_production::child_count
std::size_t child_count
Definition: parse_tree.hpp:157
lexy::parse_tree::builder::marker::marker
marker(void *unwind_pos, std::size_t cur_depth, _detail::pt_node_production< Reader > *prod=nullptr)
Definition: parse_tree.hpp:452
lexy::_detail::pt_node_production::pt_node_production
pt_node_production(production_info info) noexcept
Definition: parse_tree.hpp:161
lexy::_pt_node::sibling_range::iterator::_cur
_detail::pt_node< Reader > * _cur
Definition: parse_tree.hpp:988
LEXY_EMPTY_MEMBER
#define LEXY_EMPTY_MEMBER
Definition: config.hpp:193
lexy::_detail::forward_iterator_base
Definition: iterator.hpp:157
lexy::parse_tree::traverse_range::_value_type
Definition: parse_tree.hpp:1115
lexy::parse_tree::builder::marker::insert_list
void insert_list(std::size_t length, _detail::pt_node< Reader > *first, _detail::pt_node< Reader > *last)
Definition: parse_tree.hpp:482
lexy::parse_tree::size
std::size_t size() const noexcept
Definition: parse_tree.hpp:363
lexy::parse_tree::traverse_range::iterator::_ev
traverse_event _ev
Definition: parse_tree.hpp:1177
lexy::_pt_node::_ptr
_detail::pt_node< Reader > * _ptr
Definition: parse_tree.hpp:1093
lexy::parse_tree::traverse_range::_end
iterator _end
Definition: parse_tree.hpp:1219
lexy::parse_tree::node
_pt_node< Reader, TokenKind > node
Definition: parse_tree.hpp:382
lexy::_pt_node::children_range::iterator::deref
auto deref() const noexcept
Definition: parse_tree.hpp:891
lexy::parse_tree::traverse_range::iterator::traverse_range
friend traverse_range
Definition: parse_tree.hpp:1179
lexy::_detail::pt_buffer::block::next
block * next
Definition: parse_tree.hpp:204
lexy::_detail::pt_node_production::token_production
std::size_t token_production
Definition: parse_tree.hpp:158
lexy::_detail::pt_node_production::first_child
pt_node< Reader > * first_child()
Definition: parse_tree.hpp:169
lexy::traverse_event::enter
@ enter
We're visiting a production node before all its children.
lexy::_detail::pt_node_token
Definition: parse_tree.hpp:26
lexy::_detail::pt_buffer::allocate
T * allocate(Args &&... args)
Definition: parse_tree.hpp:285
lexy::_ptr
Definition: parse_tree_input.hpp:71
LEXY_ASSERT
#define LEXY_ASSERT(Expr, Msg)
Definition: assert.hpp:37
lexy::parse_tree::root
node root() const noexcept
Definition: parse_tree.hpp:384
lexy::parse_tree::depth
std::size_t depth() const noexcept
Definition: parse_tree.hpp:368
lexy::_detail::pt_node::next_role
unsigned next_role() const noexcept
Definition: parse_tree.hpp:65
lexy::parse_tree::builder::current_child_count
std::size_t current_child_count() const noexcept
Definition: parse_tree.hpp:751
lexy::token_kind::to_raw
static constexpr std::uint_least16_t to_raw(token_kind< TokenKind > kind) noexcept
Definition: token.hpp:199
lexy::_pt_node::sibling_range::iterator
Definition: parse_tree.hpp:960
memory_resource.hpp
lexy::_pt_node::children_range::children_range
children_range(_detail::pt_node< Reader > *node)
Definition: parse_tree.hpp:942
lexy::_pt_node_kind::operator!=
friend bool operator!=(_pt_node_kind lhs, _pt_node_kind rhs)
Definition: parse_tree.hpp:806
lexy::parse_tree::builder::marker::clear
void clear()
Definition: parse_tree.hpp:458


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Dec 13 2024 03:19:17