1 module parser;
2 
3 import std.typecons : RefCounted, refCounted;
4 import std.format : format;
5 import ast;
6 import tokenmodule;
7 
8 import lexer;
9 
10 import exception;
11 
12 struct Parser {
13 	import std.array : appender;
14 
15 	import std.format : formattedWrite;
16 
17 	Lexer lex;
18 
19 	this(Lexer lex) {
20 		this.lex = lex;
21 	}
22 
23 	bool firstDocument() const pure @nogc @safe {
24 		return this.firstDefinitions();
25 	}
26 
27 	Document parseDocument() {
28 		try {
29 			return this.parseDocumentImpl();
30 		} catch(ParseException e) {
31 			throw new ParseException(
32 				"While parsing a Document an Exception was thrown.",
33 				e, __FILE__, __LINE__
34 			);
35 		}
36 	}
37 
38 	Document parseDocumentImpl() {
39 		string[] subRules;
40 		subRules = ["Defi"];
41 		if(this.firstDefinitions()) {
42 			Definitions defs = this.parseDefinitions();
43 
44 			return new Document(DocumentEnum.Defi
45 				, defs
46 			);
47 		}
48 		auto app = appender!string();
49 		formattedWrite(app, 
50 			"Found a '%s' while looking for", 
51 			this.lex.front
52 		);
53 		throw new ParseException(app.data,
54 			__FILE__, __LINE__,
55 			subRules,
56 			["directive -> Definition","enum_ -> Definition","extend -> Definition","fragment -> Definition","input -> Definition","interface_ -> Definition","lcurly -> Definition","mutation -> Definition","query -> Definition","scalar -> Definition","schema -> Definition","subscription -> Definition","type -> Definition","union_ -> Definition"]
57 		);
58 
59 	}
60 
61 	bool firstDefinitions() const pure @nogc @safe {
62 		return this.firstDefinition();
63 	}
64 
65 	Definitions parseDefinitions() {
66 		try {
67 			return this.parseDefinitionsImpl();
68 		} catch(ParseException e) {
69 			throw new ParseException(
70 				"While parsing a Definitions an Exception was thrown.",
71 				e, __FILE__, __LINE__
72 			);
73 		}
74 	}
75 
76 	Definitions parseDefinitionsImpl() {
77 		string[] subRules;
78 		subRules = ["Def", "Defs"];
79 		if(this.firstDefinition()) {
80 			Definition def = this.parseDefinition();
81 			subRules = ["Defs"];
82 			if(this.firstDefinitions()) {
83 				Definitions follow = this.parseDefinitions();
84 
85 				return new Definitions(DefinitionsEnum.Defs
86 					, def
87 					, follow
88 				);
89 			}
90 			return new Definitions(DefinitionsEnum.Def
91 				, def
92 			);
93 		}
94 		auto app = appender!string();
95 		formattedWrite(app, 
96 			"Found a '%s' while looking for", 
97 			this.lex.front
98 		);
99 		throw new ParseException(app.data,
100 			__FILE__, __LINE__,
101 			subRules,
102 			["directive -> TypeSystemDefinition","enum_ -> TypeSystemDefinition","extend -> TypeSystemDefinition","fragment -> FragmentDefinition","input -> TypeSystemDefinition","interface_ -> TypeSystemDefinition","lcurly -> OperationDefinition","mutation -> OperationDefinition","query -> OperationDefinition","scalar -> TypeSystemDefinition","schema -> TypeSystemDefinition","subscription -> OperationDefinition","type -> TypeSystemDefinition","union_ -> TypeSystemDefinition"]
103 		);
104 
105 	}
106 
107 	bool firstDefinition() const pure @nogc @safe {
108 		return this.firstOperationDefinition()
109 			 || this.firstFragmentDefinition()
110 			 || this.firstTypeSystemDefinition();
111 	}
112 
113 	Definition parseDefinition() {
114 		try {
115 			return this.parseDefinitionImpl();
116 		} catch(ParseException e) {
117 			throw new ParseException(
118 				"While parsing a Definition an Exception was thrown.",
119 				e, __FILE__, __LINE__
120 			);
121 		}
122 	}
123 
124 	Definition parseDefinitionImpl() {
125 		string[] subRules;
126 		subRules = ["O"];
127 		if(this.firstOperationDefinition()) {
128 			OperationDefinition op = this.parseOperationDefinition();
129 
130 			return new Definition(DefinitionEnum.O
131 				, op
132 			);
133 		} else if(this.firstFragmentDefinition()) {
134 			FragmentDefinition frag = this.parseFragmentDefinition();
135 
136 			return new Definition(DefinitionEnum.F
137 				, frag
138 			);
139 		} else if(this.firstTypeSystemDefinition()) {
140 			TypeSystemDefinition type = this.parseTypeSystemDefinition();
141 
142 			return new Definition(DefinitionEnum.T
143 				, type
144 			);
145 		}
146 		auto app = appender!string();
147 		formattedWrite(app, 
148 			"Found a '%s' while looking for", 
149 			this.lex.front
150 		);
151 		throw new ParseException(app.data,
152 			__FILE__, __LINE__,
153 			subRules,
154 			["lcurly -> SelectionSet","mutation -> OperationType","query -> OperationType","subscription -> OperationType","fragment","directive -> DirectiveDefinition","enum_ -> TypeDefinition","extend -> TypeExtensionDefinition","input -> TypeDefinition","interface_ -> TypeDefinition","scalar -> TypeDefinition","schema -> SchemaDefinition","type -> TypeDefinition","union_ -> TypeDefinition"]
155 		);
156 
157 	}
158 
159 	bool firstOperationDefinition() const pure @nogc @safe {
160 		return this.firstSelectionSet()
161 			 || this.firstOperationType();
162 	}
163 
164 	OperationDefinition parseOperationDefinition() {
165 		try {
166 			return this.parseOperationDefinitionImpl();
167 		} catch(ParseException e) {
168 			throw new ParseException(
169 				"While parsing a OperationDefinition an Exception was thrown.",
170 				e, __FILE__, __LINE__
171 			);
172 		}
173 	}
174 
175 	OperationDefinition parseOperationDefinitionImpl() {
176 		string[] subRules;
177 		subRules = ["SelSet"];
178 		if(this.firstSelectionSet()) {
179 			SelectionSet ss = this.parseSelectionSet();
180 
181 			return new OperationDefinition(OperationDefinitionEnum.SelSet
182 				, ss
183 			);
184 		} else if(this.firstOperationType()) {
185 			OperationType ot = this.parseOperationType();
186 			subRules = ["OT_N", "OT_N_D", "OT_N_V", "OT_N_VD"];
187 			if(this.lex.front.type == TokenType.name) {
188 				Token name = this.lex.front;
189 				this.lex.popFront();
190 				subRules = ["OT_N_V", "OT_N_VD"];
191 				if(this.firstVariableDefinitions()) {
192 					VariableDefinitions vd = this.parseVariableDefinitions();
193 					subRules = ["OT_N_VD"];
194 					if(this.firstDirectives()) {
195 						Directives d = this.parseDirectives();
196 						subRules = ["OT_N_VD"];
197 						if(this.firstSelectionSet()) {
198 							SelectionSet ss = this.parseSelectionSet();
199 
200 							return new OperationDefinition(OperationDefinitionEnum.OT_N_VD
201 								, ot
202 								, name
203 								, vd
204 								, d
205 								, ss
206 							);
207 						}
208 						auto app = appender!string();
209 						formattedWrite(app, 
210 							"Found a '%s' while looking for", 
211 							this.lex.front
212 						);
213 						throw new ParseException(app.data,
214 							__FILE__, __LINE__,
215 							subRules,
216 							["lcurly"]
217 						);
218 
219 					} else if(this.firstSelectionSet()) {
220 						SelectionSet ss = this.parseSelectionSet();
221 
222 						return new OperationDefinition(OperationDefinitionEnum.OT_N_V
223 							, ot
224 							, name
225 							, vd
226 							, ss
227 						);
228 					}
229 					auto app = appender!string();
230 					formattedWrite(app, 
231 						"Found a '%s' while looking for", 
232 						this.lex.front
233 					);
234 					throw new ParseException(app.data,
235 						__FILE__, __LINE__,
236 						subRules,
237 						["at -> Directive","lcurly"]
238 					);
239 
240 				} else if(this.firstDirectives()) {
241 					Directives d = this.parseDirectives();
242 					subRules = ["OT_N_D"];
243 					if(this.firstSelectionSet()) {
244 						SelectionSet ss = this.parseSelectionSet();
245 
246 						return new OperationDefinition(OperationDefinitionEnum.OT_N_D
247 							, ot
248 							, name
249 							, d
250 							, ss
251 						);
252 					}
253 					auto app = appender!string();
254 					formattedWrite(app, 
255 						"Found a '%s' while looking for", 
256 						this.lex.front
257 					);
258 					throw new ParseException(app.data,
259 						__FILE__, __LINE__,
260 						subRules,
261 						["lcurly"]
262 					);
263 
264 				} else if(this.firstSelectionSet()) {
265 					SelectionSet ss = this.parseSelectionSet();
266 
267 					return new OperationDefinition(OperationDefinitionEnum.OT_N
268 						, ot
269 						, name
270 						, ss
271 					);
272 				}
273 				auto app = appender!string();
274 				formattedWrite(app, 
275 					"Found a '%s' while looking for", 
276 					this.lex.front
277 				);
278 				throw new ParseException(app.data,
279 					__FILE__, __LINE__,
280 					subRules,
281 					["lparen","at -> Directive","lcurly"]
282 				);
283 
284 			} else if(this.firstVariableDefinitions()) {
285 				VariableDefinitions vd = this.parseVariableDefinitions();
286 				subRules = ["OT_VD"];
287 				if(this.firstDirectives()) {
288 					Directives d = this.parseDirectives();
289 					subRules = ["OT_VD"];
290 					if(this.firstSelectionSet()) {
291 						SelectionSet ss = this.parseSelectionSet();
292 
293 						return new OperationDefinition(OperationDefinitionEnum.OT_VD
294 							, ot
295 							, vd
296 							, d
297 							, ss
298 						);
299 					}
300 					auto app = appender!string();
301 					formattedWrite(app, 
302 						"Found a '%s' while looking for", 
303 						this.lex.front
304 					);
305 					throw new ParseException(app.data,
306 						__FILE__, __LINE__,
307 						subRules,
308 						["lcurly"]
309 					);
310 
311 				} else if(this.firstSelectionSet()) {
312 					SelectionSet ss = this.parseSelectionSet();
313 
314 					return new OperationDefinition(OperationDefinitionEnum.OT_V
315 						, ot
316 						, vd
317 						, ss
318 					);
319 				}
320 				auto app = appender!string();
321 				formattedWrite(app, 
322 					"Found a '%s' while looking for", 
323 					this.lex.front
324 				);
325 				throw new ParseException(app.data,
326 					__FILE__, __LINE__,
327 					subRules,
328 					["at -> Directive","lcurly"]
329 				);
330 
331 			} else if(this.firstDirectives()) {
332 				Directives d = this.parseDirectives();
333 				subRules = ["OT_D"];
334 				if(this.firstSelectionSet()) {
335 					SelectionSet ss = this.parseSelectionSet();
336 
337 					return new OperationDefinition(OperationDefinitionEnum.OT_D
338 						, ot
339 						, d
340 						, ss
341 					);
342 				}
343 				auto app = appender!string();
344 				formattedWrite(app, 
345 					"Found a '%s' while looking for", 
346 					this.lex.front
347 				);
348 				throw new ParseException(app.data,
349 					__FILE__, __LINE__,
350 					subRules,
351 					["lcurly"]
352 				);
353 
354 			} else if(this.firstSelectionSet()) {
355 				SelectionSet ss = this.parseSelectionSet();
356 
357 				return new OperationDefinition(OperationDefinitionEnum.OT
358 					, ot
359 					, ss
360 				);
361 			}
362 			auto app = appender!string();
363 			formattedWrite(app, 
364 				"Found a '%s' while looking for", 
365 				this.lex.front
366 			);
367 			throw new ParseException(app.data,
368 				__FILE__, __LINE__,
369 				subRules,
370 				["name","lparen","at -> Directive","lcurly"]
371 			);
372 
373 		}
374 		auto app = appender!string();
375 		formattedWrite(app, 
376 			"Found a '%s' while looking for", 
377 			this.lex.front
378 		);
379 		throw new ParseException(app.data,
380 			__FILE__, __LINE__,
381 			subRules,
382 			["lcurly","mutation","query","subscription"]
383 		);
384 
385 	}
386 
387 	bool firstSelectionSet() const pure @nogc @safe {
388 		return this.lex.front.type == TokenType.lcurly;
389 	}
390 
391 	SelectionSet parseSelectionSet() {
392 		try {
393 			return this.parseSelectionSetImpl();
394 		} catch(ParseException e) {
395 			throw new ParseException(
396 				"While parsing a SelectionSet an Exception was thrown.",
397 				e, __FILE__, __LINE__
398 			);
399 		}
400 	}
401 
402 	SelectionSet parseSelectionSetImpl() {
403 		string[] subRules;
404 		subRules = ["SS"];
405 		if(this.lex.front.type == TokenType.lcurly) {
406 			this.lex.popFront();
407 			subRules = ["SS"];
408 			if(this.firstSelections()) {
409 				Selections sel = this.parseSelections();
410 				subRules = ["SS"];
411 				if(this.lex.front.type == TokenType.rcurly) {
412 					this.lex.popFront();
413 
414 					return new SelectionSet(SelectionSetEnum.SS
415 						, sel
416 					);
417 				}
418 				auto app = appender!string();
419 				formattedWrite(app, 
420 					"Found a '%s' while looking for", 
421 					this.lex.front
422 				);
423 				throw new ParseException(app.data,
424 					__FILE__, __LINE__,
425 					subRules,
426 					["rcurly"]
427 				);
428 
429 			}
430 			auto app = appender!string();
431 			formattedWrite(app, 
432 				"Found a '%s' while looking for", 
433 				this.lex.front
434 			);
435 			throw new ParseException(app.data,
436 				__FILE__, __LINE__,
437 				subRules,
438 				["dots -> Selection","name -> Selection","schema__ -> Selection","type -> Selection"]
439 			);
440 
441 		}
442 		auto app = appender!string();
443 		formattedWrite(app, 
444 			"Found a '%s' while looking for", 
445 			this.lex.front
446 		);
447 		throw new ParseException(app.data,
448 			__FILE__, __LINE__,
449 			subRules,
450 			["lcurly"]
451 		);
452 
453 	}
454 
455 	bool firstOperationType() const pure @nogc @safe {
456 		return this.lex.front.type == TokenType.query
457 			 || this.lex.front.type == TokenType.mutation
458 			 || this.lex.front.type == TokenType.subscription;
459 	}
460 
461 	OperationType parseOperationType() {
462 		try {
463 			return this.parseOperationTypeImpl();
464 		} catch(ParseException e) {
465 			throw new ParseException(
466 				"While parsing a OperationType an Exception was thrown.",
467 				e, __FILE__, __LINE__
468 			);
469 		}
470 	}
471 
472 	OperationType parseOperationTypeImpl() {
473 		string[] subRules;
474 		subRules = ["Query"];
475 		if(this.lex.front.type == TokenType.query) {
476 			Token tok = this.lex.front;
477 			this.lex.popFront();
478 
479 			return new OperationType(OperationTypeEnum.Query
480 				, tok
481 			);
482 		} else if(this.lex.front.type == TokenType.mutation) {
483 			Token tok = this.lex.front;
484 			this.lex.popFront();
485 
486 			return new OperationType(OperationTypeEnum.Mutation
487 				, tok
488 			);
489 		} else if(this.lex.front.type == TokenType.subscription) {
490 			Token tok = this.lex.front;
491 			this.lex.popFront();
492 
493 			return new OperationType(OperationTypeEnum.Sub
494 				, tok
495 			);
496 		}
497 		auto app = appender!string();
498 		formattedWrite(app, 
499 			"Found a '%s' while looking for", 
500 			this.lex.front
501 		);
502 		throw new ParseException(app.data,
503 			__FILE__, __LINE__,
504 			subRules,
505 			["query","mutation","subscription"]
506 		);
507 
508 	}
509 
510 	bool firstSelections() const pure @nogc @safe {
511 		return this.firstSelection();
512 	}
513 
514 	Selections parseSelections() {
515 		try {
516 			return this.parseSelectionsImpl();
517 		} catch(ParseException e) {
518 			throw new ParseException(
519 				"While parsing a Selections an Exception was thrown.",
520 				e, __FILE__, __LINE__
521 			);
522 		}
523 	}
524 
525 	Selections parseSelectionsImpl() {
526 		string[] subRules;
527 		subRules = ["Sel", "Sels", "Selsc"];
528 		if(this.firstSelection()) {
529 			Selection sel = this.parseSelection();
530 			subRules = ["Sels"];
531 			if(this.firstSelections()) {
532 				Selections follow = this.parseSelections();
533 
534 				return new Selections(SelectionsEnum.Sels
535 					, sel
536 					, follow
537 				);
538 			} else if(this.lex.front.type == TokenType.comma) {
539 				this.lex.popFront();
540 				subRules = ["Selsc"];
541 				if(this.firstSelections()) {
542 					Selections follow = this.parseSelections();
543 
544 					return new Selections(SelectionsEnum.Selsc
545 						, sel
546 						, follow
547 					);
548 				}
549 				auto app = appender!string();
550 				formattedWrite(app, 
551 					"Found a '%s' while looking for", 
552 					this.lex.front
553 				);
554 				throw new ParseException(app.data,
555 					__FILE__, __LINE__,
556 					subRules,
557 					["dots -> Selection","name -> Selection","schema__ -> Selection","type -> Selection"]
558 				);
559 
560 			}
561 			return new Selections(SelectionsEnum.Sel
562 				, sel
563 			);
564 		}
565 		auto app = appender!string();
566 		formattedWrite(app, 
567 			"Found a '%s' while looking for", 
568 			this.lex.front
569 		);
570 		throw new ParseException(app.data,
571 			__FILE__, __LINE__,
572 			subRules,
573 			["dots","name -> Field","schema__ -> Field","type -> Field"]
574 		);
575 
576 	}
577 
578 	bool firstSelection() const pure @nogc @safe {
579 		return this.firstField()
580 			 || this.lex.front.type == TokenType.dots;
581 	}
582 
583 	Selection parseSelection() {
584 		try {
585 			return this.parseSelectionImpl();
586 		} catch(ParseException e) {
587 			throw new ParseException(
588 				"While parsing a Selection an Exception was thrown.",
589 				e, __FILE__, __LINE__
590 			);
591 		}
592 	}
593 
594 	Selection parseSelectionImpl() {
595 		string[] subRules;
596 		subRules = ["Field"];
597 		if(this.firstField()) {
598 			Field field = this.parseField();
599 
600 			return new Selection(SelectionEnum.Field
601 				, field
602 			);
603 		} else if(this.lex.front.type == TokenType.dots) {
604 			this.lex.popFront();
605 			subRules = ["Spread"];
606 			if(this.firstFragmentSpread()) {
607 				FragmentSpread frag = this.parseFragmentSpread();
608 
609 				return new Selection(SelectionEnum.Spread
610 					, frag
611 				);
612 			} else if(this.firstInlineFragment()) {
613 				InlineFragment ifrag = this.parseInlineFragment();
614 
615 				return new Selection(SelectionEnum.IFrag
616 					, ifrag
617 				);
618 			}
619 			auto app = appender!string();
620 			formattedWrite(app, 
621 				"Found a '%s' while looking for", 
622 				this.lex.front
623 			);
624 			throw new ParseException(app.data,
625 				__FILE__, __LINE__,
626 				subRules,
627 				["name","at -> Directives","lcurly -> SelectionSet","on_"]
628 			);
629 
630 		}
631 		auto app = appender!string();
632 		formattedWrite(app, 
633 			"Found a '%s' while looking for", 
634 			this.lex.front
635 		);
636 		throw new ParseException(app.data,
637 			__FILE__, __LINE__,
638 			subRules,
639 			["name -> FieldName","schema__ -> FieldName","type -> FieldName","dots"]
640 		);
641 
642 	}
643 
644 	bool firstFragmentSpread() const pure @nogc @safe {
645 		return this.lex.front.type == TokenType.name;
646 	}
647 
648 	FragmentSpread parseFragmentSpread() {
649 		try {
650 			return this.parseFragmentSpreadImpl();
651 		} catch(ParseException e) {
652 			throw new ParseException(
653 				"While parsing a FragmentSpread an Exception was thrown.",
654 				e, __FILE__, __LINE__
655 			);
656 		}
657 	}
658 
659 	FragmentSpread parseFragmentSpreadImpl() {
660 		string[] subRules;
661 		subRules = ["F", "FD"];
662 		if(this.lex.front.type == TokenType.name) {
663 			Token name = this.lex.front;
664 			this.lex.popFront();
665 			subRules = ["FD"];
666 			if(this.firstDirectives()) {
667 				Directives dirs = this.parseDirectives();
668 
669 				return new FragmentSpread(FragmentSpreadEnum.FD
670 					, name
671 					, dirs
672 				);
673 			}
674 			return new FragmentSpread(FragmentSpreadEnum.F
675 				, name
676 			);
677 		}
678 		auto app = appender!string();
679 		formattedWrite(app, 
680 			"Found a '%s' while looking for", 
681 			this.lex.front
682 		);
683 		throw new ParseException(app.data,
684 			__FILE__, __LINE__,
685 			subRules,
686 			["name"]
687 		);
688 
689 	}
690 
691 	bool firstInlineFragment() const pure @nogc @safe {
692 		return this.lex.front.type == TokenType.on_
693 			 || this.firstDirectives()
694 			 || this.firstSelectionSet();
695 	}
696 
697 	InlineFragment parseInlineFragment() {
698 		try {
699 			return this.parseInlineFragmentImpl();
700 		} catch(ParseException e) {
701 			throw new ParseException(
702 				"While parsing a InlineFragment an Exception was thrown.",
703 				e, __FILE__, __LINE__
704 			);
705 		}
706 	}
707 
708 	InlineFragment parseInlineFragmentImpl() {
709 		string[] subRules;
710 		subRules = ["TDS", "TS"];
711 		if(this.lex.front.type == TokenType.on_) {
712 			this.lex.popFront();
713 			subRules = ["TDS", "TS"];
714 			if(this.lex.front.type == TokenType.name) {
715 				Token tc = this.lex.front;
716 				this.lex.popFront();
717 				subRules = ["TDS"];
718 				if(this.firstDirectives()) {
719 					Directives dirs = this.parseDirectives();
720 					subRules = ["TDS"];
721 					if(this.firstSelectionSet()) {
722 						SelectionSet ss = this.parseSelectionSet();
723 
724 						return new InlineFragment(InlineFragmentEnum.TDS
725 							, tc
726 							, dirs
727 							, ss
728 						);
729 					}
730 					auto app = appender!string();
731 					formattedWrite(app, 
732 						"Found a '%s' while looking for", 
733 						this.lex.front
734 					);
735 					throw new ParseException(app.data,
736 						__FILE__, __LINE__,
737 						subRules,
738 						["lcurly"]
739 					);
740 
741 				} else if(this.firstSelectionSet()) {
742 					SelectionSet ss = this.parseSelectionSet();
743 
744 					return new InlineFragment(InlineFragmentEnum.TS
745 						, tc
746 						, ss
747 					);
748 				}
749 				auto app = appender!string();
750 				formattedWrite(app, 
751 					"Found a '%s' while looking for", 
752 					this.lex.front
753 				);
754 				throw new ParseException(app.data,
755 					__FILE__, __LINE__,
756 					subRules,
757 					["at -> Directive","lcurly"]
758 				);
759 
760 			}
761 			auto app = appender!string();
762 			formattedWrite(app, 
763 				"Found a '%s' while looking for", 
764 				this.lex.front
765 			);
766 			throw new ParseException(app.data,
767 				__FILE__, __LINE__,
768 				subRules,
769 				["name"]
770 			);
771 
772 		} else if(this.firstDirectives()) {
773 			Directives dirs = this.parseDirectives();
774 			subRules = ["DS"];
775 			if(this.firstSelectionSet()) {
776 				SelectionSet ss = this.parseSelectionSet();
777 
778 				return new InlineFragment(InlineFragmentEnum.DS
779 					, dirs
780 					, ss
781 				);
782 			}
783 			auto app = appender!string();
784 			formattedWrite(app, 
785 				"Found a '%s' while looking for", 
786 				this.lex.front
787 			);
788 			throw new ParseException(app.data,
789 				__FILE__, __LINE__,
790 				subRules,
791 				["lcurly"]
792 			);
793 
794 		} else if(this.firstSelectionSet()) {
795 			SelectionSet ss = this.parseSelectionSet();
796 
797 			return new InlineFragment(InlineFragmentEnum.S
798 				, ss
799 			);
800 		}
801 		auto app = appender!string();
802 		formattedWrite(app, 
803 			"Found a '%s' while looking for", 
804 			this.lex.front
805 		);
806 		throw new ParseException(app.data,
807 			__FILE__, __LINE__,
808 			subRules,
809 			["on_","at -> Directive","lcurly"]
810 		);
811 
812 	}
813 
814 	bool firstField() const pure @nogc @safe {
815 		return this.firstFieldName();
816 	}
817 
818 	Field parseField() {
819 		try {
820 			return this.parseFieldImpl();
821 		} catch(ParseException e) {
822 			throw new ParseException(
823 				"While parsing a Field an Exception was thrown.",
824 				e, __FILE__, __LINE__
825 			);
826 		}
827 	}
828 
829 	Field parseFieldImpl() {
830 		string[] subRules;
831 		subRules = ["F", "FA", "FAD", "FADS", "FAS", "FD", "FDS", "FS"];
832 		if(this.firstFieldName()) {
833 			FieldName name = this.parseFieldName();
834 			subRules = ["FA", "FAD", "FADS", "FAS"];
835 			if(this.firstArguments()) {
836 				Arguments args = this.parseArguments();
837 				subRules = ["FAD", "FADS"];
838 				if(this.firstDirectives()) {
839 					Directives dirs = this.parseDirectives();
840 					subRules = ["FADS"];
841 					if(this.firstSelectionSet()) {
842 						SelectionSet ss = this.parseSelectionSet();
843 
844 						return new Field(FieldEnum.FADS
845 							, name
846 							, args
847 							, dirs
848 							, ss
849 						);
850 					}
851 					return new Field(FieldEnum.FAD
852 						, name
853 						, args
854 						, dirs
855 					);
856 				} else if(this.firstSelectionSet()) {
857 					SelectionSet ss = this.parseSelectionSet();
858 
859 					return new Field(FieldEnum.FAS
860 						, name
861 						, args
862 						, ss
863 					);
864 				}
865 				return new Field(FieldEnum.FA
866 					, name
867 					, args
868 				);
869 			} else if(this.firstDirectives()) {
870 				Directives dirs = this.parseDirectives();
871 				subRules = ["FDS"];
872 				if(this.firstSelectionSet()) {
873 					SelectionSet ss = this.parseSelectionSet();
874 
875 					return new Field(FieldEnum.FDS
876 						, name
877 						, dirs
878 						, ss
879 					);
880 				}
881 				return new Field(FieldEnum.FD
882 					, name
883 					, dirs
884 				);
885 			} else if(this.firstSelectionSet()) {
886 				SelectionSet ss = this.parseSelectionSet();
887 
888 				return new Field(FieldEnum.FS
889 					, name
890 					, ss
891 				);
892 			}
893 			return new Field(FieldEnum.F
894 				, name
895 			);
896 		}
897 		auto app = appender!string();
898 		formattedWrite(app, 
899 			"Found a '%s' while looking for", 
900 			this.lex.front
901 		);
902 		throw new ParseException(app.data,
903 			__FILE__, __LINE__,
904 			subRules,
905 			["name","schema__","type"]
906 		);
907 
908 	}
909 
910 	bool firstFieldName() const pure @nogc @safe {
911 		return this.lex.front.type == TokenType.name
912 			 || this.lex.front.type == TokenType.type
913 			 || this.lex.front.type == TokenType.schema__;
914 	}
915 
916 	FieldName parseFieldName() {
917 		try {
918 			return this.parseFieldNameImpl();
919 		} catch(ParseException e) {
920 			throw new ParseException(
921 				"While parsing a FieldName an Exception was thrown.",
922 				e, __FILE__, __LINE__
923 			);
924 		}
925 	}
926 
927 	FieldName parseFieldNameImpl() {
928 		string[] subRules;
929 		subRules = ["A", "N"];
930 		if(this.lex.front.type == TokenType.name) {
931 			Token name = this.lex.front;
932 			this.lex.popFront();
933 			subRules = ["A"];
934 			if(this.lex.front.type == TokenType.colon) {
935 				this.lex.popFront();
936 				subRules = ["A"];
937 				if(this.lex.front.type == TokenType.name) {
938 					Token aka = this.lex.front;
939 					this.lex.popFront();
940 
941 					return new FieldName(FieldNameEnum.A
942 						, name
943 						, aka
944 					);
945 				}
946 				auto app = appender!string();
947 				formattedWrite(app, 
948 					"Found a '%s' while looking for", 
949 					this.lex.front
950 				);
951 				throw new ParseException(app.data,
952 					__FILE__, __LINE__,
953 					subRules,
954 					["name"]
955 				);
956 
957 			}
958 			return new FieldName(FieldNameEnum.N
959 				, name
960 			);
961 		} else if(this.lex.front.type == TokenType.type) {
962 			Token type = this.lex.front;
963 			this.lex.popFront();
964 
965 			return new FieldName(FieldNameEnum.T
966 				, type
967 			);
968 		} else if(this.lex.front.type == TokenType.schema__) {
969 			Token schema = this.lex.front;
970 			this.lex.popFront();
971 
972 			return new FieldName(FieldNameEnum.S
973 				, schema
974 			);
975 		}
976 		auto app = appender!string();
977 		formattedWrite(app, 
978 			"Found a '%s' while looking for", 
979 			this.lex.front
980 		);
981 		throw new ParseException(app.data,
982 			__FILE__, __LINE__,
983 			subRules,
984 			["name","type","schema__"]
985 		);
986 
987 	}
988 
989 	bool firstArguments() const pure @nogc @safe {
990 		return this.lex.front.type == TokenType.lparen;
991 	}
992 
993 	Arguments parseArguments() {
994 		try {
995 			return this.parseArgumentsImpl();
996 		} catch(ParseException e) {
997 			throw new ParseException(
998 				"While parsing a Arguments an Exception was thrown.",
999 				e, __FILE__, __LINE__
1000 			);
1001 		}
1002 	}
1003 
1004 	Arguments parseArgumentsImpl() {
1005 		string[] subRules;
1006 		subRules = ["Empty", "List"];
1007 		if(this.lex.front.type == TokenType.lparen) {
1008 			this.lex.popFront();
1009 			subRules = ["List"];
1010 			if(this.firstArgumentList()) {
1011 				ArgumentList arg = this.parseArgumentList();
1012 				subRules = ["List"];
1013 				if(this.lex.front.type == TokenType.rparen) {
1014 					this.lex.popFront();
1015 
1016 					return new Arguments(ArgumentsEnum.List
1017 						, arg
1018 					);
1019 				}
1020 				auto app = appender!string();
1021 				formattedWrite(app, 
1022 					"Found a '%s' while looking for", 
1023 					this.lex.front
1024 				);
1025 				throw new ParseException(app.data,
1026 					__FILE__, __LINE__,
1027 					subRules,
1028 					["rparen"]
1029 				);
1030 
1031 			} else if(this.lex.front.type == TokenType.rparen) {
1032 				this.lex.popFront();
1033 
1034 				return new Arguments(ArgumentsEnum.Empty
1035 				);
1036 			}
1037 			auto app = appender!string();
1038 			formattedWrite(app, 
1039 				"Found a '%s' while looking for", 
1040 				this.lex.front
1041 			);
1042 			throw new ParseException(app.data,
1043 				__FILE__, __LINE__,
1044 				subRules,
1045 				["name -> Argument","rparen"]
1046 			);
1047 
1048 		}
1049 		auto app = appender!string();
1050 		formattedWrite(app, 
1051 			"Found a '%s' while looking for", 
1052 			this.lex.front
1053 		);
1054 		throw new ParseException(app.data,
1055 			__FILE__, __LINE__,
1056 			subRules,
1057 			["lparen"]
1058 		);
1059 
1060 	}
1061 
1062 	bool firstArgumentList() const pure @nogc @safe {
1063 		return this.firstArgument();
1064 	}
1065 
1066 	ArgumentList parseArgumentList() {
1067 		try {
1068 			return this.parseArgumentListImpl();
1069 		} catch(ParseException e) {
1070 			throw new ParseException(
1071 				"While parsing a ArgumentList an Exception was thrown.",
1072 				e, __FILE__, __LINE__
1073 			);
1074 		}
1075 	}
1076 
1077 	ArgumentList parseArgumentListImpl() {
1078 		string[] subRules;
1079 		subRules = ["A", "ACS", "AS"];
1080 		if(this.firstArgument()) {
1081 			Argument arg = this.parseArgument();
1082 			subRules = ["ACS"];
1083 			if(this.lex.front.type == TokenType.comma) {
1084 				this.lex.popFront();
1085 				subRules = ["ACS"];
1086 				if(this.firstArgumentList()) {
1087 					ArgumentList follow = this.parseArgumentList();
1088 
1089 					return new ArgumentList(ArgumentListEnum.ACS
1090 						, arg
1091 						, follow
1092 					);
1093 				}
1094 				auto app = appender!string();
1095 				formattedWrite(app, 
1096 					"Found a '%s' while looking for", 
1097 					this.lex.front
1098 				);
1099 				throw new ParseException(app.data,
1100 					__FILE__, __LINE__,
1101 					subRules,
1102 					["name -> Argument"]
1103 				);
1104 
1105 			} else if(this.firstArgumentList()) {
1106 				ArgumentList follow = this.parseArgumentList();
1107 
1108 				return new ArgumentList(ArgumentListEnum.AS
1109 					, arg
1110 					, follow
1111 				);
1112 			}
1113 			return new ArgumentList(ArgumentListEnum.A
1114 				, arg
1115 			);
1116 		}
1117 		auto app = appender!string();
1118 		formattedWrite(app, 
1119 			"Found a '%s' while looking for", 
1120 			this.lex.front
1121 		);
1122 		throw new ParseException(app.data,
1123 			__FILE__, __LINE__,
1124 			subRules,
1125 			["name"]
1126 		);
1127 
1128 	}
1129 
1130 	bool firstArgument() const pure @nogc @safe {
1131 		return this.lex.front.type == TokenType.name;
1132 	}
1133 
1134 	Argument parseArgument() {
1135 		try {
1136 			return this.parseArgumentImpl();
1137 		} catch(ParseException e) {
1138 			throw new ParseException(
1139 				"While parsing a Argument an Exception was thrown.",
1140 				e, __FILE__, __LINE__
1141 			);
1142 		}
1143 	}
1144 
1145 	Argument parseArgumentImpl() {
1146 		string[] subRules;
1147 		subRules = ["Name"];
1148 		if(this.lex.front.type == TokenType.name) {
1149 			Token name = this.lex.front;
1150 			this.lex.popFront();
1151 			subRules = ["Name"];
1152 			if(this.lex.front.type == TokenType.colon) {
1153 				this.lex.popFront();
1154 				subRules = ["Name"];
1155 				if(this.firstValueOrVariable()) {
1156 					ValueOrVariable vv = this.parseValueOrVariable();
1157 
1158 					return new Argument(ArgumentEnum.Name
1159 						, name
1160 						, vv
1161 					);
1162 				}
1163 				auto app = appender!string();
1164 				formattedWrite(app, 
1165 					"Found a '%s' while looking for", 
1166 					this.lex.front
1167 				);
1168 				throw new ParseException(app.data,
1169 					__FILE__, __LINE__,
1170 					subRules,
1171 					["dollar -> Variable","false_ -> Value","floatValue -> Value","intValue -> Value","lbrack -> Value","lcurly -> Value","stringValue -> Value","true_ -> Value"]
1172 				);
1173 
1174 			}
1175 			auto app = appender!string();
1176 			formattedWrite(app, 
1177 				"Found a '%s' while looking for", 
1178 				this.lex.front
1179 			);
1180 			throw new ParseException(app.data,
1181 				__FILE__, __LINE__,
1182 				subRules,
1183 				["colon"]
1184 			);
1185 
1186 		}
1187 		auto app = appender!string();
1188 		formattedWrite(app, 
1189 			"Found a '%s' while looking for", 
1190 			this.lex.front
1191 		);
1192 		throw new ParseException(app.data,
1193 			__FILE__, __LINE__,
1194 			subRules,
1195 			["name"]
1196 		);
1197 
1198 	}
1199 
1200 	bool firstFragmentDefinition() const pure @nogc @safe {
1201 		return this.lex.front.type == TokenType.fragment;
1202 	}
1203 
1204 	FragmentDefinition parseFragmentDefinition() {
1205 		try {
1206 			return this.parseFragmentDefinitionImpl();
1207 		} catch(ParseException e) {
1208 			throw new ParseException(
1209 				"While parsing a FragmentDefinition an Exception was thrown.",
1210 				e, __FILE__, __LINE__
1211 			);
1212 		}
1213 	}
1214 
1215 	FragmentDefinition parseFragmentDefinitionImpl() {
1216 		string[] subRules;
1217 		subRules = ["FTDS", "FTS"];
1218 		if(this.lex.front.type == TokenType.fragment) {
1219 			this.lex.popFront();
1220 			subRules = ["FTDS", "FTS"];
1221 			if(this.lex.front.type == TokenType.name) {
1222 				Token name = this.lex.front;
1223 				this.lex.popFront();
1224 				subRules = ["FTDS", "FTS"];
1225 				if(this.lex.front.type == TokenType.on_) {
1226 					this.lex.popFront();
1227 					subRules = ["FTDS", "FTS"];
1228 					if(this.lex.front.type == TokenType.name) {
1229 						Token tc = this.lex.front;
1230 						this.lex.popFront();
1231 						subRules = ["FTDS"];
1232 						if(this.firstDirectives()) {
1233 							Directives dirs = this.parseDirectives();
1234 							subRules = ["FTDS"];
1235 							if(this.firstSelectionSet()) {
1236 								SelectionSet ss = this.parseSelectionSet();
1237 
1238 								return new FragmentDefinition(FragmentDefinitionEnum.FTDS
1239 									, name
1240 									, tc
1241 									, dirs
1242 									, ss
1243 								);
1244 							}
1245 							auto app = appender!string();
1246 							formattedWrite(app, 
1247 								"Found a '%s' while looking for", 
1248 								this.lex.front
1249 							);
1250 							throw new ParseException(app.data,
1251 								__FILE__, __LINE__,
1252 								subRules,
1253 								["lcurly"]
1254 							);
1255 
1256 						} else if(this.firstSelectionSet()) {
1257 							SelectionSet ss = this.parseSelectionSet();
1258 
1259 							return new FragmentDefinition(FragmentDefinitionEnum.FTS
1260 								, name
1261 								, tc
1262 								, ss
1263 							);
1264 						}
1265 						auto app = appender!string();
1266 						formattedWrite(app, 
1267 							"Found a '%s' while looking for", 
1268 							this.lex.front
1269 						);
1270 						throw new ParseException(app.data,
1271 							__FILE__, __LINE__,
1272 							subRules,
1273 							["at -> Directive","lcurly"]
1274 						);
1275 
1276 					}
1277 					auto app = appender!string();
1278 					formattedWrite(app, 
1279 						"Found a '%s' while looking for", 
1280 						this.lex.front
1281 					);
1282 					throw new ParseException(app.data,
1283 						__FILE__, __LINE__,
1284 						subRules,
1285 						["name"]
1286 					);
1287 
1288 				}
1289 				auto app = appender!string();
1290 				formattedWrite(app, 
1291 					"Found a '%s' while looking for", 
1292 					this.lex.front
1293 				);
1294 				throw new ParseException(app.data,
1295 					__FILE__, __LINE__,
1296 					subRules,
1297 					["on_"]
1298 				);
1299 
1300 			}
1301 			auto app = appender!string();
1302 			formattedWrite(app, 
1303 				"Found a '%s' while looking for", 
1304 				this.lex.front
1305 			);
1306 			throw new ParseException(app.data,
1307 				__FILE__, __LINE__,
1308 				subRules,
1309 				["name"]
1310 			);
1311 
1312 		}
1313 		auto app = appender!string();
1314 		formattedWrite(app, 
1315 			"Found a '%s' while looking for", 
1316 			this.lex.front
1317 		);
1318 		throw new ParseException(app.data,
1319 			__FILE__, __LINE__,
1320 			subRules,
1321 			["fragment"]
1322 		);
1323 
1324 	}
1325 
1326 	bool firstDirectives() const pure @nogc @safe {
1327 		return this.firstDirective();
1328 	}
1329 
1330 	Directives parseDirectives() {
1331 		try {
1332 			return this.parseDirectivesImpl();
1333 		} catch(ParseException e) {
1334 			throw new ParseException(
1335 				"While parsing a Directives an Exception was thrown.",
1336 				e, __FILE__, __LINE__
1337 			);
1338 		}
1339 	}
1340 
1341 	Directives parseDirectivesImpl() {
1342 		string[] subRules;
1343 		subRules = ["Dir", "Dirs"];
1344 		if(this.firstDirective()) {
1345 			Directive dir = this.parseDirective();
1346 			subRules = ["Dirs"];
1347 			if(this.firstDirectives()) {
1348 				Directives follow = this.parseDirectives();
1349 
1350 				return new Directives(DirectivesEnum.Dirs
1351 					, dir
1352 					, follow
1353 				);
1354 			}
1355 			return new Directives(DirectivesEnum.Dir
1356 				, dir
1357 			);
1358 		}
1359 		auto app = appender!string();
1360 		formattedWrite(app, 
1361 			"Found a '%s' while looking for", 
1362 			this.lex.front
1363 		);
1364 		throw new ParseException(app.data,
1365 			__FILE__, __LINE__,
1366 			subRules,
1367 			["at"]
1368 		);
1369 
1370 	}
1371 
1372 	bool firstDirective() const pure @nogc @safe {
1373 		return this.lex.front.type == TokenType.at;
1374 	}
1375 
1376 	Directive parseDirective() {
1377 		try {
1378 			return this.parseDirectiveImpl();
1379 		} catch(ParseException e) {
1380 			throw new ParseException(
1381 				"While parsing a Directive an Exception was thrown.",
1382 				e, __FILE__, __LINE__
1383 			);
1384 		}
1385 	}
1386 
1387 	Directive parseDirectiveImpl() {
1388 		string[] subRules;
1389 		subRules = ["N", "NArg"];
1390 		if(this.lex.front.type == TokenType.at) {
1391 			this.lex.popFront();
1392 			subRules = ["N", "NArg"];
1393 			if(this.lex.front.type == TokenType.name) {
1394 				Token name = this.lex.front;
1395 				this.lex.popFront();
1396 				subRules = ["NArg"];
1397 				if(this.firstArguments()) {
1398 					Arguments arg = this.parseArguments();
1399 
1400 					return new Directive(DirectiveEnum.NArg
1401 						, name
1402 						, arg
1403 					);
1404 				}
1405 				return new Directive(DirectiveEnum.N
1406 					, name
1407 				);
1408 			}
1409 			auto app = appender!string();
1410 			formattedWrite(app, 
1411 				"Found a '%s' while looking for", 
1412 				this.lex.front
1413 			);
1414 			throw new ParseException(app.data,
1415 				__FILE__, __LINE__,
1416 				subRules,
1417 				["name"]
1418 			);
1419 
1420 		}
1421 		auto app = appender!string();
1422 		formattedWrite(app, 
1423 			"Found a '%s' while looking for", 
1424 			this.lex.front
1425 		);
1426 		throw new ParseException(app.data,
1427 			__FILE__, __LINE__,
1428 			subRules,
1429 			["at"]
1430 		);
1431 
1432 	}
1433 
1434 	bool firstVariableDefinitions() const pure @nogc @safe {
1435 		return this.lex.front.type == TokenType.lparen;
1436 	}
1437 
1438 	VariableDefinitions parseVariableDefinitions() {
1439 		try {
1440 			return this.parseVariableDefinitionsImpl();
1441 		} catch(ParseException e) {
1442 			throw new ParseException(
1443 				"While parsing a VariableDefinitions an Exception was thrown.",
1444 				e, __FILE__, __LINE__
1445 			);
1446 		}
1447 	}
1448 
1449 	VariableDefinitions parseVariableDefinitionsImpl() {
1450 		string[] subRules;
1451 		subRules = ["Empty", "Vars"];
1452 		if(this.lex.front.type == TokenType.lparen) {
1453 			this.lex.popFront();
1454 			subRules = ["Empty"];
1455 			if(this.lex.front.type == TokenType.rparen) {
1456 				this.lex.popFront();
1457 
1458 				return new VariableDefinitions(VariableDefinitionsEnum.Empty
1459 				);
1460 			} else if(this.firstVariableDefinitionList()) {
1461 				VariableDefinitionList vars = this.parseVariableDefinitionList();
1462 				subRules = ["Vars"];
1463 				if(this.lex.front.type == TokenType.rparen) {
1464 					this.lex.popFront();
1465 
1466 					return new VariableDefinitions(VariableDefinitionsEnum.Vars
1467 						, vars
1468 					);
1469 				}
1470 				auto app = appender!string();
1471 				formattedWrite(app, 
1472 					"Found a '%s' while looking for", 
1473 					this.lex.front
1474 				);
1475 				throw new ParseException(app.data,
1476 					__FILE__, __LINE__,
1477 					subRules,
1478 					["rparen"]
1479 				);
1480 
1481 			}
1482 			auto app = appender!string();
1483 			formattedWrite(app, 
1484 				"Found a '%s' while looking for", 
1485 				this.lex.front
1486 			);
1487 			throw new ParseException(app.data,
1488 				__FILE__, __LINE__,
1489 				subRules,
1490 				["rparen","dollar -> VariableDefinition"]
1491 			);
1492 
1493 		}
1494 		auto app = appender!string();
1495 		formattedWrite(app, 
1496 			"Found a '%s' while looking for", 
1497 			this.lex.front
1498 		);
1499 		throw new ParseException(app.data,
1500 			__FILE__, __LINE__,
1501 			subRules,
1502 			["lparen"]
1503 		);
1504 
1505 	}
1506 
1507 	bool firstVariableDefinitionList() const pure @nogc @safe {
1508 		return this.firstVariableDefinition();
1509 	}
1510 
1511 	VariableDefinitionList parseVariableDefinitionList() {
1512 		try {
1513 			return this.parseVariableDefinitionListImpl();
1514 		} catch(ParseException e) {
1515 			throw new ParseException(
1516 				"While parsing a VariableDefinitionList an Exception was thrown.",
1517 				e, __FILE__, __LINE__
1518 			);
1519 		}
1520 	}
1521 
1522 	VariableDefinitionList parseVariableDefinitionListImpl() {
1523 		string[] subRules;
1524 		subRules = ["V", "VCF", "VF"];
1525 		if(this.firstVariableDefinition()) {
1526 			VariableDefinition var = this.parseVariableDefinition();
1527 			subRules = ["VCF"];
1528 			if(this.lex.front.type == TokenType.comma) {
1529 				this.lex.popFront();
1530 				subRules = ["VCF"];
1531 				if(this.firstVariableDefinitionList()) {
1532 					VariableDefinitionList follow = this.parseVariableDefinitionList();
1533 
1534 					return new VariableDefinitionList(VariableDefinitionListEnum.VCF
1535 						, var
1536 						, follow
1537 					);
1538 				}
1539 				auto app = appender!string();
1540 				formattedWrite(app, 
1541 					"Found a '%s' while looking for", 
1542 					this.lex.front
1543 				);
1544 				throw new ParseException(app.data,
1545 					__FILE__, __LINE__,
1546 					subRules,
1547 					["dollar -> VariableDefinition"]
1548 				);
1549 
1550 			} else if(this.firstVariableDefinitionList()) {
1551 				VariableDefinitionList follow = this.parseVariableDefinitionList();
1552 
1553 				return new VariableDefinitionList(VariableDefinitionListEnum.VF
1554 					, var
1555 					, follow
1556 				);
1557 			}
1558 			return new VariableDefinitionList(VariableDefinitionListEnum.V
1559 				, var
1560 			);
1561 		}
1562 		auto app = appender!string();
1563 		formattedWrite(app, 
1564 			"Found a '%s' while looking for", 
1565 			this.lex.front
1566 		);
1567 		throw new ParseException(app.data,
1568 			__FILE__, __LINE__,
1569 			subRules,
1570 			["dollar -> Variable"]
1571 		);
1572 
1573 	}
1574 
1575 	bool firstVariableDefinition() const pure @nogc @safe {
1576 		return this.firstVariable();
1577 	}
1578 
1579 	VariableDefinition parseVariableDefinition() {
1580 		try {
1581 			return this.parseVariableDefinitionImpl();
1582 		} catch(ParseException e) {
1583 			throw new ParseException(
1584 				"While parsing a VariableDefinition an Exception was thrown.",
1585 				e, __FILE__, __LINE__
1586 			);
1587 		}
1588 	}
1589 
1590 	VariableDefinition parseVariableDefinitionImpl() {
1591 		string[] subRules;
1592 		subRules = ["Var", "VarD"];
1593 		if(this.firstVariable()) {
1594 			this.parseVariable();
1595 			subRules = ["Var", "VarD"];
1596 			if(this.lex.front.type == TokenType.colon) {
1597 				this.lex.popFront();
1598 				subRules = ["Var", "VarD"];
1599 				if(this.firstType()) {
1600 					Type type = this.parseType();
1601 					subRules = ["VarD"];
1602 					if(this.firstDefaultValue()) {
1603 						DefaultValue dvalue = this.parseDefaultValue();
1604 
1605 						return new VariableDefinition(VariableDefinitionEnum.VarD
1606 							, type
1607 							, dvalue
1608 						);
1609 					}
1610 					return new VariableDefinition(VariableDefinitionEnum.Var
1611 						, type
1612 					);
1613 				}
1614 				auto app = appender!string();
1615 				formattedWrite(app, 
1616 					"Found a '%s' while looking for", 
1617 					this.lex.front
1618 				);
1619 				throw new ParseException(app.data,
1620 					__FILE__, __LINE__,
1621 					subRules,
1622 					["lbrack -> ListType","name"]
1623 				);
1624 
1625 			}
1626 			auto app = appender!string();
1627 			formattedWrite(app, 
1628 				"Found a '%s' while looking for", 
1629 				this.lex.front
1630 			);
1631 			throw new ParseException(app.data,
1632 				__FILE__, __LINE__,
1633 				subRules,
1634 				["colon"]
1635 			);
1636 
1637 		}
1638 		auto app = appender!string();
1639 		formattedWrite(app, 
1640 			"Found a '%s' while looking for", 
1641 			this.lex.front
1642 		);
1643 		throw new ParseException(app.data,
1644 			__FILE__, __LINE__,
1645 			subRules,
1646 			["dollar"]
1647 		);
1648 
1649 	}
1650 
1651 	bool firstVariable() const pure @nogc @safe {
1652 		return this.lex.front.type == TokenType.dollar;
1653 	}
1654 
1655 	Variable parseVariable() {
1656 		try {
1657 			return this.parseVariableImpl();
1658 		} catch(ParseException e) {
1659 			throw new ParseException(
1660 				"While parsing a Variable an Exception was thrown.",
1661 				e, __FILE__, __LINE__
1662 			);
1663 		}
1664 	}
1665 
1666 	Variable parseVariableImpl() {
1667 		string[] subRules;
1668 		subRules = ["Var"];
1669 		if(this.lex.front.type == TokenType.dollar) {
1670 			this.lex.popFront();
1671 			subRules = ["Var"];
1672 			if(this.lex.front.type == TokenType.name) {
1673 				Token name = this.lex.front;
1674 				this.lex.popFront();
1675 
1676 				return new Variable(VariableEnum.Var
1677 					, name
1678 				);
1679 			}
1680 			auto app = appender!string();
1681 			formattedWrite(app, 
1682 				"Found a '%s' while looking for", 
1683 				this.lex.front
1684 			);
1685 			throw new ParseException(app.data,
1686 				__FILE__, __LINE__,
1687 				subRules,
1688 				["name"]
1689 			);
1690 
1691 		}
1692 		auto app = appender!string();
1693 		formattedWrite(app, 
1694 			"Found a '%s' while looking for", 
1695 			this.lex.front
1696 		);
1697 		throw new ParseException(app.data,
1698 			__FILE__, __LINE__,
1699 			subRules,
1700 			["dollar"]
1701 		);
1702 
1703 	}
1704 
1705 	bool firstDefaultValue() const pure @nogc @safe {
1706 		return this.lex.front.type == TokenType.equal;
1707 	}
1708 
1709 	DefaultValue parseDefaultValue() {
1710 		try {
1711 			return this.parseDefaultValueImpl();
1712 		} catch(ParseException e) {
1713 			throw new ParseException(
1714 				"While parsing a DefaultValue an Exception was thrown.",
1715 				e, __FILE__, __LINE__
1716 			);
1717 		}
1718 	}
1719 
1720 	DefaultValue parseDefaultValueImpl() {
1721 		string[] subRules;
1722 		subRules = ["DV"];
1723 		if(this.lex.front.type == TokenType.equal) {
1724 			this.lex.popFront();
1725 			subRules = ["DV"];
1726 			if(this.firstValue()) {
1727 				Value value = this.parseValue();
1728 
1729 				return new DefaultValue(DefaultValueEnum.DV
1730 					, value
1731 				);
1732 			}
1733 			auto app = appender!string();
1734 			formattedWrite(app, 
1735 				"Found a '%s' while looking for", 
1736 				this.lex.front
1737 			);
1738 			throw new ParseException(app.data,
1739 				__FILE__, __LINE__,
1740 				subRules,
1741 				["false_","floatValue","intValue","lbrack -> Array","lcurly -> ObjectType","stringValue","true_"]
1742 			);
1743 
1744 		}
1745 		auto app = appender!string();
1746 		formattedWrite(app, 
1747 			"Found a '%s' while looking for", 
1748 			this.lex.front
1749 		);
1750 		throw new ParseException(app.data,
1751 			__FILE__, __LINE__,
1752 			subRules,
1753 			["equal"]
1754 		);
1755 
1756 	}
1757 
1758 	bool firstValueOrVariable() const pure @nogc @safe {
1759 		return this.firstValue()
1760 			 || this.firstVariable();
1761 	}
1762 
1763 	ValueOrVariable parseValueOrVariable() {
1764 		try {
1765 			return this.parseValueOrVariableImpl();
1766 		} catch(ParseException e) {
1767 			throw new ParseException(
1768 				"While parsing a ValueOrVariable an Exception was thrown.",
1769 				e, __FILE__, __LINE__
1770 			);
1771 		}
1772 	}
1773 
1774 	ValueOrVariable parseValueOrVariableImpl() {
1775 		string[] subRules;
1776 		subRules = ["Val"];
1777 		if(this.firstValue()) {
1778 			Value val = this.parseValue();
1779 
1780 			return new ValueOrVariable(ValueOrVariableEnum.Val
1781 				, val
1782 			);
1783 		} else if(this.firstVariable()) {
1784 			Variable var = this.parseVariable();
1785 
1786 			return new ValueOrVariable(ValueOrVariableEnum.Var
1787 				, var
1788 			);
1789 		}
1790 		auto app = appender!string();
1791 		formattedWrite(app, 
1792 			"Found a '%s' while looking for", 
1793 			this.lex.front
1794 		);
1795 		throw new ParseException(app.data,
1796 			__FILE__, __LINE__,
1797 			subRules,
1798 			["false_","floatValue","intValue","lbrack -> Array","lcurly -> ObjectType","stringValue","true_","dollar"]
1799 		);
1800 
1801 	}
1802 
1803 	bool firstValue() const pure @nogc @safe {
1804 		return this.lex.front.type == TokenType.stringValue
1805 			 || this.lex.front.type == TokenType.intValue
1806 			 || this.lex.front.type == TokenType.floatValue
1807 			 || this.lex.front.type == TokenType.true_
1808 			 || this.lex.front.type == TokenType.false_
1809 			 || this.firstArray()
1810 			 || this.firstObjectType();
1811 	}
1812 
1813 	Value parseValue() {
1814 		try {
1815 			return this.parseValueImpl();
1816 		} catch(ParseException e) {
1817 			throw new ParseException(
1818 				"While parsing a Value an Exception was thrown.",
1819 				e, __FILE__, __LINE__
1820 			);
1821 		}
1822 	}
1823 
1824 	Value parseValueImpl() {
1825 		string[] subRules;
1826 		subRules = ["STR"];
1827 		if(this.lex.front.type == TokenType.stringValue) {
1828 			Token tok = this.lex.front;
1829 			this.lex.popFront();
1830 
1831 			return new Value(ValueEnum.STR
1832 				, tok
1833 			);
1834 		} else if(this.lex.front.type == TokenType.intValue) {
1835 			Token tok = this.lex.front;
1836 			this.lex.popFront();
1837 
1838 			return new Value(ValueEnum.INT
1839 				, tok
1840 			);
1841 		} else if(this.lex.front.type == TokenType.floatValue) {
1842 			Token tok = this.lex.front;
1843 			this.lex.popFront();
1844 
1845 			return new Value(ValueEnum.FLOAT
1846 				, tok
1847 			);
1848 		} else if(this.lex.front.type == TokenType.true_) {
1849 			Token tok = this.lex.front;
1850 			this.lex.popFront();
1851 
1852 			return new Value(ValueEnum.T
1853 				, tok
1854 			);
1855 		} else if(this.lex.front.type == TokenType.false_) {
1856 			Token tok = this.lex.front;
1857 			this.lex.popFront();
1858 
1859 			return new Value(ValueEnum.F
1860 				, tok
1861 			);
1862 		} else if(this.firstArray()) {
1863 			Array arr = this.parseArray();
1864 
1865 			return new Value(ValueEnum.ARR
1866 				, arr
1867 			);
1868 		} else if(this.firstObjectType()) {
1869 			ObjectType obj = this.parseObjectType();
1870 
1871 			return new Value(ValueEnum.O
1872 				, obj
1873 			);
1874 		}
1875 		auto app = appender!string();
1876 		formattedWrite(app, 
1877 			"Found a '%s' while looking for", 
1878 			this.lex.front
1879 		);
1880 		throw new ParseException(app.data,
1881 			__FILE__, __LINE__,
1882 			subRules,
1883 			["stringValue","intValue","floatValue","true_","false_","lbrack","lcurly"]
1884 		);
1885 
1886 	}
1887 
1888 	bool firstType() const pure @nogc @safe {
1889 		return this.lex.front.type == TokenType.name
1890 			 || this.firstListType();
1891 	}
1892 
1893 	Type parseType() {
1894 		try {
1895 			return this.parseTypeImpl();
1896 		} catch(ParseException e) {
1897 			throw new ParseException(
1898 				"While parsing a Type an Exception was thrown.",
1899 				e, __FILE__, __LINE__
1900 			);
1901 		}
1902 	}
1903 
1904 	Type parseTypeImpl() {
1905 		string[] subRules;
1906 		subRules = ["T", "TN"];
1907 		if(this.lex.front.type == TokenType.name) {
1908 			Token tname = this.lex.front;
1909 			this.lex.popFront();
1910 			subRules = ["TN"];
1911 			if(this.lex.front.type == TokenType.exclamation) {
1912 				this.lex.popFront();
1913 
1914 				return new Type(TypeEnum.TN
1915 					, tname
1916 				);
1917 			}
1918 			return new Type(TypeEnum.T
1919 				, tname
1920 			);
1921 		} else if(this.firstListType()) {
1922 			ListType list = this.parseListType();
1923 			subRules = ["LN"];
1924 			if(this.lex.front.type == TokenType.exclamation) {
1925 				this.lex.popFront();
1926 
1927 				return new Type(TypeEnum.LN
1928 					, list
1929 				);
1930 			}
1931 			return new Type(TypeEnum.L
1932 				, list
1933 			);
1934 		}
1935 		auto app = appender!string();
1936 		formattedWrite(app, 
1937 			"Found a '%s' while looking for", 
1938 			this.lex.front
1939 		);
1940 		throw new ParseException(app.data,
1941 			__FILE__, __LINE__,
1942 			subRules,
1943 			["name","lbrack"]
1944 		);
1945 
1946 	}
1947 
1948 	bool firstListType() const pure @nogc @safe {
1949 		return this.lex.front.type == TokenType.lbrack;
1950 	}
1951 
1952 	ListType parseListType() {
1953 		try {
1954 			return this.parseListTypeImpl();
1955 		} catch(ParseException e) {
1956 			throw new ParseException(
1957 				"While parsing a ListType an Exception was thrown.",
1958 				e, __FILE__, __LINE__
1959 			);
1960 		}
1961 	}
1962 
1963 	ListType parseListTypeImpl() {
1964 		string[] subRules;
1965 		subRules = ["T"];
1966 		if(this.lex.front.type == TokenType.lbrack) {
1967 			this.lex.popFront();
1968 			subRules = ["T"];
1969 			if(this.firstType()) {
1970 				Type type = this.parseType();
1971 				subRules = ["T"];
1972 				if(this.lex.front.type == TokenType.rbrack) {
1973 					this.lex.popFront();
1974 
1975 					return new ListType(ListTypeEnum.T
1976 						, type
1977 					);
1978 				}
1979 				auto app = appender!string();
1980 				formattedWrite(app, 
1981 					"Found a '%s' while looking for", 
1982 					this.lex.front
1983 				);
1984 				throw new ParseException(app.data,
1985 					__FILE__, __LINE__,
1986 					subRules,
1987 					["rbrack"]
1988 				);
1989 
1990 			}
1991 			auto app = appender!string();
1992 			formattedWrite(app, 
1993 				"Found a '%s' while looking for", 
1994 				this.lex.front
1995 			);
1996 			throw new ParseException(app.data,
1997 				__FILE__, __LINE__,
1998 				subRules,
1999 				["lbrack -> ListType","name"]
2000 			);
2001 
2002 		}
2003 		auto app = appender!string();
2004 		formattedWrite(app, 
2005 			"Found a '%s' while looking for", 
2006 			this.lex.front
2007 		);
2008 		throw new ParseException(app.data,
2009 			__FILE__, __LINE__,
2010 			subRules,
2011 			["lbrack"]
2012 		);
2013 
2014 	}
2015 
2016 	bool firstValues() const pure @nogc @safe {
2017 		return this.firstValue();
2018 	}
2019 
2020 	Values parseValues() {
2021 		try {
2022 			return this.parseValuesImpl();
2023 		} catch(ParseException e) {
2024 			throw new ParseException(
2025 				"While parsing a Values an Exception was thrown.",
2026 				e, __FILE__, __LINE__
2027 			);
2028 		}
2029 	}
2030 
2031 	Values parseValuesImpl() {
2032 		string[] subRules;
2033 		subRules = ["Val", "Vals"];
2034 		if(this.firstValue()) {
2035 			Value val = this.parseValue();
2036 			subRules = ["Vals"];
2037 			if(this.lex.front.type == TokenType.comma) {
2038 				this.lex.popFront();
2039 				subRules = ["Vals"];
2040 				if(this.firstValues()) {
2041 					Values follow = this.parseValues();
2042 
2043 					return new Values(ValuesEnum.Vals
2044 						, val
2045 						, follow
2046 					);
2047 				}
2048 				auto app = appender!string();
2049 				formattedWrite(app, 
2050 					"Found a '%s' while looking for", 
2051 					this.lex.front
2052 				);
2053 				throw new ParseException(app.data,
2054 					__FILE__, __LINE__,
2055 					subRules,
2056 					["false_ -> Value","floatValue -> Value","intValue -> Value","lbrack -> Value","lcurly -> Value","stringValue -> Value","true_ -> Value"]
2057 				);
2058 
2059 			}
2060 			return new Values(ValuesEnum.Val
2061 				, val
2062 			);
2063 		}
2064 		auto app = appender!string();
2065 		formattedWrite(app, 
2066 			"Found a '%s' while looking for", 
2067 			this.lex.front
2068 		);
2069 		throw new ParseException(app.data,
2070 			__FILE__, __LINE__,
2071 			subRules,
2072 			["false_","floatValue","intValue","lbrack -> Array","lcurly -> ObjectType","stringValue","true_"]
2073 		);
2074 
2075 	}
2076 
2077 	bool firstArray() const pure @nogc @safe {
2078 		return this.lex.front.type == TokenType.lbrack;
2079 	}
2080 
2081 	Array parseArray() {
2082 		try {
2083 			return this.parseArrayImpl();
2084 		} catch(ParseException e) {
2085 			throw new ParseException(
2086 				"While parsing a Array an Exception was thrown.",
2087 				e, __FILE__, __LINE__
2088 			);
2089 		}
2090 	}
2091 
2092 	Array parseArrayImpl() {
2093 		string[] subRules;
2094 		subRules = ["Empty", "Value"];
2095 		if(this.lex.front.type == TokenType.lbrack) {
2096 			this.lex.popFront();
2097 			subRules = ["Empty"];
2098 			if(this.lex.front.type == TokenType.rbrack) {
2099 				this.lex.popFront();
2100 
2101 				return new Array(ArrayEnum.Empty
2102 				);
2103 			} else if(this.firstValues()) {
2104 				Values vals = this.parseValues();
2105 				subRules = ["Value"];
2106 				if(this.lex.front.type == TokenType.rbrack) {
2107 					this.lex.popFront();
2108 
2109 					return new Array(ArrayEnum.Value
2110 						, vals
2111 					);
2112 				}
2113 				auto app = appender!string();
2114 				formattedWrite(app, 
2115 					"Found a '%s' while looking for", 
2116 					this.lex.front
2117 				);
2118 				throw new ParseException(app.data,
2119 					__FILE__, __LINE__,
2120 					subRules,
2121 					["rbrack"]
2122 				);
2123 
2124 			}
2125 			auto app = appender!string();
2126 			formattedWrite(app, 
2127 				"Found a '%s' while looking for", 
2128 				this.lex.front
2129 			);
2130 			throw new ParseException(app.data,
2131 				__FILE__, __LINE__,
2132 				subRules,
2133 				["rbrack","false_ -> Value","floatValue -> Value","intValue -> Value","lbrack -> Value","lcurly -> Value","stringValue -> Value","true_ -> Value"]
2134 			);
2135 
2136 		}
2137 		auto app = appender!string();
2138 		formattedWrite(app, 
2139 			"Found a '%s' while looking for", 
2140 			this.lex.front
2141 		);
2142 		throw new ParseException(app.data,
2143 			__FILE__, __LINE__,
2144 			subRules,
2145 			["lbrack"]
2146 		);
2147 
2148 	}
2149 
2150 	bool firstObjectValues() const pure @nogc @safe {
2151 		return this.lex.front.type == TokenType.name;
2152 	}
2153 
2154 	ObjectValues parseObjectValues() {
2155 		try {
2156 			return this.parseObjectValuesImpl();
2157 		} catch(ParseException e) {
2158 			throw new ParseException(
2159 				"While parsing a ObjectValues an Exception was thrown.",
2160 				e, __FILE__, __LINE__
2161 			);
2162 		}
2163 	}
2164 
2165 	ObjectValues parseObjectValuesImpl() {
2166 		string[] subRules;
2167 		subRules = ["V", "Vs", "Vsc"];
2168 		if(this.lex.front.type == TokenType.name) {
2169 			Token name = this.lex.front;
2170 			this.lex.popFront();
2171 			subRules = ["V", "Vs", "Vsc"];
2172 			if(this.lex.front.type == TokenType.colon) {
2173 				this.lex.popFront();
2174 				subRules = ["V", "Vs", "Vsc"];
2175 				if(this.firstValue()) {
2176 					Value val = this.parseValue();
2177 					subRules = ["Vsc"];
2178 					if(this.lex.front.type == TokenType.comma) {
2179 						this.lex.popFront();
2180 						subRules = ["Vsc"];
2181 						if(this.firstObjectValues()) {
2182 							ObjectValues follow = this.parseObjectValues();
2183 
2184 							return new ObjectValues(ObjectValuesEnum.Vsc
2185 								, name
2186 								, val
2187 								, follow
2188 							);
2189 						}
2190 						auto app = appender!string();
2191 						formattedWrite(app, 
2192 							"Found a '%s' while looking for", 
2193 							this.lex.front
2194 						);
2195 						throw new ParseException(app.data,
2196 							__FILE__, __LINE__,
2197 							subRules,
2198 							["name"]
2199 						);
2200 
2201 					} else if(this.firstObjectValues()) {
2202 						ObjectValues follow = this.parseObjectValues();
2203 
2204 						return new ObjectValues(ObjectValuesEnum.Vs
2205 							, name
2206 							, val
2207 							, follow
2208 						);
2209 					}
2210 					return new ObjectValues(ObjectValuesEnum.V
2211 						, name
2212 						, val
2213 					);
2214 				}
2215 				auto app = appender!string();
2216 				formattedWrite(app, 
2217 					"Found a '%s' while looking for", 
2218 					this.lex.front
2219 				);
2220 				throw new ParseException(app.data,
2221 					__FILE__, __LINE__,
2222 					subRules,
2223 					["false_","floatValue","intValue","lbrack -> Array","lcurly -> ObjectType","stringValue","true_"]
2224 				);
2225 
2226 			}
2227 			auto app = appender!string();
2228 			formattedWrite(app, 
2229 				"Found a '%s' while looking for", 
2230 				this.lex.front
2231 			);
2232 			throw new ParseException(app.data,
2233 				__FILE__, __LINE__,
2234 				subRules,
2235 				["colon"]
2236 			);
2237 
2238 		}
2239 		auto app = appender!string();
2240 		formattedWrite(app, 
2241 			"Found a '%s' while looking for", 
2242 			this.lex.front
2243 		);
2244 		throw new ParseException(app.data,
2245 			__FILE__, __LINE__,
2246 			subRules,
2247 			["name"]
2248 		);
2249 
2250 	}
2251 
2252 	bool firstObjectValue() const pure @nogc @safe {
2253 		return this.lex.front.type == TokenType.name;
2254 	}
2255 
2256 	ObjectValue parseObjectValue() {
2257 		try {
2258 			return this.parseObjectValueImpl();
2259 		} catch(ParseException e) {
2260 			throw new ParseException(
2261 				"While parsing a ObjectValue an Exception was thrown.",
2262 				e, __FILE__, __LINE__
2263 			);
2264 		}
2265 	}
2266 
2267 	ObjectValue parseObjectValueImpl() {
2268 		string[] subRules;
2269 		subRules = ["V"];
2270 		if(this.lex.front.type == TokenType.name) {
2271 			Token name = this.lex.front;
2272 			this.lex.popFront();
2273 			subRules = ["V"];
2274 			if(this.lex.front.type == TokenType.colon) {
2275 				this.lex.popFront();
2276 				subRules = ["V"];
2277 				if(this.firstValue()) {
2278 					Value val = this.parseValue();
2279 
2280 					return new ObjectValue(ObjectValueEnum.V
2281 						, name
2282 						, val
2283 					);
2284 				}
2285 				auto app = appender!string();
2286 				formattedWrite(app, 
2287 					"Found a '%s' while looking for", 
2288 					this.lex.front
2289 				);
2290 				throw new ParseException(app.data,
2291 					__FILE__, __LINE__,
2292 					subRules,
2293 					["false_","floatValue","intValue","lbrack -> Array","lcurly -> ObjectType","stringValue","true_"]
2294 				);
2295 
2296 			}
2297 			auto app = appender!string();
2298 			formattedWrite(app, 
2299 				"Found a '%s' while looking for", 
2300 				this.lex.front
2301 			);
2302 			throw new ParseException(app.data,
2303 				__FILE__, __LINE__,
2304 				subRules,
2305 				["colon"]
2306 			);
2307 
2308 		}
2309 		auto app = appender!string();
2310 		formattedWrite(app, 
2311 			"Found a '%s' while looking for", 
2312 			this.lex.front
2313 		);
2314 		throw new ParseException(app.data,
2315 			__FILE__, __LINE__,
2316 			subRules,
2317 			["name"]
2318 		);
2319 
2320 	}
2321 
2322 	bool firstObjectType() const pure @nogc @safe {
2323 		return this.lex.front.type == TokenType.lcurly;
2324 	}
2325 
2326 	ObjectType parseObjectType() {
2327 		try {
2328 			return this.parseObjectTypeImpl();
2329 		} catch(ParseException e) {
2330 			throw new ParseException(
2331 				"While parsing a ObjectType an Exception was thrown.",
2332 				e, __FILE__, __LINE__
2333 			);
2334 		}
2335 	}
2336 
2337 	ObjectType parseObjectTypeImpl() {
2338 		string[] subRules;
2339 		subRules = ["Var"];
2340 		if(this.lex.front.type == TokenType.lcurly) {
2341 			this.lex.popFront();
2342 			subRules = ["Var"];
2343 			if(this.firstObjectValues()) {
2344 				ObjectValues vals = this.parseObjectValues();
2345 				subRules = ["Var"];
2346 				if(this.lex.front.type == TokenType.rcurly) {
2347 					this.lex.popFront();
2348 
2349 					return new ObjectType(ObjectTypeEnum.Var
2350 						, vals
2351 					);
2352 				}
2353 				auto app = appender!string();
2354 				formattedWrite(app, 
2355 					"Found a '%s' while looking for", 
2356 					this.lex.front
2357 				);
2358 				throw new ParseException(app.data,
2359 					__FILE__, __LINE__,
2360 					subRules,
2361 					["rcurly"]
2362 				);
2363 
2364 			}
2365 			auto app = appender!string();
2366 			formattedWrite(app, 
2367 				"Found a '%s' while looking for", 
2368 				this.lex.front
2369 			);
2370 			throw new ParseException(app.data,
2371 				__FILE__, __LINE__,
2372 				subRules,
2373 				["name"]
2374 			);
2375 
2376 		}
2377 		auto app = appender!string();
2378 		formattedWrite(app, 
2379 			"Found a '%s' while looking for", 
2380 			this.lex.front
2381 		);
2382 		throw new ParseException(app.data,
2383 			__FILE__, __LINE__,
2384 			subRules,
2385 			["lcurly"]
2386 		);
2387 
2388 	}
2389 
2390 	bool firstTypeSystemDefinition() const pure @nogc @safe {
2391 		return this.firstSchemaDefinition()
2392 			 || this.firstTypeDefinition()
2393 			 || this.firstTypeExtensionDefinition()
2394 			 || this.firstDirectiveDefinition();
2395 	}
2396 
2397 	TypeSystemDefinition parseTypeSystemDefinition() {
2398 		try {
2399 			return this.parseTypeSystemDefinitionImpl();
2400 		} catch(ParseException e) {
2401 			throw new ParseException(
2402 				"While parsing a TypeSystemDefinition an Exception was thrown.",
2403 				e, __FILE__, __LINE__
2404 			);
2405 		}
2406 	}
2407 
2408 	TypeSystemDefinition parseTypeSystemDefinitionImpl() {
2409 		string[] subRules;
2410 		subRules = ["S"];
2411 		if(this.firstSchemaDefinition()) {
2412 			SchemaDefinition sch = this.parseSchemaDefinition();
2413 
2414 			return new TypeSystemDefinition(TypeSystemDefinitionEnum.S
2415 				, sch
2416 			);
2417 		} else if(this.firstTypeDefinition()) {
2418 			TypeDefinition td = this.parseTypeDefinition();
2419 
2420 			return new TypeSystemDefinition(TypeSystemDefinitionEnum.T
2421 				, td
2422 			);
2423 		} else if(this.firstTypeExtensionDefinition()) {
2424 			TypeExtensionDefinition ted = this.parseTypeExtensionDefinition();
2425 
2426 			return new TypeSystemDefinition(TypeSystemDefinitionEnum.TE
2427 				, ted
2428 			);
2429 		} else if(this.firstDirectiveDefinition()) {
2430 			DirectiveDefinition dd = this.parseDirectiveDefinition();
2431 
2432 			return new TypeSystemDefinition(TypeSystemDefinitionEnum.D
2433 				, dd
2434 			);
2435 		}
2436 		auto app = appender!string();
2437 		formattedWrite(app, 
2438 			"Found a '%s' while looking for", 
2439 			this.lex.front
2440 		);
2441 		throw new ParseException(app.data,
2442 			__FILE__, __LINE__,
2443 			subRules,
2444 			["schema","enum_ -> EnumTypeDefinition","input -> InputObjectTypeDefinition","interface_ -> InterfaceTypeDefinition","scalar -> ScalarTypeDefinition","type -> ObjectTypeDefinition","union_ -> UnionTypeDefinition","extend","directive"]
2445 		);
2446 
2447 	}
2448 
2449 	bool firstTypeDefinition() const pure @nogc @safe {
2450 		return this.firstScalarTypeDefinition()
2451 			 || this.firstObjectTypeDefinition()
2452 			 || this.firstInterfaceTypeDefinition()
2453 			 || this.firstUnionTypeDefinition()
2454 			 || this.firstEnumTypeDefinition()
2455 			 || this.firstInputObjectTypeDefinition();
2456 	}
2457 
2458 	TypeDefinition parseTypeDefinition() {
2459 		try {
2460 			return this.parseTypeDefinitionImpl();
2461 		} catch(ParseException e) {
2462 			throw new ParseException(
2463 				"While parsing a TypeDefinition an Exception was thrown.",
2464 				e, __FILE__, __LINE__
2465 			);
2466 		}
2467 	}
2468 
2469 	TypeDefinition parseTypeDefinitionImpl() {
2470 		string[] subRules;
2471 		subRules = ["S"];
2472 		if(this.firstScalarTypeDefinition()) {
2473 			ScalarTypeDefinition std = this.parseScalarTypeDefinition();
2474 
2475 			return new TypeDefinition(TypeDefinitionEnum.S
2476 				, std
2477 			);
2478 		} else if(this.firstObjectTypeDefinition()) {
2479 			ObjectTypeDefinition otd = this.parseObjectTypeDefinition();
2480 
2481 			return new TypeDefinition(TypeDefinitionEnum.O
2482 				, otd
2483 			);
2484 		} else if(this.firstInterfaceTypeDefinition()) {
2485 			InterfaceTypeDefinition itd = this.parseInterfaceTypeDefinition();
2486 
2487 			return new TypeDefinition(TypeDefinitionEnum.I
2488 				, itd
2489 			);
2490 		} else if(this.firstUnionTypeDefinition()) {
2491 			UnionTypeDefinition utd = this.parseUnionTypeDefinition();
2492 
2493 			return new TypeDefinition(TypeDefinitionEnum.U
2494 				, utd
2495 			);
2496 		} else if(this.firstEnumTypeDefinition()) {
2497 			EnumTypeDefinition etd = this.parseEnumTypeDefinition();
2498 
2499 			return new TypeDefinition(TypeDefinitionEnum.E
2500 				, etd
2501 			);
2502 		} else if(this.firstInputObjectTypeDefinition()) {
2503 			InputObjectTypeDefinition iod = this.parseInputObjectTypeDefinition();
2504 
2505 			return new TypeDefinition(TypeDefinitionEnum.IO
2506 				, iod
2507 			);
2508 		}
2509 		auto app = appender!string();
2510 		formattedWrite(app, 
2511 			"Found a '%s' while looking for", 
2512 			this.lex.front
2513 		);
2514 		throw new ParseException(app.data,
2515 			__FILE__, __LINE__,
2516 			subRules,
2517 			["scalar","type","interface_","union_","enum_","input"]
2518 		);
2519 
2520 	}
2521 
2522 	bool firstSchemaDefinition() const pure @nogc @safe {
2523 		return this.lex.front.type == TokenType.schema;
2524 	}
2525 
2526 	SchemaDefinition parseSchemaDefinition() {
2527 		try {
2528 			return this.parseSchemaDefinitionImpl();
2529 		} catch(ParseException e) {
2530 			throw new ParseException(
2531 				"While parsing a SchemaDefinition an Exception was thrown.",
2532 				e, __FILE__, __LINE__
2533 			);
2534 		}
2535 	}
2536 
2537 	SchemaDefinition parseSchemaDefinitionImpl() {
2538 		string[] subRules;
2539 		subRules = ["DO", "O"];
2540 		if(this.lex.front.type == TokenType.schema) {
2541 			this.lex.popFront();
2542 			subRules = ["DO"];
2543 			if(this.firstDirectives()) {
2544 				Directives dir = this.parseDirectives();
2545 				subRules = ["DO"];
2546 				if(this.lex.front.type == TokenType.lcurly) {
2547 					this.lex.popFront();
2548 					subRules = ["DO"];
2549 					if(this.firstOperationTypeDefinitions()) {
2550 						OperationTypeDefinitions otds = this.parseOperationTypeDefinitions();
2551 						subRules = ["DO"];
2552 						if(this.lex.front.type == TokenType.rcurly) {
2553 							this.lex.popFront();
2554 
2555 							return new SchemaDefinition(SchemaDefinitionEnum.DO
2556 								, dir
2557 								, otds
2558 							);
2559 						}
2560 						auto app = appender!string();
2561 						formattedWrite(app, 
2562 							"Found a '%s' while looking for", 
2563 							this.lex.front
2564 						);
2565 						throw new ParseException(app.data,
2566 							__FILE__, __LINE__,
2567 							subRules,
2568 							["rcurly"]
2569 						);
2570 
2571 					}
2572 					auto app = appender!string();
2573 					formattedWrite(app, 
2574 						"Found a '%s' while looking for", 
2575 						this.lex.front
2576 					);
2577 					throw new ParseException(app.data,
2578 						__FILE__, __LINE__,
2579 						subRules,
2580 						["mutation -> OperationTypeDefinition","query -> OperationTypeDefinition","subscription -> OperationTypeDefinition"]
2581 					);
2582 
2583 				}
2584 				auto app = appender!string();
2585 				formattedWrite(app, 
2586 					"Found a '%s' while looking for", 
2587 					this.lex.front
2588 				);
2589 				throw new ParseException(app.data,
2590 					__FILE__, __LINE__,
2591 					subRules,
2592 					["lcurly"]
2593 				);
2594 
2595 			} else if(this.lex.front.type == TokenType.lcurly) {
2596 				this.lex.popFront();
2597 				subRules = ["O"];
2598 				if(this.firstOperationTypeDefinitions()) {
2599 					OperationTypeDefinitions otds = this.parseOperationTypeDefinitions();
2600 					subRules = ["O"];
2601 					if(this.lex.front.type == TokenType.rcurly) {
2602 						this.lex.popFront();
2603 
2604 						return new SchemaDefinition(SchemaDefinitionEnum.O
2605 							, otds
2606 						);
2607 					}
2608 					auto app = appender!string();
2609 					formattedWrite(app, 
2610 						"Found a '%s' while looking for", 
2611 						this.lex.front
2612 					);
2613 					throw new ParseException(app.data,
2614 						__FILE__, __LINE__,
2615 						subRules,
2616 						["rcurly"]
2617 					);
2618 
2619 				}
2620 				auto app = appender!string();
2621 				formattedWrite(app, 
2622 					"Found a '%s' while looking for", 
2623 					this.lex.front
2624 				);
2625 				throw new ParseException(app.data,
2626 					__FILE__, __LINE__,
2627 					subRules,
2628 					["mutation -> OperationTypeDefinition","query -> OperationTypeDefinition","subscription -> OperationTypeDefinition"]
2629 				);
2630 
2631 			}
2632 			auto app = appender!string();
2633 			formattedWrite(app, 
2634 				"Found a '%s' while looking for", 
2635 				this.lex.front
2636 			);
2637 			throw new ParseException(app.data,
2638 				__FILE__, __LINE__,
2639 				subRules,
2640 				["at -> Directive","lcurly"]
2641 			);
2642 
2643 		}
2644 		auto app = appender!string();
2645 		formattedWrite(app, 
2646 			"Found a '%s' while looking for", 
2647 			this.lex.front
2648 		);
2649 		throw new ParseException(app.data,
2650 			__FILE__, __LINE__,
2651 			subRules,
2652 			["schema"]
2653 		);
2654 
2655 	}
2656 
2657 	bool firstOperationTypeDefinitions() const pure @nogc @safe {
2658 		return this.firstOperationTypeDefinition();
2659 	}
2660 
2661 	OperationTypeDefinitions parseOperationTypeDefinitions() {
2662 		try {
2663 			return this.parseOperationTypeDefinitionsImpl();
2664 		} catch(ParseException e) {
2665 			throw new ParseException(
2666 				"While parsing a OperationTypeDefinitions an Exception was thrown.",
2667 				e, __FILE__, __LINE__
2668 			);
2669 		}
2670 	}
2671 
2672 	OperationTypeDefinitions parseOperationTypeDefinitionsImpl() {
2673 		string[] subRules;
2674 		subRules = ["O", "OCS", "OS"];
2675 		if(this.firstOperationTypeDefinition()) {
2676 			OperationTypeDefinition otd = this.parseOperationTypeDefinition();
2677 			subRules = ["OCS"];
2678 			if(this.lex.front.type == TokenType.comma) {
2679 				this.lex.popFront();
2680 				subRules = ["OCS"];
2681 				if(this.firstOperationTypeDefinitions()) {
2682 					OperationTypeDefinitions follow = this.parseOperationTypeDefinitions();
2683 
2684 					return new OperationTypeDefinitions(OperationTypeDefinitionsEnum.OCS
2685 						, otd
2686 						, follow
2687 					);
2688 				}
2689 				auto app = appender!string();
2690 				formattedWrite(app, 
2691 					"Found a '%s' while looking for", 
2692 					this.lex.front
2693 				);
2694 				throw new ParseException(app.data,
2695 					__FILE__, __LINE__,
2696 					subRules,
2697 					["mutation -> OperationTypeDefinition","query -> OperationTypeDefinition","subscription -> OperationTypeDefinition"]
2698 				);
2699 
2700 			} else if(this.firstOperationTypeDefinitions()) {
2701 				OperationTypeDefinitions follow = this.parseOperationTypeDefinitions();
2702 
2703 				return new OperationTypeDefinitions(OperationTypeDefinitionsEnum.OS
2704 					, otd
2705 					, follow
2706 				);
2707 			}
2708 			return new OperationTypeDefinitions(OperationTypeDefinitionsEnum.O
2709 				, otd
2710 			);
2711 		}
2712 		auto app = appender!string();
2713 		formattedWrite(app, 
2714 			"Found a '%s' while looking for", 
2715 			this.lex.front
2716 		);
2717 		throw new ParseException(app.data,
2718 			__FILE__, __LINE__,
2719 			subRules,
2720 			["mutation -> OperationType","query -> OperationType","subscription -> OperationType"]
2721 		);
2722 
2723 	}
2724 
2725 	bool firstOperationTypeDefinition() const pure @nogc @safe {
2726 		return this.firstOperationType();
2727 	}
2728 
2729 	OperationTypeDefinition parseOperationTypeDefinition() {
2730 		try {
2731 			return this.parseOperationTypeDefinitionImpl();
2732 		} catch(ParseException e) {
2733 			throw new ParseException(
2734 				"While parsing a OperationTypeDefinition an Exception was thrown.",
2735 				e, __FILE__, __LINE__
2736 			);
2737 		}
2738 	}
2739 
2740 	OperationTypeDefinition parseOperationTypeDefinitionImpl() {
2741 		string[] subRules;
2742 		subRules = ["O"];
2743 		if(this.firstOperationType()) {
2744 			OperationType ot = this.parseOperationType();
2745 			subRules = ["O"];
2746 			if(this.lex.front.type == TokenType.colon) {
2747 				this.lex.popFront();
2748 				subRules = ["O"];
2749 				if(this.lex.front.type == TokenType.name) {
2750 					Token nt = this.lex.front;
2751 					this.lex.popFront();
2752 
2753 					return new OperationTypeDefinition(OperationTypeDefinitionEnum.O
2754 						, ot
2755 						, nt
2756 					);
2757 				}
2758 				auto app = appender!string();
2759 				formattedWrite(app, 
2760 					"Found a '%s' while looking for", 
2761 					this.lex.front
2762 				);
2763 				throw new ParseException(app.data,
2764 					__FILE__, __LINE__,
2765 					subRules,
2766 					["name"]
2767 				);
2768 
2769 			}
2770 			auto app = appender!string();
2771 			formattedWrite(app, 
2772 				"Found a '%s' while looking for", 
2773 				this.lex.front
2774 			);
2775 			throw new ParseException(app.data,
2776 				__FILE__, __LINE__,
2777 				subRules,
2778 				["colon"]
2779 			);
2780 
2781 		}
2782 		auto app = appender!string();
2783 		formattedWrite(app, 
2784 			"Found a '%s' while looking for", 
2785 			this.lex.front
2786 		);
2787 		throw new ParseException(app.data,
2788 			__FILE__, __LINE__,
2789 			subRules,
2790 			["mutation","query","subscription"]
2791 		);
2792 
2793 	}
2794 
2795 	bool firstScalarTypeDefinition() const pure @nogc @safe {
2796 		return this.lex.front.type == TokenType.scalar;
2797 	}
2798 
2799 	ScalarTypeDefinition parseScalarTypeDefinition() {
2800 		try {
2801 			return this.parseScalarTypeDefinitionImpl();
2802 		} catch(ParseException e) {
2803 			throw new ParseException(
2804 				"While parsing a ScalarTypeDefinition an Exception was thrown.",
2805 				e, __FILE__, __LINE__
2806 			);
2807 		}
2808 	}
2809 
2810 	ScalarTypeDefinition parseScalarTypeDefinitionImpl() {
2811 		string[] subRules;
2812 		subRules = ["D", "S"];
2813 		if(this.lex.front.type == TokenType.scalar) {
2814 			this.lex.popFront();
2815 			subRules = ["D", "S"];
2816 			if(this.lex.front.type == TokenType.name) {
2817 				Token name = this.lex.front;
2818 				this.lex.popFront();
2819 				subRules = ["D"];
2820 				if(this.firstDirectives()) {
2821 					Directives dir = this.parseDirectives();
2822 
2823 					return new ScalarTypeDefinition(ScalarTypeDefinitionEnum.D
2824 						, name
2825 						, dir
2826 					);
2827 				}
2828 				return new ScalarTypeDefinition(ScalarTypeDefinitionEnum.S
2829 					, name
2830 				);
2831 			}
2832 			auto app = appender!string();
2833 			formattedWrite(app, 
2834 				"Found a '%s' while looking for", 
2835 				this.lex.front
2836 			);
2837 			throw new ParseException(app.data,
2838 				__FILE__, __LINE__,
2839 				subRules,
2840 				["name"]
2841 			);
2842 
2843 		}
2844 		auto app = appender!string();
2845 		formattedWrite(app, 
2846 			"Found a '%s' while looking for", 
2847 			this.lex.front
2848 		);
2849 		throw new ParseException(app.data,
2850 			__FILE__, __LINE__,
2851 			subRules,
2852 			["scalar"]
2853 		);
2854 
2855 	}
2856 
2857 	bool firstObjectTypeDefinition() const pure @nogc @safe {
2858 		return this.lex.front.type == TokenType.type;
2859 	}
2860 
2861 	ObjectTypeDefinition parseObjectTypeDefinition() {
2862 		try {
2863 			return this.parseObjectTypeDefinitionImpl();
2864 		} catch(ParseException e) {
2865 			throw new ParseException(
2866 				"While parsing a ObjectTypeDefinition an Exception was thrown.",
2867 				e, __FILE__, __LINE__
2868 			);
2869 		}
2870 	}
2871 
2872 	ObjectTypeDefinition parseObjectTypeDefinitionImpl() {
2873 		string[] subRules;
2874 		subRules = ["D", "F", "I", "ID"];
2875 		if(this.lex.front.type == TokenType.type) {
2876 			this.lex.popFront();
2877 			subRules = ["D", "F", "I", "ID"];
2878 			if(this.lex.front.type == TokenType.name) {
2879 				Token name = this.lex.front;
2880 				this.lex.popFront();
2881 				subRules = ["I", "ID"];
2882 				if(this.firstImplementsInterfaces()) {
2883 					ImplementsInterfaces ii = this.parseImplementsInterfaces();
2884 					subRules = ["ID"];
2885 					if(this.firstDirectives()) {
2886 						Directives dir = this.parseDirectives();
2887 						subRules = ["ID"];
2888 						if(this.lex.front.type == TokenType.lcurly) {
2889 							this.lex.popFront();
2890 							subRules = ["ID"];
2891 							if(this.firstFieldDefinitions()) {
2892 								FieldDefinitions fds = this.parseFieldDefinitions();
2893 								subRules = ["ID"];
2894 								if(this.lex.front.type == TokenType.rcurly) {
2895 									this.lex.popFront();
2896 
2897 									return new ObjectTypeDefinition(ObjectTypeDefinitionEnum.ID
2898 										, name
2899 										, ii
2900 										, dir
2901 										, fds
2902 									);
2903 								}
2904 								auto app = appender!string();
2905 								formattedWrite(app, 
2906 									"Found a '%s' while looking for", 
2907 									this.lex.front
2908 								);
2909 								throw new ParseException(app.data,
2910 									__FILE__, __LINE__,
2911 									subRules,
2912 									["rcurly"]
2913 								);
2914 
2915 							}
2916 							auto app = appender!string();
2917 							formattedWrite(app, 
2918 								"Found a '%s' while looking for", 
2919 								this.lex.front
2920 							);
2921 							throw new ParseException(app.data,
2922 								__FILE__, __LINE__,
2923 								subRules,
2924 								["name -> FieldDefinition"]
2925 							);
2926 
2927 						}
2928 						auto app = appender!string();
2929 						formattedWrite(app, 
2930 							"Found a '%s' while looking for", 
2931 							this.lex.front
2932 						);
2933 						throw new ParseException(app.data,
2934 							__FILE__, __LINE__,
2935 							subRules,
2936 							["lcurly"]
2937 						);
2938 
2939 					} else if(this.lex.front.type == TokenType.lcurly) {
2940 						this.lex.popFront();
2941 						subRules = ["I"];
2942 						if(this.firstFieldDefinitions()) {
2943 							FieldDefinitions fds = this.parseFieldDefinitions();
2944 							subRules = ["I"];
2945 							if(this.lex.front.type == TokenType.rcurly) {
2946 								this.lex.popFront();
2947 
2948 								return new ObjectTypeDefinition(ObjectTypeDefinitionEnum.I
2949 									, name
2950 									, ii
2951 									, fds
2952 								);
2953 							}
2954 							auto app = appender!string();
2955 							formattedWrite(app, 
2956 								"Found a '%s' while looking for", 
2957 								this.lex.front
2958 							);
2959 							throw new ParseException(app.data,
2960 								__FILE__, __LINE__,
2961 								subRules,
2962 								["rcurly"]
2963 							);
2964 
2965 						}
2966 						auto app = appender!string();
2967 						formattedWrite(app, 
2968 							"Found a '%s' while looking for", 
2969 							this.lex.front
2970 						);
2971 						throw new ParseException(app.data,
2972 							__FILE__, __LINE__,
2973 							subRules,
2974 							["name -> FieldDefinition"]
2975 						);
2976 
2977 					}
2978 					auto app = appender!string();
2979 					formattedWrite(app, 
2980 						"Found a '%s' while looking for", 
2981 						this.lex.front
2982 					);
2983 					throw new ParseException(app.data,
2984 						__FILE__, __LINE__,
2985 						subRules,
2986 						["at -> Directive","lcurly"]
2987 					);
2988 
2989 				} else if(this.firstDirectives()) {
2990 					Directives dir = this.parseDirectives();
2991 					subRules = ["D"];
2992 					if(this.lex.front.type == TokenType.lcurly) {
2993 						this.lex.popFront();
2994 						subRules = ["D"];
2995 						if(this.firstFieldDefinitions()) {
2996 							FieldDefinitions fds = this.parseFieldDefinitions();
2997 							subRules = ["D"];
2998 							if(this.lex.front.type == TokenType.rcurly) {
2999 								this.lex.popFront();
3000 
3001 								return new ObjectTypeDefinition(ObjectTypeDefinitionEnum.D
3002 									, name
3003 									, dir
3004 									, fds
3005 								);
3006 							}
3007 							auto app = appender!string();
3008 							formattedWrite(app, 
3009 								"Found a '%s' while looking for", 
3010 								this.lex.front
3011 							);
3012 							throw new ParseException(app.data,
3013 								__FILE__, __LINE__,
3014 								subRules,
3015 								["rcurly"]
3016 							);
3017 
3018 						}
3019 						auto app = appender!string();
3020 						formattedWrite(app, 
3021 							"Found a '%s' while looking for", 
3022 							this.lex.front
3023 						);
3024 						throw new ParseException(app.data,
3025 							__FILE__, __LINE__,
3026 							subRules,
3027 							["name -> FieldDefinition"]
3028 						);
3029 
3030 					}
3031 					auto app = appender!string();
3032 					formattedWrite(app, 
3033 						"Found a '%s' while looking for", 
3034 						this.lex.front
3035 					);
3036 					throw new ParseException(app.data,
3037 						__FILE__, __LINE__,
3038 						subRules,
3039 						["lcurly"]
3040 					);
3041 
3042 				} else if(this.lex.front.type == TokenType.lcurly) {
3043 					this.lex.popFront();
3044 					subRules = ["F"];
3045 					if(this.firstFieldDefinitions()) {
3046 						FieldDefinitions fds = this.parseFieldDefinitions();
3047 						subRules = ["F"];
3048 						if(this.lex.front.type == TokenType.rcurly) {
3049 							this.lex.popFront();
3050 
3051 							return new ObjectTypeDefinition(ObjectTypeDefinitionEnum.F
3052 								, name
3053 								, fds
3054 							);
3055 						}
3056 						auto app = appender!string();
3057 						formattedWrite(app, 
3058 							"Found a '%s' while looking for", 
3059 							this.lex.front
3060 						);
3061 						throw new ParseException(app.data,
3062 							__FILE__, __LINE__,
3063 							subRules,
3064 							["rcurly"]
3065 						);
3066 
3067 					}
3068 					auto app = appender!string();
3069 					formattedWrite(app, 
3070 						"Found a '%s' while looking for", 
3071 						this.lex.front
3072 					);
3073 					throw new ParseException(app.data,
3074 						__FILE__, __LINE__,
3075 						subRules,
3076 						["name -> FieldDefinition"]
3077 					);
3078 
3079 				}
3080 				auto app = appender!string();
3081 				formattedWrite(app, 
3082 					"Found a '%s' while looking for", 
3083 					this.lex.front
3084 				);
3085 				throw new ParseException(app.data,
3086 					__FILE__, __LINE__,
3087 					subRules,
3088 					["implements","at -> Directive","lcurly"]
3089 				);
3090 
3091 			}
3092 			auto app = appender!string();
3093 			formattedWrite(app, 
3094 				"Found a '%s' while looking for", 
3095 				this.lex.front
3096 			);
3097 			throw new ParseException(app.data,
3098 				__FILE__, __LINE__,
3099 				subRules,
3100 				["name"]
3101 			);
3102 
3103 		}
3104 		auto app = appender!string();
3105 		formattedWrite(app, 
3106 			"Found a '%s' while looking for", 
3107 			this.lex.front
3108 		);
3109 		throw new ParseException(app.data,
3110 			__FILE__, __LINE__,
3111 			subRules,
3112 			["type"]
3113 		);
3114 
3115 	}
3116 
3117 	bool firstFieldDefinitions() const pure @nogc @safe {
3118 		return this.firstFieldDefinition();
3119 	}
3120 
3121 	FieldDefinitions parseFieldDefinitions() {
3122 		try {
3123 			return this.parseFieldDefinitionsImpl();
3124 		} catch(ParseException e) {
3125 			throw new ParseException(
3126 				"While parsing a FieldDefinitions an Exception was thrown.",
3127 				e, __FILE__, __LINE__
3128 			);
3129 		}
3130 	}
3131 
3132 	FieldDefinitions parseFieldDefinitionsImpl() {
3133 		string[] subRules;
3134 		subRules = ["F", "FC", "FNC"];
3135 		if(this.firstFieldDefinition()) {
3136 			FieldDefinition fd = this.parseFieldDefinition();
3137 			subRules = ["FC"];
3138 			if(this.lex.front.type == TokenType.comma) {
3139 				this.lex.popFront();
3140 				subRules = ["FC"];
3141 				if(this.firstFieldDefinitions()) {
3142 					FieldDefinitions follow = this.parseFieldDefinitions();
3143 
3144 					return new FieldDefinitions(FieldDefinitionsEnum.FC
3145 						, fd
3146 						, follow
3147 					);
3148 				}
3149 				auto app = appender!string();
3150 				formattedWrite(app, 
3151 					"Found a '%s' while looking for", 
3152 					this.lex.front
3153 				);
3154 				throw new ParseException(app.data,
3155 					__FILE__, __LINE__,
3156 					subRules,
3157 					["name -> FieldDefinition"]
3158 				);
3159 
3160 			} else if(this.firstFieldDefinitions()) {
3161 				FieldDefinitions follow = this.parseFieldDefinitions();
3162 
3163 				return new FieldDefinitions(FieldDefinitionsEnum.FNC
3164 					, fd
3165 					, follow
3166 				);
3167 			}
3168 			return new FieldDefinitions(FieldDefinitionsEnum.F
3169 				, fd
3170 			);
3171 		}
3172 		auto app = appender!string();
3173 		formattedWrite(app, 
3174 			"Found a '%s' while looking for", 
3175 			this.lex.front
3176 		);
3177 		throw new ParseException(app.data,
3178 			__FILE__, __LINE__,
3179 			subRules,
3180 			["name"]
3181 		);
3182 
3183 	}
3184 
3185 	bool firstFieldDefinition() const pure @nogc @safe {
3186 		return this.lex.front.type == TokenType.name;
3187 	}
3188 
3189 	FieldDefinition parseFieldDefinition() {
3190 		try {
3191 			return this.parseFieldDefinitionImpl();
3192 		} catch(ParseException e) {
3193 			throw new ParseException(
3194 				"While parsing a FieldDefinition an Exception was thrown.",
3195 				e, __FILE__, __LINE__
3196 			);
3197 		}
3198 	}
3199 
3200 	FieldDefinition parseFieldDefinitionImpl() {
3201 		string[] subRules;
3202 		subRules = ["A", "AD", "D", "T"];
3203 		if(this.lex.front.type == TokenType.name) {
3204 			Token name = this.lex.front;
3205 			this.lex.popFront();
3206 			subRules = ["A", "AD"];
3207 			if(this.firstArgumentsDefinition()) {
3208 				ArgumentsDefinition arg = this.parseArgumentsDefinition();
3209 				subRules = ["A", "AD"];
3210 				if(this.lex.front.type == TokenType.colon) {
3211 					this.lex.popFront();
3212 					subRules = ["A", "AD"];
3213 					if(this.firstType()) {
3214 						Type typ = this.parseType();
3215 						subRules = ["AD"];
3216 						if(this.firstDirectives()) {
3217 							Directives dir = this.parseDirectives();
3218 
3219 							return new FieldDefinition(FieldDefinitionEnum.AD
3220 								, name
3221 								, arg
3222 								, typ
3223 								, dir
3224 							);
3225 						}
3226 						return new FieldDefinition(FieldDefinitionEnum.A
3227 							, name
3228 							, arg
3229 							, typ
3230 						);
3231 					}
3232 					auto app = appender!string();
3233 					formattedWrite(app, 
3234 						"Found a '%s' while looking for", 
3235 						this.lex.front
3236 					);
3237 					throw new ParseException(app.data,
3238 						__FILE__, __LINE__,
3239 						subRules,
3240 						["lbrack -> ListType","name"]
3241 					);
3242 
3243 				}
3244 				auto app = appender!string();
3245 				formattedWrite(app, 
3246 					"Found a '%s' while looking for", 
3247 					this.lex.front
3248 				);
3249 				throw new ParseException(app.data,
3250 					__FILE__, __LINE__,
3251 					subRules,
3252 					["colon"]
3253 				);
3254 
3255 			} else if(this.lex.front.type == TokenType.colon) {
3256 				this.lex.popFront();
3257 				subRules = ["D", "T"];
3258 				if(this.firstType()) {
3259 					Type typ = this.parseType();
3260 					subRules = ["D"];
3261 					if(this.firstDirectives()) {
3262 						Directives dir = this.parseDirectives();
3263 
3264 						return new FieldDefinition(FieldDefinitionEnum.D
3265 							, name
3266 							, typ
3267 							, dir
3268 						);
3269 					}
3270 					return new FieldDefinition(FieldDefinitionEnum.T
3271 						, name
3272 						, typ
3273 					);
3274 				}
3275 				auto app = appender!string();
3276 				formattedWrite(app, 
3277 					"Found a '%s' while looking for", 
3278 					this.lex.front
3279 				);
3280 				throw new ParseException(app.data,
3281 					__FILE__, __LINE__,
3282 					subRules,
3283 					["lbrack -> ListType","name"]
3284 				);
3285 
3286 			}
3287 			auto app = appender!string();
3288 			formattedWrite(app, 
3289 				"Found a '%s' while looking for", 
3290 				this.lex.front
3291 			);
3292 			throw new ParseException(app.data,
3293 				__FILE__, __LINE__,
3294 				subRules,
3295 				["lparen","colon"]
3296 			);
3297 
3298 		}
3299 		auto app = appender!string();
3300 		formattedWrite(app, 
3301 			"Found a '%s' while looking for", 
3302 			this.lex.front
3303 		);
3304 		throw new ParseException(app.data,
3305 			__FILE__, __LINE__,
3306 			subRules,
3307 			["name"]
3308 		);
3309 
3310 	}
3311 
3312 	bool firstImplementsInterfaces() const pure @nogc @safe {
3313 		return this.lex.front.type == TokenType.implements;
3314 	}
3315 
3316 	ImplementsInterfaces parseImplementsInterfaces() {
3317 		try {
3318 			return this.parseImplementsInterfacesImpl();
3319 		} catch(ParseException e) {
3320 			throw new ParseException(
3321 				"While parsing a ImplementsInterfaces an Exception was thrown.",
3322 				e, __FILE__, __LINE__
3323 			);
3324 		}
3325 	}
3326 
3327 	ImplementsInterfaces parseImplementsInterfacesImpl() {
3328 		string[] subRules;
3329 		subRules = ["N"];
3330 		if(this.lex.front.type == TokenType.implements) {
3331 			this.lex.popFront();
3332 			subRules = ["N"];
3333 			if(this.firstNamedTypes()) {
3334 				NamedTypes nts = this.parseNamedTypes();
3335 
3336 				return new ImplementsInterfaces(ImplementsInterfacesEnum.N
3337 					, nts
3338 				);
3339 			}
3340 			auto app = appender!string();
3341 			formattedWrite(app, 
3342 				"Found a '%s' while looking for", 
3343 				this.lex.front
3344 			);
3345 			throw new ParseException(app.data,
3346 				__FILE__, __LINE__,
3347 				subRules,
3348 				["name"]
3349 			);
3350 
3351 		}
3352 		auto app = appender!string();
3353 		formattedWrite(app, 
3354 			"Found a '%s' while looking for", 
3355 			this.lex.front
3356 		);
3357 		throw new ParseException(app.data,
3358 			__FILE__, __LINE__,
3359 			subRules,
3360 			["implements"]
3361 		);
3362 
3363 	}
3364 
3365 	bool firstNamedTypes() const pure @nogc @safe {
3366 		return this.lex.front.type == TokenType.name;
3367 	}
3368 
3369 	NamedTypes parseNamedTypes() {
3370 		try {
3371 			return this.parseNamedTypesImpl();
3372 		} catch(ParseException e) {
3373 			throw new ParseException(
3374 				"While parsing a NamedTypes an Exception was thrown.",
3375 				e, __FILE__, __LINE__
3376 			);
3377 		}
3378 	}
3379 
3380 	NamedTypes parseNamedTypesImpl() {
3381 		string[] subRules;
3382 		subRules = ["N", "NCS", "NS"];
3383 		if(this.lex.front.type == TokenType.name) {
3384 			Token name = this.lex.front;
3385 			this.lex.popFront();
3386 			subRules = ["NCS"];
3387 			if(this.lex.front.type == TokenType.comma) {
3388 				this.lex.popFront();
3389 				subRules = ["NCS"];
3390 				if(this.firstNamedTypes()) {
3391 					NamedTypes follow = this.parseNamedTypes();
3392 
3393 					return new NamedTypes(NamedTypesEnum.NCS
3394 						, name
3395 						, follow
3396 					);
3397 				}
3398 				auto app = appender!string();
3399 				formattedWrite(app, 
3400 					"Found a '%s' while looking for", 
3401 					this.lex.front
3402 				);
3403 				throw new ParseException(app.data,
3404 					__FILE__, __LINE__,
3405 					subRules,
3406 					["name"]
3407 				);
3408 
3409 			} else if(this.firstNamedTypes()) {
3410 				NamedTypes follow = this.parseNamedTypes();
3411 
3412 				return new NamedTypes(NamedTypesEnum.NS
3413 					, name
3414 					, follow
3415 				);
3416 			}
3417 			return new NamedTypes(NamedTypesEnum.N
3418 				, name
3419 			);
3420 		}
3421 		auto app = appender!string();
3422 		formattedWrite(app, 
3423 			"Found a '%s' while looking for", 
3424 			this.lex.front
3425 		);
3426 		throw new ParseException(app.data,
3427 			__FILE__, __LINE__,
3428 			subRules,
3429 			["name"]
3430 		);
3431 
3432 	}
3433 
3434 	bool firstArgumentsDefinition() const pure @nogc @safe {
3435 		return this.lex.front.type == TokenType.lparen;
3436 	}
3437 
3438 	ArgumentsDefinition parseArgumentsDefinition() {
3439 		try {
3440 			return this.parseArgumentsDefinitionImpl();
3441 		} catch(ParseException e) {
3442 			throw new ParseException(
3443 				"While parsing a ArgumentsDefinition an Exception was thrown.",
3444 				e, __FILE__, __LINE__
3445 			);
3446 		}
3447 	}
3448 
3449 	ArgumentsDefinition parseArgumentsDefinitionImpl() {
3450 		string[] subRules;
3451 		subRules = ["A"];
3452 		if(this.lex.front.type == TokenType.lparen) {
3453 			this.lex.popFront();
3454 			subRules = ["A"];
3455 			if(this.firstInputValueDefinitions()) {
3456 				this.parseInputValueDefinitions();
3457 				subRules = ["A"];
3458 				if(this.lex.front.type == TokenType.rparen) {
3459 					this.lex.popFront();
3460 
3461 					return new ArgumentsDefinition(ArgumentsDefinitionEnum.A
3462 					);
3463 				}
3464 				auto app = appender!string();
3465 				formattedWrite(app, 
3466 					"Found a '%s' while looking for", 
3467 					this.lex.front
3468 				);
3469 				throw new ParseException(app.data,
3470 					__FILE__, __LINE__,
3471 					subRules,
3472 					["rparen"]
3473 				);
3474 
3475 			}
3476 			auto app = appender!string();
3477 			formattedWrite(app, 
3478 				"Found a '%s' while looking for", 
3479 				this.lex.front
3480 			);
3481 			throw new ParseException(app.data,
3482 				__FILE__, __LINE__,
3483 				subRules,
3484 				["name -> InputValueDefinition"]
3485 			);
3486 
3487 		}
3488 		auto app = appender!string();
3489 		formattedWrite(app, 
3490 			"Found a '%s' while looking for", 
3491 			this.lex.front
3492 		);
3493 		throw new ParseException(app.data,
3494 			__FILE__, __LINE__,
3495 			subRules,
3496 			["lparen"]
3497 		);
3498 
3499 	}
3500 
3501 	bool firstInputValueDefinitions() const pure @nogc @safe {
3502 		return this.firstInputValueDefinition();
3503 	}
3504 
3505 	InputValueDefinitions parseInputValueDefinitions() {
3506 		try {
3507 			return this.parseInputValueDefinitionsImpl();
3508 		} catch(ParseException e) {
3509 			throw new ParseException(
3510 				"While parsing a InputValueDefinitions an Exception was thrown.",
3511 				e, __FILE__, __LINE__
3512 			);
3513 		}
3514 	}
3515 
3516 	InputValueDefinitions parseInputValueDefinitionsImpl() {
3517 		string[] subRules;
3518 		subRules = ["I", "ICF", "IF"];
3519 		if(this.firstInputValueDefinition()) {
3520 			InputValueDefinition iv = this.parseInputValueDefinition();
3521 			subRules = ["ICF"];
3522 			if(this.lex.front.type == TokenType.comma) {
3523 				this.lex.popFront();
3524 				subRules = ["ICF"];
3525 				if(this.firstInputValueDefinitions()) {
3526 					InputValueDefinitions follow = this.parseInputValueDefinitions();
3527 
3528 					return new InputValueDefinitions(InputValueDefinitionsEnum.ICF
3529 						, iv
3530 						, follow
3531 					);
3532 				}
3533 				auto app = appender!string();
3534 				formattedWrite(app, 
3535 					"Found a '%s' while looking for", 
3536 					this.lex.front
3537 				);
3538 				throw new ParseException(app.data,
3539 					__FILE__, __LINE__,
3540 					subRules,
3541 					["name -> InputValueDefinition"]
3542 				);
3543 
3544 			} else if(this.firstInputValueDefinitions()) {
3545 				InputValueDefinitions follow = this.parseInputValueDefinitions();
3546 
3547 				return new InputValueDefinitions(InputValueDefinitionsEnum.IF
3548 					, iv
3549 					, follow
3550 				);
3551 			}
3552 			return new InputValueDefinitions(InputValueDefinitionsEnum.I
3553 				, iv
3554 			);
3555 		}
3556 		auto app = appender!string();
3557 		formattedWrite(app, 
3558 			"Found a '%s' while looking for", 
3559 			this.lex.front
3560 		);
3561 		throw new ParseException(app.data,
3562 			__FILE__, __LINE__,
3563 			subRules,
3564 			["name"]
3565 		);
3566 
3567 	}
3568 
3569 	bool firstInputValueDefinition() const pure @nogc @safe {
3570 		return this.lex.front.type == TokenType.name;
3571 	}
3572 
3573 	InputValueDefinition parseInputValueDefinition() {
3574 		try {
3575 			return this.parseInputValueDefinitionImpl();
3576 		} catch(ParseException e) {
3577 			throw new ParseException(
3578 				"While parsing a InputValueDefinition an Exception was thrown.",
3579 				e, __FILE__, __LINE__
3580 			);
3581 		}
3582 	}
3583 
3584 	InputValueDefinition parseInputValueDefinitionImpl() {
3585 		string[] subRules;
3586 		subRules = ["T", "TD", "TV", "TVD"];
3587 		if(this.lex.front.type == TokenType.name) {
3588 			Token name = this.lex.front;
3589 			this.lex.popFront();
3590 			subRules = ["T", "TD", "TV", "TVD"];
3591 			if(this.lex.front.type == TokenType.colon) {
3592 				this.lex.popFront();
3593 				subRules = ["T", "TD", "TV", "TVD"];
3594 				if(this.firstType()) {
3595 					Type type = this.parseType();
3596 					subRules = ["TV", "TVD"];
3597 					if(this.firstDefaultValue()) {
3598 						DefaultValue df = this.parseDefaultValue();
3599 						subRules = ["TVD"];
3600 						if(this.firstDirectives()) {
3601 							Directives dirs = this.parseDirectives();
3602 
3603 							return new InputValueDefinition(InputValueDefinitionEnum.TVD
3604 								, name
3605 								, type
3606 								, df
3607 								, dirs
3608 							);
3609 						}
3610 						return new InputValueDefinition(InputValueDefinitionEnum.TV
3611 							, name
3612 							, type
3613 							, df
3614 						);
3615 					} else if(this.firstDirectives()) {
3616 						Directives dirs = this.parseDirectives();
3617 
3618 						return new InputValueDefinition(InputValueDefinitionEnum.TD
3619 							, name
3620 							, type
3621 							, dirs
3622 						);
3623 					}
3624 					return new InputValueDefinition(InputValueDefinitionEnum.T
3625 						, name
3626 						, type
3627 					);
3628 				}
3629 				auto app = appender!string();
3630 				formattedWrite(app, 
3631 					"Found a '%s' while looking for", 
3632 					this.lex.front
3633 				);
3634 				throw new ParseException(app.data,
3635 					__FILE__, __LINE__,
3636 					subRules,
3637 					["lbrack -> ListType","name"]
3638 				);
3639 
3640 			}
3641 			auto app = appender!string();
3642 			formattedWrite(app, 
3643 				"Found a '%s' while looking for", 
3644 				this.lex.front
3645 			);
3646 			throw new ParseException(app.data,
3647 				__FILE__, __LINE__,
3648 				subRules,
3649 				["colon"]
3650 			);
3651 
3652 		}
3653 		auto app = appender!string();
3654 		formattedWrite(app, 
3655 			"Found a '%s' while looking for", 
3656 			this.lex.front
3657 		);
3658 		throw new ParseException(app.data,
3659 			__FILE__, __LINE__,
3660 			subRules,
3661 			["name"]
3662 		);
3663 
3664 	}
3665 
3666 	bool firstInterfaceTypeDefinition() const pure @nogc @safe {
3667 		return this.lex.front.type == TokenType.interface_;
3668 	}
3669 
3670 	InterfaceTypeDefinition parseInterfaceTypeDefinition() {
3671 		try {
3672 			return this.parseInterfaceTypeDefinitionImpl();
3673 		} catch(ParseException e) {
3674 			throw new ParseException(
3675 				"While parsing a InterfaceTypeDefinition an Exception was thrown.",
3676 				e, __FILE__, __LINE__
3677 			);
3678 		}
3679 	}
3680 
3681 	InterfaceTypeDefinition parseInterfaceTypeDefinitionImpl() {
3682 		string[] subRules;
3683 		subRules = ["NDF", "NF"];
3684 		if(this.lex.front.type == TokenType.interface_) {
3685 			this.lex.popFront();
3686 			subRules = ["NDF", "NF"];
3687 			if(this.lex.front.type == TokenType.name) {
3688 				Token name = this.lex.front;
3689 				this.lex.popFront();
3690 				subRules = ["NDF"];
3691 				if(this.firstDirectives()) {
3692 					Directives dirs = this.parseDirectives();
3693 					subRules = ["NDF"];
3694 					if(this.lex.front.type == TokenType.lcurly) {
3695 						this.lex.popFront();
3696 						subRules = ["NDF"];
3697 						if(this.firstFieldDefinitions()) {
3698 							FieldDefinitions fds = this.parseFieldDefinitions();
3699 							subRules = ["NDF"];
3700 							if(this.lex.front.type == TokenType.rcurly) {
3701 								this.lex.popFront();
3702 
3703 								return new InterfaceTypeDefinition(InterfaceTypeDefinitionEnum.NDF
3704 									, name
3705 									, dirs
3706 									, fds
3707 								);
3708 							}
3709 							auto app = appender!string();
3710 							formattedWrite(app, 
3711 								"Found a '%s' while looking for", 
3712 								this.lex.front
3713 							);
3714 							throw new ParseException(app.data,
3715 								__FILE__, __LINE__,
3716 								subRules,
3717 								["rcurly"]
3718 							);
3719 
3720 						}
3721 						auto app = appender!string();
3722 						formattedWrite(app, 
3723 							"Found a '%s' while looking for", 
3724 							this.lex.front
3725 						);
3726 						throw new ParseException(app.data,
3727 							__FILE__, __LINE__,
3728 							subRules,
3729 							["name -> FieldDefinition"]
3730 						);
3731 
3732 					}
3733 					auto app = appender!string();
3734 					formattedWrite(app, 
3735 						"Found a '%s' while looking for", 
3736 						this.lex.front
3737 					);
3738 					throw new ParseException(app.data,
3739 						__FILE__, __LINE__,
3740 						subRules,
3741 						["lcurly"]
3742 					);
3743 
3744 				} else if(this.lex.front.type == TokenType.lcurly) {
3745 					this.lex.popFront();
3746 					subRules = ["NF"];
3747 					if(this.firstFieldDefinitions()) {
3748 						FieldDefinitions fds = this.parseFieldDefinitions();
3749 						subRules = ["NF"];
3750 						if(this.lex.front.type == TokenType.rcurly) {
3751 							this.lex.popFront();
3752 
3753 							return new InterfaceTypeDefinition(InterfaceTypeDefinitionEnum.NF
3754 								, name
3755 								, fds
3756 							);
3757 						}
3758 						auto app = appender!string();
3759 						formattedWrite(app, 
3760 							"Found a '%s' while looking for", 
3761 							this.lex.front
3762 						);
3763 						throw new ParseException(app.data,
3764 							__FILE__, __LINE__,
3765 							subRules,
3766 							["rcurly"]
3767 						);
3768 
3769 					}
3770 					auto app = appender!string();
3771 					formattedWrite(app, 
3772 						"Found a '%s' while looking for", 
3773 						this.lex.front
3774 					);
3775 					throw new ParseException(app.data,
3776 						__FILE__, __LINE__,
3777 						subRules,
3778 						["name -> FieldDefinition"]
3779 					);
3780 
3781 				}
3782 				auto app = appender!string();
3783 				formattedWrite(app, 
3784 					"Found a '%s' while looking for", 
3785 					this.lex.front
3786 				);
3787 				throw new ParseException(app.data,
3788 					__FILE__, __LINE__,
3789 					subRules,
3790 					["at -> Directive","lcurly"]
3791 				);
3792 
3793 			}
3794 			auto app = appender!string();
3795 			formattedWrite(app, 
3796 				"Found a '%s' while looking for", 
3797 				this.lex.front
3798 			);
3799 			throw new ParseException(app.data,
3800 				__FILE__, __LINE__,
3801 				subRules,
3802 				["name"]
3803 			);
3804 
3805 		}
3806 		auto app = appender!string();
3807 		formattedWrite(app, 
3808 			"Found a '%s' while looking for", 
3809 			this.lex.front
3810 		);
3811 		throw new ParseException(app.data,
3812 			__FILE__, __LINE__,
3813 			subRules,
3814 			["interface_"]
3815 		);
3816 
3817 	}
3818 
3819 	bool firstUnionTypeDefinition() const pure @nogc @safe {
3820 		return this.lex.front.type == TokenType.union_;
3821 	}
3822 
3823 	UnionTypeDefinition parseUnionTypeDefinition() {
3824 		try {
3825 			return this.parseUnionTypeDefinitionImpl();
3826 		} catch(ParseException e) {
3827 			throw new ParseException(
3828 				"While parsing a UnionTypeDefinition an Exception was thrown.",
3829 				e, __FILE__, __LINE__
3830 			);
3831 		}
3832 	}
3833 
3834 	UnionTypeDefinition parseUnionTypeDefinitionImpl() {
3835 		string[] subRules;
3836 		subRules = ["NDU", "NU"];
3837 		if(this.lex.front.type == TokenType.union_) {
3838 			this.lex.popFront();
3839 			subRules = ["NDU", "NU"];
3840 			if(this.lex.front.type == TokenType.name) {
3841 				Token name = this.lex.front;
3842 				this.lex.popFront();
3843 				subRules = ["NDU"];
3844 				if(this.firstDirectives()) {
3845 					Directives dirs = this.parseDirectives();
3846 					subRules = ["NDU"];
3847 					if(this.lex.front.type == TokenType.equal) {
3848 						this.lex.popFront();
3849 						subRules = ["NDU"];
3850 						if(this.firstUnionMembers()) {
3851 							UnionMembers um = this.parseUnionMembers();
3852 
3853 							return new UnionTypeDefinition(UnionTypeDefinitionEnum.NDU
3854 								, name
3855 								, dirs
3856 								, um
3857 							);
3858 						}
3859 						auto app = appender!string();
3860 						formattedWrite(app, 
3861 							"Found a '%s' while looking for", 
3862 							this.lex.front
3863 						);
3864 						throw new ParseException(app.data,
3865 							__FILE__, __LINE__,
3866 							subRules,
3867 							["name"]
3868 						);
3869 
3870 					}
3871 					auto app = appender!string();
3872 					formattedWrite(app, 
3873 						"Found a '%s' while looking for", 
3874 						this.lex.front
3875 					);
3876 					throw new ParseException(app.data,
3877 						__FILE__, __LINE__,
3878 						subRules,
3879 						["equal"]
3880 					);
3881 
3882 				} else if(this.lex.front.type == TokenType.equal) {
3883 					this.lex.popFront();
3884 					subRules = ["NU"];
3885 					if(this.firstUnionMembers()) {
3886 						UnionMembers um = this.parseUnionMembers();
3887 
3888 						return new UnionTypeDefinition(UnionTypeDefinitionEnum.NU
3889 							, name
3890 							, um
3891 						);
3892 					}
3893 					auto app = appender!string();
3894 					formattedWrite(app, 
3895 						"Found a '%s' while looking for", 
3896 						this.lex.front
3897 					);
3898 					throw new ParseException(app.data,
3899 						__FILE__, __LINE__,
3900 						subRules,
3901 						["name"]
3902 					);
3903 
3904 				}
3905 				auto app = appender!string();
3906 				formattedWrite(app, 
3907 					"Found a '%s' while looking for", 
3908 					this.lex.front
3909 				);
3910 				throw new ParseException(app.data,
3911 					__FILE__, __LINE__,
3912 					subRules,
3913 					["at -> Directive","equal"]
3914 				);
3915 
3916 			}
3917 			auto app = appender!string();
3918 			formattedWrite(app, 
3919 				"Found a '%s' while looking for", 
3920 				this.lex.front
3921 			);
3922 			throw new ParseException(app.data,
3923 				__FILE__, __LINE__,
3924 				subRules,
3925 				["name"]
3926 			);
3927 
3928 		}
3929 		auto app = appender!string();
3930 		formattedWrite(app, 
3931 			"Found a '%s' while looking for", 
3932 			this.lex.front
3933 		);
3934 		throw new ParseException(app.data,
3935 			__FILE__, __LINE__,
3936 			subRules,
3937 			["union_"]
3938 		);
3939 
3940 	}
3941 
3942 	bool firstUnionMembers() const pure @nogc @safe {
3943 		return this.lex.front.type == TokenType.name;
3944 	}
3945 
3946 	UnionMembers parseUnionMembers() {
3947 		try {
3948 			return this.parseUnionMembersImpl();
3949 		} catch(ParseException e) {
3950 			throw new ParseException(
3951 				"While parsing a UnionMembers an Exception was thrown.",
3952 				e, __FILE__, __LINE__
3953 			);
3954 		}
3955 	}
3956 
3957 	UnionMembers parseUnionMembersImpl() {
3958 		string[] subRules;
3959 		subRules = ["S", "SF", "SPF"];
3960 		if(this.lex.front.type == TokenType.name) {
3961 			Token name = this.lex.front;
3962 			this.lex.popFront();
3963 			subRules = ["SPF"];
3964 			if(this.lex.front.type == TokenType.pipe) {
3965 				this.lex.popFront();
3966 				subRules = ["SPF"];
3967 				if(this.firstUnionMembers()) {
3968 					UnionMembers follow = this.parseUnionMembers();
3969 
3970 					return new UnionMembers(UnionMembersEnum.SPF
3971 						, name
3972 						, follow
3973 					);
3974 				}
3975 				auto app = appender!string();
3976 				formattedWrite(app, 
3977 					"Found a '%s' while looking for", 
3978 					this.lex.front
3979 				);
3980 				throw new ParseException(app.data,
3981 					__FILE__, __LINE__,
3982 					subRules,
3983 					["name"]
3984 				);
3985 
3986 			} else if(this.firstUnionMembers()) {
3987 				UnionMembers follow = this.parseUnionMembers();
3988 
3989 				return new UnionMembers(UnionMembersEnum.SF
3990 					, name
3991 					, follow
3992 				);
3993 			}
3994 			return new UnionMembers(UnionMembersEnum.S
3995 				, name
3996 			);
3997 		}
3998 		auto app = appender!string();
3999 		formattedWrite(app, 
4000 			"Found a '%s' while looking for", 
4001 			this.lex.front
4002 		);
4003 		throw new ParseException(app.data,
4004 			__FILE__, __LINE__,
4005 			subRules,
4006 			["name"]
4007 		);
4008 
4009 	}
4010 
4011 	bool firstEnumTypeDefinition() const pure @nogc @safe {
4012 		return this.lex.front.type == TokenType.enum_;
4013 	}
4014 
4015 	EnumTypeDefinition parseEnumTypeDefinition() {
4016 		try {
4017 			return this.parseEnumTypeDefinitionImpl();
4018 		} catch(ParseException e) {
4019 			throw new ParseException(
4020 				"While parsing a EnumTypeDefinition an Exception was thrown.",
4021 				e, __FILE__, __LINE__
4022 			);
4023 		}
4024 	}
4025 
4026 	EnumTypeDefinition parseEnumTypeDefinitionImpl() {
4027 		string[] subRules;
4028 		subRules = ["NDE", "NE"];
4029 		if(this.lex.front.type == TokenType.enum_) {
4030 			this.lex.popFront();
4031 			subRules = ["NDE", "NE"];
4032 			if(this.lex.front.type == TokenType.name) {
4033 				Token name = this.lex.front;
4034 				this.lex.popFront();
4035 				subRules = ["NDE"];
4036 				if(this.firstDirectives()) {
4037 					Directives dir = this.parseDirectives();
4038 					subRules = ["NDE"];
4039 					if(this.lex.front.type == TokenType.lcurly) {
4040 						this.lex.popFront();
4041 						subRules = ["NDE"];
4042 						if(this.firstEnumValueDefinitions()) {
4043 							EnumValueDefinitions evds = this.parseEnumValueDefinitions();
4044 							subRules = ["NDE"];
4045 							if(this.lex.front.type == TokenType.rcurly) {
4046 								this.lex.popFront();
4047 
4048 								return new EnumTypeDefinition(EnumTypeDefinitionEnum.NDE
4049 									, name
4050 									, dir
4051 									, evds
4052 								);
4053 							}
4054 							auto app = appender!string();
4055 							formattedWrite(app, 
4056 								"Found a '%s' while looking for", 
4057 								this.lex.front
4058 							);
4059 							throw new ParseException(app.data,
4060 								__FILE__, __LINE__,
4061 								subRules,
4062 								["rcurly"]
4063 							);
4064 
4065 						}
4066 						auto app = appender!string();
4067 						formattedWrite(app, 
4068 							"Found a '%s' while looking for", 
4069 							this.lex.front
4070 						);
4071 						throw new ParseException(app.data,
4072 							__FILE__, __LINE__,
4073 							subRules,
4074 							["name -> EnumValueDefinition"]
4075 						);
4076 
4077 					}
4078 					auto app = appender!string();
4079 					formattedWrite(app, 
4080 						"Found a '%s' while looking for", 
4081 						this.lex.front
4082 					);
4083 					throw new ParseException(app.data,
4084 						__FILE__, __LINE__,
4085 						subRules,
4086 						["lcurly"]
4087 					);
4088 
4089 				} else if(this.lex.front.type == TokenType.lcurly) {
4090 					this.lex.popFront();
4091 					subRules = ["NE"];
4092 					if(this.firstEnumValueDefinitions()) {
4093 						EnumValueDefinitions evds = this.parseEnumValueDefinitions();
4094 						subRules = ["NE"];
4095 						if(this.lex.front.type == TokenType.rcurly) {
4096 							this.lex.popFront();
4097 
4098 							return new EnumTypeDefinition(EnumTypeDefinitionEnum.NE
4099 								, name
4100 								, evds
4101 							);
4102 						}
4103 						auto app = appender!string();
4104 						formattedWrite(app, 
4105 							"Found a '%s' while looking for", 
4106 							this.lex.front
4107 						);
4108 						throw new ParseException(app.data,
4109 							__FILE__, __LINE__,
4110 							subRules,
4111 							["rcurly"]
4112 						);
4113 
4114 					}
4115 					auto app = appender!string();
4116 					formattedWrite(app, 
4117 						"Found a '%s' while looking for", 
4118 						this.lex.front
4119 					);
4120 					throw new ParseException(app.data,
4121 						__FILE__, __LINE__,
4122 						subRules,
4123 						["name -> EnumValueDefinition"]
4124 					);
4125 
4126 				}
4127 				auto app = appender!string();
4128 				formattedWrite(app, 
4129 					"Found a '%s' while looking for", 
4130 					this.lex.front
4131 				);
4132 				throw new ParseException(app.data,
4133 					__FILE__, __LINE__,
4134 					subRules,
4135 					["at -> Directive","lcurly"]
4136 				);
4137 
4138 			}
4139 			auto app = appender!string();
4140 			formattedWrite(app, 
4141 				"Found a '%s' while looking for", 
4142 				this.lex.front
4143 			);
4144 			throw new ParseException(app.data,
4145 				__FILE__, __LINE__,
4146 				subRules,
4147 				["name"]
4148 			);
4149 
4150 		}
4151 		auto app = appender!string();
4152 		formattedWrite(app, 
4153 			"Found a '%s' while looking for", 
4154 			this.lex.front
4155 		);
4156 		throw new ParseException(app.data,
4157 			__FILE__, __LINE__,
4158 			subRules,
4159 			["enum_"]
4160 		);
4161 
4162 	}
4163 
4164 	bool firstEnumValueDefinitions() const pure @nogc @safe {
4165 		return this.firstEnumValueDefinition();
4166 	}
4167 
4168 	EnumValueDefinitions parseEnumValueDefinitions() {
4169 		try {
4170 			return this.parseEnumValueDefinitionsImpl();
4171 		} catch(ParseException e) {
4172 			throw new ParseException(
4173 				"While parsing a EnumValueDefinitions an Exception was thrown.",
4174 				e, __FILE__, __LINE__
4175 			);
4176 		}
4177 	}
4178 
4179 	EnumValueDefinitions parseEnumValueDefinitionsImpl() {
4180 		string[] subRules;
4181 		subRules = ["D", "DCE", "DE"];
4182 		if(this.firstEnumValueDefinition()) {
4183 			EnumValueDefinition evd = this.parseEnumValueDefinition();
4184 			subRules = ["DCE"];
4185 			if(this.lex.front.type == TokenType.comma) {
4186 				this.lex.popFront();
4187 				subRules = ["DCE"];
4188 				if(this.firstEnumValueDefinitions()) {
4189 					EnumValueDefinitions follow = this.parseEnumValueDefinitions();
4190 
4191 					return new EnumValueDefinitions(EnumValueDefinitionsEnum.DCE
4192 						, evd
4193 						, follow
4194 					);
4195 				}
4196 				auto app = appender!string();
4197 				formattedWrite(app, 
4198 					"Found a '%s' while looking for", 
4199 					this.lex.front
4200 				);
4201 				throw new ParseException(app.data,
4202 					__FILE__, __LINE__,
4203 					subRules,
4204 					["name -> EnumValueDefinition"]
4205 				);
4206 
4207 			} else if(this.firstEnumValueDefinitions()) {
4208 				EnumValueDefinitions follow = this.parseEnumValueDefinitions();
4209 
4210 				return new EnumValueDefinitions(EnumValueDefinitionsEnum.DE
4211 					, evd
4212 					, follow
4213 				);
4214 			}
4215 			return new EnumValueDefinitions(EnumValueDefinitionsEnum.D
4216 				, evd
4217 			);
4218 		}
4219 		auto app = appender!string();
4220 		formattedWrite(app, 
4221 			"Found a '%s' while looking for", 
4222 			this.lex.front
4223 		);
4224 		throw new ParseException(app.data,
4225 			__FILE__, __LINE__,
4226 			subRules,
4227 			["name"]
4228 		);
4229 
4230 	}
4231 
4232 	bool firstEnumValueDefinition() const pure @nogc @safe {
4233 		return this.lex.front.type == TokenType.name;
4234 	}
4235 
4236 	EnumValueDefinition parseEnumValueDefinition() {
4237 		try {
4238 			return this.parseEnumValueDefinitionImpl();
4239 		} catch(ParseException e) {
4240 			throw new ParseException(
4241 				"While parsing a EnumValueDefinition an Exception was thrown.",
4242 				e, __FILE__, __LINE__
4243 			);
4244 		}
4245 	}
4246 
4247 	EnumValueDefinition parseEnumValueDefinitionImpl() {
4248 		string[] subRules;
4249 		subRules = ["E", "ED"];
4250 		if(this.lex.front.type == TokenType.name) {
4251 			Token name = this.lex.front;
4252 			this.lex.popFront();
4253 			subRules = ["ED"];
4254 			if(this.firstDirectives()) {
4255 				Directives dirs = this.parseDirectives();
4256 
4257 				return new EnumValueDefinition(EnumValueDefinitionEnum.ED
4258 					, name
4259 					, dirs
4260 				);
4261 			}
4262 			return new EnumValueDefinition(EnumValueDefinitionEnum.E
4263 				, name
4264 			);
4265 		}
4266 		auto app = appender!string();
4267 		formattedWrite(app, 
4268 			"Found a '%s' while looking for", 
4269 			this.lex.front
4270 		);
4271 		throw new ParseException(app.data,
4272 			__FILE__, __LINE__,
4273 			subRules,
4274 			["name"]
4275 		);
4276 
4277 	}
4278 
4279 	bool firstInputTypeDefinition() const pure @nogc @safe {
4280 		return this.lex.front.type == TokenType.input;
4281 	}
4282 
4283 	InputTypeDefinition parseInputTypeDefinition() {
4284 		try {
4285 			return this.parseInputTypeDefinitionImpl();
4286 		} catch(ParseException e) {
4287 			throw new ParseException(
4288 				"While parsing a InputTypeDefinition an Exception was thrown.",
4289 				e, __FILE__, __LINE__
4290 			);
4291 		}
4292 	}
4293 
4294 	InputTypeDefinition parseInputTypeDefinitionImpl() {
4295 		string[] subRules;
4296 		subRules = ["NDE", "NE"];
4297 		if(this.lex.front.type == TokenType.input) {
4298 			this.lex.popFront();
4299 			subRules = ["NDE", "NE"];
4300 			if(this.lex.front.type == TokenType.name) {
4301 				Token name = this.lex.front;
4302 				this.lex.popFront();
4303 				subRules = ["NDE"];
4304 				if(this.firstDirectives()) {
4305 					Directives dir = this.parseDirectives();
4306 					subRules = ["NDE"];
4307 					if(this.lex.front.type == TokenType.lcurly) {
4308 						this.lex.popFront();
4309 						subRules = ["NDE"];
4310 						if(this.firstInputValueDefinitions()) {
4311 							InputValueDefinitions ivds = this.parseInputValueDefinitions();
4312 							subRules = ["NDE"];
4313 							if(this.lex.front.type == TokenType.rcurly) {
4314 								this.lex.popFront();
4315 
4316 								return new InputTypeDefinition(InputTypeDefinitionEnum.NDE
4317 									, name
4318 									, dir
4319 									, ivds
4320 								);
4321 							}
4322 							auto app = appender!string();
4323 							formattedWrite(app, 
4324 								"Found a '%s' while looking for", 
4325 								this.lex.front
4326 							);
4327 							throw new ParseException(app.data,
4328 								__FILE__, __LINE__,
4329 								subRules,
4330 								["rcurly"]
4331 							);
4332 
4333 						}
4334 						auto app = appender!string();
4335 						formattedWrite(app, 
4336 							"Found a '%s' while looking for", 
4337 							this.lex.front
4338 						);
4339 						throw new ParseException(app.data,
4340 							__FILE__, __LINE__,
4341 							subRules,
4342 							["name -> InputValueDefinition"]
4343 						);
4344 
4345 					}
4346 					auto app = appender!string();
4347 					formattedWrite(app, 
4348 						"Found a '%s' while looking for", 
4349 						this.lex.front
4350 					);
4351 					throw new ParseException(app.data,
4352 						__FILE__, __LINE__,
4353 						subRules,
4354 						["lcurly"]
4355 					);
4356 
4357 				} else if(this.lex.front.type == TokenType.lcurly) {
4358 					this.lex.popFront();
4359 					subRules = ["NE"];
4360 					if(this.firstInputValueDefinitions()) {
4361 						InputValueDefinitions ivds = this.parseInputValueDefinitions();
4362 						subRules = ["NE"];
4363 						if(this.lex.front.type == TokenType.rcurly) {
4364 							this.lex.popFront();
4365 
4366 							return new InputTypeDefinition(InputTypeDefinitionEnum.NE
4367 								, name
4368 								, ivds
4369 							);
4370 						}
4371 						auto app = appender!string();
4372 						formattedWrite(app, 
4373 							"Found a '%s' while looking for", 
4374 							this.lex.front
4375 						);
4376 						throw new ParseException(app.data,
4377 							__FILE__, __LINE__,
4378 							subRules,
4379 							["rcurly"]
4380 						);
4381 
4382 					}
4383 					auto app = appender!string();
4384 					formattedWrite(app, 
4385 						"Found a '%s' while looking for", 
4386 						this.lex.front
4387 					);
4388 					throw new ParseException(app.data,
4389 						__FILE__, __LINE__,
4390 						subRules,
4391 						["name -> InputValueDefinition"]
4392 					);
4393 
4394 				}
4395 				auto app = appender!string();
4396 				formattedWrite(app, 
4397 					"Found a '%s' while looking for", 
4398 					this.lex.front
4399 				);
4400 				throw new ParseException(app.data,
4401 					__FILE__, __LINE__,
4402 					subRules,
4403 					["at -> Directive","lcurly"]
4404 				);
4405 
4406 			}
4407 			auto app = appender!string();
4408 			formattedWrite(app, 
4409 				"Found a '%s' while looking for", 
4410 				this.lex.front
4411 			);
4412 			throw new ParseException(app.data,
4413 				__FILE__, __LINE__,
4414 				subRules,
4415 				["name"]
4416 			);
4417 
4418 		}
4419 		auto app = appender!string();
4420 		formattedWrite(app, 
4421 			"Found a '%s' while looking for", 
4422 			this.lex.front
4423 		);
4424 		throw new ParseException(app.data,
4425 			__FILE__, __LINE__,
4426 			subRules,
4427 			["input"]
4428 		);
4429 
4430 	}
4431 
4432 	bool firstTypeExtensionDefinition() const pure @nogc @safe {
4433 		return this.lex.front.type == TokenType.extend;
4434 	}
4435 
4436 	TypeExtensionDefinition parseTypeExtensionDefinition() {
4437 		try {
4438 			return this.parseTypeExtensionDefinitionImpl();
4439 		} catch(ParseException e) {
4440 			throw new ParseException(
4441 				"While parsing a TypeExtensionDefinition an Exception was thrown.",
4442 				e, __FILE__, __LINE__
4443 			);
4444 		}
4445 	}
4446 
4447 	TypeExtensionDefinition parseTypeExtensionDefinitionImpl() {
4448 		string[] subRules;
4449 		subRules = ["O"];
4450 		if(this.lex.front.type == TokenType.extend) {
4451 			this.lex.popFront();
4452 			subRules = ["O"];
4453 			if(this.firstObjectTypeDefinition()) {
4454 				ObjectTypeDefinition otd = this.parseObjectTypeDefinition();
4455 
4456 				return new TypeExtensionDefinition(TypeExtensionDefinitionEnum.O
4457 					, otd
4458 				);
4459 			}
4460 			auto app = appender!string();
4461 			formattedWrite(app, 
4462 				"Found a '%s' while looking for", 
4463 				this.lex.front
4464 			);
4465 			throw new ParseException(app.data,
4466 				__FILE__, __LINE__,
4467 				subRules,
4468 				["type"]
4469 			);
4470 
4471 		}
4472 		auto app = appender!string();
4473 		formattedWrite(app, 
4474 			"Found a '%s' while looking for", 
4475 			this.lex.front
4476 		);
4477 		throw new ParseException(app.data,
4478 			__FILE__, __LINE__,
4479 			subRules,
4480 			["extend"]
4481 		);
4482 
4483 	}
4484 
4485 	bool firstDirectiveDefinition() const pure @nogc @safe {
4486 		return this.lex.front.type == TokenType.directive;
4487 	}
4488 
4489 	DirectiveDefinition parseDirectiveDefinition() {
4490 		try {
4491 			return this.parseDirectiveDefinitionImpl();
4492 		} catch(ParseException e) {
4493 			throw new ParseException(
4494 				"While parsing a DirectiveDefinition an Exception was thrown.",
4495 				e, __FILE__, __LINE__
4496 			);
4497 		}
4498 	}
4499 
4500 	DirectiveDefinition parseDirectiveDefinitionImpl() {
4501 		string[] subRules;
4502 		subRules = ["AD", "D"];
4503 		if(this.lex.front.type == TokenType.directive) {
4504 			this.lex.popFront();
4505 			subRules = ["AD", "D"];
4506 			if(this.lex.front.type == TokenType.at) {
4507 				this.lex.popFront();
4508 				subRules = ["AD", "D"];
4509 				if(this.lex.front.type == TokenType.name) {
4510 					Token name = this.lex.front;
4511 					this.lex.popFront();
4512 					subRules = ["AD"];
4513 					if(this.firstArgumentsDefinition()) {
4514 						ArgumentsDefinition ad = this.parseArgumentsDefinition();
4515 						subRules = ["AD"];
4516 						if(this.lex.front.type == TokenType.on_) {
4517 							this.lex.popFront();
4518 							subRules = ["AD"];
4519 							if(this.firstDirectiveLocations()) {
4520 								DirectiveLocations dl = this.parseDirectiveLocations();
4521 
4522 								return new DirectiveDefinition(DirectiveDefinitionEnum.AD
4523 									, name
4524 									, ad
4525 									, dl
4526 								);
4527 							}
4528 							auto app = appender!string();
4529 							formattedWrite(app, 
4530 								"Found a '%s' while looking for", 
4531 								this.lex.front
4532 							);
4533 							throw new ParseException(app.data,
4534 								__FILE__, __LINE__,
4535 								subRules,
4536 								["name"]
4537 							);
4538 
4539 						}
4540 						auto app = appender!string();
4541 						formattedWrite(app, 
4542 							"Found a '%s' while looking for", 
4543 							this.lex.front
4544 						);
4545 						throw new ParseException(app.data,
4546 							__FILE__, __LINE__,
4547 							subRules,
4548 							["on_"]
4549 						);
4550 
4551 					} else if(this.lex.front.type == TokenType.on_) {
4552 						this.lex.popFront();
4553 						subRules = ["D"];
4554 						if(this.firstDirectiveLocations()) {
4555 							DirectiveLocations dl = this.parseDirectiveLocations();
4556 
4557 							return new DirectiveDefinition(DirectiveDefinitionEnum.D
4558 								, name
4559 								, dl
4560 							);
4561 						}
4562 						auto app = appender!string();
4563 						formattedWrite(app, 
4564 							"Found a '%s' while looking for", 
4565 							this.lex.front
4566 						);
4567 						throw new ParseException(app.data,
4568 							__FILE__, __LINE__,
4569 							subRules,
4570 							["name"]
4571 						);
4572 
4573 					}
4574 					auto app = appender!string();
4575 					formattedWrite(app, 
4576 						"Found a '%s' while looking for", 
4577 						this.lex.front
4578 					);
4579 					throw new ParseException(app.data,
4580 						__FILE__, __LINE__,
4581 						subRules,
4582 						["lparen","on_"]
4583 					);
4584 
4585 				}
4586 				auto app = appender!string();
4587 				formattedWrite(app, 
4588 					"Found a '%s' while looking for", 
4589 					this.lex.front
4590 				);
4591 				throw new ParseException(app.data,
4592 					__FILE__, __LINE__,
4593 					subRules,
4594 					["name"]
4595 				);
4596 
4597 			}
4598 			auto app = appender!string();
4599 			formattedWrite(app, 
4600 				"Found a '%s' while looking for", 
4601 				this.lex.front
4602 			);
4603 			throw new ParseException(app.data,
4604 				__FILE__, __LINE__,
4605 				subRules,
4606 				["at"]
4607 			);
4608 
4609 		}
4610 		auto app = appender!string();
4611 		formattedWrite(app, 
4612 			"Found a '%s' while looking for", 
4613 			this.lex.front
4614 		);
4615 		throw new ParseException(app.data,
4616 			__FILE__, __LINE__,
4617 			subRules,
4618 			["directive"]
4619 		);
4620 
4621 	}
4622 
4623 	bool firstDirectiveLocations() const pure @nogc @safe {
4624 		return this.lex.front.type == TokenType.name;
4625 	}
4626 
4627 	DirectiveLocations parseDirectiveLocations() {
4628 		try {
4629 			return this.parseDirectiveLocationsImpl();
4630 		} catch(ParseException e) {
4631 			throw new ParseException(
4632 				"While parsing a DirectiveLocations an Exception was thrown.",
4633 				e, __FILE__, __LINE__
4634 			);
4635 		}
4636 	}
4637 
4638 	DirectiveLocations parseDirectiveLocationsImpl() {
4639 		string[] subRules;
4640 		subRules = ["N", "NF", "NPF"];
4641 		if(this.lex.front.type == TokenType.name) {
4642 			Token name = this.lex.front;
4643 			this.lex.popFront();
4644 			subRules = ["NPF"];
4645 			if(this.lex.front.type == TokenType.pipe) {
4646 				this.lex.popFront();
4647 				subRules = ["NPF"];
4648 				if(this.firstDirectiveLocations()) {
4649 					DirectiveLocations follow = this.parseDirectiveLocations();
4650 
4651 					return new DirectiveLocations(DirectiveLocationsEnum.NPF
4652 						, name
4653 						, follow
4654 					);
4655 				}
4656 				auto app = appender!string();
4657 				formattedWrite(app, 
4658 					"Found a '%s' while looking for", 
4659 					this.lex.front
4660 				);
4661 				throw new ParseException(app.data,
4662 					__FILE__, __LINE__,
4663 					subRules,
4664 					["name"]
4665 				);
4666 
4667 			} else if(this.firstDirectiveLocations()) {
4668 				DirectiveLocations follow = this.parseDirectiveLocations();
4669 
4670 				return new DirectiveLocations(DirectiveLocationsEnum.NF
4671 					, name
4672 					, follow
4673 				);
4674 			}
4675 			return new DirectiveLocations(DirectiveLocationsEnum.N
4676 				, name
4677 			);
4678 		}
4679 		auto app = appender!string();
4680 		formattedWrite(app, 
4681 			"Found a '%s' while looking for", 
4682 			this.lex.front
4683 		);
4684 		throw new ParseException(app.data,
4685 			__FILE__, __LINE__,
4686 			subRules,
4687 			["name"]
4688 		);
4689 
4690 	}
4691 
4692 	bool firstInputObjectTypeDefinition() const pure @nogc @safe {
4693 		return this.lex.front.type == TokenType.input;
4694 	}
4695 
4696 	InputObjectTypeDefinition parseInputObjectTypeDefinition() {
4697 		try {
4698 			return this.parseInputObjectTypeDefinitionImpl();
4699 		} catch(ParseException e) {
4700 			throw new ParseException(
4701 				"While parsing a InputObjectTypeDefinition an Exception was thrown.",
4702 				e, __FILE__, __LINE__
4703 			);
4704 		}
4705 	}
4706 
4707 	InputObjectTypeDefinition parseInputObjectTypeDefinitionImpl() {
4708 		string[] subRules;
4709 		subRules = ["NDI", "NI"];
4710 		if(this.lex.front.type == TokenType.input) {
4711 			this.lex.popFront();
4712 			subRules = ["NDI", "NI"];
4713 			if(this.lex.front.type == TokenType.name) {
4714 				Token name = this.lex.front;
4715 				this.lex.popFront();
4716 				subRules = ["NDI"];
4717 				if(this.firstDirectives()) {
4718 					Directives dirs = this.parseDirectives();
4719 					subRules = ["NDI"];
4720 					if(this.lex.front.type == TokenType.lcurly) {
4721 						this.lex.popFront();
4722 						subRules = ["NDI"];
4723 						if(this.firstInputValueDefinitions()) {
4724 							this.parseInputValueDefinitions();
4725 							subRules = ["NDI"];
4726 							if(this.lex.front.type == TokenType.rcurly) {
4727 								this.lex.popFront();
4728 
4729 								return new InputObjectTypeDefinition(InputObjectTypeDefinitionEnum.NDI
4730 									, name
4731 									, dirs
4732 								);
4733 							}
4734 							auto app = appender!string();
4735 							formattedWrite(app, 
4736 								"Found a '%s' while looking for", 
4737 								this.lex.front
4738 							);
4739 							throw new ParseException(app.data,
4740 								__FILE__, __LINE__,
4741 								subRules,
4742 								["rcurly"]
4743 							);
4744 
4745 						}
4746 						auto app = appender!string();
4747 						formattedWrite(app, 
4748 							"Found a '%s' while looking for", 
4749 							this.lex.front
4750 						);
4751 						throw new ParseException(app.data,
4752 							__FILE__, __LINE__,
4753 							subRules,
4754 							["name -> InputValueDefinition"]
4755 						);
4756 
4757 					}
4758 					auto app = appender!string();
4759 					formattedWrite(app, 
4760 						"Found a '%s' while looking for", 
4761 						this.lex.front
4762 					);
4763 					throw new ParseException(app.data,
4764 						__FILE__, __LINE__,
4765 						subRules,
4766 						["lcurly"]
4767 					);
4768 
4769 				} else if(this.lex.front.type == TokenType.lcurly) {
4770 					this.lex.popFront();
4771 					subRules = ["NI"];
4772 					if(this.firstInputValueDefinitions()) {
4773 						this.parseInputValueDefinitions();
4774 						subRules = ["NI"];
4775 						if(this.lex.front.type == TokenType.rcurly) {
4776 							this.lex.popFront();
4777 
4778 							return new InputObjectTypeDefinition(InputObjectTypeDefinitionEnum.NI
4779 								, name
4780 							);
4781 						}
4782 						auto app = appender!string();
4783 						formattedWrite(app, 
4784 							"Found a '%s' while looking for", 
4785 							this.lex.front
4786 						);
4787 						throw new ParseException(app.data,
4788 							__FILE__, __LINE__,
4789 							subRules,
4790 							["rcurly"]
4791 						);
4792 
4793 					}
4794 					auto app = appender!string();
4795 					formattedWrite(app, 
4796 						"Found a '%s' while looking for", 
4797 						this.lex.front
4798 					);
4799 					throw new ParseException(app.data,
4800 						__FILE__, __LINE__,
4801 						subRules,
4802 						["name -> InputValueDefinition"]
4803 					);
4804 
4805 				}
4806 				auto app = appender!string();
4807 				formattedWrite(app, 
4808 					"Found a '%s' while looking for", 
4809 					this.lex.front
4810 				);
4811 				throw new ParseException(app.data,
4812 					__FILE__, __LINE__,
4813 					subRules,
4814 					["at -> Directive","lcurly"]
4815 				);
4816 
4817 			}
4818 			auto app = appender!string();
4819 			formattedWrite(app, 
4820 				"Found a '%s' while looking for", 
4821 				this.lex.front
4822 			);
4823 			throw new ParseException(app.data,
4824 				__FILE__, __LINE__,
4825 				subRules,
4826 				["name"]
4827 			);
4828 
4829 		}
4830 		auto app = appender!string();
4831 		formattedWrite(app, 
4832 			"Found a '%s' while looking for", 
4833 			this.lex.front
4834 		);
4835 		throw new ParseException(app.data,
4836 			__FILE__, __LINE__,
4837 			subRules,
4838 			["input"]
4839 		);
4840 
4841 	}
4842 
4843 }