1 module format.parser;
2 
3 /**
4  * While we already have a parser in libd, we cannot use it here.
5  * This is because libd's parser is meant to validate that the source
6  * is well a formed D program. However, we want to be able to format
7  * even incomplete programs as part of the developper's process.
8  *
9  * This parser, on the other hand, is meant to recognize common patterns
10  * in the language, without ensuring that they are indeed correct.
11  */
12 struct Parser {
13 private:
14 	import source.dlexer;
15 	TokenRange trange;
16 
17 	import format.chunk;
18 	Builder builder;
19 
20 	bool needDoubleIndent = false;
21 	bool doubleIndentBlock = false;
22 	bool canBeDeclaration = false;
23 
24 	enum Mode {
25 		Declaration,
26 		Statement,
27 		Parameter,
28 	}
29 
30 	Mode mode;
31 
32 	auto changeMode(Mode m) {
33 		static struct Guard {
34 			~this() {
35 				parser.mode = oldMode;
36 			}
37 
38 		private:
39 			Parser* parser;
40 			Mode oldMode;
41 		}
42 
43 		Mode oldMode = mode;
44 		mode = m;
45 
46 		return Guard(&this, oldMode);
47 	}
48 
49 	/**
50 	 * When we can't parse we skip and forward chunks "as this"
51 	 */
52 	Location skipped;
53 
54 	/**
55 	 * Comments to be emitted before the next token.
56 	 *  - inFlightComments: Comments which are on their own.
57 	 *  - nextComments: Comment attached to what comes next.
58 	 */
59 	Location[] inFlightComments;
60 	Location[] nextComments;
61 
62 	/**
63 	 * Passthrough for portion of code not to be formatted.
64 	 *
65 	 * When formatting is disabled, we keep parsing anyways. This ensures
66 	 * the state of affairs, such as identation levels, are kept track off.
67 	 * However, nothign is sent to the builder as parsing progresses, and
68 	 * everything is sent as one signle chunk at the end of it.
69 	 */
70 	Position sdfmtOffStart;
71 
72 	bool skipFormatting() const {
73 		return sdfmtOffStart != Position();
74 	}
75 
76 public:
77 	import source.context;
78 	this(Position base, Context context) {
79 		this.trange =
80 			lex(base, context).withStringDecoding(false).withComments();
81 	}
82 
83 	Chunk[] parse() in {
84 		assert(match(TokenType.Begin));
85 	} do {
86 		// Eat the begin token and get the game rolling.
87 		nextToken();
88 		parseModule();
89 
90 		assert(match(TokenType.End));
91 
92 		emitSkippedTokens();
93 		flushComments();
94 
95 		return builder.build();
96 	}
97 
98 private:
99 	/**
100 	 * Chunk builder facilities
101 	 */
102 	void write(Location loc, string s) {
103 		if (skipFormatting()) {
104 			return;
105 		}
106 
107 		if (newLineCount(loc) == 0) {
108 			builder.write(s);
109 			return;
110 		}
111 
112 		// We have a multi line chunk.
113 		import std.array;
114 		foreach (i, l; s.split('\n')) {
115 			if (i > 0) {
116 				builder.split(true, true);
117 				builder.newline(1);
118 			}
119 
120 			builder.write(l);
121 		}
122 	}
123 
124 	void space() {
125 		if (skipFormatting()) {
126 			return;
127 		}
128 
129 		builder.space();
130 	}
131 
132 	void newline() {
133 		newline(newLineCount());
134 	}
135 
136 	void newline(int nl) {
137 		if (skipFormatting()) {
138 			return;
139 		}
140 
141 		builder.newline(nl);
142 	}
143 
144 	void clearSeparator() {
145 		if (skipFormatting()) {
146 			return;
147 		}
148 
149 		builder.clearSeparator();
150 	}
151 
152 	void split(bool glued = false, bool continuation = false) {
153 		emitRawContent();
154 		builder.split(glued || skipFormatting(), continuation);
155 	}
156 
157 	auto indent(uint level = 1) {
158 		return builder.indent(level);
159 	}
160 
161 	auto unindent(uint level = 1) {
162 		return builder.unindent(level);
163 	}
164 
165 	import format.span;
166 	auto span(S = Span, T...)(T args) {
167 		emitSkippedTokens();
168 		emitInFlightComments();
169 
170 		return builder.span!S(args);
171 	}
172 
173 	auto spliceSpan(S = Span, T...)(T args) {
174 		emitSkippedTokens();
175 		emitInFlightComments();
176 
177 		return builder.spliceSpan!S(args);
178 	}
179 
180 	auto block() {
181 		emitRawContent();
182 		return builder.block();
183 	}
184 
185 	/**
186 	 * Miscellaneous and conveniences.
187 	 */
188 	@property
189 	auto context() {
190 		return trange.context;
191 	}
192 
193 	/**
194 	 * Whitespace management.
195 	 */
196 	import source.location;
197 	uint getLineNumber(Position p) {
198 		return p.getFullPosition(context).getLineNumber();
199 	}
200 
201 	int newLineCount(Position start, Position stop) {
202 		return getLineNumber(stop) - getLineNumber(start);
203 	}
204 
205 	int newLineCount(Location location) {
206 		return newLineCount(location.start, location.stop);
207 	}
208 
209 	int newLineCount(ref TokenRange r) {
210 		return newLineCount(r.previous, r.front.location.start);
211 	}
212 
213 	int newLineCount() {
214 		return newLineCount(trange);
215 	}
216 
217 	uint getSourceOffset(Position p) {
218 		return p.getFullPosition(context).getSourceOffset();
219 	}
220 
221 	int whiteSpaceLength(Position start, Position stop) {
222 		return getSourceOffset(stop) - getSourceOffset(start);
223 	}
224 
225 	int whiteSpaceLength() {
226 		return whiteSpaceLength(trange.previous, token.location.start);
227 	}
228 
229 	void emitSourceBasedWhiteSpace(Position previous, Location current) {
230 		if (auto nl = newLineCount(previous, current.start)) {
231 			newline(nl);
232 			return;
233 		}
234 
235 		if (whiteSpaceLength(previous, current.start) > 0) {
236 			space();
237 		}
238 	}
239 
240 	void emitSourceBasedWhiteSpace() {
241 		emitSourceBasedWhiteSpace(trange.previous, token.location);
242 	}
243 
244 	/**
245 	 * Token processing.
246 	 */
247 	@property
248 	Token token() const {
249 		return trange.front;
250 	}
251 
252 	bool match(TokenType t) {
253 		return token.type == t;
254 	}
255 
256 	auto runOnType(TokenType T, alias fun)() {
257 		if (match(T)) {
258 			return fun();
259 		}
260 	}
261 
262 	void nextToken() {
263 		emitSkippedTokens();
264 		flushComments();
265 
266 		if (match(TokenType.End)) {
267 			// We reached the end of our input.
268 			return;
269 		}
270 
271 		// Process current token.
272 		write(token.location, token.toString(context));
273 
274 		trange.popFront();
275 		parseComments();
276 	}
277 
278 	/**
279 	 * We skip over portions of the code we can't parse.
280 	 */
281 	void skipToken() {
282 		flushComments();
283 
284 		if (skipped.length == 0) {
285 			emitSourceBasedWhiteSpace();
286 			space();
287 			split();
288 
289 			skipped = Location(trange.previous, token.location.stop);
290 		} else {
291 			skipped.spanTo(token.location);
292 		}
293 
294 		if (match(TokenType.End)) {
295 			// We skipped until the end.
296 			return;
297 		}
298 
299 		trange.popFront();
300 
301 		// Skip over comments that look related too.
302 		while (match(TokenType.Comment) && newLineCount() == 0) {
303 			skipped.spanTo(token.location);
304 			trange.popFront();
305 		}
306 
307 		parseComments();
308 	}
309 
310 	void emitSkippedTokens() {
311 		if (skipped.length == 0) {
312 			return;
313 		}
314 
315 		import std.string;
316 		auto str = skipped.getFullLocation(context).getSlice().strip();
317 		write(skipped, str);
318 		skipped = Location.init;
319 
320 		emitSourceBasedWhiteSpace();
321 		split();
322 	}
323 
324 	/**
325 	 * Unformateed code management.
326 	 */
327 	void emitRawContent() {
328 		auto upTo = inFlightComments.length > 0
329 			? inFlightComments[0]
330 			: nextComments.length > 0 ? nextComments[0] : token.location;
331 
332 		emitRawContent(upTo.start);
333 	}
334 
335 	void emitRawContent(Position upTo) {
336 		if (!skipFormatting()) {
337 			return;
338 		}
339 
340 		builder.write(
341 			Location(sdfmtOffStart, upTo).getFullLocation(context).getSlice());
342 		sdfmtOffStart = upTo;
343 	}
344 
345 	/**
346 	 * Comments management
347 	 */
348 	void emitComment(Location loc, Position previous) {
349 		emitSourceBasedWhiteSpace(previous, loc);
350 
351 		import std.string;
352 		auto comment = loc.getFullLocation(context).getSlice().strip();
353 		if (skipFormatting() && comment == "// sdfmt on") {
354 			emitRawContent(loc.start);
355 			sdfmtOffStart = Position();
356 		}
357 
358 		write(loc, comment);
359 
360 		if (comment == "// sdfmt off") {
361 			sdfmtOffStart = loc.stop;
362 			assert(skipFormatting(), "We should start skipping.");
363 		}
364 
365 		// Make sure we have a line split after // style comments.
366 		if (!skipFormatting() && comment.startsWith("//")) {
367 			newline(1);
368 			split();
369 		}
370 	}
371 
372 	void emitComments(ref Location[] commentBlock, Location nextTokenLoc) {
373 		if (commentBlock.length == 0) {
374 			return;
375 		}
376 
377 		scope(success) {
378 			commentBlock = [];
379 		}
380 
381 		Position previous = commentBlock[0].start;
382 
383 		foreach (loc; commentBlock) {
384 			scope(success) {
385 				previous = loc.stop;
386 			}
387 
388 			emitComment(loc, previous);
389 		}
390 
391 		emitSourceBasedWhiteSpace(previous, nextTokenLoc);
392 	}
393 
394 	void emitInFlightComments() {
395 		auto nextTokenLoc =
396 			nextComments.length > 0 ? nextComments[0] : token.location;
397 
398 		emitComments(inFlightComments, nextTokenLoc);
399 	}
400 
401 	void flushComments() {
402 		emitInFlightComments();
403 		emitComments(nextComments, token.location);
404 	}
405 
406 	void parseComments() in {
407 		assert(inFlightComments == []);
408 		assert(nextComments == []);
409 	} do {
410 		if (!match(TokenType.Comment)) {
411 			return;
412 		}
413 
414 		emitSkippedTokens();
415 
416 		/**
417 		 * We distrube comments in 3 groups:
418 		 *   1 - The comments attached to the previous structural element.
419 		 *   2 - The comments in flight between two structural elements.
420 		 *   3 - The comments attached to the next structural element.
421 		 * We want to emit group 1 right away, but wait for later when
422 		 * emitting groups 2 and 3.
423 		 */
424 		while (match(TokenType.Comment) && newLineCount() == 0) {
425 			emitComment(token.location, trange.previous);
426 			trange.popFront();
427 		}
428 
429 		emitSourceBasedWhiteSpace();
430 
431 		Location[] commentBlock = [];
432 		while (match(TokenType.Comment)) {
433 			commentBlock ~= token.location;
434 			trange.popFront();
435 
436 			if (newLineCount() < 2) {
437 				continue;
438 			}
439 
440 			inFlightComments ~= commentBlock;
441 			commentBlock = [];
442 		}
443 
444 		nextComments = commentBlock;
445 	}
446 
447 	/**
448 	 * Parsing
449 	 */
450 	void parseModule() {
451 		auto guard = changeMode(Mode.Declaration);
452 
453 		while (!match(TokenType.End)) {
454 			parseStructuralElement();
455 		}
456 	}
457 
458 	void parseStructuralElement() {
459 		emitInFlightComments();
460 
461 		canBeDeclaration = true;
462 
463 	Entry:
464 		switch (token.type) with (TokenType) {
465 			case End:
466 				return;
467 
468 			case Module:
469 				parseModuleDeclaration();
470 				break;
471 
472 			/**
473 			 * Misc
474 			 */
475 			case DotDotDot:
476 				nextToken();
477 				return;
478 
479 			/**
480 			 * Statements
481 			 */
482 			case OpenBrace:
483 				parseBlock(mode);
484 
485 				// Blocks do not end with a semicolon.
486 				return;
487 
488 			case Identifier:
489 				auto lookahead = trange.getLookahead();
490 				lookahead.popFront();
491 				auto t = lookahead.front.type;
492 
493 				if (mode == Mode.Parameter
494 					    && (t == Colon || t == Equal || t == DotDotDot)) {
495 					parseTemplateParameter();
496 					break;
497 				}
498 
499 				if (t != Colon) {
500 					// This is an expression or a declaration.
501 					goto default;
502 				}
503 
504 				lookahead.popFront();
505 				if (newLineCount(lookahead) == 0) {
506 					nextToken();
507 					nextToken();
508 					space();
509 					goto Entry;
510 				}
511 
512 				{
513 					auto guard = unindent();
514 					newline(2);
515 					nextToken();
516 				}
517 
518 				parseColonBlock();
519 				break;
520 
521 			case If:
522 				parseIf();
523 				break;
524 
525 			case Version, Debug:
526 				parseVersion();
527 				break;
528 
529 			case Else:
530 				parseElse();
531 				break;
532 
533 			case While:
534 				parseWhile();
535 				break;
536 
537 			case Do:
538 				parseDoWhile();
539 				break;
540 
541 			case For:
542 				parseFor();
543 				break;
544 
545 			case Foreach, ForeachReverse:
546 				withCaseLevelIndent!parseForeach();
547 				break;
548 
549 			case Return:
550 				// If this is a parameter, then return is a storage class.
551 				if (mode == Mode.Parameter) {
552 					goto default;
553 				}
554 
555 				goto ReturnLike;
556 
557 			case Throw:
558 				goto ReturnLike;
559 
560 			ReturnLike:
561 				parseReturn();
562 				break;
563 
564 			case Break, Continue:
565 				nextToken();
566 
567 				if (match(Identifier)) {
568 					space();
569 					nextToken();
570 				}
571 
572 				break;
573 
574 			case With:
575 				parseWith();
576 				break;
577 
578 			case Switch:
579 				parseSwitch();
580 				break;
581 
582 			case Case:
583 				{
584 					auto guard = unindent();
585 					newline();
586 
587 					while (true) {
588 						nextToken();
589 						space();
590 
591 						parseList!parseExpression(TokenType.Colon);
592 
593 						if (!match(DotDot)) {
594 							break;
595 						}
596 
597 						space();
598 						nextToken();
599 						space();
600 					}
601 				}
602 
603 				parseColonBlock();
604 				break;
605 
606 			case Default:
607 				{
608 					auto guard = unindent();
609 					newline();
610 					nextToken();
611 				}
612 
613 				parseColonBlock();
614 				break;
615 
616 			case Goto:
617 				nextToken();
618 				if (match(Identifier) || match(Default)) {
619 					space();
620 					nextToken();
621 				} else if (match(Case)) {
622 					space();
623 					nextToken();
624 
625 					if (!match(Semicolon)) {
626 						space();
627 						parseExpression();
628 					}
629 				}
630 
631 				break;
632 
633 			case Try:
634 				parseTry();
635 				break;
636 
637 			case Catch:
638 				parseCatch();
639 				break;
640 
641 			case Finally:
642 				parseFinally();
643 				break;
644 
645 			case Scope:
646 				parseScope();
647 				break;
648 
649 			case Assert:
650 				parseExpression();
651 				break;
652 
653 			/**
654 			 * Compile time constructs.
655 			 */
656 			case Static:
657 				withCaseLevelIndent!parseStatic();
658 				break;
659 
660 			case Mixin:
661 				parseMixin();
662 				break;
663 
664 			/**
665 			 * Declaration
666 			 */
667 			case This:
668 				// This template parameters.
669 				auto lookahead = trange.getLookahead();
670 				lookahead.popFront();
671 
672 				auto t = lookahead.front.type;
673 				if (t == TokenType.Identifier) {
674 					nextToken();
675 					space();
676 					parseTypedDeclaration();
677 					break;
678 				}
679 
680 				if (t != TokenType.OpenParen || mode != Mode.Declaration) {
681 					// This is an expression.
682 					goto default;
683 				}
684 
685 				parseConstructor();
686 				break;
687 
688 			case Tilde:
689 				// Check for destructors.
690 				auto lookahead = trange.getLookahead();
691 				lookahead.popFront();
692 
693 				if (lookahead.front.type != TokenType.This) {
694 					// This is an expression.
695 					goto default;
696 				}
697 
698 				lookahead.popFront();
699 
700 				auto t = lookahead.front.type;
701 				if (t != TokenType.OpenParen || mode != Mode.Declaration) {
702 					// This is an expression.
703 					goto default;
704 				}
705 
706 				parseDestructor();
707 				break;
708 
709 			case Template:
710 				parseTemplate();
711 				break;
712 
713 			case Import:
714 				auto lookahead = trange.getLookahead();
715 				lookahead.popFront();
716 
717 				if (lookahead.front.type == TokenType.OpenParen) {
718 					// This is an import expression.
719 					goto default;
720 				}
721 
722 				parseImport();
723 				break;
724 
725 			case Unittest:
726 				nextToken();
727 				space();
728 
729 				if (match(Identifier)) {
730 					nextToken();
731 					space();
732 				}
733 
734 				parseBlock(Mode.Statement);
735 
736 				// Blocks do not end with a semicolon.
737 				return;
738 
739 			case Invariant:
740 				nextToken();
741 				parseArgumentList();
742 
743 				if (!match(OpenBrace)) {
744 					break;
745 				}
746 
747 				space();
748 				parseBlock(Mode.Statement);
749 
750 				// Blocks do not end with a semicolon.
751 				return;
752 
753 			case Struct, Union, Class, Interface:
754 				parseAggregate();
755 				break;
756 
757 			default:
758 				if (parseStorageClassDeclaration()) {
759 					break;
760 				}
761 
762 				if (!parseIdentifier()) {
763 					// We made no progress, start skipping.
764 					skipToken();
765 					return;
766 				}
767 
768 				if (match(Identifier)) {
769 					// We have a declaration.
770 					parseTypedDeclaration();
771 					break;
772 				}
773 
774 				// We just have some kind of expression.
775 				parseAssignExpressionSuffix();
776 				break;
777 		}
778 
779 		if (mode != Mode.Parameter) {
780 			if (match(TokenType.Semicolon)) {
781 				nextToken();
782 				newline();
783 			} else {
784 				emitSourceBasedWhiteSpace();
785 			}
786 		}
787 	}
788 
789 	/**
790 	 * Structural elements.
791 	 */
792 	void parseModuleDeclaration() in {
793 		assert(match(TokenType.Module));
794 	} do {
795 		nextToken();
796 		space();
797 		parseIdentifier();
798 	}
799 
800 	/**
801 	 * Identifiers
802 	 */
803 	enum IdentifierKind {
804 		None,
805 		Symbol,
806 		Type,
807 		Expression,
808 	}
809 
810 	bool parseIdentifier(IdentifierKind expected = IdentifierKind.Symbol) {
811 		flushComments();
812 		auto guard = span();
813 
814 		parseIdentifierPrefix();
815 
816 		auto kind = parseBaseIdentifier(expected);
817 		if (kind == IdentifierKind.None) {
818 			return false;
819 		}
820 
821 		kind = parseIdentifierSuffix(kind);
822 
823 		if (expected <= IdentifierKind.Symbol) {
824 			return true;
825 		}
826 
827 		// We expect something specific.
828 		while (kind == IdentifierKind.Symbol) {
829 			kind = parseIdentifierSuffix(expected);
830 		}
831 
832 		return true;
833 	}
834 
835 	void parseIdentifierPrefix() {
836 		while (true) {
837 			switch (token.type) with (TokenType) {
838 				// Prefixes.
839 				case Dot:
840 				case Ampersand:
841 				case PlusPlus:
842 				case MinusMinus:
843 				case Star:
844 				case Plus:
845 				case Minus:
846 				case Bang:
847 				case Tilde:
848 					nextToken();
849 					break;
850 
851 				case Cast:
852 					nextToken();
853 					if (match(OpenParen)) {
854 						nextToken();
855 						parseType();
856 						clearSeparator();
857 					}
858 
859 					runOnType!(CloseParen, nextToken)();
860 					space();
861 					split();
862 					break;
863 
864 				default:
865 					return;
866 			}
867 		}
868 	}
869 
870 	IdentifierKind parseBaseIdentifier(IdentifierKind kind) {
871 		switch (token.type) with (TokenType) {
872 			case Identifier:
873 				nextToken();
874 
875 				import source.parserutil;
876 				auto lookahead = trange.getLookahead();
877 				auto t = getStorageClassTokenType(lookahead);
878 
879 				if (t != EqualMore) {
880 					return kind;
881 				}
882 
883 				// Lambda expression
884 				parseStorageClasses(true);
885 				space();
886 				nextToken();
887 				space();
888 				split();
889 				parseExpression();
890 				return IdentifierKind.Expression;
891 
892 			// Litterals
893 			case This:
894 			case Super:
895 			case True:
896 			case False:
897 			case Null:
898 			case IntegerLiteral:
899 			case FloatLiteral:
900 			case StringLiteral:
901 			case CharacterLiteral:
902 			case __File__:
903 			case __Line__:
904 			case Dollar:
905 				nextToken();
906 				return IdentifierKind.Expression;
907 
908 			case __Traits:
909 				nextToken();
910 				parseArgumentList();
911 				return IdentifierKind.Symbol;
912 
913 			case Assert, Import:
914 				nextToken();
915 				parseArgumentList();
916 				return IdentifierKind.Expression;
917 
918 			case New:
919 				nextToken();
920 				space();
921 
922 				if (!match(Class)) {
923 					parseType();
924 					parseArgumentList();
925 					return IdentifierKind.Expression;
926 				}
927 
928 				// Ok new class.
929 				nextToken();
930 				parseArgumentList();
931 				space();
932 				parseIdentifier();
933 				space();
934 				parseInlineBlock(Mode.Declaration);
935 
936 				return IdentifierKind.Expression;
937 
938 			case Is:
939 				parseIsExpression();
940 				return IdentifierKind.Expression;
941 
942 			case OpenParen: {
943 				import source.parserutil;
944 				auto lookahead = trange.getLookahead();
945 				lookahead.popMatchingDelimiter!OpenParen();
946 
947 				auto t = getStorageClassTokenType(lookahead);
948 				if (t != OpenBrace && t != EqualMore && t != At && t != Nothrow
949 					    && t != Pure && t != Ref && t != Synchronized) {
950 					// Not a lambda.
951 					goto ParenIdentifier;
952 				}
953 
954 				// We have a lambda.
955 				parseParameterList();
956 				space();
957 				parseStorageClasses(true);
958 
959 				switch (token.type) {
960 					case OpenBrace:
961 						goto Lambda;
962 
963 					case EqualMore:
964 						nextToken();
965 						space();
966 						split();
967 						parseExpression();
968 						break;
969 
970 					default:
971 						break;
972 				}
973 
974 				return IdentifierKind.Expression;
975 			}
976 
977 			ParenIdentifier:
978 				auto guard = span();
979 				nextToken();
980 
981 				// FIXME: Customize the list parsed based on kind.
982 				parseExpression();
983 
984 				runOnType!(CloseParen, nextToken)();
985 				return kind;
986 
987 			case OpenBrace: {
988 				// Try to detect if it is a struct literal or a parameterless lambda.
989 				import source.parserutil;
990 				auto lookahead = trange.getLookahead();
991 
992 				lookahead.popFront();
993 				if (lookahead.front.type != Identifier) {
994 					goto Lambda;
995 				}
996 
997 				lookahead.popFront();
998 				if (lookahead.front.type != Colon) {
999 					goto Lambda;
1000 				}
1001 
1002 				// We may still have a lambda starting with a labeled statement,
1003 				// so we go on the hunt for a semicolon.
1004 				lookahead.popFront();
1005 				while (true) {
1006 					switch (lookahead.front.type) {
1007 						case CloseBrace:
1008 							goto StructLiteral;
1009 
1010 						case Semicolon:
1011 							goto Lambda;
1012 
1013 						case End:
1014 							// This is malformed, assume literal.
1015 							goto StructLiteral;
1016 
1017 						case OpenParen:
1018 							lookahead.popMatchingDelimiter!OpenParen();
1019 							break;
1020 
1021 						case OpenBrace:
1022 							lookahead.popMatchingDelimiter!OpenBrace();
1023 							break;
1024 
1025 						case OpenBracket:
1026 							lookahead.popMatchingDelimiter!OpenBracket();
1027 							break;
1028 
1029 						default:
1030 							lookahead.popFront();
1031 					}
1032 				}
1033 			}
1034 
1035 			StructLiteral:
1036 				parseStructLiteral();
1037 				return IdentifierKind.Expression;
1038 
1039 			case Function, Delegate:
1040 				nextToken();
1041 				if (!match(OpenParen)) {
1042 					// We have an explicit type.
1043 					space();
1044 					parseType();
1045 				}
1046 
1047 				if (match(OpenParen)) {
1048 					parseParameterList();
1049 				}
1050 
1051 				space();
1052 				parseStorageClasses(true);
1053 				goto Lambda;
1054 
1055 			Lambda:
1056 				parseInlineBlock(Mode.Statement);
1057 				return IdentifierKind.Expression;
1058 
1059 			case OpenBracket:
1060 				parseArrayLiteral();
1061 				return IdentifierKind.Expression;
1062 
1063 			case Typeid:
1064 				nextToken();
1065 				parseArgumentList();
1066 				return IdentifierKind.Expression;
1067 
1068 			case Mixin:
1069 				parseMixin();
1070 
1071 				// Assume it is an expression. Technically, it could be a declaration,
1072 				// but it does change anything from a formatting perspective.
1073 				return IdentifierKind.Expression;
1074 
1075 			// Types
1076 			case Typeof:
1077 				nextToken();
1078 				if (!match(OpenParen)) {
1079 					return IdentifierKind.Type;
1080 				}
1081 
1082 				auto lookahead = trange.getLookahead();
1083 				lookahead.popFront();
1084 
1085 				if (lookahead.front.type == Return) {
1086 					nextToken();
1087 					nextToken();
1088 					nextToken();
1089 				} else {
1090 					parseArgumentList();
1091 				}
1092 
1093 				return IdentifierKind.Type;
1094 
1095 			case Bool:
1096 			case Byte, Ubyte:
1097 			case Short, Ushort:
1098 			case Int, Uint:
1099 			case Long, Ulong:
1100 			case Cent, Ucent:
1101 			case Char, Wchar, Dchar:
1102 			case Float, Double, Real:
1103 			case Void:
1104 				nextToken();
1105 				return IdentifierKind.Type;
1106 
1107 			// Type qualifiers
1108 			case Const, Immutable, Inout, Shared:
1109 				nextToken();
1110 				if (!match(OpenParen)) {
1111 					space();
1112 					return parseBaseIdentifier(kind);
1113 				}
1114 
1115 				nextToken();
1116 				parseType();
1117 				runOnType!(CloseParen, nextToken)();
1118 				return IdentifierKind.Type;
1119 
1120 			default:
1121 				return IdentifierKind.None;
1122 		}
1123 	}
1124 
1125 	IdentifierKind parseIdentifierSuffix(IdentifierKind kind) {
1126 		const tryDeclaration = canBeDeclaration;
1127 		canBeDeclaration = false;
1128 
1129 		while (true) {
1130 			switch (token.type) with (TokenType) {
1131 				case Dot:
1132 					split();
1133 					nextToken();
1134 
1135 					if (!match(Identifier)) {
1136 						return IdentifierKind.None;
1137 					}
1138 
1139 					kind = IdentifierKind.Symbol;
1140 					nextToken();
1141 					break;
1142 
1143 				case Star:
1144 					final switch (kind) with (IdentifierKind) {
1145 						case Type:
1146 							// This is a pointer.
1147 							nextToken();
1148 							continue;
1149 
1150 						case Expression:
1151 							// This is a multiplication.
1152 							return IdentifierKind.Expression;
1153 
1154 						case Symbol:
1155 							// This could be either. Use lookahead.
1156 							break;
1157 
1158 						case None:
1159 							assert(0);
1160 					}
1161 
1162 					auto lookahead = trange.getLookahead();
1163 					lookahead.popFront();
1164 
1165 					IdentifierStarLookahead: while (true) {
1166 						switch (lookahead.front.type) {
1167 							case Identifier:
1168 								// Lean toward Indentifier* Identifier being a delcaration.
1169 								if (tryDeclaration) {
1170 									goto IdentifierStarType;
1171 								}
1172 
1173 								goto IdentifierStarExpression;
1174 
1175 							case Comma, CloseParen, CloseBracket:
1176 								// This indicates some kind of termination, so assume a type.
1177 								goto IdentifierStarType;
1178 
1179 							case Star, Function, Delegate:
1180 								goto IdentifierStarType;
1181 
1182 							IdentifierStarType:
1183 								kind = IdentifierKind.Type;
1184 								nextToken();
1185 								break IdentifierStarLookahead;
1186 
1187 							case This:
1188 							case Super:
1189 							case True:
1190 							case False:
1191 							case Null:
1192 							case IntegerLiteral:
1193 							case FloatLiteral:
1194 							case StringLiteral:
1195 							case CharacterLiteral:
1196 							case __File__:
1197 							case __Line__:
1198 							case Dollar:
1199 								goto IdentifierStarExpression;
1200 
1201 							IdentifierStarExpression:
1202 								return IdentifierKind.Expression;
1203 
1204 							case OpenBracket:
1205 								import source.parserutil;
1206 								lookahead.popMatchingDelimiter!OpenBracket();
1207 								continue;
1208 
1209 							default:
1210 								// No idea what this is, move on.
1211 								return IdentifierKind.Symbol;
1212 						}
1213 					}
1214 
1215 					break;
1216 
1217 				case Function, Delegate:
1218 					kind = IdentifierKind.Type;
1219 					space();
1220 					nextToken();
1221 					parseParameterList();
1222 					space();
1223 					if (!parseStorageClasses(true)) {
1224 						// Not sure how this will fare in the presence of comments,
1225 						// but this will have to do for now.
1226 						clearSeparator();
1227 					}
1228 
1229 					break;
1230 
1231 				case Bang:
1232 					if (isBangIsOrIn()) {
1233 						// This is a binary expression.
1234 						return IdentifierKind.Expression;
1235 					}
1236 
1237 					// Template instance.
1238 					kind = IdentifierKind.Symbol;
1239 					nextToken();
1240 					if (!parseAliasList()) {
1241 						parseBaseIdentifier(IdentifierKind.Symbol);
1242 					}
1243 
1244 					break;
1245 
1246 				case PlusPlus, MinusMinus:
1247 					kind = IdentifierKind.Expression;
1248 					nextToken();
1249 					break;
1250 
1251 				case OpenParen:
1252 					// FIXME: customize based on kind.
1253 					kind = IdentifierKind.Expression;
1254 					parseArgumentList();
1255 					break;
1256 
1257 				case OpenBracket:
1258 					// FIXME: customize based on kind.
1259 					// Technically, this is not an array literal,
1260 					// but this should do for now.
1261 					parseArrayLiteral();
1262 					break;
1263 
1264 				default:
1265 					return kind;
1266 			}
1267 		}
1268 
1269 		assert(0, "DMD is not smart enough to figure out this is unreachable.");
1270 	}
1271 
1272 	bool parseMixin() {
1273 		if (!match(TokenType.Mixin)) {
1274 			return false;
1275 		}
1276 
1277 		nextToken();
1278 
1279 		switch (token.type) with (TokenType) {
1280 			case Template:
1281 				space();
1282 				parseTemplate();
1283 				break;
1284 
1285 			case OpenParen:
1286 				parseArgumentList();
1287 				break;
1288 
1289 			default:
1290 				space();
1291 				parseIdentifier();
1292 
1293 				if (match(Identifier)) {
1294 					space();
1295 					nextToken();
1296 				}
1297 
1298 				break;
1299 		}
1300 
1301 		return true;
1302 	}
1303 
1304 	/**
1305 	 * Statements
1306 	 */
1307 	bool parseEmptyBlock() {
1308 		if (!match(TokenType.CloseBrace) && !match(TokenType.End)) {
1309 			return false;
1310 		}
1311 
1312 		{
1313 			// Flush comments so that they have the proper indentation.
1314 			auto guard = indent();
1315 			flushComments();
1316 		}
1317 
1318 		nextToken();
1319 		return true;
1320 	}
1321 
1322 	bool parseInlineBlock(Mode m) {
1323 		auto oldNeedDoubleIndent = needDoubleIndent;
1324 		scope(exit) {
1325 			needDoubleIndent = oldNeedDoubleIndent;
1326 			clearSeparator();
1327 		}
1328 
1329 		needDoubleIndent = false;
1330 		return parseBlock(m);
1331 	}
1332 
1333 	bool parseBlock(alias fun = parseBlockContent, T...)(T args) {
1334 		if (!match(TokenType.OpenBrace)) {
1335 			return false;
1336 		}
1337 
1338 		nextToken();
1339 		if (parseEmptyBlock()) {
1340 			newline(mode == Mode.Declaration ? 2 : 1);
1341 			return true;
1342 		}
1343 
1344 		{
1345 			// We have an actual block.
1346 			clearSeparator();
1347 			newline(1);
1348 
1349 			auto blockGuard = block();
1350 			fun(args);
1351 		}
1352 
1353 		if (match(TokenType.CloseBrace)) {
1354 			nextToken();
1355 			newline(2);
1356 		}
1357 
1358 		return true;
1359 	}
1360 
1361 	void parseBlockContent(Mode m) {
1362 		auto indentGuard = indent(1 + needDoubleIndent);
1363 		auto modeGuard = changeMode(m);
1364 
1365 		auto oldNeedDoubleIndent = needDoubleIndent;
1366 		auto oldDoubleIndentBlock = doubleIndentBlock;
1367 		scope(exit) {
1368 			needDoubleIndent = oldNeedDoubleIndent;
1369 			doubleIndentBlock = oldDoubleIndentBlock;
1370 		}
1371 
1372 		doubleIndentBlock = needDoubleIndent;
1373 		needDoubleIndent = false;
1374 
1375 		split();
1376 
1377 		while (!match(TokenType.CloseBrace) && !match(TokenType.End)) {
1378 			parseStructuralElement();
1379 		}
1380 
1381 		// Flush comments so that they have the proper indentation.
1382 		flushComments();
1383 	}
1384 
1385 	static isBasicBlockEntry(ref TokenRange r) {
1386 		auto t = r.front.type;
1387 		if (t == TokenType.Case || t == TokenType.Default) {
1388 			return true;
1389 		}
1390 
1391 		if (t != TokenType.Identifier) {
1392 			return false;
1393 		}
1394 
1395 		// Check for labeled statements.
1396 		r.popFront();
1397 		return r.front.type == TokenType.Colon;
1398 	}
1399 
1400 	static isBasicBlockTerminator(TokenType t) {
1401 		return t == TokenType.CloseBrace || t == TokenType.Return
1402 			|| t == TokenType.Break || t == TokenType.Continue
1403 			|| t == TokenType.Goto || t == TokenType.Throw;
1404 	}
1405 
1406 	static isBasicBlockBoundary(ref TokenRange r) {
1407 		return isBasicBlockTerminator(r.front.type) || isBasicBlockEntry(r);
1408 	}
1409 
1410 	void parseColonBlock() {
1411 		runOnType!(TokenType.Colon, nextToken)();
1412 
1413 		if (match(TokenType.CloseBrace)) {
1414 			// Empty colon block.
1415 			return;
1416 		}
1417 
1418 		if (!match(TokenType.OpenBrace)) {
1419 			newline();
1420 			parseStructuralElement();
1421 			return;
1422 		}
1423 
1424 		import source.parserutil;
1425 		auto lookahead = trange.getLookahead();
1426 		lookahead.popMatchingDelimiter!(TokenType.OpenBrace)();
1427 		if (!isBasicBlockBoundary(lookahead)) {
1428 			newline(1);
1429 			return;
1430 		}
1431 
1432 		auto guard = unindent();
1433 		space();
1434 		parseBlock(mode);
1435 	}
1436 
1437 	bool parseControlFlowBlock(bool forceNewLine = true) {
1438 		if (parseBlock(mode)) {
1439 			return true;
1440 		}
1441 
1442 		auto guard = span();
1443 
1444 		// Carry indentation just like blocks.
1445 		auto indentGuard = indent(needDoubleIndent);
1446 
1447 		auto oldNeedDoubleIndent = needDoubleIndent;
1448 		auto oldDoubleIndentBlock = doubleIndentBlock;
1449 		scope(exit) {
1450 			needDoubleIndent = oldNeedDoubleIndent;
1451 			doubleIndentBlock = oldDoubleIndentBlock;
1452 		}
1453 
1454 		doubleIndentBlock = needDoubleIndent;
1455 		needDoubleIndent = false;
1456 
1457 		if (forceNewLine) {
1458 			newline(1);
1459 		} else {
1460 			space();
1461 		}
1462 
1463 		split();
1464 		parseStructuralElement();
1465 		return false;
1466 	}
1467 
1468 	void emitPostControlFlowWhitespace(bool isBlock) {
1469 		flushComments();
1470 		clearSeparator();
1471 		if (isBlock) {
1472 			space();
1473 		} else {
1474 			newline(1);
1475 		}
1476 	}
1477 
1478 	void parseElsableBlock() {
1479 		if (match(TokenType.Colon)) {
1480 			parseColonBlock();
1481 			return;
1482 		}
1483 
1484 		space();
1485 
1486 		bool isBlock = parseControlFlowBlock();
1487 		if (!match(TokenType.Else)) {
1488 			return;
1489 		}
1490 
1491 		emitPostControlFlowWhitespace(isBlock);
1492 		parseElse();
1493 	}
1494 
1495 	void parseCondition(bool glued = false) {
1496 		if (!match(TokenType.OpenParen)) {
1497 			return;
1498 		}
1499 
1500 		nextToken();
1501 
1502 		auto guard = span!AlignedSpan();
1503 		split(glued);
1504 
1505 		guard.registerFix(function(AlignedSpan s, size_t i) {
1506 			s.alignOn(i);
1507 		});
1508 
1509 		auto modeGuard = changeMode(Mode.Parameter);
1510 
1511 		parseStructuralElement();
1512 		runOnType!(TokenType.CloseParen, nextToken)();
1513 	}
1514 
1515 	void parseIf() in {
1516 		assert(match(TokenType.If));
1517 	} do {
1518 		nextToken();
1519 		space();
1520 
1521 		parseCondition();
1522 		parseElsableBlock();
1523 	}
1524 
1525 	void parseVersion() in {
1526 		assert(match(TokenType.Version) || match(TokenType.Debug));
1527 	} do {
1528 		nextToken();
1529 
1530 		if (match(TokenType.OpenParen)) {
1531 			space();
1532 			nextToken();
1533 
1534 			if (match(TokenType.Identifier) || match(TokenType.Unittest)) {
1535 				nextToken();
1536 			}
1537 
1538 			runOnType!(TokenType.CloseParen, nextToken)();
1539 		}
1540 
1541 		parseElsableBlock();
1542 	}
1543 
1544 	void parseElse() in {
1545 		assert(match(TokenType.Else));
1546 	} do {
1547 		space();
1548 		nextToken();
1549 		space();
1550 
1551 		switch (token.type) with (TokenType) {
1552 			case If:
1553 				parseIf();
1554 				break;
1555 
1556 			case Version, Debug:
1557 				parseVersion();
1558 				break;
1559 
1560 			case While:
1561 				parseWhile();
1562 				break;
1563 
1564 			case Do:
1565 				parseDoWhile();
1566 				break;
1567 
1568 			case For:
1569 				parseFor();
1570 				break;
1571 
1572 			case Foreach, ForeachReverse:
1573 				parseForeach();
1574 				break;
1575 
1576 			case Static:
1577 				auto lookahead = trange.getLookahead();
1578 				lookahead.popFront();
1579 
1580 				auto t = lookahead.front.type;
1581 				if (t == If || t == Foreach || t == ForeachReverse) {
1582 					parseStatic();
1583 					break;
1584 				}
1585 
1586 				goto default;
1587 
1588 			default:
1589 				parseControlFlowBlock();
1590 				break;
1591 		}
1592 	}
1593 
1594 	void parseWhile() in {
1595 		assert(match(TokenType.While));
1596 	} do {
1597 		nextToken();
1598 		space();
1599 
1600 		parseCondition();
1601 
1602 		space();
1603 		parseControlFlowBlock();
1604 	}
1605 
1606 	void parseDoWhile() in {
1607 		assert(match(TokenType.Do));
1608 	} do {
1609 		nextToken();
1610 		space();
1611 		bool isBlock = parseControlFlowBlock();
1612 
1613 		if (!match(TokenType.While)) {
1614 			return;
1615 		}
1616 
1617 		emitPostControlFlowWhitespace(isBlock);
1618 		nextToken();
1619 
1620 		space();
1621 		parseCondition();
1622 
1623 		runOnType!(TokenType.Semicolon, nextToken)();
1624 		newline(2);
1625 	}
1626 
1627 	void parseFor() in {
1628 		assert(match(TokenType.For));
1629 	} do {
1630 		nextToken();
1631 		space();
1632 
1633 		if (match(TokenType.OpenParen)) {
1634 			nextToken();
1635 			parseForArguments();
1636 			runOnType!(TokenType.CloseParen, nextToken)();
1637 		}
1638 
1639 		space();
1640 		parseControlFlowBlock();
1641 	}
1642 
1643 	void parseForArguments() {
1644 		auto guard = span!CompactListSpan();
1645 
1646 		if (match(TokenType.Semicolon)) {
1647 			nextToken();
1648 		} else {
1649 			split();
1650 			guard.registerFix(function(CompactListSpan s, size_t i) {
1651 				s.registerElement(i);
1652 			});
1653 
1654 			parseStructuralElement();
1655 			clearSeparator();
1656 		}
1657 
1658 		if (match(TokenType.Semicolon)) {
1659 			nextToken();
1660 		} else {
1661 			space();
1662 			split();
1663 			guard.registerFix(function(CompactListSpan s, size_t i) {
1664 				s.registerElement(i);
1665 			});
1666 
1667 			parseCommaExpression();
1668 			runOnType!(TokenType.Semicolon, nextToken)();
1669 		}
1670 
1671 		if (match(TokenType.CloseParen)) {
1672 			nextToken();
1673 		} else {
1674 			space();
1675 			split();
1676 			guard.registerFix(function(CompactListSpan s, size_t i) {
1677 				s.registerElement(i);
1678 			});
1679 
1680 			parseCommaExpression();
1681 		}
1682 	}
1683 
1684 	void parseForeach() in {
1685 		assert(match(TokenType.Foreach) || match(TokenType.ForeachReverse));
1686 	} do {
1687 		nextToken();
1688 		space();
1689 
1690 		if (match(TokenType.OpenParen)) {
1691 			nextToken();
1692 			auto modeGuard = changeMode(Mode.Parameter);
1693 			auto listGuard = span!CompactListSpan();
1694 
1695 			split();
1696 			listGuard.registerFix(function(CompactListSpan s, size_t i) {
1697 				s.registerElement(i);
1698 			});
1699 
1700 			parseList!parseStructuralElement(TokenType.Semicolon);
1701 
1702 			split();
1703 			listGuard.registerFix(function(CompactListSpan s, size_t i) {
1704 				s.registerElement(i);
1705 			});
1706 
1707 			space();
1708 			parseList!parseArrayElement(TokenType.CloseParen);
1709 		}
1710 
1711 		space();
1712 		parseControlFlowBlock();
1713 	}
1714 
1715 	void parseReturn() in {
1716 		assert(match(TokenType.Return) || match(TokenType.Throw));
1717 	} do {
1718 		nextToken();
1719 		if (token.type == TokenType.Semicolon) {
1720 			nextToken();
1721 			return;
1722 		}
1723 
1724 		auto guard = span();
1725 
1726 		space();
1727 		split();
1728 
1729 		parseExpression();
1730 	}
1731 
1732 	void parseWith() in {
1733 		assert(match(TokenType.With));
1734 	} do {
1735 		nextToken();
1736 		space();
1737 
1738 		parseCondition();
1739 		space();
1740 
1741 		parseStructuralElement();
1742 	}
1743 
1744 	void parseSwitch() in {
1745 		assert(match(TokenType.Switch));
1746 	} do {
1747 		nextToken();
1748 		space();
1749 
1750 		parseCondition();
1751 		space();
1752 		split();
1753 
1754 		// Request the next nested block to be double indented.
1755 		auto oldNeedDoubleIndent = needDoubleIndent;
1756 		scope(exit) {
1757 			needDoubleIndent = oldNeedDoubleIndent;
1758 		}
1759 
1760 		needDoubleIndent = true;
1761 		parseStructuralElement();
1762 	}
1763 
1764 	auto withCaseLevelIndent(alias fun)() {
1765 		// There is nothing special to do in this case, just move on.
1766 		if (!isCaseLevelStatement()) {
1767 			return fun();
1768 		}
1769 
1770 		// Request the next nested block to be double indented.
1771 		auto oldNeedDoubleIndent = needDoubleIndent;
1772 		scope(exit) {
1773 			needDoubleIndent = oldNeedDoubleIndent;
1774 		}
1775 
1776 		needDoubleIndent = true;
1777 
1778 		auto guard = unindent();
1779 		split();
1780 
1781 		return fun();
1782 	}
1783 
1784 	bool isCaseLevelStatement() {
1785 		if (!doubleIndentBlock) {
1786 			// No case level statement if we are not in
1787 			// switch style block.
1788 			return false;
1789 		}
1790 
1791 		static void skip(ref TokenRange r) {
1792 			while (true) {
1793 				switch (r.front.type) with (TokenType) {
1794 					case CloseBrace, End:
1795 						return;
1796 
1797 					case Semicolon:
1798 						r.popFront();
1799 						return;
1800 
1801 					case OpenBrace:
1802 						import source.parserutil;
1803 						r.popMatchingDelimiter!OpenBrace();
1804 						return;
1805 
1806 					case OpenParen:
1807 						// Make sure we don't stop on `for (;;)`
1808 						// so skip over parentheses.
1809 						import source.parserutil;
1810 						r.popMatchingDelimiter!OpenParen();
1811 						continue;
1812 
1813 					default:
1814 						r.popFront();
1815 						continue;
1816 				}
1817 			}
1818 		}
1819 
1820 		static bool isCaseBlock()(ref TokenRange r) {
1821 			if (r.front.type != TokenType.OpenBrace) {
1822 				return containsCase(r);
1823 			}
1824 
1825 			r.popFront();
1826 			while (r.front.type != TokenType.End) {
1827 				if (containsCase(r)) {
1828 					return true;
1829 				}
1830 
1831 				if (r.front.type == TokenType.CloseBrace) {
1832 					r.popFront();
1833 					break;
1834 				}
1835 			}
1836 
1837 			return false;
1838 		}
1839 
1840 		static bool containsCase(ref TokenRange r, bool doSkip = true) {
1841 			// Pop labels.
1842 			while (r.front.type == TokenType.Identifier) {
1843 				r.popFront();
1844 				if (r.front.type != TokenType.Colon) {
1845 					goto Skip;
1846 				}
1847 
1848 				r.popFront();
1849 			}
1850 
1851 			switch (r.front.type) with (TokenType) {
1852 				case Case, Default:
1853 					return true;
1854 
1855 				case Static:
1856 					r.popFront();
1857 
1858 					auto t = r.front.type;
1859 					if (t == If || t == Foreach || t == ForeachReverse) {
1860 						goto CheckBlock;
1861 					}
1862 
1863 					break;
1864 
1865 				case Foreach, ForeachReverse:
1866 					goto CheckBlock;
1867 
1868 				CheckBlock:
1869 					// As far as we are concenred here, foreach and
1870 					// static if have the same syntax.
1871 					r.popFront();
1872 					if (r.front.type == OpenParen) {
1873 						import source.parserutil;
1874 						r.popMatchingDelimiter!OpenParen();
1875 					}
1876 
1877 					return isCaseBlock(r);
1878 
1879 				default:
1880 					break;
1881 			}
1882 
1883 		Skip:
1884 			if (doSkip) {
1885 				skip(r);
1886 			}
1887 
1888 			return false;
1889 		}
1890 
1891 		auto lookahead = trange.getLookahead();
1892 		return containsCase(lookahead, false);
1893 	}
1894 
1895 	void parseTry() in {
1896 		assert(match(TokenType.Try));
1897 	} do {
1898 		nextToken();
1899 		space();
1900 		bool isBlock = parseControlFlowBlock();
1901 
1902 		while (true) {
1903 			while (match(TokenType.Catch)) {
1904 				emitPostControlFlowWhitespace(isBlock);
1905 				isBlock = parseCatch();
1906 			}
1907 
1908 			if (!match(TokenType.Finally)) {
1909 				break;
1910 			}
1911 
1912 			emitPostControlFlowWhitespace(isBlock);
1913 			isBlock = parseFinally();
1914 		}
1915 	}
1916 
1917 	bool parseCatch() in {
1918 		assert(match(TokenType.Catch));
1919 	} do {
1920 		nextToken();
1921 		space();
1922 		parseParameterList();
1923 		space();
1924 		return parseControlFlowBlock();
1925 	}
1926 
1927 	bool parseFinally() in {
1928 		assert(match(TokenType.Finally));
1929 	} do {
1930 		nextToken();
1931 		space();
1932 		return parseControlFlowBlock();
1933 	}
1934 
1935 	void parseScope() in {
1936 		assert(match(TokenType.Scope));
1937 	} do {
1938 		auto lookahead = trange.getLookahead();
1939 		lookahead.popFront();
1940 
1941 		if (lookahead.front.type != TokenType.OpenParen) {
1942 			parseStorageClassDeclaration();
1943 			return;
1944 		}
1945 
1946 		nextToken();
1947 		parseArgumentList();
1948 
1949 		space();
1950 		parseControlFlowBlock(false);
1951 	}
1952 
1953 	/**
1954 	 * Types
1955 	 */
1956 	bool parseType() {
1957 		return parseIdentifier(IdentifierKind.Type);
1958 	}
1959 
1960 	/**
1961 	 * Expressions
1962 	 */
1963 	void parseExpression() {
1964 		canBeDeclaration = false;
1965 		parseBaseExpression();
1966 		parseAssignExpressionSuffix();
1967 	}
1968 
1969 	bool parseBaseExpression() {
1970 		return parseIdentifier(IdentifierKind.Expression);
1971 	}
1972 
1973 	void parseCommaExpression() {
1974 		parseBaseExpression();
1975 		parseCommaExpressionSuffix();
1976 	}
1977 
1978 	void parseCommaExpressionSuffix() {
1979 		parseAssignExpressionSuffix();
1980 
1981 		if (!match(TokenType.Comma)) {
1982 			return;
1983 		}
1984 
1985 		auto guard = spliceSpan();
1986 		do {
1987 			nextToken();
1988 			split();
1989 			space();
1990 
1991 			parseExpression();
1992 		} while (match(TokenType.Comma));
1993 	}
1994 
1995 	void parseAssignExpressionSuffix() {
1996 		parseConditionalExpressionSuffix();
1997 
1998 		static bool isAssignExpression(TokenType t) {
1999 			return t == TokenType.Equal || t == TokenType.PlusEqual
2000 				|| t == TokenType.MinusEqual || t == TokenType.StarEqual
2001 				|| t == TokenType.SlashEqual || t == TokenType.PercentEqual
2002 				|| t == TokenType.AmpersandEqual || t == TokenType.PipeEqual
2003 				|| t == TokenType.CaretEqual || t == TokenType.TildeEqual
2004 				|| t == TokenType.LessLessEqual || t == TokenType.MoreMoreEqual
2005 				|| t == TokenType.MoreMoreMoreEqual
2006 				|| t == TokenType.CaretCaretEqual;
2007 		}
2008 
2009 		if (!isAssignExpression(token.type)) {
2010 			return;
2011 		}
2012 
2013 		auto guard = spliceSpan();
2014 		do {
2015 			space();
2016 			nextToken();
2017 			split();
2018 			space();
2019 
2020 			parseBaseExpression();
2021 			parseConditionalExpressionSuffix();
2022 		} while (isAssignExpression(token.type));
2023 	}
2024 
2025 	void parseConditionalExpressionSuffix() {
2026 		parseBinaryExpressionSuffix();
2027 
2028 		if (!match(TokenType.QuestionMark)) {
2029 			return;
2030 		}
2031 
2032 		auto guard = spliceSpan!ConditionalSpan();
2033 
2034 		space();
2035 		split();
2036 
2037 		guard.registerFix(function(ConditionalSpan s, size_t i) {
2038 			s.setQuestionMarkIndex(i);
2039 		});
2040 
2041 		nextToken();
2042 		space();
2043 
2044 		parseExpression();
2045 
2046 		space();
2047 		split();
2048 
2049 		runOnType!(TokenType.Comma, nextToken)();
2050 		guard.registerFix(function(ConditionalSpan s, size_t i) {
2051 			s.setColonIndex(i);
2052 		});
2053 
2054 		nextToken();
2055 		space();
2056 
2057 		parseBaseExpression();
2058 		parseConditionalExpressionSuffix();
2059 	}
2060 
2061 	bool isBangIsOrIn() in {
2062 		assert(match(TokenType.Bang));
2063 	} do {
2064 		auto lookahead = trange.getLookahead();
2065 		lookahead.popFront();
2066 		auto t = lookahead.front.type;
2067 		return t == TokenType.Is || t == TokenType.In;
2068 	}
2069 
2070 	uint getPrecedence() {
2071 		switch (token.type) with (TokenType) {
2072 			case PipePipe:
2073 				return 1;
2074 
2075 			case AmpersandAmpersand:
2076 				return 2;
2077 
2078 			case Pipe:
2079 				return 3;
2080 
2081 			case Caret:
2082 				return 4;
2083 
2084 			case Ampersand:
2085 				return 5;
2086 
2087 			case Is:
2088 			case In:
2089 				return 6;
2090 
2091 			case Bang:
2092 				return isBangIsOrIn() ? 6 : 0;
2093 
2094 			case EqualEqual:
2095 			case BangEqual:
2096 				return 6;
2097 
2098 			case More:
2099 			case MoreEqual:
2100 			case Less:
2101 			case LessEqual:
2102 				return 6;
2103 
2104 			case LessLess:
2105 			case MoreMore:
2106 			case MoreMoreMore:
2107 				return 7;
2108 
2109 			case BangLessMoreEqual:
2110 			case BangLessMore:
2111 			case LessMore:
2112 			case LessMoreEqual:
2113 			case BangMore:
2114 			case BangMoreEqual:
2115 			case BangLess:
2116 			case BangLessEqual:
2117 				return 7;
2118 
2119 			case Plus:
2120 			case Minus:
2121 				return 8;
2122 
2123 			case Slash:
2124 			case Star:
2125 			case Percent:
2126 				return 9;
2127 
2128 			case Tilde:
2129 				return 10;
2130 
2131 			default:
2132 				return 0;
2133 		}
2134 	}
2135 
2136 	void parseBinaryExpressionSuffix(uint minPrecedence = 0) {
2137 		auto currentPrecedence = getPrecedence();
2138 
2139 		while (currentPrecedence > minPrecedence) {
2140 			auto previousPrecedence = currentPrecedence;
2141 			auto guard = spliceSpan();
2142 
2143 			while (previousPrecedence == currentPrecedence) {
2144 				scope(success) {
2145 					currentPrecedence = getPrecedence();
2146 					if (currentPrecedence > previousPrecedence) {
2147 						parseBinaryExpressionSuffix(previousPrecedence);
2148 						currentPrecedence = getPrecedence();
2149 					}
2150 
2151 					assert(currentPrecedence <= previousPrecedence);
2152 				}
2153 
2154 				space();
2155 				split();
2156 				if (match(TokenType.Bang)) {
2157 					nextToken();
2158 				}
2159 
2160 				nextToken();
2161 				space();
2162 
2163 				parseBaseExpression();
2164 			}
2165 		}
2166 	}
2167 
2168 	void parseArgumentList() {
2169 		if (!match(TokenType.OpenParen)) {
2170 			return;
2171 		}
2172 
2173 		nextToken();
2174 		parseList!parseExpression(TokenType.CloseParen);
2175 	}
2176 
2177 	void parseArrayLiteral() {
2178 		if (!match(TokenType.OpenBracket)) {
2179 			return;
2180 		}
2181 
2182 		nextToken();
2183 		parseList!parseArrayElement(TokenType.CloseBracket);
2184 	}
2185 
2186 	void parseArrayElement() {
2187 		parseExpression();
2188 
2189 		switch (token.type) with (TokenType) {
2190 			case Colon: {
2191 				auto guard = spliceSpan();
2192 				space();
2193 				nextToken();
2194 				space();
2195 				split();
2196 				parseExpression();
2197 				break;
2198 			}
2199 
2200 			case DotDot: {
2201 				auto guard = spliceSpan();
2202 				space();
2203 				split();
2204 				nextToken();
2205 				space();
2206 				parseExpression();
2207 				break;
2208 			}
2209 
2210 			default:
2211 				break;
2212 		}
2213 	}
2214 
2215 	void parseIsExpression() in {
2216 		assert(match(TokenType.Is));
2217 	} do {
2218 		auto modeGuard = changeMode(Mode.Parameter);
2219 		nextToken();
2220 		runOnType!(TokenType.OpenParen, nextToken)();
2221 		parseList!parseIsElement(TokenType.CloseParen);
2222 	}
2223 
2224 	void parseIsElement(size_t i) {
2225 		if (i == 0) {
2226 			parseIsSpecialization();
2227 		} else {
2228 			parseStructuralElement();
2229 		}
2230 	}
2231 
2232 	void parseIsSpecialization() {
2233 		parseType();
2234 		if (match(TokenType.Identifier)) {
2235 			space();
2236 			nextToken();
2237 		}
2238 
2239 		static bool isTypeSpecialization(TokenType t) {
2240 			return t == TokenType.Struct || t == TokenType.Union
2241 				|| t == TokenType.Class || t == TokenType.Interface
2242 				|| t == TokenType.Enum || t == TokenType.__Vector
2243 				|| t == TokenType.Function || t == TokenType.Delegate
2244 				|| t == TokenType.Super || t == TokenType.Return
2245 				|| t == TokenType.__Parameters || t == TokenType.Module
2246 				|| t == TokenType.Package;
2247 		}
2248 
2249 		while (match(TokenType.EqualEqual) || match(TokenType.Colon)) {
2250 			auto specGuard = span();
2251 
2252 			space();
2253 			split();
2254 			nextToken();
2255 			space();
2256 
2257 			if (isTypeSpecialization(token.type)) {
2258 				nextToken();
2259 			} else {
2260 				parseType();
2261 			}
2262 
2263 			clearSeparator();
2264 		}
2265 	}
2266 
2267 	void parseStructLiteral() {
2268 		parseBlock!parseStructLiteralContent();
2269 		clearSeparator();
2270 	}
2271 
2272 	void parseStructLiteralContent() {
2273 		auto indentGuard = indent();
2274 
2275 		split();
2276 
2277 		while (!match(TokenType.CloseBrace) && !match(TokenType.End)) {
2278 			parseMapEntry();
2279 			runOnType!(TokenType.Comma, nextToken)();
2280 			newline(1);
2281 		}
2282 
2283 		// Flush comments so that they have the proper indentation.
2284 		flushComments();
2285 	}
2286 
2287 	void parseMapEntry() {
2288 		auto guard = span();
2289 		runOnType!(TokenType.Identifier, nextToken)();
2290 		runOnType!(TokenType.Colon, nextToken)();
2291 
2292 		split();
2293 		space();
2294 		parseExpression();
2295 	}
2296 
2297 	/**
2298 	 * Declarations
2299 	 */
2300 	void parseParameterPacks() {
2301 		auto guard = changeMode(Mode.Parameter);
2302 
2303 		while (match(TokenType.OpenParen)) {
2304 			nextToken();
2305 			parseList!(parseStructuralElement,
2306 			           ExpandingListSpan)(TokenType.CloseParen);
2307 		}
2308 	}
2309 
2310 	void parseTypedDeclaration() in {
2311 		assert(match(TokenType.Identifier));
2312 	} do {
2313 		bool isParameter = mode == Mode.Parameter;
2314 		while (true) {
2315 			auto guard = span!PrefixSpan();
2316 			split();
2317 			space();
2318 			runOnType!(TokenType.Identifier, nextToken)();
2319 
2320 			parseParameterPacks();
2321 
2322 			// Variable, template parameters, whatever.
2323 			if (match(TokenType.Equal) || match(TokenType.Colon)) {
2324 				auto valueGuard = spliceSpan();
2325 
2326 				space();
2327 				nextToken();
2328 				space();
2329 				split();
2330 
2331 				parseExpression();
2332 			}
2333 
2334 			if (isParameter) {
2335 				if (match(TokenType.DotDotDot)) {
2336 					nextToken();
2337 				}
2338 
2339 				break;
2340 			}
2341 
2342 			if (!match(TokenType.Comma)) {
2343 				break;
2344 			}
2345 
2346 			nextToken();
2347 		}
2348 
2349 		parseFunctionBody();
2350 	}
2351 
2352 	void parseConstructor() in {
2353 		assert(match(TokenType.This));
2354 	} do {
2355 		nextToken();
2356 		parseParameterPacks();
2357 		parseFunctionBody();
2358 	}
2359 
2360 	void parseDestructor() in {
2361 		assert(match(TokenType.Tilde));
2362 	} do {
2363 		nextToken();
2364 		parseConstructor();
2365 	}
2366 
2367 	void parseFunctionBody() {
2368 		if (parseFunctionPostfix()) {
2369 			space();
2370 			parseBlock(Mode.Statement);
2371 		}
2372 	}
2373 
2374 	bool parseFunctionPostfix() {
2375 		auto guard = span!IndentSpan(2);
2376 
2377 		while (true) {
2378 			clearSeparator();
2379 			space();
2380 
2381 			switch (token.type) with (TokenType) {
2382 				case OpenBrace:
2383 					// Function declaration.
2384 					return true;
2385 
2386 				case Body, Do:
2387 					split();
2388 					nextToken();
2389 					return true;
2390 
2391 				case In:
2392 					auto lookahead = trange.getLookahead();
2393 					lookahead.popFront();
2394 
2395 					if (lookahead.front.type == OpenParen) {
2396 						split();
2397 						nextToken();
2398 						parseParameterList();
2399 					} else {
2400 						nextToken();
2401 						space();
2402 						parseBlock(Mode.Statement);
2403 					}
2404 
2405 					break;
2406 
2407 				case Out:
2408 					// FIXME: This doesn't looks like it is doing the right thing.
2409 					split();
2410 					nextToken();
2411 					parseParameterList();
2412 					space();
2413 					parseBlock(Mode.Statement);
2414 					break;
2415 
2416 				case If:
2417 					parseConstraint();
2418 					break;
2419 
2420 				default:
2421 					if (!parseStorageClasses(true)) {
2422 						clearSeparator();
2423 						return false;
2424 					}
2425 
2426 					break;
2427 			}
2428 		}
2429 	}
2430 
2431 	void parseConstraint() {
2432 		if (!match(TokenType.If)) {
2433 			return;
2434 		}
2435 
2436 		split();
2437 		nextToken();
2438 		space();
2439 		parseCondition(true);
2440 	}
2441 
2442 	void parseTemplate() in {
2443 		assert(match(TokenType.Template));
2444 	} do {
2445 		nextToken();
2446 		space();
2447 		runOnType!(TokenType.Identifier, nextToken)();
2448 		parseParameterList();
2449 		space();
2450 
2451 		if (match(TokenType.If)) {
2452 			auto guard = span!IndentSpan(2);
2453 			parseConstraint();
2454 			space();
2455 		}
2456 
2457 		parseBlock(Mode.Declaration);
2458 	}
2459 
2460 	void parseTemplateParameter() in {
2461 		assert(token.type == TokenType.Identifier);
2462 	} do {
2463 		nextToken();
2464 
2465 		if (match(TokenType.DotDotDot)) {
2466 			nextToken();
2467 		}
2468 
2469 		while (match(TokenType.Colon) || match(TokenType.Equal)) {
2470 			space();
2471 			nextToken();
2472 			space();
2473 			parseType();
2474 		}
2475 	}
2476 
2477 	bool parseParameterList() {
2478 		if (!match(TokenType.OpenParen)) {
2479 			return false;
2480 		}
2481 
2482 		auto guard = changeMode(Mode.Parameter);
2483 		nextToken();
2484 
2485 		parseList!(parseStructuralElement,
2486 		           ExpandingListSpan)(TokenType.CloseParen);
2487 		return true;
2488 	}
2489 
2490 	void parseImport() in {
2491 		assert(match(TokenType.Import));
2492 	} do {
2493 		nextToken();
2494 
2495 		auto guard = span!PrefixSpan();
2496 
2497 		while (true) {
2498 			space();
2499 			split();
2500 			parseIdentifier();
2501 
2502 			if (!match(TokenType.Comma)) {
2503 				break;
2504 			}
2505 
2506 			nextToken();
2507 		}
2508 
2509 		parseColonList!parseImportBind();
2510 	}
2511 
2512 	void parseImportBind() {
2513 		parseIdentifier();
2514 
2515 		if (!match(TokenType.Equal)) {
2516 			return;
2517 		}
2518 
2519 		auto guard = spliceSpan();
2520 		space();
2521 		nextToken();
2522 		space();
2523 		split();
2524 
2525 		parseIdentifier();
2526 	}
2527 
2528 	bool parseAttribute() {
2529 		if (!match(TokenType.At)) {
2530 			return false;
2531 		}
2532 
2533 		nextToken();
2534 		if (parseAliasList()) {
2535 			return true;
2536 		}
2537 
2538 		if (!match(TokenType.Identifier)) {
2539 			parseIdentifier();
2540 			return true;
2541 		}
2542 
2543 		nextToken();
2544 		parseIdentifierSuffix(IdentifierKind.Symbol);
2545 		return true;
2546 	}
2547 
2548 	bool parseAttributes() {
2549 		if (!parseAttribute()) {
2550 			return false;
2551 		}
2552 
2553 		while (match(TokenType.At)) {
2554 			space();
2555 			split();
2556 			parseAttribute();
2557 		}
2558 
2559 		space();
2560 		return true;
2561 	}
2562 
2563 	static popDeclarator(ref TokenRange lookahead) {
2564 		lookahead.popFront();
2565 
2566 		if (lookahead.front.type == TokenType.Identifier) {
2567 			lookahead.popFront();
2568 		}
2569 
2570 		if (lookahead.front.type == TokenType.OpenParen) {
2571 			import source.parserutil;
2572 			lookahead.popMatchingDelimiter!(TokenType.OpenParen)();
2573 		}
2574 
2575 		return lookahead.front.type;
2576 	}
2577 
2578 	TokenType getStorageClassTokenType() {
2579 		auto lookahead = trange.getLookahead();
2580 		return getStorageClassTokenType(lookahead);
2581 	}
2582 
2583 	static getStorageClassTokenType(ref TokenRange lookahead) {
2584 		while (true) {
2585 			auto t = lookahead.front.type;
2586 			switch (t) with (TokenType) {
2587 				case Const, Immutable, Inout, Shared, Scope:
2588 					lookahead.popFront();
2589 					if (lookahead.front.type == OpenParen) {
2590 						// This is a type.
2591 						return t;
2592 					}
2593 
2594 					break;
2595 
2596 				case Abstract, Auto, Export, Final, In, Lazy, Nothrow, Out,
2597 				     Override, Private, Protected, Pure, Ref, Return, __Gshared:
2598 					lookahead.popFront();
2599 					break;
2600 
2601 				case Align, Deprecated, Extern, Package, Pragma, Synchronized:
2602 					lookahead.popFront();
2603 					if (lookahead.front.type == OpenParen) {
2604 						import source.parserutil;
2605 						lookahead.popMatchingDelimiter!OpenParen();
2606 					}
2607 
2608 					break;
2609 
2610 				case At:
2611 					// FIXME: A declarator is not apropriate here.
2612 					popDeclarator(lookahead);
2613 					break;
2614 
2615 				case Public:
2616 					auto l2 = lookahead.getLookahead();
2617 					l2.popFront();
2618 
2619 					if (l2.front.type == Import) {
2620 						// This is a public import.
2621 						return t;
2622 					}
2623 
2624 					lookahead.popFront();
2625 					break;
2626 
2627 				case Static:
2628 					auto l2 = lookahead.getLookahead();
2629 					l2.popFront();
2630 
2631 					auto t2 = l2.front.type;
2632 					if (t2 == Assert || t2 == Import || t2 == If
2633 						    || t2 == Foreach || t2 == ForeachReverse) {
2634 						// This is a static something.
2635 						return t;
2636 					}
2637 
2638 					lookahead.popFront();
2639 					break;
2640 
2641 				case Enum:
2642 					auto l2 = lookahead.getLookahead();
2643 					popDeclarator(l2);
2644 
2645 					auto t2 = l2.front.type;
2646 					if (t2 == Colon || t2 == OpenBrace) {
2647 						// This is an enum declaration.
2648 						return t;
2649 					}
2650 
2651 					lookahead.popFront();
2652 					break;
2653 
2654 				case Alias:
2655 					auto l2 = lookahead.getLookahead();
2656 					popDeclarator(l2);
2657 
2658 					auto t2 = l2.front.type;
2659 					if (t2 == This || t2 == Identifier) {
2660 						// This is an alias declaration.
2661 						return t;
2662 					}
2663 
2664 					lookahead.popFront();
2665 					break;
2666 
2667 				default:
2668 					return t;
2669 			}
2670 		}
2671 	}
2672 
2673 	bool parseStorageClasses(bool isPostfix = false) {
2674 		bool foundStorageClass = false;
2675 		while (true) {
2676 			scope(success) {
2677 				// This will be true after the first loop iterration.
2678 				foundStorageClass = true;
2679 			}
2680 
2681 			switch (token.type) with (TokenType) {
2682 				case Const, Immutable, Inout, Shared, Scope:
2683 					auto lookahead = trange.getLookahead();
2684 					lookahead.popFront();
2685 					if (lookahead.front.type == OpenParen) {
2686 						// This is a type.
2687 						goto default;
2688 					}
2689 
2690 					nextToken();
2691 					break;
2692 
2693 				case In, Out:
2694 					// Make sure we deambiguate with contracts.
2695 					if (isPostfix) {
2696 						goto default;
2697 					}
2698 
2699 					nextToken();
2700 					break;
2701 
2702 				case Abstract, Auto, Export, Final, Lazy, Nothrow, Override,
2703 				     Private, Protected, Pure, Ref, Return, __Gshared:
2704 					nextToken();
2705 					break;
2706 
2707 				case Align, Deprecated, Extern, Package, Synchronized:
2708 					nextToken();
2709 					parseArgumentList();
2710 					break;
2711 
2712 				case Pragma:
2713 					nextToken();
2714 					parseArgumentList();
2715 					if (!isPostfix && !match(Colon)) {
2716 						newline(1);
2717 					}
2718 
2719 					break;
2720 
2721 				case At:
2722 					parseAttributes();
2723 					if (!isPostfix && !foundStorageClass && !match(Colon)) {
2724 						newline(1);
2725 					}
2726 
2727 					break;
2728 
2729 				case Public:
2730 					auto lookahead = trange.getLookahead();
2731 					lookahead.popFront();
2732 
2733 					if (lookahead.front.type == Import) {
2734 						// This is a public import.
2735 						goto default;
2736 					}
2737 
2738 					nextToken();
2739 					break;
2740 
2741 				case Static:
2742 					auto lookahead = trange.getLookahead();
2743 					lookahead.popFront();
2744 
2745 					auto t = lookahead.front.type;
2746 					if (t == Assert || t == Import || t == If || t == Foreach
2747 						    || t == ForeachReverse) {
2748 						// This is a static something.
2749 						goto default;
2750 					}
2751 
2752 					nextToken();
2753 					break;
2754 
2755 				case Enum:
2756 					auto lookahead = trange.getLookahead();
2757 					popDeclarator(lookahead);
2758 
2759 					auto t = lookahead.front.type;
2760 					if (t == Colon || t == OpenBrace) {
2761 						// This is an enum declaration.
2762 						goto default;
2763 					}
2764 
2765 					nextToken();
2766 					break;
2767 
2768 				case Alias:
2769 					auto lookahead = trange.getLookahead();
2770 					popDeclarator(lookahead);
2771 
2772 					auto t = lookahead.front.type;
2773 					if (t == This || t == Identifier) {
2774 						// This is an alias declaration.
2775 						goto default;
2776 					}
2777 
2778 					nextToken();
2779 					break;
2780 
2781 				default:
2782 					return foundStorageClass;
2783 			}
2784 
2785 			if (match(TokenType.Colon) || match(TokenType.Semicolon)) {
2786 				clearSeparator();
2787 			} else {
2788 				if (!isPostfix && !match(TokenType.Identifier)) {
2789 					split();
2790 				}
2791 
2792 				space();
2793 			}
2794 		}
2795 
2796 		return foundStorageClass;
2797 	}
2798 
2799 	bool parseStorageClassDeclaration() {
2800 		auto guard = span!StorageClassSpan();
2801 
2802 		bool isColonBlock = getStorageClassTokenType() == TokenType.Colon;
2803 		bool foundStorageClass = false;
2804 
2805 		{
2806 			auto indentGuard = unindent(isColonBlock);
2807 			foundStorageClass = parseStorageClasses();
2808 		}
2809 
2810 		// Before bailing, try storage class looking declarations.
2811 		switch (token.type) with (TokenType) {
2812 			case Public:
2813 				return parsePublic();
2814 
2815 			case Enum:
2816 				return parseEnum();
2817 
2818 			case Alias:
2819 				return parseAlias();
2820 
2821 			default:
2822 				break;
2823 		}
2824 
2825 		if (!foundStorageClass) {
2826 			return false;
2827 		}
2828 
2829 		switch (token.type) with (TokenType) {
2830 			case Colon:
2831 				clearSeparator();
2832 				parseColonBlock();
2833 				break;
2834 
2835 			case Semicolon:
2836 				clearSeparator();
2837 				nextToken();
2838 				break;
2839 
2840 			case OpenBrace:
2841 				parseBlock(mode);
2842 				break;
2843 
2844 			case Identifier:
2845 				auto lookahead = trange.getLookahead();
2846 				lookahead.popFront();
2847 
2848 				auto t = lookahead.front.type;
2849 				if (t == Equal || t == OpenParen) {
2850 					split();
2851 					parseTypedDeclaration();
2852 					break;
2853 				}
2854 
2855 				goto default;
2856 
2857 			default:
2858 				split();
2859 				parseStructuralElement();
2860 				break;
2861 		}
2862 
2863 		return true;
2864 	}
2865 
2866 	bool parsePublic() {
2867 		if (!match(TokenType.Public)) {
2868 			return false;
2869 		}
2870 
2871 		auto lookahead = trange.getLookahead();
2872 		lookahead.popFront();
2873 
2874 		if (lookahead.front.type == TokenType.Import) {
2875 			nextToken();
2876 			space();
2877 			parseImport();
2878 		} else {
2879 			parseStorageClassDeclaration();
2880 		}
2881 
2882 		return true;
2883 	}
2884 
2885 	bool parseStatic() {
2886 		if (!match(TokenType.Static)) {
2887 			return false;
2888 		}
2889 
2890 		auto lookahead = trange.getLookahead();
2891 		lookahead.popFront();
2892 
2893 		auto t = lookahead.front.type;
2894 		switch (t) with (TokenType) {
2895 			case If:
2896 				nextToken();
2897 				space();
2898 				parseIf();
2899 				break;
2900 
2901 			case Foreach, ForeachReverse:
2902 				nextToken();
2903 				space();
2904 				parseForeach();
2905 				break;
2906 
2907 			case Assert:
2908 				nextToken();
2909 				space();
2910 				parseExpression();
2911 				break;
2912 
2913 			case Import:
2914 				nextToken();
2915 				space();
2916 				parseImport();
2917 				break;
2918 
2919 			default:
2920 				parseStorageClassDeclaration();
2921 				break;
2922 		}
2923 
2924 		return true;
2925 	}
2926 
2927 	bool parseEnum() {
2928 		if (!match(TokenType.Enum)) {
2929 			return false;
2930 		}
2931 
2932 		nextToken();
2933 		if (match(TokenType.Identifier)) {
2934 			space();
2935 			nextToken();
2936 		}
2937 
2938 		if (match(TokenType.Colon)) {
2939 			space();
2940 			nextToken();
2941 			space();
2942 			parseType();
2943 		}
2944 
2945 		if (match(TokenType.OpenBrace)) {
2946 			space();
2947 			nextToken();
2948 			parseList!parseEnumEntry(TokenType.CloseBrace, true);
2949 		}
2950 
2951 		return true;
2952 	}
2953 
2954 	void parseEnumEntry() {
2955 		if (parseAttributes()) {
2956 			newline(1);
2957 		}
2958 
2959 		parseExpression();
2960 	}
2961 
2962 	bool parseAlias() {
2963 		if (!match(TokenType.Alias)) {
2964 			return false;
2965 		}
2966 
2967 		nextToken();
2968 		space();
2969 
2970 		parseIdentifier();
2971 
2972 		if (match(TokenType.Identifier) || match(TokenType.This)) {
2973 			space();
2974 			nextToken();
2975 		}
2976 
2977 		return true;
2978 	}
2979 
2980 	void parseAliasEntry() {
2981 		// FIXME: This is wrong because identifier * identifier shouldn't be
2982 		// parsed as a declaration here, but provide the right entry point for the
2983 		// rest of the code.
2984 		parseType();
2985 		parseAssignExpressionSuffix();
2986 	}
2987 
2988 	bool parseAliasList() {
2989 		if (!match(TokenType.OpenParen)) {
2990 			return false;
2991 		}
2992 
2993 		nextToken();
2994 		parseList!parseAliasEntry(TokenType.CloseParen);
2995 		return true;
2996 	}
2997 
2998 	void parseAggregate() in {
2999 		assert(match(TokenType.Struct) || match(TokenType.Union)
3000 			|| match(TokenType.Class) || match(TokenType.Interface));
3001 	} do {
3002 		nextToken();
3003 		space();
3004 
3005 		runOnType!(TokenType.Identifier, nextToken)();
3006 
3007 		parseParameterList();
3008 
3009 		while (true) {
3010 			space();
3011 
3012 			switch (token.type) with (TokenType) {
3013 				case Colon:
3014 					parseColonList!parseIdentifier();
3015 					break;
3016 
3017 				case If: {
3018 					auto guard = span!IndentSpan(2);
3019 					parseConstraint();
3020 					break;
3021 				}
3022 
3023 				default:
3024 					parseBlock(Mode.Declaration);
3025 					return;
3026 			}
3027 		}
3028 	}
3029 
3030 	/**
3031 	 * Parsing utilities
3032 	 */
3033 	void parseListAdapter(alias fun)(size_t i) {
3034 		fun();
3035 	}
3036 
3037 	void parseList(alias fun, S = CompactListSpan)(TokenType closingTokenType,
3038 	                                               bool addNewLines = false) {
3039 		if (match(closingTokenType)) {
3040 			auto guard = builder.virtualSpan();
3041 			nextToken();
3042 			return;
3043 		}
3044 
3045 		static if (is(typeof(fun(0)))) {
3046 			alias afun = fun;
3047 		} else {
3048 			alias afun = parseListAdapter!fun;
3049 		}
3050 
3051 		auto guard = span!S();
3052 
3053 		size_t i = 0;
3054 		while (!match(closingTokenType)) {
3055 			if (addNewLines) {
3056 				newline(1);
3057 			}
3058 
3059 			split();
3060 			guard.registerFix(function(S s, size_t i) {
3061 				s.registerElement(i);
3062 			});
3063 
3064 			afun(i++);
3065 
3066 			if (!match(TokenType.Comma)) {
3067 				break;
3068 			}
3069 
3070 			nextToken();
3071 			space();
3072 		}
3073 
3074 		if (match(closingTokenType)) {
3075 			if (addNewLines) {
3076 				newline(1);
3077 			}
3078 
3079 			split();
3080 			guard.registerFix(function(S s, size_t i) {
3081 				s.registerTrailingSplit(i);
3082 			});
3083 
3084 			nextToken();
3085 		}
3086 
3087 		if (addNewLines) {
3088 			newline(2);
3089 		}
3090 	}
3091 
3092 	bool parseColonList(alias fun)() {
3093 		if (!match(TokenType.Colon)) {
3094 			return false;
3095 		}
3096 
3097 		auto colonGuard = spliceSpan();
3098 		space();
3099 		split();
3100 		nextToken();
3101 
3102 		auto listGuard = span!CompactListSpan();
3103 		bool first = true;
3104 		while (true) {
3105 			space();
3106 			split(first);
3107 			first = false;
3108 
3109 			listGuard.registerFix(function(CompactListSpan s, size_t i) {
3110 				s.registerElement(i);
3111 			});
3112 
3113 			fun();
3114 
3115 			if (!match(TokenType.Comma)) {
3116 				break;
3117 			}
3118 
3119 			nextToken();
3120 		}
3121 
3122 		return true;
3123 	}
3124 }