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