1 module dpp.translation.tokens;
2 
3 
4 import dpp.from;
5 
6 
7 string translateTokens(in from!"clang".Token[] tokens) @safe {
8     import dpp.translation.type: translateString;
9     import dpp.runtime.context: Context;
10     import clang: Token;
11     import std.algorithm: map, filter, canFind, endsWith;
12     import std.array: array, join, replace;
13 
14     const translatedPropertyTokens = tokens
15         .translateProperty("sizeof")
16         .translateProperty("alignof")
17         ;
18 
19     // we can't rely on `translateString` for angle brackets here since it
20     // checks if there are matching pairs in the string to translate.
21     // Since we have an array of tokens, the matching pair might be in a different position
22 
23     const canFindOpeningAngle = translatedPropertyTokens
24         .canFind!(t => t.kind == Token.Kind.Punctuation && t.spelling == "<");
25     const canFindClosingAngle = translatedPropertyTokens
26         .canFind!(t => t.kind == Token.Kind.Punctuation && (t.spelling == ">" || t.spelling == ">>"));
27 
28     const translatedAngleBracketTokens = canFindOpeningAngle && canFindClosingAngle
29         ? translatedPropertyTokens
30             .map!(t => Token(t.kind, t.spelling.replace("<", "!(").replace(">>", "))").replace(">", ")")))
31             .array
32         : translatedPropertyTokens;
33 
34     auto ret = translatedAngleBracketTokens
35         .filter!(t => t.kind != Token.Kind.Keyword || t.spelling != "typename")
36         .map!(t => translateString(t.spelling, Context()))
37         .join;
38 
39     // this can happen because of ending with ">>"
40     if(ret.endsWith("))")) ret = ret[0 .. $-1];
41 
42     return ret;
43 }
44 
45 
46 // sizeof(foo) -> foo.sizeof, alignof(foo) -> foo.alignof
47 private auto translateProperty(const(from!"clang".Token)[] tokens, in string property) @safe {
48     import dpp.translation.type: translateString;
49     import dpp.runtime.context: Context;
50     import clang: Token;
51     import std.algorithm: countUntil, map;
52     import std.array: join, replace;
53 
54     for(;;) {
55         const indexProperty = tokens.countUntil!(a => a.kind == Token.Kind.Keyword && a.spelling == property);
56         if(indexProperty == -1) return tokens;
57         const indexCloseParen = indexProperty + tokens[indexProperty..$].countUntil!(a => a.kind == Token.Kind.Punctuation && a.spelling == ")");
58         const newTokenSpelling =
59             "(" ~ tokens[indexProperty + 2 .. indexCloseParen]
60             .map!(a => a.spelling)
61             .join(" ")
62             ~ ")." ~ property
63             ;
64 
65         tokens =
66             tokens[0 .. indexProperty] ~
67             Token(Token.Kind.Literal, translateString(newTokenSpelling, Context())) ~
68             tokens[indexCloseParen + 1 .. $];
69     }
70 }