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