File: Production.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 (217 lines) | stat: -rw-r--r-- 6,155 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
#pragma once
#include "Decl.h"
#include "Token.h"
#include "Delimiters.h"
#include "Compiler/Type.h"
#include "Compiler/Scope.h"

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

		class Production;
		class ProductionType;

		/**
		 * Iterator for a production.
		 *
		 * This iterator does not follow the convention in Storm, since productions are not
		 * deterministic. This nondeterminism is due to the ?, + and * operators. However, it is
		 * only ever possible to enter two new states from an existing state, which is why nextA and
		 * nextB suffice. firstA and nextA are just advancing through the linear stream of tokens
		 * while firstB and nextB account for any jumps that may occur in the sequence.
		 */
		class ProductionIter {
			STORM_VALUE;
			friend class Production;
		public:
			// Create an invalid iterator.
			STORM_CTOR ProductionIter();

			// Are we at the end of the iteration?
			Bool STORM_FN end() const;

			// Is this a valid iterator?
			Bool STORM_FN valid() const;

			// Get the two iterators which follow this. Returns an iterator where 'valid' == false
			// if the operation is not feasible.
			ProductionIter STORM_FN nextA() const;
			ProductionIter STORM_FN nextB() const;

			// Compare for equality.
			Bool STORM_FN operator ==(const ProductionIter &o) const;
			Bool STORM_FN operator !=(const ProductionIter &o) const;

			// At start/end of repeat?
			Bool STORM_FN repStart() const;
			Bool STORM_FN repEnd() const;

			// Get the position in the production.
			inline Nat STORM_FN position() const { return pos; }

			// Get the rule this production is a part of.
			MAYBE(Rule *) STORM_FN rule() const;

			// Get the production we're a part of.
			MAYBE(Production *) STORM_FN production() const;

			// Get the current token.
			MAYBE(Token *) STORM_FN token() const;

			// Output.
			void STORM_FN toS(StrBuf *to) const;

		private:
			// Create.
			ProductionIter(Production *p, Nat pos);

			// The production we refer to.
			Production *p;

			// Position into the option's tokens.
			Nat pos;
		};

		wostream &operator <<(wostream &to, const ProductionIter &o);


		/**
		 * Syntax production.
		 */
		class Production : public ObjectOn<Compiler> {
			STORM_CLASS;
		public:
			// Create with no parent.
			STORM_CTOR Production();

			// Create, but populate manually.
			STORM_CTOR Production(ProductionType *owner);

			// Create.
			STORM_CTOR Production(ProductionType *owner, ProductionDecl *decl, Delimiters *delim, Scope scope);

			// Owning rule.
			MAYBE(Rule *) STORM_FN rule() const;

			// Owning type.
			MAYBE(ProductionType *) STORM_FN type() const;

			// Parent syntax element. When parsing, this element needs to be an indirect parent of
			// this production. Otherwise this production should not be considered.
			MAYBE(Rule *) parent;

			// Tokens.
			Array<Token *> *tokens;

			// Priority.
			Int priority;

			// Repeat logic.
			Nat repStart;
			Nat repEnd;
			RepType repType;

			// Indentation logic.
			Nat indentStart;
			Nat indentEnd;
			IndentType indentType;

			// Capture a raw string between repStart and repEnd?
			MAYBE(Token *) repCapture;

			// Is the position 'n' inside a repeat?
			Bool STORM_FN inRepeat(Nat pos) const;

			// Create iterators.
			ProductionIter STORM_FN firstA();
			ProductionIter STORM_FN firstB();

			// Create an iterator at a specific position.
			ProductionIter STORM_FN posIter(Nat pos);

			// Result, if given.
			MAYBE(Name *) result;

			// Parameters to the result, if any.
			MAYBE(Array<Str *> *) resultParams;

			// Output.
			virtual void STORM_FN toS(StrBuf *to) const;
			void STORM_FN toS(StrBuf *to, Nat mark) const;
			void STORM_FN toS(StrBuf *to, Nat mark, Bool bindings) const;

		private:
			// Owner.
			ProductionType *owner;

			// Output the end of a repeat.
			void outputRepEnd(StrBuf *to, Bool bindings) const;

			// Add a single token here.
			void addToken(TokenDecl *decl, Delimiters *delim, SrcPos pos, Scope scope, Nat &counter);

			// Create a target for a token (if needed).
			MAYBE(MemberVar *) createTarget(SrcPos pos, Value type, TokenDecl *token, Nat &counter);
			MAYBE(MemberVar *) createTarget(SrcPos p, TokenDecl *decl, Token *token, Nat pos, Nat &counter);
		};


		/**
		 * The type used to name and find a syntax option.
		 *
		 * This is represented as a type which inherits from a Rule type. This class will override
		 * the 'transform' of the parent type.
		 *
		 * These types also contain variables representing the syntax trees for the captured parts
		 * of the production. Tokens captured outside of any repetition are stored as regular
		 * variables, tokens repeated zero or one time are stored as Maybe<T> and parts that are
		 * repeated zero or more times are stored as Array<T>.
		 *
		 * Note: Types created by this does not currently have any constructor except the copy
		 * constructor. The parser will create these using a custom (read hacky) constructor to keep
		 * it clean and simple. However, we do want to add a constructor that can initialize all
		 * members properly.
		 */
		class ProductionType : public Type {
			STORM_CLASS;
		public:
			// Create.
			STORM_CTOR ProductionType(Str *name, ProductionDecl *decl, Delimiters *delim, Scope scope);

			// Create, populate manually later.
			STORM_CTOR ProductionType(SrcPos pos, Str *name, Rule *rule);

			// Production.
			Production *production;

			// Get the owner rule.
			Rule *STORM_FN rule() const;

			// All members needing initialization (ie. arrays).
			Array<MemberVar *> *arrayMembers;

			// Add members.
			virtual void STORM_FN add(Named *m);

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

		protected:
			// Load contents.
			virtual Bool STORM_FN loadAll();

			// Create custom functions. Called from 'loadAll'. The default implementation creates
			// 'children' and 'transform'.
			virtual void STORM_FN loadFunctions(ProductionDecl *decl, Scope scope);

		private:
			// The declaration, stored only until the first time 'loadAll' is called.
			MAYBE(ProductionDecl *) decl;

			// Save the scope for a while.
			Scope scope;
		};

	}
}