1 module source.parserutil;
2 
3 import source.dlexer;
4 
5 void match(Lexer, TokenType)(ref Lexer lexer, TokenType type) {
6 	auto token = lexer.front;
7 	
8 	if (token.type == type) {
9 		lexer.popFront();
10 		return;
11 	}
12 	
13 	import std.conv, std.string;
14 	auto error = token.type == TokenType.Invalid
15 		? token.name.toString(lexer.context)
16 		: format!"expected '%s', got '%s'."(to!string(type), to!string(token.type));
17 	
18 	import source.exception;
19 	throw new CompileException(token.location, error);
20 }
21 
22 /**
23  * Get the matching delimiter
24  */
25 template MatchingDelimiter(TokenType openTokenType) {
26 	static if (openTokenType == TokenType.OpenParen) {
27 		alias MatchingDelimiter = TokenType.CloseParen;
28 	} else static if (openTokenType == TokenType.OpenBrace) {
29 		alias MatchingDelimiter = TokenType.CloseBrace;
30 	} else static if (openTokenType == TokenType.OpenBracket) {
31 		alias MatchingDelimiter = TokenType.CloseBracket;
32 	} else static if (openTokenType == TokenType.Less) {
33 		alias MatchingDelimiter = TokenType.Greater;
34 	} else {
35 		import std.conv;
36 		static assert(0, to!string(openTokenType) ~ " isn't a token that goes by pair. Use (, {, [, <");
37 	}
38 }
39 
40 /**
41  * Pop a range of token until we pop the matchin delimiter.
42  * matchin tokens are (), [], <> and {}
43  */
44 void popMatchingDelimiter(TokenType openTokenType)(ref TokenRange trange) {
45 	auto startLocation = trange.front.location;
46 	alias closeTokenType = MatchingDelimiter!openTokenType;
47 	
48 	assert(trange.front.type == openTokenType);
49 	uint level = 1;
50 	
51 	while(level > 0) {
52 		trange.popFront();
53 		
54 		switch(trange.front.type) {
55 			case openTokenType :
56 				level++;
57 				break;
58 			
59 			case closeTokenType :
60 				level--;
61 				break;
62 			
63 			case TokenType.End :
64 				import source.exception;
65 				throw new CompileException(startLocation, "Matching delimiter not found");
66 			
67 			default :
68 				break;
69 		}
70 	}
71 	
72 	assert(trange.front.type == closeTokenType);
73 	trange.popFront();
74 }