Advertisement
Guest User

Tarwins AS3 to Haxe conversion script ( Haxe Neko )

a guest
Jul 2nd, 2012
1,231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.42 KB | None | 0 0
  1. /*
  2. * Copyright (c) 2011, TouchMyPixel & contributors
  3. * Original author : Tarwin Stroh-Spijer <tarwin@touchmypixel.com>
  4. * Contributers: Tony Polinelli <tonyp@touchmypixel.com>
  5. * All rights reserved.
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE TOUCH MY PIXEL & CONTRIBUTERS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE TOUCH MY PIXEL & CONTRIBUTORS
  19. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  25. * THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27.  
  28. package;
  29.  
  30. import neko.FileSystem;
  31. import neko.Lib;
  32. import neko.Sys;
  33.  
  34. using StringTools;
  35. using As3ToHaxe;
  36.  
  37. /**
  38. * Simple Program which iterates -from folder, finds .mtt templates and compiles them to the -to folder
  39. */
  40. class As3ToHaxe
  41. {
  42. public static inline var keys = ["-from", "-to", "-remove"];
  43.  
  44. var to:String;
  45. var from:String;
  46. var remove:String;
  47. var sysargs:Array<String>;
  48.  
  49. var items:Array<String>;
  50.  
  51. public static var basePackage:String = "away3d";
  52.  
  53. private var nameSpaces:Hash<Ns>;
  54. private var maxLoop:Int;
  55.  
  56. static function main()
  57. {
  58. new As3ToHaxe();
  59. }
  60.  
  61. public function new()
  62. {
  63. maxLoop = 1000;
  64.  
  65. if (parseArgs())
  66. {
  67.  
  68. // make sure that the to directory exists
  69. if (!FileSystem.exists(to)) FileSystem.createDirectory(to);
  70.  
  71. // delete old files
  72. if (remove == "true")
  73. removeDirectory(to);
  74.  
  75. items = [];
  76. // fill items
  77. recurse(from);
  78.  
  79. // to remember namespaces
  80. nameSpaces = new Hash();
  81.  
  82. for (item in items)
  83. {
  84. // make sure we only work wtih AS fiels
  85. var ext = getExt(item);
  86. switch(ext)
  87. {
  88. case "as":
  89. doConversion(item);
  90. }
  91. }
  92.  
  93. // build namespace files
  94. buildNameSpaces();
  95. }
  96. }
  97.  
  98. private function doConversion(file:String):Void
  99. {
  100. var fromFile = file;
  101. var toFile = to + "/" + file.substr(from.length + 1, file.lastIndexOf(".") - (from.length)) + "hx";
  102.  
  103. var rF = "";
  104. var rC = "";
  105.  
  106. var b = 0;
  107.  
  108. // create the folder if it doesn''t exist
  109. var dir = toFile.substr(0, toFile.lastIndexOf("/"));
  110. createFolder(dir);
  111.  
  112. var s = neko.io.File.getContent(fromFile);
  113.  
  114. // spacse to tabs
  115. s = quickRegR(s, " ", "\t");
  116. // undent
  117. s = quickRegR(s, "\t\t", "\t");
  118.  
  119. // some quick setup, finding what we''ve got
  120. var className = quickRegM(s, "public class([ ]*)([A-Z][a-zA-Z0-9_]*)", 2)[1];
  121. var hasVectors = (quickRegM(s, "Vector([ ]*)\\.([ ]*)<([ ]*)([^>]*)([ ]*)>").length != 0);
  122.  
  123. // package
  124. s = quickRegR(s, "package ([a-zA-Z\\.0-9-_]*)([ \n\r]*){", "package $1;\n", "gs");
  125. // remove last
  126. s = quickRegR(s, "\\}([\n\r\t ]*)\\}([\n\r\t ]*)$", "}", "gs");
  127.  
  128. // extra indentation
  129. s = quickRegR(s, "\n\t", "\n");
  130.  
  131. // class
  132. s = quickRegR(s, "public class", "class");
  133.  
  134. // constructor
  135. s = quickRegR(s, "function " + className, "function new");
  136.  
  137. // simple typing
  138. s = quickRegR(s, ":([ ]*)void", ":$1Void");
  139. s = quickRegR(s, ":([ ]*)Boolean", ":$1Bool");
  140. s = quickRegR(s, ":([ ]*)int", ":$1Int");
  141. s = quickRegR(s, ":([ ]*)uint", ":$1UInt");
  142. s = quickRegR(s, ":([ ]*)Number", ":$1Float");
  143. s = quickRegR(s, ":([ ]*)\\*", ":$1Dynamic");
  144.  
  145. s = quickRegR(s, "<Number>", "<Float>");
  146. s = quickRegR(s, "<int>", "<Int>");
  147. s = quickRegR(s, "<uint>", "<UInt>");
  148. s = quickRegR(s, "<Boolean>", "<Bool>");
  149.  
  150. // vector
  151. // definition
  152. s = quickRegR(s, "Vector([ ]*)\\.([ ]*)<([ ]*)([^>]*)([ ]*)>", "Vector<$3$4$5>");
  153. // new (including removing stupid spaces)
  154. s = quickRegR(s, "new Vector([ ]*)([ ]*)<([ ]*)([^>]*)([ ]*)>([ ]*)\\(([ ]*)\\)([ ]*)", "new Vector()");
  155. // and import if we have to
  156. if (hasVectors) {
  157. s = quickRegR(s, "class([ ]*)(" + className + ")", "import flash.Vector;\n\nclass$1$2");
  158. }
  159.  
  160. // array
  161. s = quickRegR(s, " Array([ ]*);", " Array<Dynamic>;");
  162.  
  163. // remap protected -> private & internal -> private
  164. s = quickRegR(s, "protected var", "private var");
  165. s = quickRegR(s, "internal var", "private var");
  166. s = quickRegR(s, "protected function", "private function");
  167. s = quickRegR(s, "internal function", "private function");
  168.  
  169. /* -----------------------------------------------------------*/
  170. // namespaces
  171. // find which namespaces are used in this class
  172. var r = new EReg("([^#])use([ ]+)namespace([ ]+)([a-zA-Z-]+)([ ]*);", "g");
  173. b = 0;
  174. while (true) {
  175. b++; if (b > maxLoop) { logLoopError("namespaces find", file); break; }
  176. if (r.match(s)) {
  177. var ns:Ns = {
  178. name : r.matched(4),
  179. classDefs : new Hash()
  180. };
  181. nameSpaces.set(ns.name, ns);
  182. s = r.replace(s, "//" + r.matched(0).replace("use", "#use") + "\nusing " + basePackage + ".namespace." + ns.name.fUpper() + ";");
  183. }else {
  184. break;
  185. }
  186. }
  187.  
  188. // collect all namespace definitions
  189. // replace them with private
  190. for (k in nameSpaces.keys()) {
  191. var n = nameSpaces.get(k);
  192. b = 0;
  193. while (true) {
  194. b++; if (b > maxLoop) { logLoopError("namespaces collect/replace var", file); break; }
  195. // vars
  196. var r = new EReg(n.name + "([ ]+)var([ ]+)", "g");
  197. s = r.replace(s, "private$1var$2");
  198. if (!r.match(s)) break;
  199. }
  200. b = 0;
  201. while (true) {
  202. b++; if (b > maxLoop) { logLoopError("namespaces collect/replace func", file); break; }
  203. // funcs
  204. var matched:Bool = false;
  205. var r = new EReg(n.name + "([ ]+)function([ ]+)", "g");
  206. if (r.match(s)) matched = true;
  207. s = r.replace(s, "private$1function$2");
  208. r = new EReg(n.name + "([ ]+)function([ ]+)get([ ]+)", "g");
  209. if (r.match(s)) matched = true;
  210. s = r.replace(s, "private$1function$2get$3");
  211. r = new EReg(n.name + "([ ]+)function([ ]+)set([ ]+)", "g");
  212. if (r.match(s)) matched = true;
  213. s = r.replace(s, "private$1function$2$3set");
  214. if (!matched) break;
  215. }
  216. }
  217.  
  218. /* -----------------------------------------------------------*/
  219. // change const to inline statics
  220. s = quickRegR(s, "([\n\t ]+)(public|private)([ ]*)const([ ]+)([a-zA-Z0-9_]+)([ ]*):", "$1$2$3static inline var$4$5$6:");
  221. s = quickRegR(s, "([\n\t ]+)(public|private)([ ]*)(static)*([ ]+)const([ ]+)([a-zA-Z0-9_]+)([ ]*):", "$1$2$3$4$5inline var$6$7$8:");
  222.  
  223. /* -----------------------------------------------------------*/
  224. // move variables being set from var def to top of constructor
  225. // do NOT do this for const
  226. // if they're static, leave them there
  227. // TODO!
  228.  
  229. /* -----------------------------------------------------------*/
  230. // Error > flash.Error
  231. // if " Error (" then add "import flash.Error" to head
  232. var r = new EReg("([ ]+)new([ ]+)Error([ ]*)\\(", "");
  233. if (r.match(s))
  234. s = quickRegR(s, "class([ ]*)(" + className + ")", "import flash.Error;\n\nclass$1$2");
  235.  
  236. /* -----------------------------------------------------------*/
  237.  
  238. // create getters and setters
  239. b = 0;
  240. while (true) {
  241. b++;
  242. var d = { get: null, set: null, type: null, ppg: null, pps: null, name: null };
  243.  
  244. // get
  245. var r = new EReg("([\n\t ]+)([a-z]+)([ ]*)function([ ]*)get([ ]+)([a-zA-Z_][a-zA-Z0-9_]+)([ ]*)\\(([ ]*)\\)([ ]*):([ ]*)([A-Z][a-zA-Z0-9_]*)", "");
  246. var m = r.match(s);
  247. if (m) {
  248. d.ppg = r.matched(2);
  249. if (d.ppg == "") d.ppg = "public";
  250. d.name = r.matched(6);
  251. d.get = "get" + d.name.substr(0, 1).toUpperCase() + d.name.substr(1);
  252. d.type = r.matched(11);
  253. }
  254.  
  255. // set
  256. var r = new EReg("([\n\t ]+)([a-z]+)([ ]*)function([ ]*)set([ ]+)([a-zA-Z_][a-zA-Z0-9_]*)([ ]*)\\(([ ]*)([a-zA-Z][a-zA-Z0-9_]*)([ ]*):([ ]*)([a-zA-Z][a-zA-Z0-9_]*)", "");
  257. var m = r.match(s);
  258. if (m) {
  259. if (r.matched(6) == d.get || d.get == null)
  260. if (d.name == null) d.name = r.matched(6);
  261. d.pps = r.matched(2);
  262. if (d.pps == "") d.pps = "public";
  263. d.set = "set" + d.name.substr(0, 1).toUpperCase() + d.name.substr(1);
  264. if (d.type == null) d.type = r.matched(12);
  265. }
  266.  
  267. // ERROR
  268. if (b > maxLoop) { logLoopError("getter/setter: " + d, file); break; }
  269.  
  270. // replace get
  271. if (d.get != null)
  272. s = quickRegR(s, d.ppg + "([ ]+)function([ ]+)get([ ]+)" + d.name, "private function " + d.get);
  273.  
  274. // replace set
  275. if (d.set != null)
  276. s = quickRegR(s, d.pps + "([ ]+)function([ ]+)set([ ]+)" + d.name, "private function " + d.set);
  277.  
  278. // make haxe getter/setter OR finish
  279. if (d.get != null || d.set != null) {
  280. var gs = (d.ppg != null ? d.ppg : d.pps) + " var " + d.name + "(" + d.get + ", " + d.set + "):" + d.type + ";";
  281. s = quickRegR(s, "private function " + (d.get != null ? d.get : d.set), gs + "\n \tprivate function " + (d.get != null ? d.get : d.set));
  282. }else {
  283. break;
  284. }
  285. }
  286.  
  287. /* -----------------------------------------------------------*/
  288.  
  289. // for loops (?)
  290. // TODO!
  291. //s = quickRegR(s, "for([ ]*)\\(([ ]*)var([ ]*)([A-Z][a-zA-Z0-9_]*)([.^;]*);([.^;]*);([.^\\)]*)\\)", "");
  292. //var t = quickRegM(s, "for([ ]*)\\(([ ]*)var([ ]*)([a-zA-Z][a-zA-Z0-9_]*)([.^;]*)", 5);
  293. //trace(t);
  294. //for (var i : Int = 0; i < len; ++i)
  295.  
  296. /* -----------------------------------------------------------*/
  297.  
  298. var o = neko.io.File.write(toFile, true);
  299. o.writeString(s);
  300. o.close();
  301.  
  302. // use for testing on a single file
  303. //Sys.exit(1);
  304. }
  305.  
  306. private function logLoopError(type:String, file:String)
  307. {
  308. trace("ERROR: " + type + " - " + file);
  309. }
  310.  
  311. private function buildNameSpaces()
  312. {
  313. // build friend namespaces!
  314. trace(nameSpaces);
  315. }
  316.  
  317. public static function quickRegR(str:String, reg:String, rep:String, ?regOpt:String = "g"):String
  318. {
  319. return new EReg(reg, regOpt).replace(str, rep);
  320. }
  321.  
  322. public static function quickRegM(str:String, reg:String, ?numMatches:Int = 1, ?regOpt:String = "g"):Array<String>
  323. {
  324. var r = new EReg(reg, regOpt);
  325. var m = r.match(str);
  326. if (m) {
  327. var a = [];
  328. var i = 1;
  329. while (i <= numMatches) {
  330. a.push(r.matched(i));
  331. i++;
  332. }
  333. return a;
  334. }
  335. return [];
  336. }
  337.  
  338. private function createFolder(path:String):Void
  339. {
  340. var parts = path.split("/");
  341. var folder = "";
  342. for (part in parts)
  343. {
  344. if (folder == "") folder += part;
  345. else folder += "/" + part;
  346. if (!FileSystem.exists(folder)) FileSystem.createDirectory(folder);
  347. }
  348. }
  349.  
  350. private function parseArgs():Bool
  351. {
  352. // Parse args
  353. var args = Sys.args();
  354. for (i in 0...args.length)
  355. if (Lambda.has(keys, args[i]))
  356. Reflect.setField(this, args[i].substr(1), args[i + 1]);
  357.  
  358. // Check to see if argument is missing
  359. if (to == null) { Lib.println("Missing argument '-to'"); return false; }
  360. if (from == null) { Lib.println("Missing argument '-from'"); return false; }
  361.  
  362. return true;
  363. }
  364.  
  365. public function recurse(path:String)
  366. {
  367. var dir = FileSystem.readDirectory(path);
  368.  
  369. for (item in dir)
  370. {
  371. var s = path + "/" + item;
  372. if (FileSystem.isDirectory(s))
  373. {
  374. recurse(s);
  375. }
  376. else
  377. {
  378. var exts = ["as"];
  379. if(Lambda.has(exts, getExt(item)))
  380. items.push(s);
  381. }
  382. }
  383. }
  384.  
  385. public function getExt(s:String)
  386. {
  387. return s.substr(s.lastIndexOf(".") + 1).toLowerCase();
  388. }
  389.  
  390. public function removeDirectory(d, p = null)
  391. {
  392. if (p == null) p = d;
  393. var dir = FileSystem.readDirectory(d);
  394.  
  395. for (item in dir)
  396. {
  397. item = p + "/" + item;
  398. if (FileSystem.isDirectory(item)) {
  399. removeDirectory(item);
  400. }else{
  401. FileSystem.deleteFile(item);
  402. }
  403. }
  404.  
  405. FileSystem.deleteDirectory(d);
  406. }
  407.  
  408. public static function fUpper(s:String)
  409. {
  410. return s.charAt(0).toUpperCase() + s.substr(1);
  411. }
  412. }
  413.  
  414. typedef Ns = {
  415. var name:String;
  416. var classDefs:Hash<String>;
  417. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement