File: Tree.h

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (275 lines) | stat: -rw-r--r-- 7,390 bytes parent folder | download | duplicates (3)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#pragma once
#include "Core/Object.h"
#include "Core/GcArray.h"
#include "Core/PODArray.h"
#include "Syntax.h"
#include "Compiler/Syntax/InfoErrors.h"

namespace storm {
	namespace syntax {
		namespace glr {
			STORM_PKG(lang.bnf.glr);

			class TreeStore;
			extern const Nat countMask;
			extern const Nat errorMask;
			extern const Nat posMask;

			inline Nat read(TreeStore *src, Nat pos);
			inline void write(TreeStore *src, Nat pos, Nat val);

			/**
			 * Easy acces to an array of children from a TreeNode.
			 */
			class TreeArray {
				STORM_VALUE;
			public:
				// Does this array exist?
				inline Bool STORM_FN exists() const { return ptr != 0; }
				inline operator bool() const { return ptr != 0; }

				// Get number of elements.
				inline Nat STORM_FN count() const {
					return cnt;
				}

				// Any elements?
				inline Bool STORM_FN any() const { return count() > 0; }
				inline Bool STORM_FN empty() const { return count() == 0; }

				// Get element #n.
				inline Nat STORM_FN operator[] (Nat i) const {
					return read(src, ptr + i + 2);
				}

				// Set element #n.
				inline void STORM_FN set(Nat i, Nat v) const {
					write(src, ptr + i + 2, v);
				}

				// Get the reduced production.
				inline Nat STORM_FN production() const {
					return read(src, ptr + 1);
				}

			private:
				friend class TreeNode;
				inline TreeArray(TreeStore *in, Nat pos) {
					src = in;
					ptr = pos;
					cnt = read(src, ptr) & ~countMask;
				}

				// Access to data. Might be null.
				TreeStore *src;

				// Starting point of this node.
				Nat ptr;

				// Cached element count.
				Nat cnt;
			};


			/**
			 * Easy access to a tree node stored in TreeStore somewhere.
			 */
			class TreeNode {
				STORM_VALUE;
			public:
				// Get a 'pointer' to this node.
				inline Nat STORM_FN id() const {
					return ptr;
				}

				// Get the starting position of this node.
				inline Nat STORM_FN pos() const {
					return read(src, ptr) & posMask;
				}

				// Set the starting position of this node.
				inline void STORM_FN pos(Nat v) const {
					v &= posMask;
					v |= read(src, ptr) & ~posMask;
					return write(src, ptr, v);
				}

				// Is this a leaf node (ie. no children?).
				inline Bool STORM_FN leaf() const {
					Nat first = read(src, ptr);
					return (first & countMask) == 0;
				}

				// Get the child array.
				inline TreeArray STORM_FN children() const {
					Nat first = read(src, ptr);
					if ((first & countMask) == 0)
						return TreeArray(src, 0);

					Nat offset = 1;
					offset += (first & errorMask) != 0;

					Nat pos = read(src, ptr + offset);
					if (pos & countMask) {
						return TreeArray(src, ptr + offset);
					} else {
						return TreeArray(src, pos);
					}
				}

				// Get the number of errors encountered to reach this node.
				inline InfoErrors STORM_FN errors() const {
					if ((read(src, ptr) & errorMask) == 0)
						return infoSuccess();
					else
						return InfoErrors::fromData(read(src, ptr + 1));
				}

				// Replace the contents of this node with another. This is only doable if both this
				// and the other tree node have children. Unable to set 'errors' in some cases.
				void STORM_FN replace(const TreeNode &other);

				// Get the production.
				inline Nat STORM_FN production() const {
					return children().production();
				}

			private:
				friend class TreeStore;

				// Create with a 'pointer' to the first entry used by this node.
				inline TreeNode(TreeStore *in, Nat pos) {
					src = in;
					ptr = pos;
				}

				// Access to data.
				TreeStore *src;

