File: Functional.hh

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (124 lines) | stat: -rw-r--r-- 3,259 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

#pragma once

#include <functional>
#include "Storage.hh"

namespace cadabra {

	/// \ingroup core
	///
	/// Apply a function on every element of a list, or if the iterator
	/// 'it' does not point to a list, only on that single
	/// element. Handles lists wrapped in an \expression node as well.
	/// It is safe to remove the node pointed to by 'it' in 'f'.
	/// If your 'f' returns false, the loop is aborted immediately.

	void do_list(const Ex& tr, Ex::iterator it, std::function<bool(Ex::iterator)> f);

	/// \ingroup core
	///
	/// For lists as defined above for 'do_list', return their size (in case you
	/// really need to know the size before iterating over the elements).

	int list_size(const Ex& tr, Ex::iterator it);

	/// \ingroup core
	///
	/// Returns an iterator to the first element for which 'f' does not return tr.end().

	Ex::iterator find_in_list(const Ex& tr, Ex::iterator it, std::function<Ex::iterator(Ex::iterator)> f);

	/// \ingroup core
	///
	/// Returns an iterator to the first element for which 'f' returns 'true', or 'tr.end()'.

	Ex::iterator find_in_subtree(const Ex& tr, Ex::iterator it, std::function<bool(Ex::iterator)> f, bool including_head=true);

	/// \ingroup core
	///
	/// Ensure that the tree is a list, even if it contains only a single element.

	Ex make_list(Ex el);



	/// \ingroup core
	///
	/// Apply a function on every node in the tree at and below the
	/// given node, depth-first. Return an iterator to the top node,
	/// which replaces 'it' (may be the same).

	template<typename T>
	typename T::iterator do_subtree(const T& tr, typename T::iterator it, std::function<typename T::iterator(typename T::iterator)> f)
		{
		if(it==tr.end()) return it;

		class T::post_order_iterator walk=it, last=it;
		++last;
		walk.descend_all();

		do {
			auto nxt=walk;
			++nxt;

			bool cpy=false;
			if(walk==it) cpy=true;
			walk = f(walk);
			if(cpy) it=walk;

			walk=nxt;
			}
		while(walk!=last);

		return it;
		}

	// Iterate over the children of 'it' if the node is named 'delim', otherwise only
	// iterate over the single node. Note: this yields iterators, not str_nodes.
	struct split_it
	{
		struct iterator {
			using value_type = Ex::sibling_iterator;
			using difference_type = ptrdiff_t;
			using reference = value_type&;
			using const_reference = const value_type&;
			using pointer = value_type*;
			using const_pointer = const value_type*;
			using iterator_category = std::input_iterator_tag;

			iterator() {}
			iterator(Ex::sibling_iterator it) : it(it) {}

			bool operator == (const iterator& other) { return it == other.it; }
			bool operator != (const iterator& other) { return !(*this == other); }
			reference operator* () { return it; }
			pointer operator-> () { return &it; }
			reference operator ++ () { return ++it; }
			value_type operator ++ (int) { return it++; }


			Ex::sibling_iterator it;
		};

		split_it(Ex::iterator it, const std::string& delim = "")
		{
			if (delim == "" || *it->name == delim) {
				begin_ = it.begin();
				end_ = it.end();
			}
			else {
				begin_ = it;
				end_ = it;
				++end_;
			}
		}

		iterator begin() { return iterator(begin_); }
		iterator end() { return iterator(end_); }

	private:
		Ex::sibling_iterator begin_, end_;
	};

	};