1 module d.parser.expression;
2 
3 import d.ast.expression;
4 import d.ast.identifier;
5 
6 import d.ir.expression;
7 
8 import d.parser.ambiguous;
9 import d.parser.base;
10 import d.parser.identifier;
11 import d.parser.statement;
12 import d.parser.type;
13 import source.parserutil;
14 
15 /**
16  * Parse Expression
17  */
18 AstExpression parseExpression(ParseMode mode = ParseMode.Greedy)(ref TokenRange trange) {
19 	auto lhs = trange.parsePrefixExpression!mode();
20 	return trange.parseAstBinaryExpression!(
21 		TokenType.Comma,
22 		AstBinaryOp.Comma,
23 		function AstExpression(ref TokenRange trange, AstExpression e) {
24 			return trange.parseAssignExpression(e);
25 		}
26 	)(lhs);
27 }
28 
29 /**
30  * Template used to parse basic AstBinaryExpressions.
31  */
32 private AstExpression parseAstBinaryExpression(
33 	TokenType tokenType,
34 	AstBinaryOp op,
35 	alias parseNext,
36 	R,
37 )(ref R trange, AstExpression lhs) {
38 	lhs = parseNext(trange, lhs);
39 	Location location = lhs.location;
40 	
41 	while (trange.front.type == tokenType) {
42 		trange.popFront();
43 		
44 		auto rhs = trange.parsePrefixExpression();
45 		rhs = parseNext(trange, rhs);
46 		
47 		location.spanTo(rhs.location);
48 		lhs = new AstBinaryExpression(location, op, lhs, rhs);
49 	}
50 	
51 	return lhs;
52 }
53 
54 /**
55  * Parse assignement expressions.
56  */
57 AstExpression parseAssignExpression(ref TokenRange trange) {
58 	return trange.parseAssignExpression(trange.parsePrefixExpression());
59 }
60 
61 AstExpression parseAssignExpression(ref TokenRange trange, AstExpression lhs) {
62 	lhs = trange.parseTernaryExpression(lhs);
63 	Location location = lhs.location;
64 	
65 	void processToken(AstBinaryOp op) {
66 		trange.popFront();
67 		
68 		auto rhs = trange.parsePrefixExpression();
69 		rhs = trange.parseAssignExpression(rhs);
70 		
71 		location.spanTo(rhs.location);
72 		
73 		lhs = new AstBinaryExpression(location, op, lhs, rhs);
74 	}
75 	
76 	switch (trange.front.type) with(AstBinaryOp) with(TokenType) {
77 		case Equal:
78 			processToken(Assign);
79 			break;
80 		
81 		case PlusEqual:
82 			processToken(AddAssign);
83 			break;
84 		
85 		case MinusEqual:
86 			processToken(SubAssign);
87 			break;
88 		
89 		case StarEqual:
90 			processToken(MulAssign);
91 			break;
92 		
93 		case SlashEqual:
94 			processToken(DivAssign);
95 			break;
96 		
97 		case PercentEqual:
98 			processToken(RemAssign);
99 			break;
100 		
101 		case AmpersandEqual:
102 			processToken(AndAssign);
103 			break;
104 		
105 		case PipeEqual:
106 			processToken(OrAssign);
107 			break;
108 		
109 		case CaretEqual:
110 			processToken(XorAssign);
111 			break;
112 		
113 		case TildeEqual:
114 			processToken(ConcatAssign);
115 			break;
116 		
117 		case LessLessEqual:
118 			processToken(LeftShiftAssign);
119 			break;
120 		
121 		case MoreMoreEqual:
122 			processToken(SignedRightShiftAssign);
123 			break;
124 		
125 		case MoreMoreMoreEqual:
126 			processToken(UnsignedRightShiftAssign);
127 			break;
128 		
129 		case CaretCaretEqual:
130 			processToken(PowAssign);
131 			break;
132 		
133 		default:
134 			// No assignement.
135 			break;
136 	}
137 	
138 	return lhs;
139 }
140 
141 /**
142  * Parse ?:
143  */
144 // FIXME: Should be private, but dmd don't like that.
145 AstExpression parseTernaryExpression(ref TokenRange trange) {
146 	return trange.parseTernaryExpression(trange.parsePrefixExpression());
147 }
148 
149 AstExpression parseTernaryExpression(ref TokenRange trange, AstExpression condition) {
150 	condition = trange.parseLogicalOrExpression(condition);
151 	
152 	if (trange.front.type == TokenType.QuestionMark) {
153 		Location location = condition.location;
154 		
155 		trange.popFront();
156 		auto ifTrue = trange.parseExpression();
157 		
158 		trange.match(TokenType.Colon);
159 		auto ifFalse = trange.parseTernaryExpression();
160 		
161 		location.spanTo(ifFalse.location);
162 		return new AstTernaryExpression(location, condition, ifTrue, ifFalse);
163 	}
164 	
165 	return condition;
166 }
167 
168 /**
169  * Parse ||
170  */
171 // FIXME: Should be private, but dmd don't like that.
172 AstExpression parseLogicalOrExpression(ref TokenRange trange) {
173 	return trange.parseLogicalOrExpression(trange.parsePrefixExpression());
174 }
175 
176 auto parseLogicalOrExpression(ref TokenRange trange, AstExpression lhs) {
177 	return trange.parseAstBinaryExpression!(
178 		TokenType.PipePipe,
179 		AstBinaryOp.LogicalOr,
180 		function AstExpression(ref TokenRange trange, AstExpression e) {
181 			return trange.parseLogicalAndExpression(e);
182 		}
183 	)(lhs);
184 }
185 
186 /**
187  * Parse &&
188  */
189 // FIXME: Should be private, but dmd don't like that.
190 AstExpression parseLogicalAndExpression(ref TokenRange trange) {
191 	return trange.parseLogicalAndExpression(trange.parsePrefixExpression());
192 }
193 
194 auto parseLogicalAndExpression(ref TokenRange trange, AstExpression lhs) {
195 	return trange.parseAstBinaryExpression!(
196 		TokenType.AmpersandAmpersand,
197 		AstBinaryOp.LogicalAnd,
198 		function AstExpression(ref TokenRange trange, AstExpression e) {
199 			return trange.parseBitwiseOrExpression(e);
200 		}
201 	)(lhs);
202 }
203 
204 /**
205  * Parse |
206  */
207 // FIXME: Should be private, but dmd don't like that.
208 AstExpression parseBitwiseOrExpression(ref TokenRange trange) {
209 	return trange.parseBitwiseOrExpression(trange.parsePrefixExpression());
210 }
211 
212 auto parseBitwiseOrExpression(ref TokenRange trange, AstExpression lhs) {
213 	return trange.parseAstBinaryExpression!(
214 		TokenType.Pipe,
215 		AstBinaryOp.Or,
216 		function AstExpression(ref TokenRange trange, AstExpression e) {
217 			return trange.parseBitwiseXorExpression(e);
218 		}
219 	)(lhs);
220 }
221 
222 /**
223  * Parse ^
224  */
225 // FIXME: Should be private, but dmd don't like that.
226 AstExpression parseBitwiseXorExpression(ref TokenRange trange) {
227 	return trange.parseBitwiseXorExpression(trange.parsePrefixExpression());
228 }
229 
230 auto parseBitwiseXorExpression(ref TokenRange trange, AstExpression lhs) {
231 	return trange.parseAstBinaryExpression!(
232 		TokenType.Caret,
233 		AstBinaryOp.Xor,
234 		function AstExpression(ref TokenRange trange, AstExpression e) {
235 			return trange.parseBitwiseAndExpression(e);
236 		}
237 	)(lhs);
238 }
239 
240 /**
241  * Parse &
242  */
243 // FIXME: Should be private, but dmd don't like that.
244 AstExpression parseBitwiseAndExpression(ref TokenRange trange) {
245 	return trange.parseBitwiseAndExpression(trange.parsePrefixExpression());
246 }
247 
248 auto parseBitwiseAndExpression(ref TokenRange trange, AstExpression lhs) {
249 	return trange.parseAstBinaryExpression!(
250 		TokenType.Ampersand,
251 		AstBinaryOp.And,
252 		function AstExpression(ref TokenRange trange, AstExpression e) {
253 			return trange.parseComparaisonExpression(e);
254 		}
255 	)(lhs);
256 }
257 
258 /**
259  * Parse ==, != and comparaisons
260  */
261 // FIXME: Should be private, but dmd don't like that.
262 AstExpression parseComparaisonExpression(ref TokenRange trange) {
263 	return trange.parseComparaisonExpression(trange.parsePrefixExpression());
264 }
265 
266 AstExpression parseComparaisonExpression(ref TokenRange trange, AstExpression lhs) {
267 	lhs = trange.parseShiftExpression(lhs);
268 	Location location = lhs.location;
269 	
270 	void processToken(AstBinaryOp op) {
271 		trange.popFront();
272 		
273 		auto rhs = trange.parseShiftExpression();
274 		
275 		location.spanTo(rhs.location);
276 		lhs = new AstBinaryExpression(location, op, lhs, rhs);
277 	}
278 	
279 	switch(trange.front.type) with(TokenType) {
280 		case EqualEqual :
281 			processToken(AstBinaryOp.Equal);
282 			break;
283 		
284 		case BangEqual :
285 			processToken(AstBinaryOp.NotEqual);
286 			break;
287 		
288 		case More:
289 			processToken(AstBinaryOp.Greater);
290 			break;
291 		
292 		case MoreEqual:
293 			processToken(AstBinaryOp.GreaterEqual);
294 			break;
295 		
296 		case Less :
297 			processToken(AstBinaryOp.Less);
298 			break;
299 		
300 		case LessEqual :
301 			processToken(AstBinaryOp.LessEqual);
302 			break;
303 		
304 		case BangLessMoreEqual:
305 			processToken(AstBinaryOp.Unordered);
306 			break;
307 		
308 		case BangLessMore:
309 			processToken(AstBinaryOp.UnorderedEqual);
310 			break;
311 		
312 		case LessMore:
313 			processToken(AstBinaryOp.LessGreater);
314 			break;
315 		
316 		case LessMoreEqual:
317 			processToken(AstBinaryOp.LessEqualGreater);
318 			break;
319 		
320 		case BangMore:
321 			processToken(AstBinaryOp.UnorderedLessEqual);
322 			break;
323 		
324 		case BangMoreEqual:
325 			processToken(AstBinaryOp.UnorderedLess);
326 			break;
327 		
328 		case BangLess:
329 			processToken(AstBinaryOp.UnorderedGreaterEqual);
330 			break;
331 		
332 		case BangLessEqual:
333 			processToken(AstBinaryOp.UnorderedGreater);
334 			break;
335 		
336 		case Is:
337 			processToken(AstBinaryOp.Identical);
338 			break;
339 		
340 		case In:
341 			processToken(AstBinaryOp.In);
342 			break;
343 		
344 		case Bang:
345 			trange.popFront();
346 			switch(trange.front.type) {
347 				case Is:
348 					processToken(AstBinaryOp.NotIdentical);
349 					break;
350 				
351 				case In:
352 					processToken(AstBinaryOp.NotIn);
353 					break;
354 				
355 				default:
356 					trange.match(TokenType.Begin);
357 					break;
358 			}
359 			
360 			break;
361 		
362 		default:
363 			// We have no comparaison, so we just return.
364 			break;
365 	}
366 	
367 	return lhs;
368 }
369 
370 /**
371  * Parse <<, >> and >>>
372  */
373 // FIXME: Should be private, but dmd don't like that.
374 AstExpression parseShiftExpression(ref TokenRange trange) {
375 	return trange.parseShiftExpression(trange.parsePrefixExpression());
376 }
377 
378 AstExpression parseShiftExpression(ref TokenRange trange, AstExpression lhs) {
379 	lhs = trange.parseAddExpression(lhs);
380 	Location location = lhs.location;
381 	
382 	while(1) {
383 		void processToken(AstBinaryOp op) {
384 			trange.popFront();
385 			
386 			auto rhs = trange.parseAddExpression();
387 			
388 			location.spanTo(rhs.location);
389 			lhs = new AstBinaryExpression(location, op, lhs, rhs);
390 		}
391 		
392 		switch (trange.front.type) with(AstBinaryOp) with(TokenType) {
393 			case LessLess:
394 				processToken(LeftShift);
395 				break;
396 			
397 			case MoreMore:
398 				processToken(SignedRightShift);
399 				break;
400 			
401 			case MoreMoreMore:
402 				processToken(UnsignedRightShift);
403 				break;
404 			
405 			default :
406 				return lhs;
407 		}
408 	}
409 }
410 
411 /**
412  * Parse +, - and ~
413  */
414 // FIXME: Should be private, but dmd don't like that.
415 AstExpression parseAddExpression(ref TokenRange trange) {
416 	return trange.parseAddExpression(trange.parsePrefixExpression());
417 }
418 
419 AstExpression parseAddExpression(ref TokenRange trange, AstExpression lhs) {
420 	lhs = trange.parseMulExpression(lhs);
421 	Location location = lhs.location;
422 	
423 	while(1) {
424 		void processToken(AstBinaryOp op) {
425 			trange.popFront();
426 			
427 			auto rhs = trange.parseMulExpression();
428 			
429 			location.spanTo(rhs.location);
430 			lhs = new AstBinaryExpression(location, op, lhs, rhs);
431 		}
432 		
433 		switch (trange.front.type) with(AstBinaryOp) with(TokenType) {
434 			case Plus:
435 				processToken(Add);
436 				break;
437 			
438 			case Minus:
439 				processToken(Sub);
440 				break;
441 			
442 			case Tilde:
443 				processToken(Concat);
444 				break;
445 			
446 			default :
447 				return lhs;
448 		}
449 	}
450 }
451 
452 /**
453  * Parse *, / and %
454  */
455 // FIXME: Should be private, but dmd don't like that.
456 AstExpression parseMulExpression(ref TokenRange trange) {
457 	return trange.parseMulExpression(trange.parsePrefixExpression());
458 }
459 
460 AstExpression parseMulExpression(ref TokenRange trange, AstExpression lhs) {
461 	Location location = lhs.location;
462 	
463 	while(1) {
464 		void processToken(AstBinaryOp op) {
465 			trange.popFront();
466 			
467 			auto rhs = trange.parsePrefixExpression();
468 			
469 			location.spanTo(rhs.location);
470 			lhs = new AstBinaryExpression(location, op, lhs, rhs);
471 		}
472 		
473 		switch (trange.front.type) with(AstBinaryOp) with(TokenType) {
474 			case Star:
475 				processToken(Mul);
476 				break;
477 			
478 			case Slash:
479 				processToken(Div);
480 				break;
481 			
482 			case Percent:
483 				processToken(Rem);
484 				break;
485 			
486 			default :
487 				return lhs;
488 		}
489 	}
490 }
491 
492 /**
493  * Unary prefixes
494  */
495 private AstExpression parsePrefixExpression(
496 	ParseMode mode = ParseMode.Greedy,
497 )(ref TokenRange trange) {
498 	AstExpression result;
499 	
500 	void processToken(UnaryOp op) {
501 		Location location = trange.front.location;
502 		trange.popFront();
503 		
504 		// Drop mode on purpose.
505 		result = trange.parsePrefixExpression();
506 		
507 		location.spanTo(result.location);
508 		result = new AstUnaryExpression(location, op, result);
509 	}
510 	
511 	switch (trange.front.type) with(TokenType) {
512 		case Ampersand:
513 			processToken(UnaryOp.AddressOf);
514 			break;
515 		
516 		case PlusPlus:
517 			processToken(UnaryOp.PreInc);
518 			break;
519 		
520 		case MinusMinus:
521 			processToken(UnaryOp.PreDec);
522 			break;
523 		
524 		case Star:
525 			processToken(UnaryOp.Dereference);
526 			break;
527 		
528 		case Plus:
529 			processToken(UnaryOp.Plus);
530 			break;
531 		
532 		case Minus:
533 			processToken(UnaryOp.Minus);
534 			break;
535 		
536 		case Bang:
537 			processToken(UnaryOp.Not);
538 			break;
539 		
540 		case Tilde:
541 			processToken(UnaryOp.Complement);
542 			break;
543 		
544 		// TODO: parse qualifier casts.
545 		case Cast:
546 			Location location = trange.front.location;
547 			trange.popFront();
548 			trange.match(OpenParen);
549 			
550 			switch (trange.front.type) {
551 				case CloseParen:
552 					assert(0, "cast() isn't supported.");
553 				
554 				default:
555 					auto type = trange.parseType();
556 					trange.match(CloseParen);
557 					
558 					result = trange.parsePrefixExpression();
559 					location.spanTo(result.location);
560 					
561 					result = new AstCastExpression(location, type, result);
562 			}
563 			
564 			break;
565 		
566 		default:
567 			result = trange.parsePrimaryExpression();
568 			result = trange.parsePostfixExpression!mode(result);
569 	}
570 	
571 	// Ensure we do not screwed up.
572 	assert(result);
573 	
574 	return trange.parsePowExpression(result);
575 }
576 
577 AstExpression parsePrimaryExpression(ref TokenRange trange) {
578 	Location location = trange.front.location;
579 	
580 	switch (trange.front.type) with(TokenType) {
581 		// Identified expressions
582 		case Identifier:
583 			return trange.parseIdentifierExpression(trange.parseIdentifier());
584 		
585 		case New:
586 			trange.popFront();
587 			auto type = trange.parseType();
588 			auto args = trange.parseArguments!OpenParen();
589 			
590 			location.spanTo(trange.front.location);
591 			return new AstNewExpression(location, type, args);
592 		
593 		case Dot:
594 			return trange.parseIdentifierExpression(trange.parseDotIdentifier());
595 		
596 		case This:
597 			trange.popFront();
598 			return new ThisExpression(location);
599 		
600 		case Super:
601 			trange.popFront();
602 			return new SuperExpression(location);
603 		
604 		case True:
605 			trange.popFront();
606 			return new BooleanLiteral(location, true);
607 		
608 		case False:
609 			trange.popFront();
610 			return new BooleanLiteral(location, false);
611 		
612 		case Null:
613 			trange.popFront();
614 			return new NullLiteral(location);
615 		
616 		case IntegerLiteral:
617 			return trange.parseIntegerLiteral();
618 		
619 		case StringLiteral:
620 			return trange.parseStringLiteral();
621 		
622 		case CharacterLiteral:
623 			return trange.parseCharacterLiteral();
624 		
625 		case OpenBracket:
626 			// FIXME: Support map literals.
627 			AstExpression[] values;
628 			trange.popFront();
629 			
630 			while (trange.front.type != CloseBracket) {
631 				values ~= trange.parseAssignExpression();
632 				if (trange.front.type != Comma) {
633 					break;
634 				}
635 				
636 				trange.popFront();
637 			}
638 			
639 			location.spanTo(trange.front.location);
640 			trange.match(CloseBracket);
641 			
642 			return new AstArrayLiteral(location, values);
643 		
644 		case OpenBrace:
645 			return new DelegateLiteral(trange.parseBlock());
646 		
647 		case Function, Delegate:
648 			assert(0, "Functions or Delegates not implemented ");
649 		
650 		case __File__:
651 			trange.popFront();
652 			return new __File__Literal(location);
653 		
654 		case __Line__:
655 			trange.popFront();
656 			return new __Line__Literal(location);
657 		
658 		case Dollar:
659 			trange.popFront();
660 			return new DollarExpression(location);
661 		
662 		case Typeid:
663 			trange.popFront();
664 			trange.match(OpenParen);
665 			
666 			return trange.parseAmbiguous!(delegate AstExpression(parsed) {
667 				location.spanTo(trange.front.location);
668 				trange.match(CloseParen);
669 				
670 				import d.ast.type;
671 				
672 				alias T = typeof(parsed);
673 				static if(is(T : AstType)) {
674 					return new AstStaticTypeidExpression(location, parsed);
675 				} else static if(is(T : AstExpression)) {
676 					return new AstTypeidExpression(location, parsed);
677 				} else {
678 					return new IdentifierTypeidExpression(location, parsed);
679 				}
680 			})();
681 		
682 		case Is:
683 			return trange.parseIsExpression();
684 		
685 		case Mixin:
686 			import d.parser.conditional;
687 			return trange.parseMixin!AstExpression();
688 		
689 		case OpenParen:
690 			auto matchingParen = trange.getLookahead();
691 			matchingParen.popMatchingDelimiter!OpenParen();
692 			
693 			switch (matchingParen.front.type) {
694 				case Dot:
695 					trange.popFront();
696 					return trange.parseAmbiguous!((parsed) {
697 						trange.match(CloseParen);
698 						trange.match(Dot);
699 						
700 						auto qi = trange.parseQualifiedIdentifier(
701 							location,
702 							parsed,
703 						);
704 						return trange.parseIdentifierExpression(qi);
705 					})();
706 				
707 				case OpenBrace:
708 					import d.parser.declaration;
709 					bool isVariadic;
710 					auto params = trange.parseParameters(isVariadic);
711 					
712 					auto block = trange.parseBlock();
713 					location.spanTo(block.location);
714 					
715 					return new DelegateLiteral(location, params, isVariadic, block);
716 				
717 				case EqualMore:
718 					import d.parser.declaration;
719 					bool isVariadic;
720 					auto params = trange.parseParameters(isVariadic);
721 					assert(!isVariadic, "Variadic lambda not supported");
722 					
723 					trange.match(EqualMore);
724 					
725 					auto value = trange.parseExpression();
726 					location.spanTo(value.location);
727 					
728 					return new Lambda(location, params, value);
729 				
730 				default:
731 					trange.popFront();
732 					auto expression = trange.parseExpression();
733 					
734 					location.spanTo(trange.front.location);
735 					trange.match(CloseParen);
736 					
737 					return new ParenExpression(location, expression);
738 			}
739 		
740 		default:
741 			// Our last resort are type.identifier expressions.
742 			auto type = trange.parseType!(ParseMode.Reluctant)();
743 			switch (trange.front.type) {
744 				case Dot:
745 					trange.popFront();
746 					return trange.parseIdentifierExpression(
747 						trange.parseQualifiedIdentifier(location, type),
748 					);
749 				
750 				case OpenParen:
751 					auto args = trange.parseArguments!OpenParen();
752 					location.spanTo(trange.previous);
753 					return new TypeCallExpression(location, type, args);
754 				
755 				default:
756 					break;
757 			}
758 			
759 			// TODO: error message that make sense.
760 			trange.match(Begin);
761 			assert(0, "Implement proper error handling :)");
762 	}
763 }
764 
765 /**
766  * Parse postfix ++, --, (...), [...], .identifier
767  */
768 AstExpression parsePostfixExpression(ParseMode mode)(ref TokenRange trange, AstExpression e) {
769 	Location location = e.location;
770 	
771 	while (true) {
772 		switch (trange.front.type) with(TokenType) {
773 			case PlusPlus:
774 				location.spanTo(trange.front.location);
775 				trange.popFront();
776 				
777 				e = new AstUnaryExpression(location, UnaryOp.PostInc, e);
778 				break;
779 			
780 			case MinusMinus:
781 				location.spanTo(trange.front.location);
782 				trange.popFront();
783 				
784 				e = new AstUnaryExpression(location, UnaryOp.PostDec, e);
785 				break;
786 			
787 			case OpenParen:
788 				auto args = trange.parseArguments!OpenParen();
789 				
790 				location.spanTo(trange.previous);
791 				e = new AstCallExpression(location, e, args);
792 				
793 				break;
794 			
795 			// TODO: Indices, Slices.
796 			case OpenBracket:
797 				trange.popFront();
798 				
799 				if (trange.front.type == CloseBracket) {
800 					// We have a slicing operation here.
801 					assert(0, "Slice expressions can not be parsed yet");
802 				} else {
803 					auto args = trange.parseArguments();
804 					switch(trange.front.type) {
805 						case CloseBracket:
806 							location.spanTo(trange.front.location);
807 							e = new AstIndexExpression(location, e, args);
808 							
809 							break;
810 						
811 						case DotDot:
812 							trange.popFront();
813 							auto second = trange.parseArguments();
814 							
815 							location.spanTo(trange.front.location);
816 							e = new AstSliceExpression(location, e, args, second);
817 							
818 							break;
819 						
820 						default:
821 							// TODO: error message that make sense.
822 							trange.match(Begin);
823 							break;
824 					}
825 				}
826 				
827 				trange.match(CloseBracket);
828 				break;
829 			
830 			static if (mode == ParseMode.Greedy) {
831 			case Dot:
832 				trange.popFront();
833 				
834 				e = trange.parseIdentifierExpression(
835 					trange.parseQualifiedIdentifier(location, e),
836 				);
837 				
838 				break;
839 			}
840 			
841 			default :
842 				return e;
843 		}
844 	}
845 }
846 
847 /**
848  * Parse ^^
849  */
850 private
851 AstExpression parsePowExpression(ref TokenRange trange, AstExpression expr) {
852 	Location location = expr.location;
853 	
854 	while (trange.front.type == TokenType.CaretCaret) {
855 		trange.popFront();
856 		AstExpression power = trange.parsePrefixExpression();
857 		location.spanTo(power.location);
858 		expr = new AstBinaryExpression(location, AstBinaryOp.Pow, expr, power);
859 	}
860 	
861 	return expr;
862 }
863 
864 /**
865  * Parse unary is expression.
866  */
867 private auto parseIsExpression(ref TokenRange trange) {
868 	Location location = trange.front.location;
869 	trange.match(TokenType.Is);
870 	trange.match(TokenType.OpenParen);
871 	
872 	auto type = trange.parseType();
873 	
874 	// Handle alias throw is expression.
875 	if (trange.front.type == TokenType.Identifier) {
876 		trange.popFront();
877 	}
878 	
879 	switch (trange.front.type) with(TokenType) {
880 		case Colon:
881 			trange.popFront();
882 			trange.parseType();
883 			break;
884 		
885 		case EqualEqual:
886 			trange.popFront();
887 			
888 			switch(trange.front.type) {
889 				case Struct, Union, Class, Interface, Enum, Function, Delegate:
890 				case Super, Const, Immutable, Inout, Shared, Return:
891 					assert(0, "Not implemented.");
892 				
893 				default:
894 					trange.parseType();
895 			}
896 			
897 			break;
898 		
899 		default :
900 			break;
901 	}
902 	
903 	location.spanTo(trange.front.location);
904 	trange.match(TokenType.CloseParen);
905 	
906 	return new IsExpression(location, type);
907 }
908 
909 /**
910  * Parse identifier expression
911  */
912 AstExpression parseIdentifierExpression(ref TokenRange trange, Identifier i) {
913 	if (trange.front.type != TokenType.OpenParen) {
914 		return new IdentifierExpression(i);
915 	}
916 	
917 	auto args = trange.parseArguments!(TokenType.OpenParen)();
918 	
919 	auto location = i.location;
920 	location.spanTo(trange.previous);
921 	return new IdentifierCallExpression(location, i, args);
922 }
923 
924 /**
925  * Parse function arguments
926  */
927 AstExpression[] parseArguments(TokenType openTokenType)(ref TokenRange trange) {
928 	alias closeTokenType = MatchingDelimiter!openTokenType;
929 	
930 	trange.match(openTokenType);
931 	
932 	AstExpression[] args;
933 	while (trange.front.type != closeTokenType) {
934 		args ~= trange.parseAssignExpression();
935 		if (trange.front.type != TokenType.Comma) {
936 			break;
937 		}
938 		
939 		trange.popFront();
940 	}
941 	
942 	trange.match(closeTokenType);
943 	return args;
944 }
945 
946 AstExpression[] parseArguments(ref TokenRange trange) {
947 	AstExpression[] args = [trange.parseAssignExpression()];
948 	while(trange.front.type == TokenType.Comma) {
949 		trange.popFront();
950 		
951 		args ~= trange.parseAssignExpression();
952 	}
953 	
954 	return args;
955 }
956 
957 /**
958  * Parse integer literals
959  */
960 IntegerLiteral parseIntegerLiteral(ref TokenRange trange) {
961 	Location location = trange.front.location;
962 	
963 	// Consider computing the value in the lexer and make it a Name.
964 	// This would avoid the duplication with code here and probably
965 	// would be faster as well.
966 	auto strVal = trange.front.toString(trange.context);
967 	assert(strVal.length > 0);
968 	
969 	trange.match(TokenType.IntegerLiteral);
970 	
971 	bool isUnsigned, isLong;
972 	if (strVal.length > 1) {
973 		switch (strVal[$ - 1]) {
974 			case 'u', 'U':
975 				isUnsigned = true;
976 				
977 				auto penultimo = strVal[$ - 2];
978 				if (penultimo == 'l' || penultimo == 'L') {
979 					isLong = true;
980 					strVal = strVal[0 .. $ - 2];
981 				} else {
982 					strVal = strVal[0 .. $ - 1];
983 				}
984 				
985 				break;
986 			
987 			case 'l', 'L':
988 				isLong = true;
989 				
990 				auto penultimo = strVal[$ - 2];
991 				if (penultimo == 'u' || penultimo == 'U') {
992 					isUnsigned = true;
993 					strVal = strVal[0 .. $ - 2];
994 				} else {
995 					strVal = strVal[0 .. $ - 1];
996 				}
997 				
998 				break;
999 			
1000 			default:
1001 				break;
1002 		}
1003 	}
1004 	
1005 	import source.strtoint;
1006 	ulong value = strToInt(strVal);
1007 	
1008 	import d.common.builtintype;
1009 	auto type = isUnsigned
1010 		? ((isLong || value > uint.max) ? BuiltinType.Ulong : BuiltinType.Uint)
1011 		: ((isLong || value > int.max) ? BuiltinType.Long : BuiltinType.Int);
1012 	
1013 	return new IntegerLiteral(location, value, type);
1014 }
1015 
1016 /**
1017  * Parse character literals
1018  */
1019 CharacterLiteral parseCharacterLiteral(ref TokenRange trange) {
1020 	Location location = trange.front.location;
1021 	auto str = trange.front.name.toString(trange.context);
1022 	
1023 	trange.match(TokenType.CharacterLiteral);
1024 	
1025 	size_t i = 0;
1026 	
1027 	import std.utf;
1028 	dchar c = str.decode(i);
1029 	
1030 	if (i != str.length) {
1031 		import source.exception;
1032 		throw new CompileException(location, "Invalid character literal");
1033 	}
1034 	
1035 	import d.common.builtintype : BuiltinType;
1036 	return new CharacterLiteral(location, c, BuiltinType.Char);
1037 }
1038 
1039 /**
1040  * Parse string literals
1041  */
1042 StringLiteral parseStringLiteral(ref TokenRange trange) {
1043 	Location location = trange.front.location;
1044 	auto name = trange.front.name;
1045 	
1046 	trange.match(TokenType.StringLiteral);
1047 	
1048 	return new StringLiteral(location, name.toString(trange.context));
1049 }