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 }