1 module IDL.idl_parse; 2 3 import std.array; 4 import std.range.primitives : popFrontN; 5 import std.array : appender; 6 import std.regex; 7 import std.stdio; 8 import std.conv; 9 import std.file; 10 import std.format; 11 import std.process; 12 13 import IDL.IdlSymbol; 14 import IDL.IdlParseStruct; 15 import IDL.IdlParseInterface; 16 import IDL.IdlBaseInterface; 17 import IDL.IdlFlatbufferCreateCode; 18 import IDL.IdlUnit; 19 20 import core.thread; 21 22 class idl_parse 23 { 24 this() 25 { 26 //idlDlangVariable["void"] = "void"; 27 idlDlangVariable["bool"] = "bool"; 28 idlDlangVariable["byte"] = "byte"; 29 idlDlangVariable["ubyte"] = "ubyte"; 30 idlDlangVariable["short"] = "short"; 31 idlDlangVariable["ushort"] = "ushort"; 32 idlDlangVariable["int"] = "int"; 33 idlDlangVariable["uint"] = "uint"; 34 idlDlangVariable["long"] = "long"; 35 idlDlangVariable["ulong"] = "ulong"; 36 idlDlangVariable["float"] = "float"; 37 idlDlangVariable["double"] = "double"; 38 idlDlangVariable["char"] = "char"; 39 idlDlangVariable["string"] = "string"; 40 } 41 42 void setParseFile(string path) 43 { 44 inFilePath = path; 45 } 46 47 void setOutputFile(string path) 48 { 49 outFilePath = path; 50 } 51 52 void setFileName(string name) 53 { 54 fileName = name; 55 } 56 57 void startParse() 58 { 59 auto file = File(inFilePath); 60 61 string text; 62 63 while(!file.eof) 64 { 65 text ~= file.readln(); 66 } 67 68 this.parse(text); 69 } 70 71 bool parse(string data) 72 { 73 data = replaceAll(data, regex(`\/\/[^\n]*`), ""); 74 data = replaceAll(data, regex("\n|\t"), ""); 75 data = replaceAll(data, regex(`\s{2,}`), ""); 76 77 auto clesses = split(data, regex(`[@\}]`)); 78 79 if(clesses.length == 0) 80 { 81 throw new Exception("parse classes is failed, no class struct!!", data); 82 } 83 84 foreach(c; clesses) 85 { 86 auto symbolFlag = split(c, "{"); 87 88 if(symbolFlag.length == 2) 89 { 90 91 auto symbolAttr = split(symbolFlag[0], ":"); 92 93 if(symbolAttr.length != 2) 94 { 95 throw new Exception("parse symbol attr is failed, symbol missing :, " ~ symbolFlag[0]); 96 } 97 98 IdlBaseInterface idlInterface; 99 100 switch(symbolAttr[0]) 101 { 102 case SYMBOL_STRUCT: 103 idlInterface = new IdlParseStruct; 104 break; 105 106 case SYMBOL_INTERFACE: 107 idlInterface = new IdlParseInterface; 108 break; 109 110 default: 111 throw new Exception("parse symbol attr is error, symbol: " ~ symbolAttr[0]); 112 } 113 114 if(idlInterface.parse(fileName, symbolAttr[1], symbolFlag[1])) 115 { 116 switch(symbolAttr[0]) 117 { 118 case SYMBOL_STRUCT: 119 idlStructList[idlInterface.getName] = cast(IdlParseStruct)idlInterface; 120 break; 121 122 case SYMBOL_INTERFACE: 123 idlInerfaceList[idlInterface.getName] = idlInterface; 124 break; 125 126 default: 127 throw new Exception("parse symbol attr is error, symbol: " ~ symbolAttr[0]); 128 } 129 } 130 } 131 } 132 133 this.create_code(); 134 return true; 135 } 136 137 138 void create_code() 139 { 140 string serverCodeInterface, serverCodeService; 141 string clientCodeInterface, clientCodeService; 142 string structCode; 143 string flatbufferIdlCode; 144 145 auto serverInterfaceStrings = appender!string(); 146 formattedWrite(serverInterfaceStrings, "module kissrpc.generated.%sInterface;\n\n", fileName); 147 formattedWrite(serverInterfaceStrings, "import kissrpc.generated.%sMessage;\n", fileName); 148 formattedWrite(serverInterfaceStrings, "import kissrpc.generated.%sService;\n\n", fileName); 149 150 151 152 formattedWrite(serverInterfaceStrings, "import kissrpc.RpcServer;\n"); 153 formattedWrite(serverInterfaceStrings, "import kissrpc.RpcServerImpl;\n"); 154 formattedWrite(serverInterfaceStrings, "import kissrpc.RpcResponse;\n"); 155 formattedWrite(serverInterfaceStrings, "import kissrpc.RpcRequest;\n"); 156 formattedWrite(serverInterfaceStrings, "import flatbuffers;\n"); 157 158 auto server_service_strings = appender!string(); 159 formattedWrite(server_service_strings, "module kissrpc.generated.%sService;\n\n", fileName); 160 formattedWrite(server_service_strings, "import kissrpc.generated.%sInterface;\n", fileName); 161 formattedWrite(server_service_strings, "import kissrpc.generated.%sMessage;\n\n", fileName); 162 formattedWrite(server_service_strings, "import kissrpc.RpcServer;\n"); 163 formattedWrite(server_service_strings, "import kissrpc.Unit;\n\n"); 164 165 auto client_interface_strings = appender!string(); 166 formattedWrite(client_interface_strings, "module kissrpc.generated.%sInterface;\n\n", fileName); 167 formattedWrite(client_interface_strings, "import kissrpc.generated.%sMessage;\n", fileName); 168 formattedWrite(client_interface_strings, "import kissrpc.generated.%sService;\n\n", fileName); 169 170 formattedWrite(client_interface_strings, "import kissrpc.RpcRequest;\n"); 171 formattedWrite(client_interface_strings, "import kissrpc.RpcClientImpl;\n"); 172 formattedWrite(client_interface_strings, "import kissrpc.RpcClient;\n"); 173 formattedWrite(client_interface_strings, "import kissrpc.RpcResponse;\n"); 174 formattedWrite(client_interface_strings, "import kissrpc.Unit;\n"); 175 formattedWrite(client_interface_strings, "import flatbuffers;\n"); 176 177 178 auto client_service_strings = appender!string(); 179 formattedWrite(client_service_strings, "module kissrpc.generated.%sService;\n\n\n", fileName); 180 formattedWrite(client_service_strings, "import kissrpc.generated.%sInterface;\n", fileName); 181 formattedWrite(client_service_strings, "import kissrpc.generated.%sMessage;\n\n", fileName); 182 formattedWrite(client_service_strings, "import kissrpc.RpcClient;\n"); 183 formattedWrite(client_service_strings, "import kissrpc.Unit;\n\n"); 184 185 186 187 auto struct_strings = appender!string(); 188 formattedWrite(struct_strings, "module kissrpc.generated.%sMessage;\n", fileName); 189 formattedWrite(struct_strings, "import std.typetuple;\n\n\n"); 190 191 192 193 foreach(k, v; idlInerfaceList) 194 { 195 serverCodeInterface ~= v.createServerCodeForInterface(CODE_LANGUAGE.CL_DLANG); 196 serverCodeService ~= v.createServerCodeForService(CODE_LANGUAGE.CL_DLANG); 197 198 clientCodeInterface ~= v.createClientCodeForInterface(CODE_LANGUAGE.CL_DLANG); 199 clientCodeService ~= v.createClientCodeForService(CODE_LANGUAGE.CL_DLANG); 200 } 201 202 foreach(k, v; idlStructList) 203 { 204 structCode ~= v.createCodeForLanguage(CODE_LANGUAGE.CL_DLANG); 205 } 206 207 foreach(k,v; idlStructList) 208 { 209 flatbufferIdlCode ~= IdlFlatbufferCode.createFlatbufferCode(v); 210 } 211 212 213 auto flatbuffer_strings = appender!string(); 214 215 216 auto modulePath = split(fileName, "."); 217 218 // if(modulePath.length > 1) 219 // { 220 // for(int i = 0; i < modulePath.length-1; ++i) 221 // { 222 // outFilePath ~= ("/" ~ modulePath[i]); 223 // if(!exists(outFilePath)) { 224 // rmdir(outFilePath); 225 // } 226 // mkdir(outFilePath); 227 // moduleFilePath ~= (modulePath[i] ~ "."); 228 // } 229 230 // fileName = modulePath[modulePath.length-1]; 231 232 // formattedWrite(flatbuffer_strings, "namespace kissrpc.generated.%smessage;\n\n", moduleFilePath); 233 // formattedWrite(serverInterfaceStrings, "import kissrpc.generated.%smessage.%s;\n\n", moduleFilePath, fileName); 234 // formattedWrite(client_interface_strings, "import kissrpc.generated.%smessage.%s;\n\n", moduleFilePath, fileName); 235 // }else 236 // { 237 // formattedWrite(flatbuffer_strings, "namespace kissrpc.generated.message.hakar;\n\n"); 238 // formattedWrite(serverInterfaceStrings, "import kissrpc.generated.message.%s;\n\n",fileName); 239 // formattedWrite(client_interface_strings, "import kissrpc.generated.message.%s;\n\n", fileName); 240 // } 241 242 243 244 if (!exists(outFilePath ~ "/kissrpc/")) { 245 mkdir(outFilePath ~ "/kissrpc/"); 246 } 247 outFilePath ~= "/kissrpc"; 248 249 if (!exists(outFilePath ~ "/generated")) { 250 mkdir(outFilePath ~ "/generated"); 251 } 252 outFilePath ~= "/generated"; 253 254 255 formattedWrite(flatbuffer_strings, "namespace kissrpc.generated.message;\n\n"); 256 formattedWrite(serverInterfaceStrings, "import kissrpc.generated.message.%s;\n\n",fileName); 257 formattedWrite(client_interface_strings, "import kissrpc.generated.message.%s;\n\n", fileName); 258 259 260 261 //generated server 262 if(!exists(outFilePath ~ "/server/")) 263 { 264 mkdir(outFilePath ~ "/server/"); 265 } 266 auto file = File(outFilePath ~ "/server/" ~ fileName ~ "Interface.d", "w+"); 267 file.write(serverInterfaceStrings.data ~ serverCodeInterface); 268 file.close(); 269 270 271 file = File(outFilePath ~ "/server/" ~ fileName ~ "Service.d", "w+"); 272 file.write(server_service_strings.data ~ serverCodeService); 273 file.close(); 274 275 276 //generated client 277 if(!exists(outFilePath ~ "/client/")) 278 { 279 mkdir(outFilePath ~ "/client/"); 280 } 281 282 file = File(outFilePath ~ "/client/" ~ fileName ~ "Interface.d", "w+"); 283 file.write(client_interface_strings.data ~ clientCodeInterface); 284 file.close(); 285 286 file = File(outFilePath ~ "/client/" ~ fileName ~ "Service.d", "w+"); 287 file.write(client_service_strings.data ~ clientCodeService); 288 file.close(); 289 290 291 292 //generated message 293 if(!exists(outFilePath ~ "/message/")) 294 { 295 mkdir(outFilePath ~ "/message/"); 296 } 297 298 file = File(outFilePath ~ "/message/" ~ fileName ~ "Message.d", "w+"); 299 file.write(struct_strings.data ~ structCode); 300 file.close(); 301 302 303 file = File(outFilePath ~ "/message/" ~ fileName ~ ".fbs", "w+"); 304 file.write(flatbuffer_strings.data ~ flatbufferIdlCode); 305 306 spawnProcess(["flatc", "-d", "-b", outFilePath ~ "/message/" ~ fileName ~ ".fbs", "--gen-onefile"], 307 std.stdio.stdin, std.stdio.stdout, std.stdio.stderr, null, Config.none, outFilePath ~ "/message/"); 308 309 310 311 new Thread({ 312 Thread.sleep(2000.msecs); 313 auto b = std.file.read(outFilePath ~ "/message/" ~ fileName ~ ".d"); 314 315 string bb = cast(string)b; 316 file = File(outFilePath ~ "/message/" ~ fileName ~ ".d", "w+"); 317 318 auto apstring = appender!string(); 319 formattedWrite(apstring, "module kissrpc.generated.message.%s;\n\n%s", fileName,bb); 320 file.write(apstring.data); 321 file.close(); 322 323 }).start(); 324 325 326 327 } 328 329 private: 330 IdlBaseInterface[string] idlInerfaceList; 331 332 string inFilePath = "."; 333 string outFilePath = "."; 334 string fileName; 335 string moduleFilePath; 336 } 337