# HaLeX: A Haskell Library to Model, # Manipulate and # Animate Regular Languages # # http://www.di.uminho.pt/~jas/Research/HaLeX # # The script to animate the Reactive Finite Automata produced by HaLeX # # copyright Joćo Saraiva # Department of Computer Science, # University of Minho, # Braga, Portugal # jas@di.uminho.pt # # Version: 1.0 (January, 2002) # load('dotty.lefty'); # filenames fa.graphfilename = 'fa.dot'; fa.transfilename = 'fa.trans'; # tracking the states/nodes fa.normalcolor = 'black'; fa.highlightcolor = 'light_grey'; fa.currentcolor = 'tan'; fa.trackcur = 0; # 0: No 1: Yes # tracking the path fa.trackpath = 0; # 0: No 1: Yes fa.trackhighlightcolor = 'red'; fa.trackhighlightfontcolor = 'red'; fa.trackhighlightfontsize = '30'; # tracking the input sentence fa.sentence = ''; fa.protogt.graph.edgeattr.color = 'red'; fa.sleep = 500000; fa.start = '1'; fa.init = function () { dotty.init (); monitorfile = dotty.monitorfile; }; fa.protogt = [ 'layoutmode' = 'sync'; 'actions' = copy (dotty.protogt.actions); ]; fa.protovt = [ 'name' = 'FA'; 'type' = 'normal'; ]; fa.main = function () { local gnvt , gt ; gnvt = dotty.createviewandgraph(null,'file',fa.protogt,fa.protovt); gt = gnvt.gt ; gt.loadgraph (gt, fa.graphfilename,'file',fa.protogt.graph, 1); fa.currstate = gt.graph.nodes[gt.graph.nodedict[fa.start]]; # <-- Init Node fa.loadtrans ('fa.trans'); fa.setcurrcolor(gt, fa.currstate); fa.focuson (gt , fa.currstate); }; fa.loadtrans = function (filename) { local fd , i ; if (~((fd = openio ('file',filename,'r')) >= 0)) { echo ('cannot open transition file: ',filename); return; } echo ('reading transition file'); i = 0; while ((fa.trans[i] = readline (fd))) i = i + 1; closeio (fd); fa.trani = 0 ; fa.states[0] = fa.currstate ; fa.currstate.count = 1 ; }; fa.next = function (gt) { local label , eid , edge , tran ; if (~(label = fa.trans[fa.trani])) return 0; for (eid in fa.currstate.edges) { edge = fa.currstate.edges[eid]; if (edge.attr.label == label & edge.tail == fa.currstate) { tran = edge ; break ; } } if (tran) { if (fa.trackpath) fa.setedegecolor (gt , tran); sleep(fa.sleep); fa.trani = fa.trani + 1; fa.setcolor (gt , fa.currstate); fa.currstate = (fa.states[fa.trani] = tran.head) ; if (fa.currstate.count) fa.currstate.count = fa.currstate.count + 1; else fa.currstate.count = 1; fa.setcurrcolor (gt, fa.currstate); fa.focuson (gt , fa.currstate); sleep(fa.sleep); } return 1; }; fa.prev = function (gt) { if (fa.trani == 0) return 0; sleep(fa.sleep); remove (fa.trani , fa.states); fa.trani = fa.trani - 1; fa.currstate.count = fa.currstate.count - 1; fa.setcolor (gt , fa.currstate ); fa.currstate = fa.states[fa.trani]; fa.setcurrcolor (gt, fa.currstate); fa.focuson (gt , fa.currstate); return 1; }; fa.setedegecolor = function (gt , edge) { edge.attr.color = fa.trackhighlightcolor; edge.attr.fontcolor = fa.trackhighlightfontcolor; edge.attr.fontsize = fa.trackhighlightfontsize; ge.undrawedge(gt , gt.views , edge); remove('style',edge.attr); gt.unpackedgeattr (gt, edge); gt.drawedge (gt , gt.views , edge); }; fa.setcolor = function (gt , node) { if (node.count) { node.attr.style = 'filled' ; node.attr.color = fa.highlightcolor ; } else { gt.undrawnode (gt , gt.views , node); remove ('style' , node.attr); node.attr.color = fa.normalcolor ; } gt.unpacknodeattr (gt, node); gt.drawnode (gt , gt.views , node); }; fa.setcurrcolor = function (gt , node) { node.attr.style = 'filled' ; node.attr.color = fa.currentcolor ; gt.unpacknodeattr (gt, node); gt.drawnode (gt , gt.views , node); }; fa.focuson = function (gt , node) { gt.setviewcenter (gt.views , node.pos); }; fa.protogt.actions.general['play fwd'] = function (gt , vt , data) { while (fa.next(gt)) ; }; fa.protogt.actions.general['play bwd'] = function (gt , vt , data) { while (fa.prev(gt)) ; }; fa.protogt.actions.general['track node'] = function (gt , vt , data) { if (fa.trackcur) fa.trackcur = 0; else { fa.trackcur = 1; fa.focuson (gt , fa.currstate); } }; fa.protogt.actions.general['track path (y/n)'] = function (gt , vt , data) { if (fa.trackpath) fa.trackpath = 0 ; else fa.trackpath = 1 ; }; fa.protogt.actions.general['inc sleep'] = function (gt , vt , data) { fa.sleep = fa.sleep + 200000; }; fa.protogt.actions.general['dec sleep'] = function (gt , vt , data) { fa.sleep = fa.sleep - 200000; }; fa.protovt.menus = [ 'general' = [ 0 = "undo"; 1 = "paste"; 2 = "do layout"; 3 = "cancel layout"; 4 = "redraw"; 5 = "new graph"; 6 = "load graph"; 7 = "reload graph"; 8 = "open view"; 9 = "copy view"; 10 = "clone view"; 11 = "birdseye view"; 12 = "close view"; 13 = "play fwd"; 14 = "play bwd"; 15 = "inc sleep"; 16 = "dec sleep"; 17 = "zoom in"; 18 = "zoom out"; 19 = "find node"; 20 = "track node"; 21 = "track path (y/n)"; 22 = "print graph"; 23 = "text view"; 24 = "quit"; ]; 'node' = [ 0 = "cut"; 1 = "Cut"; 2 = "copy"; 3 = "Copy"; 4 = "group"; 5 = "Group"; 6 = "delete"; 7 = "Delete"; 8 = "remove"; 9 = "Remove"; 10 = "set attr"; 11 = "print attr"; ]; 'edge' = [ 0 = "cut"; 1 = "Cut"; 2 = "copy"; 3 = "Copy"; 4 = "group"; 5 = "Group"; 6 = "delete"; 7 = "Delete"; 8 = "set attr"; 9 = "print attr"; ]; ]; fa.protovt.uifuncs.rightdown = dotty.protovt.normal.uifuncs.rightdown; fa.protovt.uifuncs.keyup = dotty.protovt.normal.uifuncs.keyup; fa.protovt.uifuncs.redraw = dotty.protovt.normal.uifuncs.redraw; fa.protovt.uifuncs.closeview = dotty.protovt.normal.uifuncs.closeview; fa.protovt.uifuncs.leftup = function (data) { local gt ; gt = dotty.graphs[dotty.views[data.widget].gtid]; if (fa.next(gt) == 0) echo ('at end of log'); }; fa.protovt.uifuncs.middleup = function (data) { local gt ; gt = dotty.graphs[dotty.views[data.widget].gtid]; if (fa.prev(gt) == 0) echo ('at end of log'); };