File: InfoNode.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; 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 (232 lines) | stat: -rw-r--r-- 6,940 bytes parent folder | download
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
#pragma once
#include "Core/Str.h"
#include "Compiler/Thread.h"
#include "TokenColor.h"
#include "Token.h"
#include "InfoIndent.h"

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

		class Production;
		class InfoInternal;
		class InfoLeaf;
		class Node;

		/**
		 * Syntax nodes containing all information about a parse. The main difference from 'Node' is
		 * that this representation contains all nodes, where 'Node' only contain the nodes the
		 * author of the syntax deemed interesting for generating further intermediate
		 * representations. This representation is also able to represent partial parses.
		 *
		 * A partial match is represented as usual, but the partial match may contain string nodes
		 * where an internal node would otherwise be expected. This represents failure to match a
		 * non-terminal.
		 *
		 * This representation is mainly intended for operations like syntax highlighting and
		 * indentation. It is also possible to incrementally update this representation when changes
		 * have been made to the source string since the nodes do not contain any absolute offsets
		 * into the original string.
		 *
		 * TODO: Skip ObjectOn<Compiler> to save some memory.
		 */
		class InfoNode : public ObjectOn<Compiler> {
			STORM_CLASS;
		public:
			// Create.
			STORM_CTOR InfoNode();

			// Specified color of this node.
			TokenColor color;

			// Length of this match (in codepoints).
			Nat STORM_FN length();

			// Error occured during parsing of this node?
			Bool STORM_FN error() const;
			void STORM_FN error(Bool v);

			// Does this node represent a node captured using a delimiter in the grammar?
			Bool STORM_FN delimiter() const;
			void STORM_FN delimiter(Bool v);

			// Find the first leaf node with a non-zero length at position `pos` relative to this
			// node. `pos` is a number of codepoints in the input string.
			virtual MAYBE(InfoLeaf *) STORM_FN leafAt(Nat pos);

			// Find the indentation of characters at offset 'pos'. This returns either an absolute
			// number of indentation levels, or another position which indicates that the
			// indentation should be the same as the indentation on that line.
			virtual TextIndent STORM_FN indentAt(Nat pos);

			// Format this info node into a human-readable representation.
			Str *STORM_FN format() const;

			// Generate the formatted string.
			virtual void STORM_FN format(StrBuf *to) const;

			// Get our parent.
			MAYBE(InfoInternal *) STORM_FN parent() const { return parentNode; }

			// Set parent.
			inline void parent(InfoInternal *n) { parentNode = n; }

			// Get the size of this node.
			virtual Nat STORM_FN dbg_size();

		protected:
			// Compute the length of this node.
			virtual Nat STORM_FN computeLength();

			// Invalidate any pre-computed data. Also invalidate any parent nodes.
			void STORM_FN invalidate();

		private:
			// Parent node.
			InfoInternal *parentNode;

			// Data stored here. Stores:
			// msb: set if an error was corrected within this node (ignoring child nodes).
			// rest: cached length of this node. If set to all ones: the length needs to be re-computed.
			Nat data;

			// Masks for 'data'.
			static const Nat errorMask;
			static const Nat delimMask;
			static const Nat lengthMask;
		};


		/**
		 * Internal node. Contains a fixed number of children.
		 */
		class InfoInternal : public InfoNode {
			STORM_CLASS;
		public:
			// Create and allocate space for a pre-defined number of child nodes. Make sure to
			// initialize all elements in the array before letting Storm access this node!
			InfoInternal(Production *prod, Nat children);

			// Create a copy of another node with a different number of elements.
			InfoInternal(InfoInternal *src, Nat children);

			// Information about indentation.
			MAYBE(InfoIndent *) indent;

			// Get our production.
			inline MAYBE(Production *) STORM_FN production() const { return prod; }

			// Number of children.
			inline Nat STORM_FN count() const {
				return Nat(children->count);
			}

			// Get child at offset.
			inline InfoNode *STORM_FN operator [](Nat id) { return at(id); }
			InfoNode *at(Nat id) {
				if (id < count()) {
					return children->v[id];
				} else {
					outOfBounds(id);
					return children->v[0];
				}
			}

			// Set child at offset.
			void STORM_FN set(Nat id, InfoNode *node);

			// Find the first leaf node at position 'pos' relative to this node.
			virtual MAYBE(InfoLeaf *) STORM_FN leafAt(Nat pos);

			// Find the indentation for 'pos'.
			virtual TextIndent STORM_FN indentAt(Nat pos);

			// Create a "normal" syntax tree from this internal node. It assumes (but checks) that
			// this segment of the syntax tree still represents a valid parse according to the
			// grammar. Note that this function is mostly provided to avoid having to re-parse a
			// string if one needs to inspect the info tree first and then extract a syntax tree of
			// some subset later. If you need the parse tree at a later stage, it is often faster to
			// just rely on `Parser:tree` directly.
			//
			// The `url` and `start` parameters are used to create `SrcPos` instances in the parse
			// tree. If `start` is not provided, then 0 is assumed.
			Node *STORM_FN tree(Url *url);
			Node *STORM_FN tree(Url *url, Nat start);

			// To string.
			virtual void STORM_FN toS(StrBuf *to) const;

			// Format.
			using InfoNode::format;
			virtual void STORM_FN format(StrBuf *to) const;

			// Get the size of this node.
			virtual Nat STORM_FN dbg_size();

		protected:
			// Compute the lenght of this node.
			virtual Nat STORM_FN computeLength();

		private:
			// Instance of which production?
			Production *prod;

			// Data.
			GcArray<InfoNode *> *children;

			// Throw out of bounds error.
			void outOfBounds(Nat id);
		};


		/**
		 * Leaf node. Contains the string matched at the leaf.
		 */
		class InfoLeaf : public InfoNode {
			STORM_CLASS;
		public:
			// Create.
			STORM_CTOR InfoLeaf(MAYBE(RegexToken *) regex, Str *match);

			// Find leaf nodes.
			virtual MAYBE(InfoLeaf *) STORM_FN leafAt(Nat pos);

			// Set value.
			void set(Str *v);

			// Get the matching regex.
			inline MAYBE(RegexToken *) STORM_FN matches() const { return regex; }

			// Does the content of this node match the regex in here? Returns 'false' if this node
			// does not contain a regex.
			Bool STORM_FN matchesRegex() const;
			Bool STORM_FN matchesRegex(Str *v) const;

			// To string.
			virtual Str *STORM_FN toS() const;

			// To string.
			virtual void STORM_FN toS(StrBuf *to) const;

			// Format.
			using InfoNode::format;
			virtual void STORM_FN format(StrBuf *to) const;

			// Get the size of this node.
			virtual Nat STORM_FN dbg_size();

		protected:
			// Compute the lenght of this node.
			virtual Nat STORM_FN computeLength();

		private:
			// Which regex did this leaf match?
			MAYBE(RegexToken *) regex;

			// The matched string.
			Str *v;
		};

	}
}