				// Starting point of this node.
				Nat ptr;
			};


			/**
			 * Batch allocation of tree nodes. Note: Element #0 is always empty (acts as the null pointer).
			 *
			 * This is just an array of Nat elements. The classes TreeNode and TreeArray just read
			 * from here. Nodes are stored as follows (one entry per item):
			 * - position this node started in the input string. If msb of the position is set, this node
			 *   contains children. If the next msb is set, this node also contains an error count.
			 * - number of children / 'pointer' to the data array. If msb is set, then this is a count and the
			 *   child array is allocated right here. Otherwise, this is a pointer (possibly to null, which
			 *   equals no children) to the child array, starting with a number of children.
			 * - production reduced
			 * - pointer to child n (n times).
			 *
			 * Implements an array-like data structure where index lookup is constant time and
			 * growing is also (near)constant time.
			 */
			class TreeStore : public ObjectOn<Compiler> {
				STORM_CLASS;
			public:
				// Create.
				STORM_CTOR TreeStore(Syntax *syntax);

				// Item access.
				inline TreeNode at(Nat i) {
					return TreeNode(this, i);
				}

				// Add a new terminal node and return its ID.
				TreeNode push(Nat pos);

				// Add a new terminal node with a specific number of encountered errors.
				TreeNode push(Nat pos, InfoErrors errors);

				// Add a new nonterminal with a specific number of children.
				TreeNode push(Nat pos, Nat production, Nat children);

				// Add a new nonterminal with a specific number of encountered errors and a specific number of children.
				TreeNode push(Nat pos, Nat production, InfoErrors errors, Nat children);

				// Free a node deemed unneeded.
				void free(Nat node);

				// Priority for tree comparisions.
				enum Priority {
					higher,
					equal,
					lower,
				};

				// Find out if a node has a higher priority compared to another.
				Priority STORM_FN priority(Nat a, Nat b);

				// See if the node 'haystack' contains node 'needle'.
				Bool STORM_FN contains(Nat haystack, Nat needle);

				// Size information.
				inline Nat STORM_FN count() const { return size; }
				inline Nat STORM_FN byteCount() const { return size*sizeof(Nat); }

				/**
				 * Interface that TreeNode and TreeArray are supposed to use.
				 */

				// Low-level access.
				inline Nat read(Nat i) const {
					return chunks->v[chunkId(i)]->v[chunkOffset(i)];
				}

				inline void write(Nat i, Nat v) const {
					chunks->v[chunkId(i)]->v[chunkOffset(i)] = v;
				}

			private:
				enum {
					// Bits used for each chunk.
					chunkBits = 8,
					// Elements per chunk. Assumed to be a power of two.
					chunkSize = 1 << chunkBits,
				};

				// Compute the chunk id and the chunk offset.
				inline Nat chunkId(Nat id) const { return id >> chunkBits; }
				inline Nat chunkOffset(Nat id) const { return id & (chunkSize - 1); }

				// List of all chunks.
				typedef GcArray<Nat> Chunk;
				GcArray<Chunk *> *chunks;

				// Current number of elements.
				Nat size;

				// Last allocated node ptr.
				Nat lastAlloc;

				// Remember the syntax.
				Syntax *syntax;

				// Allocate room for 'n' more items.
				Nat alloc(Nat n);

				// Grow 'chunks'.
				void grow();

				// Type for storing the expanded list of children.
				typedef PODArray<Nat, 40> ChildArray;

				// Traverse the node 'x' and find all subtrees wrt to pseudoproductions.
				void allChildren(ChildArray &out, Nat productionId, TreeNode &node);
				bool addNode(ChildArray &out, Nat productionId, Nat node);
			};

			inline Nat read(TreeStore *src, Nat pos) {
				return src->read(pos);
			}

			inline void write(TreeStore *src, Nat pos, Nat val) {
				src->write(pos, val);
			}

		}
	}
}