PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/cyclone/tools/yakker/Parseviz.hx

https://bitbucket.org/mirrorbot/cyclone-full
Haxe | 511 lines | 441 code | 25 blank | 45 comment | 55 complexity | 6e09b8127a8db0bb99b3c480fa354b19 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0, BSD-3-Clause
  1. /**********************************************************************/
  2. /**********************************************************************/
  3. import flash.display.Sprite;
  4. import mx.controls.TextArea;
  5. import flash.events.Event;
  6. import mx.events.ResizeEvent;
  7. import mx.events.NumericStepperEvent;
  8. import mx.events.FlexEvent;
  9. import mx.controls.ToolTip;
  10. import mx.managers.ToolTipManager;
  11. import flash.events.MouseEvent;
  12. import flash.events.IOErrorEvent;
  13. import flash.display.DisplayObjectContainer;
  14. import flash.text.TextField;
  15. import flash.text.TextFormat;
  16. import flash.geom.Rectangle;
  17. import flash.geom.Point;
  18. class Color {
  19. public static function
  20. hsvtorgb(h:Float,s:Float,v:Float):Int {
  21. // h(ue): 0-360
  22. // s(aturation): 0-1.0
  23. // v(alue): 0-1.0
  24. var r, g, b;
  25. h %= 360;
  26. h /= 60;
  27. var i = Math.floor(h) % 6;
  28. var f = h-i;
  29. var p = v*(1-s);
  30. var q = v*(1-(s*f));
  31. var t = v*(1-(s*(1-f)));
  32. switch(i) {
  33. case 0: r=v; g=t; b=p;
  34. case 1: r=q; g=v; b=p;
  35. case 2: r=p; g=v; b=t;
  36. case 3: r=p; g=q; b=v;
  37. case 4: r=t; g=p; b=v;
  38. case 5: r=v; g=p; b=q;
  39. }
  40. var R =Math.round(r*255);
  41. var G =Math.round(g*255);
  42. var B =Math.round(b*255);
  43. return ((R<<16) | (G<<8) | B);
  44. }
  45. public static function random() {
  46. return hsvtorgb(Math.random()*360,1.0,1.0);
  47. }
  48. static var onethird = (1.0/3);
  49. static var twothirds = (2.0/3);
  50. static var onesixth = (1.0/6);
  51. public static function
  52. hsltorgb(h:Float,s:Float,l:Float):Int {
  53. // h(ue): 0-360
  54. // s(aturation): 0-1.0
  55. // l(uminance): 0-1.0
  56. if (s == 0) {
  57. var rgb = Math.round(l * 255) % 255;
  58. return ((rgb << 16) | (rgb << 8) | rgb);
  59. }
  60. var q;
  61. if (l < 0.5) q = l * (1.0 + s);
  62. else q = l + s - (l * s);
  63. var p = 2.0 * l - q;
  64. var k = h/360;
  65. var r = k + onethird;
  66. var g = k;
  67. var b = k - onethird;
  68. var normalize = function (c:Float):Int {
  69. if (c < 0) c += 1;
  70. else if (c > 1) c -= 1;
  71. if (c < onesixth)
  72. c = p + ((q-p) * 6 * c);
  73. else if (c < 0.5)
  74. c = q;
  75. else if (c < twothirds)
  76. c = p + ((q-p) * (twothirds - c) * 6);
  77. else
  78. c = p;
  79. return Math.round(c * 255);
  80. }
  81. var R = normalize(r);
  82. var G = normalize(g);
  83. var B = normalize(b);
  84. return ((R<<16) | (G<<8) | B);
  85. }
  86. private static var colorMap = new Hash();
  87. public static function
  88. colorFor(s:String):Int {
  89. if (colorMap.exists(s))
  90. return colorMap.get(s);
  91. var c = random();
  92. colorMap.set(s,c);
  93. return c;
  94. }
  95. }
  96. class Parseviz {
  97. static var zoom = 1.0;
  98. static var gridHeight = 20;
  99. static var gridWidth = 12;
  100. static function hex(cCode:Int):String {
  101. switch (cCode%16) {
  102. case 0: return "0";
  103. case 1: return "1";
  104. case 2: return "2";
  105. case 3: return "3";
  106. case 4: return "4";
  107. case 5: return "5";
  108. case 6: return "6";
  109. case 7: return "7";
  110. case 8: return "8";
  111. case 9: return "9";
  112. case 10: return "A";
  113. case 11: return "B";
  114. case 12: return "C";
  115. case 13: return "D";
  116. case 14: return "E";
  117. case 15: return "F";
  118. default: return ""; // impossible
  119. }
  120. }
  121. public static function
  122. drawText(spr:DisplayObjectContainer,tf:TextFormat,
  123. x:Float,y:Float,s:String):Sprite
  124. {
  125. var c = new Sprite();
  126. for (i in 0...s.length) {
  127. var cCode = s.charCodeAt(i);
  128. if (31 < cCode && cCode < 127) {
  129. var t:TextField = new TextField();
  130. t.defaultTextFormat = tf;
  131. t.autoSize = flash.text.TextFieldAutoSize.LEFT;
  132. t.selectable = false;
  133. t.text = Std.chr(cCode);
  134. t.x = i*gridWidth;
  135. t.y = 0;
  136. c.addChild(t);
  137. }
  138. else {
  139. {
  140. var upper = hex(Std.int(cCode / 16));
  141. var t:TextField = new TextField();
  142. t.defaultTextFormat = quarterFont;
  143. t.autoSize = flash.text.TextFieldAutoSize.LEFT;
  144. t.selectable = false;
  145. t.text = upper;
  146. t.x = i*gridWidth;
  147. t.y = 0;
  148. c.addChild(t);
  149. }
  150. {
  151. var lower = hex(cCode % 16);
  152. var t:TextField = new TextField();
  153. t.defaultTextFormat = quarterFont;
  154. t.autoSize = flash.text.TextFieldAutoSize.LEFT;
  155. t.selectable = false;
  156. t.text = lower;
  157. t.x = (i+0.3) * gridWidth;
  158. t.y = 0.4 * gridHeight;
  159. c.addChild(t);
  160. }
  161. }
  162. }
  163. c.x = x;
  164. c.y = y;
  165. spr.addChild(c);
  166. return c;
  167. }
  168. public static function
  169. drawSpanBelow(spr:DisplayObjectContainer,tf:TextFormat,
  170. x:Float,y:Float,i:Int,w:Int,z:Int,s:String):Sprite
  171. {
  172. var c = new Sprite();
  173. var t:TextField = new TextField();
  174. t.defaultTextFormat = tf;
  175. t.autoSize = flash.text.TextFieldAutoSize.LEFT;
  176. t.selectable = false;
  177. if (s.length > w)
  178. t.text = s.substr(0,w);
  179. else
  180. t.text = s;
  181. t.x = i * gridWidth;
  182. t.y = z * gridHeight;
  183. c.addChild(t);
  184. c.graphics.lineStyle(1,0x0,0.5);
  185. c.graphics.beginFill(Color.colorFor(s));
  186. c.graphics.drawRect(i*gridWidth,gridHeight,w*gridWidth,z*gridHeight);
  187. c.graphics.endFill();
  188. c.x = x;
  189. c.y = y;
  190. spr.addChild(c);
  191. var mouseOut = function (e:MouseEvent) {};
  192. var mouseOver = function (e:MouseEvent) {
  193. var pt = c.localToGlobal(new Point(i*gridWidth+c.width,c.y+c.height));
  194. var tt = ToolTipManager.createToolTip(s,pt.x,pt.y);
  195. mouseOut = function (e:MouseEvent) {
  196. ToolTipManager.destroyToolTip(tt);
  197. c.removeEventListener(MouseEvent.ROLL_OUT,mouseOut);
  198. };
  199. c.addEventListener(MouseEvent.ROLL_OUT,mouseOut);
  200. };
  201. c.addEventListener(MouseEvent.ROLL_OVER,mouseOver);
  202. return c;
  203. }
  204. static function drawSpansBelow(spr:DisplayObjectContainer,a:Array<Dynamic>) {
  205. for (x in a) {
  206. drawSpanBelow(spr,font,0,0,x.l,x.r-x.l,x.h,x.s);
  207. if (x.h == 1 || !Reflect.hasField(x,"c")) continue;
  208. var a:Array<Dynamic> = x.c;
  209. drawSpansBelow(spr,a);
  210. }
  211. }
  212. public static function
  213. drawSpanAbove(spr:DisplayObjectContainer,tf:TextFormat,
  214. x:Float,y:Float,i:Int,w:Int,z:Int,s:String):Sprite
  215. {
  216. var c = new Sprite();
  217. var t:TextField = new TextField();
  218. t.defaultTextFormat = tf;
  219. t.autoSize = flash.text.TextFieldAutoSize.LEFT;
  220. t.selectable = false;
  221. if (s.length > w)
  222. t.text = s.substr(0,w);
  223. else
  224. t.text = s;
  225. t.x = i * gridWidth;
  226. t.y = -z * gridHeight;
  227. c.addChild(t);
  228. c.graphics.lineStyle(1,0x0,0.5);
  229. c.graphics.beginFill(Color.colorFor(s));
  230. c.graphics.drawRect(i*gridWidth,0,w*gridWidth,-z*gridHeight);
  231. c.graphics.endFill();
  232. c.x = x;
  233. c.y = y;
  234. spr.addChild(c);
  235. var mouseOut = function (e:MouseEvent) {};
  236. var mouseOver = function (e:MouseEvent) {
  237. var pt = c.localToGlobal(new Point(i*gridWidth+c.width,c.y-c.height));
  238. var tt = ToolTipManager.createToolTip(s,pt.x,pt.y);
  239. mouseOut = function (e:MouseEvent) {
  240. ToolTipManager.destroyToolTip(tt);
  241. c.removeEventListener(MouseEvent.ROLL_OUT,mouseOut);
  242. };
  243. c.addEventListener(MouseEvent.ROLL_OUT,mouseOut);
  244. };
  245. c.addEventListener(MouseEvent.ROLL_OVER,mouseOver);
  246. return c;
  247. }
  248. static function drawSpansAbove(spr:DisplayObjectContainer,a:Array<Dynamic>) {
  249. for (x in a) {
  250. drawSpanAbove(spr,font,0,0,x.l,x.r-x.l,x.h,x.s);
  251. if (x.h == 1 || !Reflect.hasField(x,"c")) continue;
  252. var a:Array<Dynamic> = x.c;
  253. drawSpansAbove(spr,a);
  254. }
  255. }
  256. static function markHeight(x:Dynamic,limit:Int):Int {
  257. if (limit == 1 || !Reflect.hasField(x,"c")) {
  258. Reflect.setField(x,"h",1);
  259. return 1;
  260. }
  261. var h = 0;
  262. var a:Array<Dynamic> = x.c;
  263. for (y in a) {
  264. var yh = markHeight(y,limit-1);
  265. if (yh > h) h = yh;
  266. }
  267. h++;
  268. Reflect.setField(x,"h",h);
  269. return h;
  270. }
  271. static var font = new TextFormat("Courier",16,0x0);
  272. static var quarterFont = new TextFormat("Courier",12,0x0);
  273. static var parseInput:String = "";
  274. static var parseAbove:Array<Dynamic> = [];
  275. static var parseBelow:Array<Dynamic> = [];
  276. static var maxHeightAbove = 0;
  277. static var limit = 0;
  278. static function drawTrees(spr:DisplayObjectContainer) {
  279. maxHeightAbove = 0; // needed if limit can change
  280. for (x in parseAbove) {
  281. var h = markHeight(x,limit);
  282. if (h > maxHeightAbove) maxHeightAbove = h;
  283. }
  284. var maxHeightBelow = 0;
  285. for (x in parseBelow) {
  286. var h = markHeight(x,limit);
  287. if (h > maxHeightBelow) maxHeightBelow = h;
  288. }
  289. var bg = new Sprite();
  290. spr.addChild(bg);
  291. bg.graphics.beginFill(0xffffff);
  292. bg.graphics.drawRect(0,
  293. -maxHeightAbove * gridHeight,
  294. parseInput.length * gridWidth,
  295. (maxHeightAbove + maxHeightBelow + 1) * gridHeight);
  296. bg.graphics.endFill();
  297. var tf = drawText(spr,font,0,0,parseInput);
  298. drawSpansBelow(spr,parseBelow);
  299. drawSpansAbove(spr,parseAbove);
  300. }
  301. static function decode(t:String):Array<Dynamic> {
  302. var c:Array<Dynamic> = [];
  303. try {
  304. var xml = Xml.parse(t);
  305. if (xml == null) return c;
  306. for (x in xml.elements()) {
  307. c.push(xml2obj(x));
  308. }
  309. }
  310. catch (e:Dynamic) {
  311. }
  312. return c;
  313. }
  314. static function xml2obj(xml:Xml):Dynamic {
  315. if (xml == null) return null;
  316. var s = xml.get('s');
  317. var l = Std.parseInt(xml.get('l'));
  318. var r = Std.parseInt(xml.get('r'));
  319. var c:Array<Dynamic> = [];
  320. for (x in xml.elements()) {
  321. c.push(xml2obj(x));
  322. }
  323. return {s:s,l:l,r:r,c:c};
  324. }
  325. static function loadFile(file:String,t:TextArea) {
  326. var ul:flash.net.URLLoader = new flash.net.URLLoader();
  327. ul.addEventListener
  328. (Event.COMPLETE,
  329. function (e:Event) {
  330. t.text = ul.data;
  331. });
  332. ul.addEventListener
  333. (IOErrorEvent.IO_ERROR,
  334. function (e:Event) {
  335. /* if file does not exist just ignore it */
  336. });
  337. ul.load(new flash.net.URLRequest(file));
  338. }
  339. /* Main entry point */
  340. public function start(app:Dynamic) {
  341. // In fact app:Application, but it is convenient to use Dynamic to
  342. // more easily access UI components
  343. loadFile("input",app.parseInput);
  344. /*
  345. loadFile("left.xml",app.parseAbove);
  346. loadFile("right.xml",app.parseBelow);
  347. */
  348. /* mainCanvas is a mx.containers.Canvas, and its addChild method
  349. requires that the argument implement IUIComponent, which most
  350. flash DisplayObjects do not. Therefore we add a regular
  351. DisplayObject as a child using rawChildren, and the rest of the
  352. program will add children to c as usual. */
  353. var c = new Sprite();
  354. app.mainCanvas.rawChildren.addChild(c);
  355. // c.opaqueBackground = 0xffffff; // useless b/c doesn't get mouse
  356. var bg = new Sprite();
  357. c.addChild(bg);
  358. bg.graphics.beginFill(0xffffff,0.5);
  359. bg.graphics.drawRect(0,0,1,1);
  360. bg.graphics.endFill();
  361. c.scrollRect = new Rectangle(0,0,app.mainCanvas.width,app.mainCanvas.height);
  362. var resizeC = function () {
  363. var r = c.scrollRect;
  364. r.width = app.mainCanvas.width;
  365. r.height = app.mainCanvas.height;
  366. c.scrollRect = r;
  367. bg.scaleX = app.mainCanvas.width;
  368. bg.scaleY = app.mainCanvas.height;
  369. }
  370. resizeC();
  371. app.mainCanvas.addEventListener(ResizeEvent.RESIZE,
  372. function (e:Event) {
  373. resizeC();
  374. });
  375. var scrollX = 0.0;
  376. var scrollY = 0.0;
  377. var inScroll = function (e:MouseEvent) {
  378. var dX = e.stageX - scrollX;
  379. var dY = e.stageY - scrollY;
  380. scrollX = e.stageX;
  381. scrollY = e.stageY;
  382. var r = c.scrollRect;
  383. r.x -= dX;
  384. r.y -= dY;
  385. c.scrollRect = r;
  386. bg.x = r.x;
  387. bg.y = r.y;
  388. }
  389. var spr:Sprite = null;
  390. var stopScroll = function (e:MouseEvent) {}
  391. stopScroll = function (e:MouseEvent) {
  392. bg.removeEventListener(MouseEvent.MOUSE_MOVE,inScroll);
  393. bg.removeEventListener(MouseEvent.MOUSE_UP,stopScroll);
  394. bg.removeEventListener(MouseEvent.MOUSE_OUT,stopScroll);
  395. if (spr != null) {
  396. spr.removeEventListener(MouseEvent.MOUSE_MOVE,inScroll);
  397. spr.removeEventListener(MouseEvent.MOUSE_UP,stopScroll);
  398. }
  399. }
  400. var startScroll = function (e:MouseEvent) {
  401. bg.addEventListener(MouseEvent.MOUSE_MOVE,inScroll);
  402. bg.addEventListener(MouseEvent.MOUSE_UP,stopScroll);
  403. bg.addEventListener(MouseEvent.MOUSE_OUT,stopScroll);
  404. if (spr != null) {
  405. spr.addEventListener(MouseEvent.MOUSE_MOVE,inScroll);
  406. spr.addEventListener(MouseEvent.MOUSE_UP,stopScroll);
  407. }
  408. scrollX = e.stageX;
  409. scrollY = e.stageY;
  410. }
  411. bg.addEventListener(MouseEvent.MOUSE_DOWN,startScroll);
  412. var render = function () {
  413. if (spr != null)
  414. c.removeChild(spr);
  415. spr = new Sprite();
  416. c.addChild(spr);
  417. spr.addEventListener(MouseEvent.MOUSE_DOWN,startScroll);
  418. limit = app.limit.value;
  419. drawTrees(spr);
  420. // zoom = 1;
  421. spr.scaleX = spr.scaleY = zoom;
  422. var r = c.scrollRect;
  423. bg.x = r.x = 0;
  424. bg.y = r.y = -maxHeightAbove * gridHeight;
  425. c.scrollRect = r;
  426. }
  427. /*
  428. app.renderButton.addEventListener
  429. (MouseEvent.CLICK,
  430. function (e:Event) {
  431. try {
  432. parseInput = app.parseInput.text;
  433. parseAbove = decode(app.parseAbove.text);
  434. parseBelow = decode(app.parseBelow.text);
  435. render();
  436. }
  437. catch (e:Dynamic) {
  438. drawText(c,font,0,0,"Error: uncaught exception");
  439. }
  440. });
  441. */
  442. app.minusButton.addEventListener
  443. (FlexEvent.BUTTON_DOWN,
  444. function (e:Event) {
  445. if (spr == null || zoom <= 0.6) return;
  446. zoom -= 0.1;
  447. spr.scaleX = spr.scaleY = zoom;
  448. });
  449. app.plusButton.addEventListener
  450. (FlexEvent.BUTTON_DOWN,
  451. function (e:Event) {
  452. if (spr == null || zoom >= 4) return;
  453. zoom += 0.1;
  454. spr.scaleX = spr.scaleY = zoom;
  455. });
  456. limit = app.limit.value;
  457. app.limit.addEventListener
  458. (NumericStepperEvent.CHANGE,
  459. function (e:Event) {
  460. limit = app.limit.value;
  461. render();
  462. });
  463. app.parseButton.addEventListener
  464. (MouseEvent.CLICK,
  465. function (e:Event) {
  466. try {
  467. parseInput = app.parseInput.text;
  468. /* The above assignment messes with line endings, we force CRLF */
  469. parseInput = StringTools.replace(parseInput,"\r","\r\n");
  470. var parses = Earley.parseToRender(parseInput);
  471. parseAbove = parses.left;
  472. parseBelow = parses.right;
  473. render();
  474. }
  475. catch (e:Dynamic) {
  476. drawText(c,font,0,0,"Uncaught exn " + e.toString());
  477. }
  478. });
  479. }
  480. }
  481. /*
  482. foo login bar "baz"
  483. */
  484. /*
  485. <t s="TOP" l="0" r="21"><t s="command" l="0" r="21"><t s="CRLF" l="19" r="21"><t s="LF" l="20" r="21"></t><t s="CR" l="19" r="20"></t></t><t s="command-nonauth" l="4" r="19"><t s="login" l="4" r="19"><t s="password" l="14" r="19"><t s="astring" l="14" r="19"><t s="string" l="14" r="19"><t s="quoted" l="14" r="19"><t s="DQUOTE" l="18" r="19"></t><t s="QUOTED-CHAR" l="17" r="18"></t><t s="QUOTED-CHAR" l="16" r="17"></t><t s="QUOTED-CHAR" l="15" r="16"></t><t s="DQUOTE" l="14" r="15"></t></t></t></t></t><t s="SP" l="13" r="14"></t><t s="userid" l="10" r="13"><t s="astring" l="10" r="13"><t s="ASTRING-CHAR" l="12" r="13"></t><t s="ASTRING-CHAR" l="11" r="12"></t><t s="ASTRING-CHAR" l="10" r="11"></t></t></t><t s="SP" l="9" r="10"></t></t></t><t s="SP" l="3" r="4"></t><t s="tag" l="0" r="3"></t></t></t>
  486. */