1 module d.parser.identifier; 2 3 import d.ast.identifier; 4 import d.ast.expression; 5 import d.ast.type; 6 7 import d.parser.base; 8 import d.parser.dtemplate; 9 10 /** 11 * Parse Identifier 12 */ 13 Identifier parseIdentifier(ref TokenRange trange) { 14 auto location = trange.front.location; 15 16 auto name = trange.front.name; 17 trange.match(TokenType.Identifier); 18 19 return trange.parseBuiltIdentifier(new BasicIdentifier(location, name)); 20 } 21 22 /** 23 * Parse dotted identifier (.identifier) 24 */ 25 Identifier parseDotIdentifier(ref TokenRange trange) { 26 auto location = trange.front.location; 27 trange.match(TokenType.Dot); 28 29 location.spanTo(trange.front.location); 30 31 auto name = trange.front.name; 32 trange.match(TokenType.Identifier); 33 34 return trange.parseBuiltIdentifier(new DotIdentifier(location, name)); 35 } 36 37 /** 38 * Parse any qualifier identifier (qualifier.identifier) 39 */ 40 auto parseQualifiedIdentifier(Namespace)( 41 ref TokenRange trange, 42 Location location, 43 Namespace ns, 44 ) { 45 auto name = trange.front.name; 46 location.spanTo(trange.front.location); 47 trange.match(TokenType.Identifier); 48 49 static if (is(Namespace : Identifier)) { 50 alias QualifiedIdentifier = IdentifierDotIdentifier; 51 } else static if (is(Namespace : AstType)) { 52 alias QualifiedIdentifier = TypeDotIdentifier; 53 } else static if (is(Namespace : AstExpression)) { 54 alias QualifiedIdentifier = ExpressionDotIdentifier; 55 } else { 56 static assert( 57 0, 58 "Namespace can only be an Identifier, a AstType or an Expression." 59 ~ " Not a " ~ Namespace.stringof 60 ); 61 } 62 63 return trange.parseBuiltIdentifier( 64 new QualifiedIdentifier(location, name, ns), 65 ); 66 } 67 68 /** 69 * Parse built identifier 70 */ 71 private Identifier parseBuiltIdentifier( 72 ref TokenRange trange, 73 Identifier identifier, 74 ) { 75 auto location = identifier.location; 76 while (true) { 77 switch (trange.front.type) with(TokenType) { 78 case Dot: 79 trange.popFront(); 80 auto name = trange.front.name; 81 82 location.spanTo(trange.front.location); 83 trange.match(Identifier); 84 85 identifier = new IdentifierDotIdentifier( 86 location, 87 name, 88 identifier, 89 ); 90 break; 91 92 case Bang: 93 auto lookahead = trange.getLookahead(); 94 lookahead.popFront(); 95 if (lookahead.front.type == Is || lookahead.front.type == In) { 96 return identifier; 97 } 98 99 trange.popFront(); 100 auto arguments = parseTemplateArguments(trange); 101 102 location.spanTo(trange.previous); 103 104 identifier = new TemplateInstantiation( 105 location, 106 identifier, 107 arguments, 108 ); 109 break; 110 111 default: 112 return identifier; 113 } 114 } 115 }