furnace-xray 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +5 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +60 -0
  5. data/Rakefile +1 -0
  6. data/bin/furnace-xray +23 -0
  7. data/furnace-xray.gemspec +33 -0
  8. data/lib/furnace-xray.rb +1 -0
  9. data/lib/furnace-xray/app/app.rb +56 -0
  10. data/lib/furnace-xray/app/assets/images/chosen-sprite.png +0 -0
  11. data/lib/furnace-xray/app/assets/images/evil_martians_bw_logo.svg +3 -0
  12. data/lib/furnace-xray/app/assets/images/evil_martians_logo.svg +3 -0
  13. data/lib/furnace-xray/app/assets/images/ui/ui-bg_diagonal-maze_20_6e4f1c_10x10.png +0 -0
  14. data/lib/furnace-xray/app/assets/images/ui/ui-bg_diagonal-maze_40_000000_10x10.png +0 -0
  15. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_10_eceadf_60x60.png +0 -0
  16. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_10_f8f7f6_60x60.png +0 -0
  17. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_15_eceadf_60x60.png +0 -0
  18. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_15_f7f3de_60x60.png +0 -0
  19. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_15_ffffff_60x60.png +0 -0
  20. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_65_654b24_60x60.png +0 -0
  21. data/lib/furnace-xray/app/assets/images/ui/ui-bg_fine-grain_68_b83400_60x60.png +0 -0
  22. data/lib/furnace-xray/app/assets/images/ui/ui-icons_222222_256x240.png +0 -0
  23. data/lib/furnace-xray/app/assets/images/ui/ui-icons_3572ac_256x240.png +0 -0
  24. data/lib/furnace-xray/app/assets/images/ui/ui-icons_8c291d_256x240.png +0 -0
  25. data/lib/furnace-xray/app/assets/images/ui/ui-icons_b83400_256x240.png +0 -0
  26. data/lib/furnace-xray/app/assets/images/ui/ui-icons_fbdb93_256x240.png +0 -0
  27. data/lib/furnace-xray/app/assets/images/ui/ui-icons_ffffff_256x240.png +0 -0
  28. data/lib/furnace-xray/app/assets/javascripts/application.js.coffee +219 -0
  29. data/lib/furnace-xray/app/assets/javascripts/lib/drawer.js.coffee +206 -0
  30. data/lib/furnace-xray/app/assets/javascripts/lib/graph.js.coffee +26 -0
  31. data/lib/furnace-xray/app/assets/javascripts/lib/input.js.coffee +134 -0
  32. data/lib/furnace-xray/app/assets/javascripts/lib/input_state.js.coffee +8 -0
  33. data/lib/furnace-xray/app/assets/javascripts/lib/map.js.coffee +45 -0
  34. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/argument.js.coffee +7 -0
  35. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/block.js.coffee +76 -0
  36. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/function.js.coffee +15 -0
  37. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/instruction.js.coffee +33 -0
  38. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/operand.js.coffee +21 -0
  39. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/type.js.coffee +12 -0
  40. data/lib/furnace-xray/app/assets/javascripts/vendor/chosen.jquery.js +1090 -0
  41. data/lib/furnace-xray/app/assets/javascripts/vendor/d3.v3.js +7806 -0
  42. data/lib/furnace-xray/app/assets/javascripts/vendor/dagre.js +4053 -0
  43. data/lib/furnace-xray/app/assets/javascripts/vendor/hotkeys.jquery.js +106 -0
  44. data/lib/furnace-xray/app/assets/javascripts/vendor/jquery.js +9472 -0
  45. data/lib/furnace-xray/app/assets/javascripts/vendor/mustache.js +532 -0
  46. data/lib/furnace-xray/app/assets/javascripts/vendor/stacktrace-0.4.js +424 -0
  47. data/lib/furnace-xray/app/assets/javascripts/vendor/sugar-1.3.8.js +8615 -0
  48. data/lib/furnace-xray/app/assets/javascripts/vendor/ui.jquery.js +14850 -0
  49. data/lib/furnace-xray/app/assets/stylesheets/app.css.sass +199 -0
  50. data/lib/furnace-xray/app/assets/stylesheets/chosen.jquery.css +413 -0
  51. data/lib/furnace-xray/app/assets/stylesheets/elements.css.sass +31 -0
  52. data/lib/furnace-xray/app/assets/stylesheets/graph.css.sass +29 -0
  53. data/lib/furnace-xray/app/assets/stylesheets/ui.jquery.css +1174 -0
  54. data/lib/furnace-xray/app/public/fonts/iconic_stroke.afm +170 -0
  55. data/lib/furnace-xray/app/public/fonts/iconic_stroke.eot +0 -0
  56. data/lib/furnace-xray/app/public/fonts/iconic_stroke.otf +0 -0
  57. data/lib/furnace-xray/app/public/fonts/iconic_stroke.svg +553 -0
  58. data/lib/furnace-xray/app/public/fonts/iconic_stroke.ttf +0 -0
  59. data/lib/furnace-xray/app/public/fonts/iconic_stroke.woff +0 -0
  60. data/lib/furnace-xray/app/public/fonts/iconic_stroke_demo.html +1 -0
  61. data/lib/furnace-xray/app/views/index.haml +52 -0
  62. data/lib/furnace-xray/app/views/nodes/argument.jst.mustache +1 -0
  63. data/lib/furnace-xray/app/views/nodes/block.jst.mustache +4 -0
  64. data/lib/furnace-xray/app/views/nodes/diff/added_line.jst.mustache +1 -0
  65. data/lib/furnace-xray/app/views/nodes/diff/changed_line.jst.mustache +2 -0
  66. data/lib/furnace-xray/app/views/nodes/diff/removed_line.jst.mustache +1 -0
  67. data/lib/furnace-xray/app/views/nodes/diff/unchanged_line.jst.mustache +1 -0
  68. data/lib/furnace-xray/app/views/nodes/function.jst.mustache +1 -0
  69. data/lib/furnace-xray/app/views/nodes/function_removed.jst.mustache +1 -0
  70. data/lib/furnace-xray/app/views/nodes/instruction_typed.jst.mustache +3 -0
  71. data/lib/furnace-xray/app/views/nodes/instruction_void.jst.mustache +3 -0
  72. data/lib/furnace-xray/app/views/nodes/operand_argument.jst.mustache +1 -0
  73. data/lib/furnace-xray/app/views/nodes/operand_basic_block.jst.mustache +1 -0
  74. data/lib/furnace-xray/app/views/nodes/operand_constant.jst.mustache +1 -0
  75. data/lib/furnace-xray/app/views/nodes/operand_constant_function.jst.mustache +1 -0
  76. data/lib/furnace-xray/app/views/nodes/operand_instruction.jst.mustache +1 -0
  77. data/lib/furnace-xray/app/views/nodes/type_constant.jst.mustache +1 -0
  78. data/lib/furnace-xray/app/views/nodes/type_parametric.jst.mustache +3 -0
  79. data/lib/furnace-xray/lib/jst_pages.rb +226 -0
  80. data/lib/furnace-xray/version.rb +5 -0
  81. data/sample.json +1 -0
  82. metadata +251 -0
@@ -0,0 +1,4053 @@
1
+ /*
2
+ Copyright (c) 2012 Chris Pettitt
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+ */
22
+ (function() {
23
+ dagre = {};
24
+ dagre.version = "0.0.6";
25
+ /*
26
+ * Directed multi-graph used during layout.
27
+ */
28
+ dagre.graph = {};
29
+
30
+ /*
31
+ * Creates a new directed multi-graph. This should be invoked with
32
+ * `var g = dagre.graph()` and _not_ `var g = new dagre.graph()`.
33
+ */
34
+ dagre.graph = function() {
35
+ var nodes = {},
36
+ inEdges = {},
37
+ outEdges = {},
38
+ edges = {},
39
+ graph = {},
40
+ idCounter = 0;
41
+
42
+ graph.addNode = function(u, value) {
43
+ if (graph.hasNode(u)) {
44
+ throw new Error("Graph already has node '" + u + "':\n" + graph.toString());
45
+ }
46
+ nodes[u] = { id: u, value: value };
47
+ inEdges[u] = {};
48
+ outEdges[u] = {};
49
+ }
50
+
51
+ graph.delNode = function(u) {
52
+ strictGetNode(u);
53
+
54
+ graph.edges(u).forEach(function(e) { graph.delEdge(e); });
55
+
56
+ delete inEdges[u];
57
+ delete outEdges[u];
58
+ delete nodes[u];
59
+ }
60
+
61
+ graph.node = function(u) {
62
+ return strictGetNode(u).value;
63
+ }
64
+
65
+ graph.hasNode = function(u) {
66
+ return u in nodes;
67
+ }
68
+
69
+ graph.addEdge = function(e, source, target, value) {
70
+ strictGetNode(source);
71
+ strictGetNode(target);
72
+
73
+ if (e === null) {
74
+ e = "_ANON-" + ++idCounter;
75
+ }
76
+ else if (graph.hasEdge(e)) {
77
+ throw new Error("Graph already has edge '" + e + "':\n" + graph.toString());
78
+ }
79
+
80
+ edges[e] = { id: e, source: source, target: target, value: value };
81
+ addEdgeToMap(inEdges[target], source, e);
82
+ addEdgeToMap(outEdges[source], target, e);
83
+ }
84
+
85
+ graph.delEdge = function(e) {
86
+ var edge = strictGetEdge(e);
87
+ delEdgeFromMap(inEdges[edge.target], edge.source, e)
88
+ delEdgeFromMap(outEdges[edge.source], edge.target, e)
89
+ delete edges[e];
90
+ }
91
+
92
+ graph.edge = function(e) {
93
+ return strictGetEdge(e).value;
94
+ }
95
+
96
+ graph.source = function(e) {
97
+ return strictGetEdge(e).source;
98
+ }
99
+
100
+ graph.target = function(e) {
101
+ return strictGetEdge(e).target;
102
+ }
103
+
104
+ graph.hasEdge = function(e) {
105
+ return e in edges;
106
+ }
107
+
108
+ graph.successors = function(u) {
109
+ strictGetNode(u);
110
+ return keys(outEdges[u]).map(function(v) { return nodes[v].id; });
111
+ }
112
+
113
+ graph.predecessors = function(u) {
114
+ strictGetNode(u);
115
+ return keys(inEdges[u]).map(function(v) { return nodes[v].id; });
116
+ }
117
+
118
+ graph.neighbors = function(u) {
119
+ strictGetNode(u);
120
+ var vs = {};
121
+ keys(outEdges[u]).map(function(v) { vs[v] = true; });
122
+ keys(inEdges[u]).map(function(v) { vs[v] = true; });
123
+ return keys(vs).map(function(v) { return nodes[v].id; });
124
+ }
125
+
126
+ graph.nodes = function() {
127
+ var nodes = [];
128
+ graph.eachNode(function(id, _) { nodes.push(id); });
129
+ return nodes;
130
+ }
131
+
132
+ graph.eachNode = function(func) {
133
+ for (var k in nodes) {
134
+ var node = nodes[k];
135
+ func(node.id, node.value);
136
+ }
137
+ }
138
+
139
+ /*
140
+ * Return all edges with no arguments,
141
+ * the ones that are incident on a node (one argument),
142
+ * or all edges from a source to a target (two arguments)
143
+ */
144
+ graph.edges = function(u, v) {
145
+ var es, sourceEdges;
146
+ if (!arguments.length) {
147
+ es = [];
148
+ graph.eachEdge(function(id) { es.push(id); });
149
+ return es;
150
+ } else if (arguments.length === 1) {
151
+ return union([graph.inEdges(u), graph.outEdges(u)]);
152
+ } else if (arguments.length === 2) {
153
+ strictGetNode(u);
154
+ strictGetNode(v);
155
+ sourceEdges = outEdges[u];
156
+ es = (v in sourceEdges) ? keys(sourceEdges[v].edges) : [];
157
+ return es.map(function(e) { return edges[e].id });
158
+ }
159
+ };
160
+
161
+ graph.eachEdge = function(func) {
162
+ for (var k in edges) {
163
+ var edge = edges[k];
164
+ func(edge.id, edge.source, edge.target, edge.value);
165
+ }
166
+ }
167
+
168
+ /*
169
+ * Return all in edges to a target node
170
+ */
171
+ graph.inEdges = function(target) {
172
+ strictGetNode(target);
173
+ return concat(values(inEdges[target]).map(function(es) { return keys(es.edges); }));
174
+ };
175
+
176
+ /*
177
+ * Return all out edges from a source node
178
+ */
179
+ graph.outEdges = function(source) {
180
+ strictGetNode(source);
181
+ return concat(values(outEdges[source]).map(function(es) { return keys(es.edges); }));
182
+ };
183
+
184
+ graph.subgraph = function(us) {
185
+ var g = dagre.graph();
186
+ us.forEach(function(u) {
187
+ g.addNode(u, graph.node(u));
188
+ });
189
+ values(edges).forEach(function(e) {
190
+ if (g.hasNode(e.source) && g.hasNode(e.target)) {
191
+ g.addEdge(e.id, e.source, e.target, graph.edge(e.id));
192
+ }
193
+ });
194
+ return g;
195
+ };
196
+
197
+ graph.toString = function() {
198
+ var str = "GRAPH:\n";
199
+ str += " Nodes:\n";
200
+ keys(nodes).forEach(function(u) {
201
+ str += " " + u + ": " + JSON.stringify(nodes[u].value) + "\n";
202
+ });
203
+ str += " Edges:\n";
204
+ keys(edges).forEach(function(e) {
205
+ var edge = edges[e];
206
+ str += " " + e + " (" + edge.source + " -> " + edge.target + "): " + JSON.stringify(edges[e].value) + "\n";
207
+ });
208
+ return str;
209
+ };
210
+
211
+ function addEdgeToMap(map, v, e) {
212
+ var vEntry = map[v];
213
+ if (!vEntry) {
214
+ vEntry = map[v] = { count: 0, edges: {} };
215
+ }
216
+ vEntry.count++;
217
+ vEntry.edges[e] = true;
218
+ }
219
+
220
+ function delEdgeFromMap(map, v, e) {
221
+ var vEntry = map[v];
222
+ if (--vEntry.count == 0) {
223
+ delete map[v];
224
+ } else {
225
+ delete vEntry.edges[e];
226
+ }
227
+ }
228
+
229
+ function strictGetNode(u) {
230
+ var node = nodes[u];
231
+ if (!(u in nodes)) {
232
+ throw new Error("Node '" + u + "' is not in graph:\n" + graph.toString());
233
+ }
234
+ return node;
235
+ }
236
+
237
+ function strictGetEdge(e) {
238
+ var edge = edges[e];
239
+ if (!edge) {
240
+ throw new Error("Edge '" + e + "' is not in graph:\n" + graph.toString());
241
+ }
242
+ return edge;
243
+ }
244
+
245
+ return graph;
246
+ }
247
+ dagre.layout = function() {
248
+ // External configuration
249
+ var config = {
250
+ // Nodes to lay out. At minimum must have `width` and `height` attributes.
251
+ nodes: [],
252
+ // Edges to lay out. At mimimum must have `source` and `target` attributes.
253
+ edges: [],
254
+ // How much debug information to include?
255
+ debugLevel: 0,
256
+ };
257
+
258
+ var timer = createTimer();
259
+
260
+ // Phase functions
261
+ var
262
+ acyclic = dagre.layout.acyclic(),
263
+ rank = dagre.layout.rank(),
264
+ order = dagre.layout.order(),
265
+ position = dagre.layout.position();
266
+
267
+ // This layout object
268
+ var self = {};
269
+
270
+ self.nodes = propertyAccessor(self, config, "nodes");
271
+ self.edges = propertyAccessor(self, config, "edges");
272
+
273
+ self.orderIters = delegateProperty(order.iterations);
274
+
275
+ self.nodeSep = delegateProperty(position.nodeSep);
276
+ self.edgeSep = delegateProperty(position.edgeSep);
277
+ self.universalSep = delegateProperty(position.universalSep);
278
+ self.rankSep = delegateProperty(position.rankSep);
279
+ self.rankDir = delegateProperty(position.rankDir);
280
+ self.debugAlignment = delegateProperty(position.debugAlignment);
281
+
282
+ self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
283
+ timer.enabled(x);
284
+ acyclic.debugLevel(x);
285
+ rank.debugLevel(x);
286
+ order.debugLevel(x);
287
+ position.debugLevel(x);
288
+ });
289
+
290
+ self.run = timer.wrap("Total layout", run);
291
+
292
+ return self;
293
+
294
+ // Build graph and save mapping of generated ids to original nodes and edges
295
+ function init() {
296
+ var g = dagre.graph();
297
+ var nextId = 0;
298
+
299
+ // Tag each node so that we can properly represent relationships when
300
+ // we add edges. Also copy relevant dimension information.
301
+ config.nodes.forEach(function(u) {
302
+ var id = "id" in u ? u.id : "_N" + nextId++;
303
+ u.dagre = { id: id, width: u.width, height: u.height };
304
+ g.addNode(id, u.dagre);
305
+ });
306
+
307
+ config.edges.forEach(function(e) {
308
+ var source = e.source.dagre.id;
309
+ if (!g.hasNode(source)) {
310
+ throw new Error("Source node for '" + e + "' not in node list");
311
+ }
312
+
313
+ var target = e.target.dagre.id;
314
+ if (!g.hasNode(target)) {
315
+ throw new Error("Target node for '" + e + "' not in node list");
316
+ }
317
+
318
+ e.dagre = {
319
+ points: []
320
+ };
321
+
322
+ // Track edges that aren't self loops - layout does nothing for self
323
+ // loops, so they can be skipped.
324
+ if (source !== target) {
325
+ var id = "id" in e ? e.id : "_E" + nextId++;
326
+ e.dagre.id = id;
327
+ e.dagre.minLen = e.minLen || 1;
328
+ e.dagre.width = e.width || 0;
329
+ e.dagre.height = e.height || 0;
330
+ g.addEdge(id, source, target, e.dagre);
331
+ }
332
+ });
333
+
334
+ return g;
335
+ }
336
+
337
+ function run () {
338
+ var rankSep = self.rankSep();
339
+ try {
340
+ if (!config.nodes.length) {
341
+ return;
342
+ }
343
+
344
+ // Build internal graph
345
+ var g = init();
346
+
347
+ // Make space for edge labels
348
+ g.eachEdge(function(e, s, t, a) {
349
+ a.minLen *= 2;
350
+ });
351
+ self.rankSep(rankSep / 2);
352
+
353
+ // Reverse edges to get an acyclic graph, we keep the graph in an acyclic
354
+ // state until the very end.
355
+ acyclic.run(g);
356
+
357
+ // Determine the rank for each node. Nodes with a lower rank will appear
358
+ // above nodes of higher rank.
359
+ rank.run(g);
360
+
361
+ // Normalize the graph by ensuring that every edge is proper (each edge has
362
+ // a length of 1). We achieve this by adding dummy nodes to long edges,
363
+ // thus shortening them.
364
+ normalize(g);
365
+
366
+ // Order the nodes so that edge crossings are minimized.
367
+ order.run(g);
368
+
369
+ // Find the x and y coordinates for every node in the graph.
370
+ position.run(g);
371
+
372
+ // De-normalize the graph by removing dummy nodes and augmenting the
373
+ // original long edges with coordinate information.
374
+ undoNormalize(g);
375
+
376
+ // Reverses points for edges that are in a reversed state.
377
+ fixupEdgePoints(g);
378
+
379
+ // Reverse edges that were revered previously to get an acyclic graph.
380
+ acyclic.undo(g);
381
+ } finally {
382
+ self.rankSep(rankSep);
383
+ }
384
+
385
+ return self;
386
+ }
387
+
388
+ // Assumes input graph has no self-loops and is otherwise acyclic.
389
+ function normalize(g) {
390
+ var dummyCount = 0;
391
+ g.eachEdge(function(e, s, t, a) {
392
+ var sourceRank = g.node(s).rank;
393
+ var targetRank = g.node(t).rank;
394
+ if (sourceRank + 1 < targetRank) {
395
+ for (var u = s, rank = sourceRank + 1, i = 0; rank < targetRank; ++rank, ++i) {
396
+ var v = "_D" + ++dummyCount;
397
+ var node = {
398
+ width: a.width,
399
+ height: a.height,
400
+ edge: { id: e, source: s, target: t, attrs: a },
401
+ rank: rank,
402
+ dummy: true
403
+ };
404
+
405
+ // If this node represents a bend then we will use it as a control
406
+ // point. For edges with 2 segments this will be the center dummy
407
+ // node. For edges with more than two segments, this will be the
408
+ // first and last dummy node.
409
+ if (i === 0) node.index = 0;
410
+ else if (rank + 1 === targetRank) node.index = 1;
411
+
412
+ g.addNode(v, node);
413
+ g.addEdge(null, u, v, {});
414
+ u = v;
415
+ }
416
+ g.addEdge(null, u, t, {});
417
+ g.delEdge(e);
418
+ }
419
+ });
420
+ }
421
+
422
+ function undoNormalize(g) {
423
+ var visited = {};
424
+
425
+ g.eachNode(function(u, a) {
426
+ if (a.dummy && "index" in a) {
427
+ var edge = a.edge;
428
+ if (!g.hasEdge(edge.id)) {
429
+ g.addEdge(edge.id, edge.source, edge.target, edge.attrs);
430
+ }
431
+ var points = g.edge(edge.id).points;
432
+ points[a.index] = { x: a.x, y: a.y, ul: a.ul, ur: a.ur, dl: a.dl, dr: a.dr };
433
+ g.delNode(u);
434
+ }
435
+ });
436
+ }
437
+
438
+ function fixupEdgePoints(g) {
439
+ g.eachEdge(function(e, s, t, a) { if (a.reversed) a.points.reverse(); });
440
+ }
441
+
442
+ function delegateProperty(f) {
443
+ return function() {
444
+ if (!arguments.length) return f();
445
+ f.apply(null, arguments);
446
+ return self;
447
+ }
448
+ }
449
+ }
450
+ dagre.layout.acyclic = function() {
451
+ // External configuration
452
+ var config = {
453
+ debugLevel: 0
454
+ }
455
+
456
+ var timer = createTimer();
457
+
458
+ var self = {};
459
+
460
+ self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
461
+ timer.enabled(x);
462
+ });
463
+
464
+ self.run = timer.wrap("Acyclic Phase", run);
465
+
466
+ self.undo = function(g) {
467
+ g.eachEdge(function(e, s, t, a) {
468
+ if (a.reversed) {
469
+ delete a.reversed;
470
+ g.delEdge(e);
471
+ g.addEdge(e, t, s, a);
472
+ }
473
+ });
474
+ }
475
+
476
+ return self;
477
+
478
+ function run(g) {
479
+ var onStack = {},
480
+ visited = {},
481
+ reverseCount = 0;
482
+
483
+ function dfs(u) {
484
+ if (u in visited) return;
485
+
486
+ visited[u] = onStack[u] = true;
487
+ g.outEdges(u).forEach(function(e) {
488
+ var t = g.target(e),
489
+ a;
490
+
491
+ if (t in onStack) {
492
+ a = g.edge(e);
493
+ g.delEdge(e);
494
+ a.reversed = true;
495
+ ++reverseCount;
496
+ g.addEdge(e, t, u, a);
497
+ } else {
498
+ dfs(t);
499
+ }
500
+ });
501
+
502
+ delete onStack[u];
503
+ }
504
+
505
+ g.eachNode(function(u) { dfs(u); });
506
+
507
+ if (config.debugLevel >= 2) console.log("Acyclic Phase: reversed " + reverseCount + " edge(s)");
508
+ }
509
+ };
510
+ dagre.layout.rank = function() {
511
+ // External configuration
512
+ var config = {
513
+ debugLevel: 0
514
+ };
515
+
516
+ var timer = createTimer();
517
+
518
+ var self = {};
519
+
520
+ self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
521
+ timer.enabled(x);
522
+ });
523
+
524
+ self.run = timer.wrap("Rank Phase", run);
525
+
526
+ return self;
527
+
528
+ function run(g) {
529
+ initRank(g);
530
+ components(g).forEach(function(cmpt) {
531
+ var subgraph = g.subgraph(cmpt);
532
+ feasibleTree(subgraph);
533
+ normalize(subgraph);
534
+ });
535
+ };
536
+
537
+
538
+ function initRank(g) {
539
+ var minRank = {};
540
+ var pq = priorityQueue();
541
+
542
+ g.eachNode(function(u) {
543
+ pq.add(u, g.inEdges(u).length);
544
+ minRank[u] = 0;
545
+ });
546
+
547
+ while (pq.size() > 0) {
548
+ var minId = pq.min();
549
+ if (pq.priority(minId) > 0) {
550
+ throw new Error("Input graph is not acyclic: " + g.toString());
551
+ }
552
+ pq.removeMin();
553
+
554
+ var rank = minRank[minId];
555
+ g.node(minId).rank = rank;
556
+
557
+ g.outEdges(minId).forEach(function(e) {
558
+ var target = g.target(e);
559
+ minRank[target] = Math.max(minRank[target], rank + (g.edge(e).minLen || 1));
560
+ pq.decrease(target, pq.priority(target) - 1);
561
+ });
562
+ }
563
+ }
564
+
565
+ function feasibleTree(g) {
566
+ // Precompute minimum lengths for each directed edge
567
+ var minLen = {};
568
+ g.eachEdge(function(e, source, target, edge) {
569
+ var id = incidenceId(source, target);
570
+ minLen[id] = Math.max(minLen[id] || 1, edge.minLen || 1);
571
+ });
572
+
573
+ var tree = dagre.util.prim(g, function(u, v) {
574
+ return Math.abs(g.node(u).rank - g.node(v).rank) - minLen[incidenceId(u, v)];
575
+ });
576
+
577
+ var visited = {};
578
+ function dfs(u, rank) {
579
+ visited[u] = true;
580
+ g.node(u).rank = rank;
581
+
582
+ tree[u].forEach(function(v) {
583
+ if (!(v in visited)) {
584
+ var delta = minLen[incidenceId(u, v)];
585
+ dfs(v, rank + (g.edges(u, v).length ? delta : -delta));
586
+ }
587
+ });
588
+ }
589
+
590
+ dfs(g.nodes()[0], 0);
591
+
592
+ return tree;
593
+ }
594
+
595
+ function normalize(g) {
596
+ var m = min(g.nodes().map(function(u) { return g.node(u).rank; }));
597
+ g.eachNode(function(u, node) { node.rank -= m; });
598
+ }
599
+
600
+ /*
601
+ * This id can be used to group (in an undirected manner) multi-edges
602
+ * incident on the same two nodes.
603
+ */
604
+ function incidenceId(u, v) {
605
+ return u < v ? u.length + ":" + u + "-" + v : v.length + ":" + v + "-" + u;
606
+ }
607
+ }
608
+ dagre.layout.order = function() {
609
+ var config = {
610
+ iterations: 24, // max number of iterations
611
+ debugLevel: 0
612
+ };
613
+
614
+ var timer = createTimer();
615
+
616
+ var self = {};
617
+
618
+ self.iterations = propertyAccessor(self, config, "iterations");
619
+
620
+ self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
621
+ timer.enabled(x);
622
+ });
623
+
624
+ self.run = timer.wrap("Order Phase", run);
625
+
626
+ // Expose barycenterLayer for testing
627
+ self._barycenterLayer = barycenterLayer;
628
+
629
+ return self;
630
+
631
+ function run(g) {
632
+ var layering = initOrder(g);
633
+ var bestLayering = copyLayering(layering);
634
+ var bestCC = crossCount(g, layering);
635
+
636
+ if (config.debugLevel >= 2) {
637
+ console.log("Order phase start cross count: " + bestCC);
638
+ }
639
+
640
+ var cc, i, lastBest;
641
+ for (i = 0, lastBest = 0; lastBest < 4 && i < config.iterations; ++i, ++lastBest) {
642
+ cc = sweep(g, i, layering);
643
+ if (cc < bestCC) {
644
+ bestLayering = copyLayering(layering);
645
+ bestCC = cc;
646
+ lastBest = 0;
647
+ }
648
+ if (config.debugLevel >= 3) {
649
+ console.log("Order phase iter " + i + " cross count: " + bestCC);
650
+ }
651
+ }
652
+
653
+ bestLayering.forEach(function(layer) {
654
+ layer.forEach(function(u, i) {
655
+ g.node(u).order = i;
656
+ });
657
+ });
658
+
659
+ if (config.debugLevel >= 2) {
660
+ console.log("Order iterations: " + i);
661
+ console.log("Order phase best cross count: " + bestCC);
662
+ }
663
+
664
+ return bestLayering;
665
+ }
666
+
667
+ function initOrder(g) {
668
+ var layering = [];
669
+ g.eachNode(function(n, a) {
670
+ var layer = layering[a.rank] || (layering[a.rank] = []);
671
+ layer.push(n);
672
+ });
673
+ return layering;
674
+ }
675
+
676
+ /*
677
+ * Returns a function that will return the predecessors for a node. This
678
+ * function differs from `g.predecessors(u)` in that a predecessor appears
679
+ * for each incident edge (`g.predecessors(u)` treats predecessors as a set).
680
+ * This allows pseudo-weighting of predecessor nodes.
681
+ */
682
+ function multiPredecessors(g) {
683
+ return function(u) {
684
+ var preds = [];
685
+ g.inEdges(u).forEach(function(e) {
686
+ preds.push(g.source(e));
687
+ });
688
+ return preds;
689
+ }
690
+ }
691
+
692
+ /*
693
+ * Same as `multiPredecessors(g)` but for successors.
694
+ */
695
+ function multiSuccessors(g) {
696
+ return function(u) {
697
+ var sucs = [];
698
+ g.outEdges(u).forEach(function(e) {
699
+ sucs.push(g.target(e));
700
+ });
701
+ return sucs;
702
+ }
703
+ }
704
+
705
+ function sweep(g, iter, layering) {
706
+ if (iter % 2 === 0) {
707
+ for (var i = 1; i < layering.length; ++i) {
708
+ barycenterLayer(layering[i - 1], layering[i], multiPredecessors(g));
709
+ }
710
+ } else {
711
+ for (var i = layering.length - 2; i >= 0; --i) {
712
+ barycenterLayer(layering[i + 1], layering[i], multiSuccessors(g));
713
+ }
714
+ }
715
+ return crossCount(g, layering);
716
+ }
717
+
718
+ /*
719
+ * Given a fixed layer and a movable layer in a graph this function will
720
+ * attempt to find an improved ordering for the movable layer such that
721
+ * edge crossings may be reduced.
722
+ *
723
+ * This algorithm is based on the barycenter method.
724
+ */
725
+ function barycenterLayer(fixed, movable, predecessors) {
726
+ var pos = layerPos(movable);
727
+ var bs = barycenters(fixed, movable, predecessors);
728
+
729
+ var toSort = movable.filter(function(u) { return bs[u] !== -1; });
730
+ toSort.sort(function(x, y) {
731
+ return bs[x] - bs[y] || pos[x] - pos[y];
732
+ });
733
+
734
+ for (var i = movable.length - 1; i >= 0; --i) {
735
+ if (bs[movable[i]] !== -1) {
736
+ movable[i] = toSort.pop();
737
+ }
738
+ }
739
+ }
740
+
741
+ /*
742
+ * Given a fixed layer and a movable layer in a graph, this function will
743
+ * return weights for the movable layer that can be used to reorder the layer
744
+ * for potentially reduced edge crossings.
745
+ */
746
+ function barycenters(fixed, movable, predecessors) {
747
+ var pos = layerPos(fixed), // Position of node in fixed list
748
+ bs = {}; // Barycenters for each node
749
+
750
+ movable.forEach(function(u) {
751
+ var b = -1;
752
+ var preds = predecessors(u);
753
+ if (preds.length > 0) {
754
+ b = 0;
755
+ preds.forEach(function(v) { b += pos[v]; });
756
+ b = b / preds.length;
757
+ }
758
+ bs[u] = b;
759
+ });
760
+
761
+ return bs;
762
+ }
763
+
764
+ function copyLayering(layering) {
765
+ return layering.map(function(l) { return l.slice(0); });
766
+ }
767
+ }
768
+
769
+ var crossCount = dagre.layout.order.crossCount = function(g, layering) {
770
+ var cc = 0;
771
+ var prevLayer;
772
+ layering.forEach(function(layer) {
773
+ if (prevLayer) {
774
+ cc += bilayerCrossCount(g, prevLayer, layer);
775
+ }
776
+ prevLayer = layer;
777
+ });
778
+ return cc;
779
+ }
780
+
781
+ /*
782
+ * This function searches through a ranked and ordered graph and counts the
783
+ * number of edges that cross. This algorithm is derived from:
784
+ *
785
+ * W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004)
786
+ */
787
+ var bilayerCrossCount = dagre.layout.order.bilayerCrossCount = function(g, layer1, layer2) {
788
+ var layer2Pos = layerPos(layer2);
789
+
790
+ var indices = [];
791
+ layer1.forEach(function(u) {
792
+ var nodeIndices = [];
793
+ g.outEdges(u).forEach(function(e) { nodeIndices.push(layer2Pos[g.target(e)]); });
794
+ nodeIndices.sort(function(x, y) { return x - y; });
795
+ indices = indices.concat(nodeIndices);
796
+ });
797
+
798
+ var firstIndex = 1;
799
+ while (firstIndex < layer2.length) firstIndex <<= 1;
800
+
801
+ var treeSize = 2 * firstIndex - 1;
802
+ firstIndex -= 1;
803
+
804
+ var tree = [];
805
+ for (var i = 0; i < treeSize; ++i) { tree[i] = 0; }
806
+
807
+ var cc = 0;
808
+ indices.forEach(function(i) {
809
+ var treeIndex = i + firstIndex;
810
+ ++tree[treeIndex];
811
+ var weightSum = 0;
812
+ while (treeIndex > 0) {
813
+ if (treeIndex % 2) {
814
+ cc += tree[treeIndex + 1];
815
+ }
816
+ treeIndex = (treeIndex - 1) >> 1;
817
+ ++tree[treeIndex];
818
+ }
819
+ });
820
+
821
+ return cc;
822
+ }
823
+
824
+ function layerPos(layer) {
825
+ var pos = {};
826
+ layer.forEach(function(u, i) { pos[u] = i; });
827
+ return pos;
828
+ }
829
+ /*
830
+ * The algorithms here are based on Brandes and Köpf, "Fast and Simple
831
+ * Horizontal Coordinate Assignment".
832
+ */
833
+ dagre.layout.position = function() {
834
+ // External configuration
835
+ var config = {
836
+ nodeSep: 50,
837
+ edgeSep: 10,
838
+ universalSep: null,
839
+ rankSep: 30,
840
+ rankDir: "TB",
841
+ debugLevel: 0
842
+ };
843
+
844
+ var timer = createTimer();
845
+
846
+ var self = {};
847
+
848
+ self.nodeSep = propertyAccessor(self, config, "nodeSep");
849
+ self.edgeSep = propertyAccessor(self, config, "edgeSep");
850
+ // If not null this separation value is used for all nodes and edges
851
+ // regardless of their widths. `nodeSep` and `edgeSep` are ignored with this
852
+ // option.
853
+ self.universalSep = propertyAccessor(self, config, "universalSep");
854
+ self.rankSep = propertyAccessor(self, config, "rankSep");
855
+ self.rankDir = propertyAccessor(self, config, "rankDir");
856
+ self.debugLevel = propertyAccessor(self, config, "debugLevel", function(x) {
857
+ timer.enabled(x);
858
+ });
859
+
860
+ self.run = timer.wrap("Position Phase", run);
861
+
862
+ return self;
863
+
864
+ function run(g) {
865
+ var layering = [];
866
+ g.eachNode(function(u, node) {
867
+ var layer = layering[node.rank] || (layering[node.rank] = []);
868
+ layer[node.order] = u;
869
+ });
870
+
871
+ var conflicts = findConflicts(g, layering);
872
+
873
+ var xss = {};
874
+ ["u", "d"].forEach(function(vertDir) {
875
+ if (vertDir === "d") layering.reverse();
876
+
877
+ ["l", "r"].forEach(function(horizDir) {
878
+ if (horizDir === "r") reverseInnerOrder(layering);
879
+
880
+ var dir = vertDir + horizDir;
881
+ var align = verticalAlignment(g, layering, conflicts, vertDir === "u" ? "predecessors" : "successors");
882
+ xss[dir]= horizontalCompaction(g, layering, align.pos, align.root, align.align);
883
+ if (horizDir === "r") flipHorizontally(xss[dir]);
884
+
885
+ if (horizDir === "r") reverseInnerOrder(layering);
886
+ });
887
+
888
+ if (vertDir === "d") layering.reverse();
889
+ });
890
+
891
+ balance(g, layering, xss);
892
+ g.eachNode(function(v) {
893
+ var xs = [];
894
+ for (var alignment in xss) {
895
+ xDebug(alignment, g, v, xss[alignment][v]);
896
+ xs.push(xss[alignment][v]);
897
+ }
898
+ xs.sort(function(x, y) { return x - y; });
899
+ x(g, v, (xs[1] + xs[2]) / 2);
900
+ });
901
+
902
+ // Translate layout so left edge of bounding rectangle has coordinate 0
903
+ var minX = min(g.nodes().map(function(u) { return x(g, u) - width(g, u) / 2; }));
904
+ g.eachNode(function(u) { x(g, u, x(g, u) - minX); });
905
+
906
+ // Align y coordinates with ranks
907
+ var posY = 0;
908
+ layering.forEach(function(layer) {
909
+ var maxHeight = max(layer.map(function(u) { return height(g, u); }));
910
+ posY += maxHeight / 2;
911
+ layer.forEach(function(u) { y(g, u, posY); });
912
+ posY += maxHeight / 2 + config.rankSep;
913
+ });
914
+ };
915
+
916
+ /*
917
+ * Generate an ID that can be used to represent any undirected edge that is
918
+ * incident on `u` and `v`.
919
+ */
920
+ function undirEdgeId(u, v) {
921
+ return u < v
922
+ ? u.toString().length + ":" + u + "-" + v
923
+ : v.toString().length + ":" + v + "-" + u;
924
+ }
925
+
926
+ function findConflicts(g, layering) {
927
+ var conflicts = {}, // Set of conflicting edge ids
928
+ pos = {}; // Position of node in its layer
929
+
930
+ if (layering.length <= 2) return conflicts;
931
+
932
+ layering[1].forEach(function(u, i) { pos[u] = i; });
933
+ for (var i = 1; i < layering.length - 1; ++i) {
934
+ var prevLayer = layering[i];
935
+ var currLayer = layering[i+1];
936
+ var k0 = 0; // Position of the last inner segment in the previous layer
937
+ var l = 0; // Current position in the current layer (for iteration up to `l1`)
938
+
939
+ // Scan current layer for next node that is incident to an inner segement
940
+ // between layering[i+1] and layering[i].
941
+ for (var l1 = 0; l1 < currLayer.length; ++l1) {
942
+ var u = currLayer[l1]; // Next inner segment in the current layer or
943
+ // last node in the current layer
944
+ pos[u] = l1;
945
+
946
+ var k1 = undefined; // Position of the next inner segment in the previous layer or
947
+ // the position of the last element in the previous layer
948
+ if (g.node(u).dummy) {
949
+ var uPred = g.predecessors(u)[0];
950
+ if (g.node(uPred).dummy)
951
+ k1 = pos[uPred];
952
+ }
953
+ if (k1 === undefined && l1 === currLayer.length - 1)
954
+ k1 = prevLayer.length - 1;
955
+
956
+ if (k1 !== undefined) {
957
+ for (; l <= l1; ++l) {
958
+ g.predecessors(currLayer[l]).forEach(function(v) {
959
+ var k = pos[v];
960
+ if (k < k0 || k > k1)
961
+ conflicts[undirEdgeId(currLayer[l], v)] = true;
962
+ });
963
+ }
964
+ k0 = k1;
965
+ }
966
+ }
967
+ }
968
+
969
+ return conflicts;
970
+ }
971
+
972
+ function verticalAlignment(g, layering, conflicts, relationship) {
973
+ var pos = {}, // Position for a node in its layer
974
+ root = {}, // Root of the block that the node participates in
975
+ align = {}; // Points to the next node in the block or, if the last
976
+ // element in the block, points to the first block's root
977
+
978
+ layering.forEach(function(layer) {
979
+ layer.forEach(function(u, i) {
980
+ root[u] = u;
981
+ align[u] = u;
982
+ pos[u] = i;
983
+ });
984
+ });
985
+
986
+ layering.forEach(function(layer) {
987
+ var prevIdx = -1;
988
+ layer.forEach(function(v) {
989
+ var related = g[relationship](v), // Adjacent nodes from the previous layer
990
+ mid; // The mid point in the related array
991
+
992
+ if (related.length > 0) {
993
+ related.sort(function(x, y) { return pos[x] - pos[y]; });
994
+ mid = (related.length - 1) / 2;
995
+ related.slice(Math.floor(mid), Math.ceil(mid) + 1).forEach(function(u) {
996
+ if (align[v] === v) {
997
+ if (!conflicts[undirEdgeId(u, v)] && prevIdx < pos[u]) {
998
+ align[u] = v;
999
+ align[v] = root[v] = root[u];
1000
+ prevIdx = pos[u];
1001
+ }
1002
+ }
1003
+ });
1004
+ }
1005
+ });
1006
+ });
1007
+
1008
+ return { pos: pos, root: root, align: align };
1009
+ }
1010
+
1011
+ // This function deviates from the standard BK algorithm in two ways. First
1012
+ // it takes into account the size of the nodes. Second it includes a fix to
1013
+ // the original algorithm that is described in Carstens, "Node and Label
1014
+ // Placement in a Layered Layout Algorithm".
1015
+ function horizontalCompaction(g, layering, pos, root, align) {
1016
+ var sink = {}, // Mapping of node id -> sink node id for class
1017
+ shift = {}, // Mapping of sink node id -> x delta
1018
+ pred = {}, // Mapping of node id -> predecessor node (or null)
1019
+ xs = {}; // Calculated X positions
1020
+
1021
+ layering.forEach(function(layer) {
1022
+ layer.forEach(function(u, i) {
1023
+ sink[u] = u;
1024
+ if (i > 0)
1025
+ pred[u] = layer[i - 1];
1026
+ });
1027
+ });
1028
+
1029
+ function placeBlock(v) {
1030
+ if (!(v in xs)) {
1031
+ xs[v] = 0;
1032
+ var w = v;
1033
+ do {
1034
+ if (pos[w] > 0) {
1035
+ var u = root[pred[w]];
1036
+ placeBlock(u);
1037
+ if (sink[v] === v) {
1038
+ sink[v] = sink[u];
1039
+ }
1040
+ var delta = sep(g, pred[w]) + sep(g, w);
1041
+ if (sink[v] !== sink[u]) {
1042
+ shift[sink[u]] = Math.min(shift[sink[u]] || Number.POSITIVE_INFINITY, xs[v] - xs[u] - delta);
1043
+ } else {
1044
+ xs[v] = Math.max(xs[v], xs[u] + delta);
1045
+ }
1046
+ }
1047
+ w = align[w];
1048
+ } while (w !== v);
1049
+ }
1050
+ }
1051
+
1052
+ // Root coordinates relative to sink
1053
+ values(root).forEach(function(v) {
1054
+ placeBlock(v);
1055
+ });
1056
+
1057
+ // Absolute coordinates
1058
+ layering.forEach(function(layer) {
1059
+ layer.forEach(function(v) {
1060
+ xs[v] = xs[root[v]];
1061
+ var xDelta = shift[sink[v]];
1062
+ if (root[v] === v && xDelta < Number.POSITIVE_INFINITY)
1063
+ xs[v] += xDelta;
1064
+ });
1065
+ });
1066
+
1067
+ return xs;
1068
+ }
1069
+
1070
+ function findMinCoord(g, layering, xs) {
1071
+ return min(layering.map(function(layer) {
1072
+ var u = layer[0];
1073
+ return xs[u];
1074
+ }));
1075
+ }
1076
+
1077
+ function findMaxCoord(g, layering, xs) {
1078
+ return max(layering.map(function(layer) {
1079
+ var u = layer[layer.length - 1];
1080
+ return xs[u];
1081
+ }));
1082
+ }
1083
+
1084
+ function balance(g, layering, xss) {
1085
+ var min = {}, // Min coordinate for the alignment
1086
+ max = {}, // Max coordinate for the alginment
1087
+ smallestAlignment,
1088
+ shift = {}; // Amount to shift a given alignment
1089
+
1090
+ var smallest = Number.POSITIVE_INFINITY;
1091
+ for (var alignment in xss) {
1092
+ var xs = xss[alignment];
1093
+ min[alignment] = findMinCoord(g, layering, xs);
1094
+ max[alignment] = findMaxCoord(g, layering, xs);
1095
+ var w = max[alignment] - min[alignment];
1096
+ if (w < smallest) {
1097
+ smallest = w;
1098
+ smallestAlignment = alignment;
1099
+ }
1100
+ }
1101
+
1102
+ // Determine how much to adjust positioning for each alignment
1103
+ ["u", "d"].forEach(function(vertDir) {
1104
+ ["l", "r"].forEach(function(horizDir) {
1105
+ var alignment = vertDir + horizDir;
1106
+ shift[alignment] = horizDir === "l"
1107
+ ? min[smallestAlignment] - min[alignment]
1108
+ : max[smallestAlignment] - max[alignment];
1109
+ });
1110
+ });
1111
+
1112
+ // Find average of medians for xss array
1113
+ for (var alignment in xss) {
1114
+ g.eachNode(function(v) {
1115
+ xss[alignment][v] += shift[alignment];
1116
+ });
1117
+ };
1118
+ }
1119
+
1120
+ function flipHorizontally(xs) {
1121
+ for (var u in xs) {
1122
+ xs[u] = -xs[u];
1123
+ }
1124
+ }
1125
+
1126
+ function reverseInnerOrder(layering) {
1127
+ layering.forEach(function(layer) {
1128
+ layer.reverse();
1129
+ });
1130
+ }
1131
+
1132
+ function width(g, u) {
1133
+ switch (config.rankDir) {
1134
+ case "LR": return g.node(u).height;
1135
+ default: return g.node(u).width;
1136
+ }
1137
+ }
1138
+
1139
+ function height(g, u) {
1140
+ switch(config.rankDir) {
1141
+ case "LR": return g.node(u).width;
1142
+ default: return g.node(u).height;
1143
+ }
1144
+ }
1145
+
1146
+ function sep(g, u) {
1147
+ if (config.universalSep !== null) {
1148
+ return config.universalSep;
1149
+ }
1150
+ var w = width(g, u);
1151
+ var s = g.node(u).dummy ? config.edgeSep : config.nodeSep;
1152
+ return (w + s) / 2;
1153
+ }
1154
+
1155
+ function x(g, u, x) {
1156
+ switch (config.rankDir) {
1157
+ case "LR":
1158
+ if (arguments.length < 3) {
1159
+ return g.node(u).y;
1160
+ } else {
1161
+ g.node(u).y = x;
1162
+ }
1163
+ break;
1164
+ default:
1165
+ if (arguments.length < 3) {
1166
+ return g.node(u).x;
1167
+ } else {
1168
+ g.node(u).x = x;
1169
+ }
1170
+ }
1171
+ }
1172
+
1173
+ function xDebug(name, g, u, x) {
1174
+ switch (config.rankDir) {
1175
+ case "LR":
1176
+ if (arguments.length < 3) {
1177
+ return g.node(u)[name];
1178
+ } else {
1179
+ g.node(u)[name] = x;
1180
+ }
1181
+ break;
1182
+ default:
1183
+ if (arguments.length < 3) {
1184
+ return g.node(u)[name];
1185
+ } else {
1186
+ g.node(u)[name] = x;
1187
+ }
1188
+ }
1189
+ }
1190
+
1191
+ function y(g, u, y) {
1192
+ switch (config.rankDir) {
1193
+ case "LR":
1194
+ if (arguments.length < 3) {
1195
+ return g.node(u).x;
1196
+ } else {
1197
+ g.node(u).x = y;
1198
+ }
1199
+ break;
1200
+ default:
1201
+ if (arguments.length < 3) {
1202
+ return g.node(u).y;
1203
+ } else {
1204
+ g.node(u).y = y;
1205
+ }
1206
+ }
1207
+ }
1208
+ }
1209
+ dagre.util = {};
1210
+
1211
+ /*
1212
+ * Copies attributes from `src` to `dst`. If an attribute name is in both
1213
+ * `src` and `dst` then the attribute value from `src` takes precedence.
1214
+ */
1215
+ function mergeAttributes(src, dst) {
1216
+ Object.keys(src).forEach(function(k) { dst[k] = src[k]; });
1217
+ }
1218
+
1219
+ function min(values) {
1220
+ return Math.min.apply(null, values);
1221
+ }
1222
+
1223
+ function max(values) {
1224
+ return Math.max.apply(null, values);
1225
+ }
1226
+
1227
+ function concat(arrays) {
1228
+ return Array.prototype.concat.apply([], arrays);
1229
+ }
1230
+
1231
+ var keys = dagre.util.keys = Object.keys;
1232
+
1233
+ /*
1234
+ * Returns an array of all values in the given object.
1235
+ */
1236
+ function values(obj) {
1237
+ return Object.keys(obj).map(function(k) { return obj[k]; });
1238
+ }
1239
+
1240
+ function union(arrays) {
1241
+ var obj = {};
1242
+ for (var i = 0; i < arrays.length; ++i) {
1243
+ var a = arrays[i];
1244
+ for (var j = 0; j < a.length; ++j) {
1245
+ var v = a[j];
1246
+ obj[v] = v;
1247
+ }
1248
+ }
1249
+
1250
+ var results = [];
1251
+ for (var k in obj) {
1252
+ results.push(obj[k]);
1253
+ }
1254
+
1255
+ return results;
1256
+ }
1257
+
1258
+ /*
1259
+ * Returns all components in the graph using undirected navigation.
1260
+ */
1261
+ var components = dagre.util.components = function(g) {
1262
+ var results = [];
1263
+ var visited = {};
1264
+
1265
+ function dfs(u, component) {
1266
+ if (!(u in visited)) {
1267
+ visited[u] = true;
1268
+ component.push(u);
1269
+ g.neighbors(u).forEach(function(v) {
1270
+ dfs(v, component);
1271
+ });
1272
+ }
1273
+ };
1274
+
1275
+ g.eachNode(function(u) {
1276
+ var component = [];
1277
+ dfs(u, component);
1278
+ if (component.length > 0) {
1279
+ results.push(component);
1280
+ }
1281
+ });
1282
+
1283
+ return results;
1284
+ };
1285
+
1286
+ /*
1287
+ * This algorithm uses undirected traversal to find a miminum spanning tree
1288
+ * using the supplied weight function. The algorithm is described in
1289
+ * Cormen, et al., "Introduction to Algorithms". The returned structure
1290
+ * is an array of node id to an array of adjacent nodes.
1291
+ */
1292
+ var prim = dagre.util.prim = function(g, weight) {
1293
+ var result = {};
1294
+ var parent = {};
1295
+ var q = priorityQueue();
1296
+
1297
+ if (g.nodes().length === 0) {
1298
+ return result;
1299
+ }
1300
+
1301
+ g.eachNode(function(u) {
1302
+ q.add(u, Number.POSITIVE_INFINITY);
1303
+ result[u] = [];
1304
+ });
1305
+
1306
+ // Start from arbitrary node
1307
+ q.decrease(g.nodes()[0], 0);
1308
+
1309
+ var u;
1310
+ var init = false;
1311
+ while (q.size() > 0) {
1312
+ u = q.removeMin();
1313
+ if (u in parent) {
1314
+ result[u].push(parent[u]);
1315
+ result[parent[u]].push(u);
1316
+ } else if (init) {
1317
+ throw new Error("Input graph is not connected:\n" + g.toString());
1318
+ } else {
1319
+ init = true;
1320
+ }
1321
+
1322
+ g.neighbors(u).forEach(function(v) {
1323
+ var pri = q.priority(v);
1324
+ if (pri !== undefined) {
1325
+ var edgeWeight = weight(u, v);
1326
+ if (edgeWeight < pri) {
1327
+ parent[v] = u;
1328
+ q.decrease(v, edgeWeight);
1329
+ }
1330
+ }
1331
+ });
1332
+ }
1333
+
1334
+ return result;
1335
+ };
1336
+
1337
+ var intersectRect = dagre.util.intersectRect = function(rect, point) {
1338
+ var x = rect.x;
1339
+ var y = rect.y;
1340
+
1341
+ // For now we only support rectangles
1342
+
1343
+ // Rectangle intersection algorithm from:
1344
+ // http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
1345
+ var dx = point.x - x;
1346
+ var dy = point.y - y;
1347
+ var w = rect.width / 2;
1348
+ var h = rect.height / 2;
1349
+
1350
+ var sx, sy;
1351
+ if (Math.abs(dy) * w > Math.abs(dx) * h) {
1352
+ // Intersection is top or bottom of rect.
1353
+ if (dy < 0) {
1354
+ h = -h;
1355
+ }
1356
+ sx = dy === 0 ? 0 : h * dx / dy;
1357
+ sy = h;
1358
+ } else {
1359
+ // Intersection is left or right of rect.
1360
+ if (dx < 0) {
1361
+ w = -w;
1362
+ }
1363
+ sx = w;
1364
+ sy = dx === 0 ? 0 : w * dy / dx;
1365
+ }
1366
+
1367
+ return {x: x + sx, y: y + sy};
1368
+ }
1369
+
1370
+ var pointStr = dagre.util.pointStr = function(point) {
1371
+ return point.x + "," + point.y;
1372
+ }
1373
+
1374
+ var createTimer = function() {
1375
+ var self = {},
1376
+ enabled = false;
1377
+
1378
+ self.enabled = function(x) {
1379
+ if (!arguments.length) return enabled;
1380
+ enabled = x;
1381
+ return self;
1382
+ };
1383
+
1384
+ self.wrap = function(name, func) {
1385
+ return function() {
1386
+ var start = enabled ? new Date().getTime() : null;
1387
+ try {
1388
+ return func.apply(null, arguments);
1389
+ } finally {
1390
+ if (start) console.log(name + " time: " + (new Date().getTime() - start) + "ms");
1391
+ }
1392
+ }
1393
+ };
1394
+
1395
+ return self;
1396
+ }
1397
+
1398
+ function propertyAccessor(self, config, field, setHook) {
1399
+ return function(x) {
1400
+ if (!arguments.length) return config[field];
1401
+ config[field] = x;
1402
+ if (setHook) setHook(x);
1403
+ return self;
1404
+ };
1405
+ }
1406
+ function priorityQueue() {
1407
+ var _arr = [];
1408
+ var _keyIndices = {};
1409
+
1410
+ function _heapify(i) {
1411
+ var arr = _arr;
1412
+ var l = 2 * i,
1413
+ r = l + 1,
1414
+ largest = i;
1415
+ if (l < arr.length) {
1416
+ largest = arr[l].pri < arr[largest].pri ? l : largest;
1417
+ if (r < arr.length) {
1418
+ largest = arr[r].pri < arr[largest].pri ? r : largest;
1419
+ }
1420
+ if (largest !== i) {
1421
+ _swap(i, largest);
1422
+ _heapify(largest);
1423
+ }
1424
+ }
1425
+ }
1426
+
1427
+ function _decrease(index) {
1428
+ var arr = _arr;
1429
+ var pri = arr[index].pri;
1430
+ var parent;
1431
+ while (index > 0) {
1432
+ parent = index >> 1;
1433
+ if (arr[parent].pri < pri) {
1434
+ break;
1435
+ }
1436
+ _swap(index, parent);
1437
+ index = parent;
1438
+ }
1439
+ }
1440
+
1441
+ function _swap(i, j) {
1442
+ var arr = _arr;
1443
+ var keyIndices = _keyIndices;
1444
+ var tmp = arr[i];
1445
+ arr[i] = arr[j];
1446
+ arr[j] = tmp;
1447
+ keyIndices[arr[i].key] = i;
1448
+ keyIndices[arr[j].key] = j;
1449
+ }
1450
+
1451
+ function size() { return _arr.length; }
1452
+
1453
+ function keys() { return Object.keys(_keyIndices); }
1454
+
1455
+ function has(key) { return key in _keyIndices; }
1456
+
1457
+ function priority(key) {
1458
+ var index = _keyIndices[key];
1459
+ if (index !== undefined) {
1460
+ return _arr[index].pri;
1461
+ }
1462
+ }
1463
+
1464
+ function add(key, pri) {
1465
+ if (!(key in _keyIndices)) {
1466
+ var entry = {key: key, pri: pri};
1467
+ var index = _arr.length;
1468
+ _keyIndices[key] = index;
1469
+ _arr.push(entry);
1470
+ _decrease(index);
1471
+ return true;
1472
+ }
1473
+ return false;
1474
+ }
1475
+
1476
+ function min() {
1477
+ if (size() > 0) {
1478
+ return _arr[0].key;
1479
+ }
1480
+ }
1481
+
1482
+ function removeMin() {
1483
+ _swap(0, _arr.length - 1);
1484
+ var min = _arr.pop();
1485
+ delete _keyIndices[min.key];
1486
+ _heapify(0);
1487
+ return min.key;
1488
+ }
1489
+
1490
+ function decrease(key, pri) {
1491
+ var index = _keyIndices[key];
1492
+ if (pri > _arr[index].pri) {
1493
+ throw new Error("New priority is greater than current priority. " +
1494
+ "Key: " + key + " Old: " + _arr[index].pri + " New: " + pri);
1495
+ }
1496
+ _arr[index].pri = pri;
1497
+ _decrease(index);
1498
+ }
1499
+
1500
+ return {
1501
+ size: size,
1502
+ keys: keys,
1503
+ has: has,
1504
+ priority: priority,
1505
+ add: add,
1506
+ min: min,
1507
+ removeMin: removeMin,
1508
+ decrease: decrease
1509
+ };
1510
+ }
1511
+ dagre.dot = {};
1512
+
1513
+ dagre.dot.toGraph = function(str) {
1514
+ var parseTree = dot_parser.parse(str);
1515
+ var g = dagre.graph();
1516
+ var undir = parseTree.type === "graph";
1517
+
1518
+ function createNode(id, attrs) {
1519
+ if (!(g.hasNode(id))) {
1520
+ g.addNode(id, { id: id, label: id });
1521
+ }
1522
+ if (attrs) {
1523
+ mergeAttributes(attrs, g.node(id));
1524
+ }
1525
+ }
1526
+
1527
+ var edgeCount = {};
1528
+ function createEdge(source, target, attrs) {
1529
+ var edgeKey = source + "-" + target;
1530
+ var count = edgeCount[edgeKey];
1531
+ if (!count) {
1532
+ count = edgeCount[edgeKey] = 0;
1533
+ }
1534
+ edgeCount[edgeKey]++;
1535
+
1536
+ var id = attrs.id || edgeKey + "-" + count;
1537
+ var edge = {};
1538
+ mergeAttributes(attrs, edge);
1539
+ mergeAttributes({ id: id }, edge);
1540
+ g.addEdge(id, source, target, edge);
1541
+ }
1542
+
1543
+ function handleStmt(stmt) {
1544
+ switch (stmt.type) {
1545
+ case "node":
1546
+ createNode(stmt.id, stmt.attrs);
1547
+ break;
1548
+ case "edge":
1549
+ var prev;
1550
+ stmt.elems.forEach(function(elem) {
1551
+ handleStmt(elem);
1552
+
1553
+ switch(elem.type) {
1554
+ case "node":
1555
+ var curr = elem.id;
1556
+
1557
+ if (prev) {
1558
+ createEdge(prev, curr, stmt.attrs);
1559
+ if (undir) {
1560
+ createEdge(curr, prev, stmt.attrs);
1561
+ }
1562
+ }
1563
+ prev = curr;
1564
+ break;
1565
+ default:
1566
+ // We don't currently support subgraphs incident on an edge
1567
+ throw new Error("Unsupported type incident on edge: " + elem.type);
1568
+ }
1569
+ });
1570
+ break;
1571
+ case "attr":
1572
+ // Ignore for now
1573
+ break;
1574
+ default:
1575
+ throw new Error("Unsupported statement type: " + stmt.type);
1576
+ }
1577
+ }
1578
+
1579
+ if (parseTree.stmts) {
1580
+ parseTree.stmts.forEach(function(stmt) {
1581
+ handleStmt(stmt);
1582
+ });
1583
+ }
1584
+
1585
+ return g;
1586
+ };
1587
+
1588
+ dagre.dot.toObjects = function(str) {
1589
+ var g = dagre.dot.toGraph(str);
1590
+ var nodes = g.nodes().map(function(u) { return g.node(u); });
1591
+ var edges = g.edges().map(function(e) {
1592
+ var edge = g.edge(e);
1593
+ edge.source = g.node(g.source(e));
1594
+ edge.target = g.node(g.target(e));
1595
+ return edge;
1596
+ });
1597
+ return { nodes: nodes, edges: edges };
1598
+ };
1599
+ dot_parser = (function(){
1600
+ /*
1601
+ * Generated by PEG.js 0.7.0.
1602
+ *
1603
+ * http://pegjs.majda.cz/
1604
+ */
1605
+
1606
+ function quote(s) {
1607
+ /*
1608
+ * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
1609
+ * string literal except for the closing quote character, backslash,
1610
+ * carriage return, line separator, paragraph separator, and line feed.
1611
+ * Any character may appear in the form of an escape sequence.
1612
+ *
1613
+ * For portability, we also escape escape all control and non-ASCII
1614
+ * characters. Note that "\0" and "\v" escape sequences are not used
1615
+ * because JSHint does not like the first and IE the second.
1616
+ */
1617
+ return '"' + s
1618
+ .replace(/\\/g, '\\\\') // backslash
1619
+ .replace(/"/g, '\\"') // closing quote character
1620
+ .replace(/\x08/g, '\\b') // backspace
1621
+ .replace(/\t/g, '\\t') // horizontal tab
1622
+ .replace(/\n/g, '\\n') // line feed
1623
+ .replace(/\f/g, '\\f') // form feed
1624
+ .replace(/\r/g, '\\r') // carriage return
1625
+ .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
1626
+ + '"';
1627
+ }
1628
+
1629
+ var result = {
1630
+ /*
1631
+ * Parses the input with a generated parser. If the parsing is successfull,
1632
+ * returns a value explicitly or implicitly specified by the grammar from
1633
+ * which the parser was generated (see |PEG.buildParser|). If the parsing is
1634
+ * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
1635
+ */
1636
+ parse: function(input, startRule) {
1637
+ var parseFunctions = {
1638
+ "start": parse_start,
1639
+ "stmtList": parse_stmtList,
1640
+ "stmt": parse_stmt,
1641
+ "attrStmt": parse_attrStmt,
1642
+ "inlineAttrStmt": parse_inlineAttrStmt,
1643
+ "nodeStmt": parse_nodeStmt,
1644
+ "edgeStmt": parse_edgeStmt,
1645
+ "subgraphStmt": parse_subgraphStmt,
1646
+ "attrList": parse_attrList,
1647
+ "attrListBlock": parse_attrListBlock,
1648
+ "aList": parse_aList,
1649
+ "edgeRHS": parse_edgeRHS,
1650
+ "idDef": parse_idDef,
1651
+ "nodeIdOrSubgraph": parse_nodeIdOrSubgraph,
1652
+ "nodeId": parse_nodeId,
1653
+ "port": parse_port,
1654
+ "compassPt": parse_compassPt,
1655
+ "id": parse_id,
1656
+ "node": parse_node,
1657
+ "edge": parse_edge,
1658
+ "graph": parse_graph,
1659
+ "digraph": parse_digraph,
1660
+ "subgraph": parse_subgraph,
1661
+ "strict": parse_strict,
1662
+ "graphType": parse_graphType,
1663
+ "whitespace": parse_whitespace,
1664
+ "comment": parse_comment,
1665
+ "_": parse__
1666
+ };
1667
+
1668
+ if (startRule !== undefined) {
1669
+ if (parseFunctions[startRule] === undefined) {
1670
+ throw new Error("Invalid rule name: " + quote(startRule) + ".");
1671
+ }
1672
+ } else {
1673
+ startRule = "start";
1674
+ }
1675
+
1676
+ var pos = 0;
1677
+ var reportFailures = 0;
1678
+ var rightmostFailuresPos = 0;
1679
+ var rightmostFailuresExpected = [];
1680
+
1681
+ function padLeft(input, padding, length) {
1682
+ var result = input;
1683
+
1684
+ var padLength = length - input.length;
1685
+ for (var i = 0; i < padLength; i++) {
1686
+ result = padding + result;
1687
+ }
1688
+
1689
+ return result;
1690
+ }
1691
+
1692
+ function escape(ch) {
1693
+ var charCode = ch.charCodeAt(0);
1694
+ var escapeChar;
1695
+ var length;
1696
+
1697
+ if (charCode <= 0xFF) {
1698
+ escapeChar = 'x';
1699
+ length = 2;
1700
+ } else {
1701
+ escapeChar = 'u';
1702
+ length = 4;
1703
+ }
1704
+
1705
+ return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
1706
+ }
1707
+
1708
+ function matchFailed(failure) {
1709
+ if (pos < rightmostFailuresPos) {
1710
+ return;
1711
+ }
1712
+
1713
+ if (pos > rightmostFailuresPos) {
1714
+ rightmostFailuresPos = pos;
1715
+ rightmostFailuresExpected = [];
1716
+ }
1717
+
1718
+ rightmostFailuresExpected.push(failure);
1719
+ }
1720
+
1721
+ function parse_start() {
1722
+ var result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12;
1723
+ var pos0, pos1, pos2;
1724
+
1725
+ pos0 = pos;
1726
+ pos1 = pos;
1727
+ result0 = [];
1728
+ result1 = parse__();
1729
+ while (result1 !== null) {
1730
+ result0.push(result1);
1731
+ result1 = parse__();
1732
+ }
1733
+ if (result0 !== null) {
1734
+ pos2 = pos;
1735
+ result1 = parse_strict();
1736
+ if (result1 !== null) {
1737
+ result2 = parse__();
1738
+ if (result2 !== null) {
1739
+ result1 = [result1, result2];
1740
+ } else {
1741
+ result1 = null;
1742
+ pos = pos2;
1743
+ }
1744
+ } else {
1745
+ result1 = null;
1746
+ pos = pos2;
1747
+ }
1748
+ result1 = result1 !== null ? result1 : "";
1749
+ if (result1 !== null) {
1750
+ result2 = parse_graphType();
1751
+ if (result2 !== null) {
1752
+ result3 = [];
1753
+ result4 = parse__();
1754
+ while (result4 !== null) {
1755
+ result3.push(result4);
1756
+ result4 = parse__();
1757
+ }
1758
+ if (result3 !== null) {
1759
+ result4 = parse_id();
1760
+ result4 = result4 !== null ? result4 : "";
1761
+ if (result4 !== null) {
1762
+ result5 = [];
1763
+ result6 = parse__();
1764
+ while (result6 !== null) {
1765
+ result5.push(result6);
1766
+ result6 = parse__();
1767
+ }
1768
+ if (result5 !== null) {
1769
+ if (input.charCodeAt(pos) === 123) {
1770
+ result6 = "{";
1771
+ pos++;
1772
+ } else {
1773
+ result6 = null;
1774
+ if (reportFailures === 0) {
1775
+ matchFailed("\"{\"");
1776
+ }
1777
+ }
1778
+ if (result6 !== null) {
1779
+ result7 = [];
1780
+ result8 = parse__();
1781
+ while (result8 !== null) {
1782
+ result7.push(result8);
1783
+ result8 = parse__();
1784
+ }
1785
+ if (result7 !== null) {
1786
+ result8 = parse_stmtList();
1787
+ result8 = result8 !== null ? result8 : "";
1788
+ if (result8 !== null) {
1789
+ result9 = [];
1790
+ result10 = parse__();
1791
+ while (result10 !== null) {
1792
+ result9.push(result10);
1793
+ result10 = parse__();
1794
+ }
1795
+ if (result9 !== null) {
1796
+ if (input.charCodeAt(pos) === 125) {
1797
+ result10 = "}";
1798
+ pos++;
1799
+ } else {
1800
+ result10 = null;
1801
+ if (reportFailures === 0) {
1802
+ matchFailed("\"}\"");
1803
+ }
1804
+ }
1805
+ if (result10 !== null) {
1806
+ result11 = [];
1807
+ result12 = parse__();
1808
+ while (result12 !== null) {
1809
+ result11.push(result12);
1810
+ result12 = parse__();
1811
+ }
1812
+ if (result11 !== null) {
1813
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11];
1814
+ } else {
1815
+ result0 = null;
1816
+ pos = pos1;
1817
+ }
1818
+ } else {
1819
+ result0 = null;
1820
+ pos = pos1;
1821
+ }
1822
+ } else {
1823
+ result0 = null;
1824
+ pos = pos1;
1825
+ }
1826
+ } else {
1827
+ result0 = null;
1828
+ pos = pos1;
1829
+ }
1830
+ } else {
1831
+ result0 = null;
1832
+ pos = pos1;
1833
+ }
1834
+ } else {
1835
+ result0 = null;
1836
+ pos = pos1;
1837
+ }
1838
+ } else {
1839
+ result0 = null;
1840
+ pos = pos1;
1841
+ }
1842
+ } else {
1843
+ result0 = null;
1844
+ pos = pos1;
1845
+ }
1846
+ } else {
1847
+ result0 = null;
1848
+ pos = pos1;
1849
+ }
1850
+ } else {
1851
+ result0 = null;
1852
+ pos = pos1;
1853
+ }
1854
+ } else {
1855
+ result0 = null;
1856
+ pos = pos1;
1857
+ }
1858
+ } else {
1859
+ result0 = null;
1860
+ pos = pos1;
1861
+ }
1862
+ if (result0 !== null) {
1863
+ result0 = (function(offset, type, id, stmts) {
1864
+ return {type: type, id: id, stmts: stmts};
1865
+ })(pos0, result0[2], result0[4], result0[8]);
1866
+ }
1867
+ if (result0 === null) {
1868
+ pos = pos0;
1869
+ }
1870
+ return result0;
1871
+ }
1872
+
1873
+ function parse_stmtList() {
1874
+ var result0, result1, result2, result3, result4, result5, result6, result7;
1875
+ var pos0, pos1, pos2;
1876
+
1877
+ pos0 = pos;
1878
+ pos1 = pos;
1879
+ result0 = parse_stmt();
1880
+ if (result0 !== null) {
1881
+ result1 = [];
1882
+ result2 = parse__();
1883
+ while (result2 !== null) {
1884
+ result1.push(result2);
1885
+ result2 = parse__();
1886
+ }
1887
+ if (result1 !== null) {
1888
+ if (input.charCodeAt(pos) === 59) {
1889
+ result2 = ";";
1890
+ pos++;
1891
+ } else {
1892
+ result2 = null;
1893
+ if (reportFailures === 0) {
1894
+ matchFailed("\";\"");
1895
+ }
1896
+ }
1897
+ result2 = result2 !== null ? result2 : "";
1898
+ if (result2 !== null) {
1899
+ result3 = [];
1900
+ pos2 = pos;
1901
+ result4 = [];
1902
+ result5 = parse__();
1903
+ while (result5 !== null) {
1904
+ result4.push(result5);
1905
+ result5 = parse__();
1906
+ }
1907
+ if (result4 !== null) {
1908
+ result5 = parse_stmt();
1909
+ if (result5 !== null) {
1910
+ result6 = [];
1911
+ result7 = parse__();
1912
+ while (result7 !== null) {
1913
+ result6.push(result7);
1914
+ result7 = parse__();
1915
+ }
1916
+ if (result6 !== null) {
1917
+ if (input.charCodeAt(pos) === 59) {
1918
+ result7 = ";";
1919
+ pos++;
1920
+ } else {
1921
+ result7 = null;
1922
+ if (reportFailures === 0) {
1923
+ matchFailed("\";\"");
1924
+ }
1925
+ }
1926
+ result7 = result7 !== null ? result7 : "";
1927
+ if (result7 !== null) {
1928
+ result4 = [result4, result5, result6, result7];
1929
+ } else {
1930
+ result4 = null;
1931
+ pos = pos2;
1932
+ }
1933
+ } else {
1934
+ result4 = null;
1935
+ pos = pos2;
1936
+ }
1937
+ } else {
1938
+ result4 = null;
1939
+ pos = pos2;
1940
+ }
1941
+ } else {
1942
+ result4 = null;
1943
+ pos = pos2;
1944
+ }
1945
+ while (result4 !== null) {
1946
+ result3.push(result4);
1947
+ pos2 = pos;
1948
+ result4 = [];
1949
+ result5 = parse__();
1950
+ while (result5 !== null) {
1951
+ result4.push(result5);
1952
+ result5 = parse__();
1953
+ }
1954
+ if (result4 !== null) {
1955
+ result5 = parse_stmt();
1956
+ if (result5 !== null) {
1957
+ result6 = [];
1958
+ result7 = parse__();
1959
+ while (result7 !== null) {
1960
+ result6.push(result7);
1961
+ result7 = parse__();
1962
+ }
1963
+ if (result6 !== null) {
1964
+ if (input.charCodeAt(pos) === 59) {
1965
+ result7 = ";";
1966
+ pos++;
1967
+ } else {
1968
+ result7 = null;
1969
+ if (reportFailures === 0) {
1970
+ matchFailed("\";\"");
1971
+ }
1972
+ }
1973
+ result7 = result7 !== null ? result7 : "";
1974
+ if (result7 !== null) {
1975
+ result4 = [result4, result5, result6, result7];
1976
+ } else {
1977
+ result4 = null;
1978
+ pos = pos2;
1979
+ }
1980
+ } else {
1981
+ result4 = null;
1982
+ pos = pos2;
1983
+ }
1984
+ } else {
1985
+ result4 = null;
1986
+ pos = pos2;
1987
+ }
1988
+ } else {
1989
+ result4 = null;
1990
+ pos = pos2;
1991
+ }
1992
+ }
1993
+ if (result3 !== null) {
1994
+ result0 = [result0, result1, result2, result3];
1995
+ } else {
1996
+ result0 = null;
1997
+ pos = pos1;
1998
+ }
1999
+ } else {
2000
+ result0 = null;
2001
+ pos = pos1;
2002
+ }
2003
+ } else {
2004
+ result0 = null;
2005
+ pos = pos1;
2006
+ }
2007
+ } else {
2008
+ result0 = null;
2009
+ pos = pos1;
2010
+ }
2011
+ if (result0 !== null) {
2012
+ result0 = (function(offset, first, rest) {
2013
+ var result = [first];
2014
+ for (var i = 0; i < rest.length; ++i) {
2015
+ result.push(rest[i][1]);
2016
+ }
2017
+ return result;
2018
+ })(pos0, result0[0], result0[3]);
2019
+ }
2020
+ if (result0 === null) {
2021
+ pos = pos0;
2022
+ }
2023
+ return result0;
2024
+ }
2025
+
2026
+ function parse_stmt() {
2027
+ var result0;
2028
+
2029
+ result0 = parse_attrStmt();
2030
+ if (result0 === null) {
2031
+ result0 = parse_subgraphStmt();
2032
+ if (result0 === null) {
2033
+ result0 = parse_inlineAttrStmt();
2034
+ if (result0 === null) {
2035
+ result0 = parse_edgeStmt();
2036
+ if (result0 === null) {
2037
+ result0 = parse_nodeStmt();
2038
+ }
2039
+ }
2040
+ }
2041
+ }
2042
+ return result0;
2043
+ }
2044
+
2045
+ function parse_attrStmt() {
2046
+ var result0, result1, result2;
2047
+ var pos0, pos1;
2048
+
2049
+ pos0 = pos;
2050
+ pos1 = pos;
2051
+ result0 = parse_graph();
2052
+ if (result0 === null) {
2053
+ result0 = parse_node();
2054
+ if (result0 === null) {
2055
+ result0 = parse_edge();
2056
+ }
2057
+ }
2058
+ if (result0 !== null) {
2059
+ result1 = [];
2060
+ result2 = parse__();
2061
+ while (result2 !== null) {
2062
+ result1.push(result2);
2063
+ result2 = parse__();
2064
+ }
2065
+ if (result1 !== null) {
2066
+ result2 = parse_attrList();
2067
+ if (result2 !== null) {
2068
+ result0 = [result0, result1, result2];
2069
+ } else {
2070
+ result0 = null;
2071
+ pos = pos1;
2072
+ }
2073
+ } else {
2074
+ result0 = null;
2075
+ pos = pos1;
2076
+ }
2077
+ } else {
2078
+ result0 = null;
2079
+ pos = pos1;
2080
+ }
2081
+ if (result0 !== null) {
2082
+ result0 = (function(offset, type, attrs) {
2083
+ return { type: "attr", attrType: type, attrs: attrs || {}};
2084
+ })(pos0, result0[0], result0[2]);
2085
+ }
2086
+ if (result0 === null) {
2087
+ pos = pos0;
2088
+ }
2089
+ return result0;
2090
+ }
2091
+
2092
+ function parse_inlineAttrStmt() {
2093
+ var result0, result1, result2, result3, result4;
2094
+ var pos0, pos1;
2095
+
2096
+ pos0 = pos;
2097
+ pos1 = pos;
2098
+ result0 = parse_id();
2099
+ if (result0 !== null) {
2100
+ result1 = [];
2101
+ result2 = parse__();
2102
+ while (result2 !== null) {
2103
+ result1.push(result2);
2104
+ result2 = parse__();
2105
+ }
2106
+ if (result1 !== null) {
2107
+ if (input.charCodeAt(pos) === 61) {
2108
+ result2 = "=";
2109
+ pos++;
2110
+ } else {
2111
+ result2 = null;
2112
+ if (reportFailures === 0) {
2113
+ matchFailed("\"=\"");
2114
+ }
2115
+ }
2116
+ if (result2 !== null) {
2117
+ result3 = [];
2118
+ result4 = parse__();
2119
+ while (result4 !== null) {
2120
+ result3.push(result4);
2121
+ result4 = parse__();
2122
+ }
2123
+ if (result3 !== null) {
2124
+ result4 = parse_id();
2125
+ if (result4 !== null) {
2126
+ result0 = [result0, result1, result2, result3, result4];
2127
+ } else {
2128
+ result0 = null;
2129
+ pos = pos1;
2130
+ }
2131
+ } else {
2132
+ result0 = null;
2133
+ pos = pos1;
2134
+ }
2135
+ } else {
2136
+ result0 = null;
2137
+ pos = pos1;
2138
+ }
2139
+ } else {
2140
+ result0 = null;
2141
+ pos = pos1;
2142
+ }
2143
+ } else {
2144
+ result0 = null;
2145
+ pos = pos1;
2146
+ }
2147
+ if (result0 !== null) {
2148
+ result0 = (function(offset, k, v) {
2149
+ var attrs = {};
2150
+ attrs[k] = v;
2151
+ return { type: "inlineAttr", attrs: attrs };
2152
+ })(pos0, result0[0], result0[4]);
2153
+ }
2154
+ if (result0 === null) {
2155
+ pos = pos0;
2156
+ }
2157
+ return result0;
2158
+ }
2159
+
2160
+ function parse_nodeStmt() {
2161
+ var result0, result1, result2;
2162
+ var pos0, pos1;
2163
+
2164
+ pos0 = pos;
2165
+ pos1 = pos;
2166
+ result0 = parse_nodeId();
2167
+ if (result0 !== null) {
2168
+ result1 = [];
2169
+ result2 = parse__();
2170
+ while (result2 !== null) {
2171
+ result1.push(result2);
2172
+ result2 = parse__();
2173
+ }
2174
+ if (result1 !== null) {
2175
+ result2 = parse_attrList();
2176
+ result2 = result2 !== null ? result2 : "";
2177
+ if (result2 !== null) {
2178
+ result0 = [result0, result1, result2];
2179
+ } else {
2180
+ result0 = null;
2181
+ pos = pos1;
2182
+ }
2183
+ } else {
2184
+ result0 = null;
2185
+ pos = pos1;
2186
+ }
2187
+ } else {
2188
+ result0 = null;
2189
+ pos = pos1;
2190
+ }
2191
+ if (result0 !== null) {
2192
+ result0 = (function(offset, id, attrs) { return {type: "node", id: id, attrs: attrs || {}}; })(pos0, result0[0], result0[2]);
2193
+ }
2194
+ if (result0 === null) {
2195
+ pos = pos0;
2196
+ }
2197
+ return result0;
2198
+ }
2199
+
2200
+ function parse_edgeStmt() {
2201
+ var result0, result1, result2, result3, result4;
2202
+ var pos0, pos1;
2203
+
2204
+ pos0 = pos;
2205
+ pos1 = pos;
2206
+ result0 = parse_nodeIdOrSubgraph();
2207
+ if (result0 !== null) {
2208
+ result1 = [];
2209
+ result2 = parse__();
2210
+ while (result2 !== null) {
2211
+ result1.push(result2);
2212
+ result2 = parse__();
2213
+ }
2214
+ if (result1 !== null) {
2215
+ result2 = parse_edgeRHS();
2216
+ if (result2 !== null) {
2217
+ result3 = [];
2218
+ result4 = parse__();
2219
+ while (result4 !== null) {
2220
+ result3.push(result4);
2221
+ result4 = parse__();
2222
+ }
2223
+ if (result3 !== null) {
2224
+ result4 = parse_attrList();
2225
+ result4 = result4 !== null ? result4 : "";
2226
+ if (result4 !== null) {
2227
+ result0 = [result0, result1, result2, result3, result4];
2228
+ } else {
2229
+ result0 = null;
2230
+ pos = pos1;
2231
+ }
2232
+ } else {
2233
+ result0 = null;
2234
+ pos = pos1;
2235
+ }
2236
+ } else {
2237
+ result0 = null;
2238
+ pos = pos1;
2239
+ }
2240
+ } else {
2241
+ result0 = null;
2242
+ pos = pos1;
2243
+ }
2244
+ } else {
2245
+ result0 = null;
2246
+ pos = pos1;
2247
+ }
2248
+ if (result0 !== null) {
2249
+ result0 = (function(offset, lhs, rhs, attrs) {
2250
+ var elems = [lhs];
2251
+ for (var i = 0; i < rhs.length; ++i) {
2252
+ elems.push(rhs[i]);
2253
+ }
2254
+ return { type: "edge", elems: elems, attrs: attrs || {} };
2255
+ })(pos0, result0[0], result0[2], result0[4]);
2256
+ }
2257
+ if (result0 === null) {
2258
+ pos = pos0;
2259
+ }
2260
+ return result0;
2261
+ }
2262
+
2263
+ function parse_subgraphStmt() {
2264
+ var result0, result1, result2, result3, result4, result5;
2265
+ var pos0, pos1, pos2, pos3;
2266
+
2267
+ pos0 = pos;
2268
+ pos1 = pos;
2269
+ pos2 = pos;
2270
+ result0 = parse_subgraph();
2271
+ if (result0 !== null) {
2272
+ result1 = [];
2273
+ result2 = parse__();
2274
+ while (result2 !== null) {
2275
+ result1.push(result2);
2276
+ result2 = parse__();
2277
+ }
2278
+ if (result1 !== null) {
2279
+ pos3 = pos;
2280
+ result2 = parse_id();
2281
+ if (result2 !== null) {
2282
+ result3 = [];
2283
+ result4 = parse__();
2284
+ while (result4 !== null) {
2285
+ result3.push(result4);
2286
+ result4 = parse__();
2287
+ }
2288
+ if (result3 !== null) {
2289
+ result2 = [result2, result3];
2290
+ } else {
2291
+ result2 = null;
2292
+ pos = pos3;
2293
+ }
2294
+ } else {
2295
+ result2 = null;
2296
+ pos = pos3;
2297
+ }
2298
+ result2 = result2 !== null ? result2 : "";
2299
+ if (result2 !== null) {
2300
+ result0 = [result0, result1, result2];
2301
+ } else {
2302
+ result0 = null;
2303
+ pos = pos2;
2304
+ }
2305
+ } else {
2306
+ result0 = null;
2307
+ pos = pos2;
2308
+ }
2309
+ } else {
2310
+ result0 = null;
2311
+ pos = pos2;
2312
+ }
2313
+ result0 = result0 !== null ? result0 : "";
2314
+ if (result0 !== null) {
2315
+ if (input.charCodeAt(pos) === 123) {
2316
+ result1 = "{";
2317
+ pos++;
2318
+ } else {
2319
+ result1 = null;
2320
+ if (reportFailures === 0) {
2321
+ matchFailed("\"{\"");
2322
+ }
2323
+ }
2324
+ if (result1 !== null) {
2325
+ result2 = [];
2326
+ result3 = parse__();
2327
+ while (result3 !== null) {
2328
+ result2.push(result3);
2329
+ result3 = parse__();
2330
+ }
2331
+ if (result2 !== null) {
2332
+ result3 = parse_stmtList();
2333
+ if (result3 !== null) {
2334
+ result4 = [];
2335
+ result5 = parse__();
2336
+ while (result5 !== null) {
2337
+ result4.push(result5);
2338
+ result5 = parse__();
2339
+ }
2340
+ if (result4 !== null) {
2341
+ if (input.charCodeAt(pos) === 125) {
2342
+ result5 = "}";
2343
+ pos++;
2344
+ } else {
2345
+ result5 = null;
2346
+ if (reportFailures === 0) {
2347
+ matchFailed("\"}\"");
2348
+ }
2349
+ }
2350
+ if (result5 !== null) {
2351
+ result0 = [result0, result1, result2, result3, result4, result5];
2352
+ } else {
2353
+ result0 = null;
2354
+ pos = pos1;
2355
+ }
2356
+ } else {
2357
+ result0 = null;
2358
+ pos = pos1;
2359
+ }
2360
+ } else {
2361
+ result0 = null;
2362
+ pos = pos1;
2363
+ }
2364
+ } else {
2365
+ result0 = null;
2366
+ pos = pos1;
2367
+ }
2368
+ } else {
2369
+ result0 = null;
2370
+ pos = pos1;
2371
+ }
2372
+ } else {
2373
+ result0 = null;
2374
+ pos = pos1;
2375
+ }
2376
+ if (result0 !== null) {
2377
+ result0 = (function(offset, id, stmts) {
2378
+ id = id[2] || [];
2379
+ return { type: "subgraph", id: id[0], stmts: stmts };
2380
+ })(pos0, result0[0], result0[3]);
2381
+ }
2382
+ if (result0 === null) {
2383
+ pos = pos0;
2384
+ }
2385
+ return result0;
2386
+ }
2387
+
2388
+ function parse_attrList() {
2389
+ var result0, result1, result2, result3;
2390
+ var pos0, pos1, pos2;
2391
+
2392
+ pos0 = pos;
2393
+ pos1 = pos;
2394
+ result0 = parse_attrListBlock();
2395
+ if (result0 !== null) {
2396
+ result1 = [];
2397
+ pos2 = pos;
2398
+ result2 = [];
2399
+ result3 = parse__();
2400
+ while (result3 !== null) {
2401
+ result2.push(result3);
2402
+ result3 = parse__();
2403
+ }
2404
+ if (result2 !== null) {
2405
+ result3 = parse_attrListBlock();
2406
+ if (result3 !== null) {
2407
+ result2 = [result2, result3];
2408
+ } else {
2409
+ result2 = null;
2410
+ pos = pos2;
2411
+ }
2412
+ } else {
2413
+ result2 = null;
2414
+ pos = pos2;
2415
+ }
2416
+ while (result2 !== null) {
2417
+ result1.push(result2);
2418
+ pos2 = pos;
2419
+ result2 = [];
2420
+ result3 = parse__();
2421
+ while (result3 !== null) {
2422
+ result2.push(result3);
2423
+ result3 = parse__();
2424
+ }
2425
+ if (result2 !== null) {
2426
+ result3 = parse_attrListBlock();
2427
+ if (result3 !== null) {
2428
+ result2 = [result2, result3];
2429
+ } else {
2430
+ result2 = null;
2431
+ pos = pos2;
2432
+ }
2433
+ } else {
2434
+ result2 = null;
2435
+ pos = pos2;
2436
+ }
2437
+ }
2438
+ if (result1 !== null) {
2439
+ result0 = [result0, result1];
2440
+ } else {
2441
+ result0 = null;
2442
+ pos = pos1;
2443
+ }
2444
+ } else {
2445
+ result0 = null;
2446
+ pos = pos1;
2447
+ }
2448
+ if (result0 !== null) {
2449
+ result0 = (function(offset, first, rest) {
2450
+ var result = first;
2451
+ for (var i = 0; i < rest.length; ++i) {
2452
+ result = rightBiasedMerge(result, rest[i][1]);
2453
+ }
2454
+ return result;
2455
+ })(pos0, result0[0], result0[1]);
2456
+ }
2457
+ if (result0 === null) {
2458
+ pos = pos0;
2459
+ }
2460
+ return result0;
2461
+ }
2462
+
2463
+ function parse_attrListBlock() {
2464
+ var result0, result1, result2, result3, result4;
2465
+ var pos0, pos1;
2466
+
2467
+ pos0 = pos;
2468
+ pos1 = pos;
2469
+ if (input.charCodeAt(pos) === 91) {
2470
+ result0 = "[";
2471
+ pos++;
2472
+ } else {
2473
+ result0 = null;
2474
+ if (reportFailures === 0) {
2475
+ matchFailed("\"[\"");
2476
+ }
2477
+ }
2478
+ if (result0 !== null) {
2479
+ result1 = [];
2480
+ result2 = parse__();
2481
+ while (result2 !== null) {
2482
+ result1.push(result2);
2483
+ result2 = parse__();
2484
+ }
2485
+ if (result1 !== null) {
2486
+ result2 = parse_aList();
2487
+ result2 = result2 !== null ? result2 : "";
2488
+ if (result2 !== null) {
2489
+ result3 = [];
2490
+ result4 = parse__();
2491
+ while (result4 !== null) {
2492
+ result3.push(result4);
2493
+ result4 = parse__();
2494
+ }
2495
+ if (result3 !== null) {
2496
+ if (input.charCodeAt(pos) === 93) {
2497
+ result4 = "]";
2498
+ pos++;
2499
+ } else {
2500
+ result4 = null;
2501
+ if (reportFailures === 0) {
2502
+ matchFailed("\"]\"");
2503
+ }
2504
+ }
2505
+ if (result4 !== null) {
2506
+ result0 = [result0, result1, result2, result3, result4];
2507
+ } else {
2508
+ result0 = null;
2509
+ pos = pos1;
2510
+ }
2511
+ } else {
2512
+ result0 = null;
2513
+ pos = pos1;
2514
+ }
2515
+ } else {
2516
+ result0 = null;
2517
+ pos = pos1;
2518
+ }
2519
+ } else {
2520
+ result0 = null;
2521
+ pos = pos1;
2522
+ }
2523
+ } else {
2524
+ result0 = null;
2525
+ pos = pos1;
2526
+ }
2527
+ if (result0 !== null) {
2528
+ result0 = (function(offset, aList) { return aList; })(pos0, result0[2]);
2529
+ }
2530
+ if (result0 === null) {
2531
+ pos = pos0;
2532
+ }
2533
+ return result0;
2534
+ }
2535
+
2536
+ function parse_aList() {
2537
+ var result0, result1, result2, result3, result4, result5;
2538
+ var pos0, pos1, pos2;
2539
+
2540
+ pos0 = pos;
2541
+ pos1 = pos;
2542
+ result0 = parse_idDef();
2543
+ if (result0 !== null) {
2544
+ result1 = [];
2545
+ pos2 = pos;
2546
+ result2 = [];
2547
+ result3 = parse__();
2548
+ while (result3 !== null) {
2549
+ result2.push(result3);
2550
+ result3 = parse__();
2551
+ }
2552
+ if (result2 !== null) {
2553
+ if (input.charCodeAt(pos) === 44) {
2554
+ result3 = ",";
2555
+ pos++;
2556
+ } else {
2557
+ result3 = null;
2558
+ if (reportFailures === 0) {
2559
+ matchFailed("\",\"");
2560
+ }
2561
+ }
2562
+ result3 = result3 !== null ? result3 : "";
2563
+ if (result3 !== null) {
2564
+ result4 = [];
2565
+ result5 = parse__();
2566
+ while (result5 !== null) {
2567
+ result4.push(result5);
2568
+ result5 = parse__();
2569
+ }
2570
+ if (result4 !== null) {
2571
+ result5 = parse_idDef();
2572
+ if (result5 !== null) {
2573
+ result2 = [result2, result3, result4, result5];
2574
+ } else {
2575
+ result2 = null;
2576
+ pos = pos2;
2577
+ }
2578
+ } else {
2579
+ result2 = null;
2580
+ pos = pos2;
2581
+ }
2582
+ } else {
2583
+ result2 = null;
2584
+ pos = pos2;
2585
+ }
2586
+ } else {
2587
+ result2 = null;
2588
+ pos = pos2;
2589
+ }
2590
+ while (result2 !== null) {
2591
+ result1.push(result2);
2592
+ pos2 = pos;
2593
+ result2 = [];
2594
+ result3 = parse__();
2595
+ while (result3 !== null) {
2596
+ result2.push(result3);
2597
+ result3 = parse__();
2598
+ }
2599
+ if (result2 !== null) {
2600
+ if (input.charCodeAt(pos) === 44) {
2601
+ result3 = ",";
2602
+ pos++;
2603
+ } else {
2604
+ result3 = null;
2605
+ if (reportFailures === 0) {
2606
+ matchFailed("\",\"");
2607
+ }
2608
+ }
2609
+ result3 = result3 !== null ? result3 : "";
2610
+ if (result3 !== null) {
2611
+ result4 = [];
2612
+ result5 = parse__();
2613
+ while (result5 !== null) {
2614
+ result4.push(result5);
2615
+ result5 = parse__();
2616
+ }
2617
+ if (result4 !== null) {
2618
+ result5 = parse_idDef();
2619
+ if (result5 !== null) {
2620
+ result2 = [result2, result3, result4, result5];
2621
+ } else {
2622
+ result2 = null;
2623
+ pos = pos2;
2624
+ }
2625
+ } else {
2626
+ result2 = null;
2627
+ pos = pos2;
2628
+ }
2629
+ } else {
2630
+ result2 = null;
2631
+ pos = pos2;
2632
+ }
2633
+ } else {
2634
+ result2 = null;
2635
+ pos = pos2;
2636
+ }
2637
+ }
2638
+ if (result1 !== null) {
2639
+ result0 = [result0, result1];
2640
+ } else {
2641
+ result0 = null;
2642
+ pos = pos1;
2643
+ }
2644
+ } else {
2645
+ result0 = null;
2646
+ pos = pos1;
2647
+ }
2648
+ if (result0 !== null) {
2649
+ result0 = (function(offset, first, rest) {
2650
+ var result = first;
2651
+ for (var i = 0; i < rest.length; ++i) {
2652
+ result = rightBiasedMerge(result, rest[i][3]);
2653
+ }
2654
+ return result;
2655
+ })(pos0, result0[0], result0[1]);
2656
+ }
2657
+ if (result0 === null) {
2658
+ pos = pos0;
2659
+ }
2660
+ return result0;
2661
+ }
2662
+
2663
+ function parse_edgeRHS() {
2664
+ var result0, result1, result2, result3, result4;
2665
+ var pos0, pos1, pos2;
2666
+
2667
+ pos0 = pos;
2668
+ pos1 = pos;
2669
+ pos2 = pos;
2670
+ if (input.substr(pos, 2) === "--") {
2671
+ result0 = "--";
2672
+ pos += 2;
2673
+ } else {
2674
+ result0 = null;
2675
+ if (reportFailures === 0) {
2676
+ matchFailed("\"--\"");
2677
+ }
2678
+ }
2679
+ if (result0 !== null) {
2680
+ result1 = (function(offset) { return directed; })(pos) ? null : "";
2681
+ if (result1 !== null) {
2682
+ result0 = [result0, result1];
2683
+ } else {
2684
+ result0 = null;
2685
+ pos = pos2;
2686
+ }
2687
+ } else {
2688
+ result0 = null;
2689
+ pos = pos2;
2690
+ }
2691
+ if (result0 === null) {
2692
+ pos2 = pos;
2693
+ if (input.substr(pos, 2) === "->") {
2694
+ result0 = "->";
2695
+ pos += 2;
2696
+ } else {
2697
+ result0 = null;
2698
+ if (reportFailures === 0) {
2699
+ matchFailed("\"->\"");
2700
+ }
2701
+ }
2702
+ if (result0 !== null) {
2703
+ result1 = (function(offset) { return directed; })(pos) ? "" : null;
2704
+ if (result1 !== null) {
2705
+ result0 = [result0, result1];
2706
+ } else {
2707
+ result0 = null;
2708
+ pos = pos2;
2709
+ }
2710
+ } else {
2711
+ result0 = null;
2712
+ pos = pos2;
2713
+ }
2714
+ }
2715
+ if (result0 !== null) {
2716
+ result1 = [];
2717
+ result2 = parse__();
2718
+ while (result2 !== null) {
2719
+ result1.push(result2);
2720
+ result2 = parse__();
2721
+ }
2722
+ if (result1 !== null) {
2723
+ result2 = parse_nodeIdOrSubgraph();
2724
+ if (result2 !== null) {
2725
+ result3 = [];
2726
+ result4 = parse__();
2727
+ while (result4 !== null) {
2728
+ result3.push(result4);
2729
+ result4 = parse__();
2730
+ }
2731
+ if (result3 !== null) {
2732
+ result4 = parse_edgeRHS();
2733
+ result4 = result4 !== null ? result4 : "";
2734
+ if (result4 !== null) {
2735
+ result0 = [result0, result1, result2, result3, result4];
2736
+ } else {
2737
+ result0 = null;
2738
+ pos = pos1;
2739
+ }
2740
+ } else {
2741
+ result0 = null;
2742
+ pos = pos1;
2743
+ }
2744
+ } else {
2745
+ result0 = null;
2746
+ pos = pos1;
2747
+ }
2748
+ } else {
2749
+ result0 = null;
2750
+ pos = pos1;
2751
+ }
2752
+ } else {
2753
+ result0 = null;
2754
+ pos = pos1;
2755
+ }
2756
+ if (result0 !== null) {
2757
+ result0 = (function(offset, rhs, rest) {
2758
+ var result = [rhs];
2759
+ for (var i = 0; i < rest.length; ++i) {
2760
+ result.push(rest[i]);
2761
+ }
2762
+ return result;
2763
+ })(pos0, result0[2], result0[4]);
2764
+ }
2765
+ if (result0 === null) {
2766
+ pos = pos0;
2767
+ }
2768
+ return result0;
2769
+ }
2770
+
2771
+ function parse_idDef() {
2772
+ var result0, result1, result2, result3, result4;
2773
+ var pos0, pos1, pos2;
2774
+
2775
+ pos0 = pos;
2776
+ pos1 = pos;
2777
+ result0 = parse_id();
2778
+ if (result0 !== null) {
2779
+ pos2 = pos;
2780
+ result1 = [];
2781
+ result2 = parse__();
2782
+ while (result2 !== null) {
2783
+ result1.push(result2);
2784
+ result2 = parse__();
2785
+ }
2786
+ if (result1 !== null) {
2787
+ if (input.charCodeAt(pos) === 61) {
2788
+ result2 = "=";
2789
+ pos++;
2790
+ } else {
2791
+ result2 = null;
2792
+ if (reportFailures === 0) {
2793
+ matchFailed("\"=\"");
2794
+ }
2795
+ }
2796
+ if (result2 !== null) {
2797
+ result3 = [];
2798
+ result4 = parse__();
2799
+ while (result4 !== null) {
2800
+ result3.push(result4);
2801
+ result4 = parse__();
2802
+ }
2803
+ if (result3 !== null) {
2804
+ result4 = parse_id();
2805
+ if (result4 !== null) {
2806
+ result1 = [result1, result2, result3, result4];
2807
+ } else {
2808
+ result1 = null;
2809
+ pos = pos2;
2810
+ }
2811
+ } else {
2812
+ result1 = null;
2813
+ pos = pos2;
2814
+ }
2815
+ } else {
2816
+ result1 = null;
2817
+ pos = pos2;
2818
+ }
2819
+ } else {
2820
+ result1 = null;
2821
+ pos = pos2;
2822
+ }
2823
+ result1 = result1 !== null ? result1 : "";
2824
+ if (result1 !== null) {
2825
+ result0 = [result0, result1];
2826
+ } else {
2827
+ result0 = null;
2828
+ pos = pos1;
2829
+ }
2830
+ } else {
2831
+ result0 = null;
2832
+ pos = pos1;
2833
+ }
2834
+ if (result0 !== null) {
2835
+ result0 = (function(offset, k, v) {
2836
+ var result = {};
2837
+ result[k] = v[3];
2838
+ return result;
2839
+ })(pos0, result0[0], result0[1]);
2840
+ }
2841
+ if (result0 === null) {
2842
+ pos = pos0;
2843
+ }
2844
+ return result0;
2845
+ }
2846
+
2847
+ function parse_nodeIdOrSubgraph() {
2848
+ var result0;
2849
+ var pos0;
2850
+
2851
+ result0 = parse_subgraphStmt();
2852
+ if (result0 === null) {
2853
+ pos0 = pos;
2854
+ result0 = parse_nodeId();
2855
+ if (result0 !== null) {
2856
+ result0 = (function(offset, id) { return { type: "node", id: id, attrs: {} }; })(pos0, result0);
2857
+ }
2858
+ if (result0 === null) {
2859
+ pos = pos0;
2860
+ }
2861
+ }
2862
+ return result0;
2863
+ }
2864
+
2865
+ function parse_nodeId() {
2866
+ var result0, result1, result2;
2867
+ var pos0, pos1;
2868
+
2869
+ pos0 = pos;
2870
+ pos1 = pos;
2871
+ result0 = parse_id();
2872
+ if (result0 !== null) {
2873
+ result1 = [];
2874
+ result2 = parse__();
2875
+ while (result2 !== null) {
2876
+ result1.push(result2);
2877
+ result2 = parse__();
2878
+ }
2879
+ if (result1 !== null) {
2880
+ result2 = parse_port();
2881
+ result2 = result2 !== null ? result2 : "";
2882
+ if (result2 !== null) {
2883
+ result0 = [result0, result1, result2];
2884
+ } else {
2885
+ result0 = null;
2886
+ pos = pos1;
2887
+ }
2888
+ } else {
2889
+ result0 = null;
2890
+ pos = pos1;
2891
+ }
2892
+ } else {
2893
+ result0 = null;
2894
+ pos = pos1;
2895
+ }
2896
+ if (result0 !== null) {
2897
+ result0 = (function(offset, id) { return id; })(pos0, result0[0]);
2898
+ }
2899
+ if (result0 === null) {
2900
+ pos = pos0;
2901
+ }
2902
+ return result0;
2903
+ }
2904
+
2905
+ function parse_port() {
2906
+ var result0, result1, result2, result3, result4, result5, result6;
2907
+ var pos0, pos1;
2908
+
2909
+ pos0 = pos;
2910
+ if (input.charCodeAt(pos) === 58) {
2911
+ result0 = ":";
2912
+ pos++;
2913
+ } else {
2914
+ result0 = null;
2915
+ if (reportFailures === 0) {
2916
+ matchFailed("\":\"");
2917
+ }
2918
+ }
2919
+ if (result0 !== null) {
2920
+ result1 = [];
2921
+ result2 = parse__();
2922
+ while (result2 !== null) {
2923
+ result1.push(result2);
2924
+ result2 = parse__();
2925
+ }
2926
+ if (result1 !== null) {
2927
+ result2 = parse_id();
2928
+ if (result2 !== null) {
2929
+ result3 = [];
2930
+ result4 = parse__();
2931
+ while (result4 !== null) {
2932
+ result3.push(result4);
2933
+ result4 = parse__();
2934
+ }
2935
+ if (result3 !== null) {
2936
+ pos1 = pos;
2937
+ if (input.charCodeAt(pos) === 58) {
2938
+ result4 = ":";
2939
+ pos++;
2940
+ } else {
2941
+ result4 = null;
2942
+ if (reportFailures === 0) {
2943
+ matchFailed("\":\"");
2944
+ }
2945
+ }
2946
+ if (result4 !== null) {
2947
+ result5 = [];
2948
+ result6 = parse__();
2949
+ while (result6 !== null) {
2950
+ result5.push(result6);
2951
+ result6 = parse__();
2952
+ }
2953
+ if (result5 !== null) {
2954
+ result6 = parse_compassPt();
2955
+ if (result6 !== null) {
2956
+ result4 = [result4, result5, result6];
2957
+ } else {
2958
+ result4 = null;
2959
+ pos = pos1;
2960
+ }
2961
+ } else {
2962
+ result4 = null;
2963
+ pos = pos1;
2964
+ }
2965
+ } else {
2966
+ result4 = null;
2967
+ pos = pos1;
2968
+ }
2969
+ result4 = result4 !== null ? result4 : "";
2970
+ if (result4 !== null) {
2971
+ result0 = [result0, result1, result2, result3, result4];
2972
+ } else {
2973
+ result0 = null;
2974
+ pos = pos0;
2975
+ }
2976
+ } else {
2977
+ result0 = null;
2978
+ pos = pos0;
2979
+ }
2980
+ } else {
2981
+ result0 = null;
2982
+ pos = pos0;
2983
+ }
2984
+ } else {
2985
+ result0 = null;
2986
+ pos = pos0;
2987
+ }
2988
+ } else {
2989
+ result0 = null;
2990
+ pos = pos0;
2991
+ }
2992
+ return result0;
2993
+ }
2994
+
2995
+ function parse_compassPt() {
2996
+ var result0;
2997
+
2998
+ if (input.charCodeAt(pos) === 110) {
2999
+ result0 = "n";
3000
+ pos++;
3001
+ } else {
3002
+ result0 = null;
3003
+ if (reportFailures === 0) {
3004
+ matchFailed("\"n\"");
3005
+ }
3006
+ }
3007
+ if (result0 === null) {
3008
+ if (input.substr(pos, 2) === "ne") {
3009
+ result0 = "ne";
3010
+ pos += 2;
3011
+ } else {
3012
+ result0 = null;
3013
+ if (reportFailures === 0) {
3014
+ matchFailed("\"ne\"");
3015
+ }
3016
+ }
3017
+ if (result0 === null) {
3018
+ if (input.charCodeAt(pos) === 101) {
3019
+ result0 = "e";
3020
+ pos++;
3021
+ } else {
3022
+ result0 = null;
3023
+ if (reportFailures === 0) {
3024
+ matchFailed("\"e\"");
3025
+ }
3026
+ }
3027
+ if (result0 === null) {
3028
+ if (input.substr(pos, 2) === "se") {
3029
+ result0 = "se";
3030
+ pos += 2;
3031
+ } else {
3032
+ result0 = null;
3033
+ if (reportFailures === 0) {
3034
+ matchFailed("\"se\"");
3035
+ }
3036
+ }
3037
+ if (result0 === null) {
3038
+ if (input.charCodeAt(pos) === 115) {
3039
+ result0 = "s";
3040
+ pos++;
3041
+ } else {
3042
+ result0 = null;
3043
+ if (reportFailures === 0) {
3044
+ matchFailed("\"s\"");
3045
+ }
3046
+ }
3047
+ if (result0 === null) {
3048
+ if (input.substr(pos, 2) === "sw") {
3049
+ result0 = "sw";
3050
+ pos += 2;
3051
+ } else {
3052
+ result0 = null;
3053
+ if (reportFailures === 0) {
3054
+ matchFailed("\"sw\"");
3055
+ }
3056
+ }
3057
+ if (result0 === null) {
3058
+ if (input.charCodeAt(pos) === 119) {
3059
+ result0 = "w";
3060
+ pos++;
3061
+ } else {
3062
+ result0 = null;
3063
+ if (reportFailures === 0) {
3064
+ matchFailed("\"w\"");
3065
+ }
3066
+ }
3067
+ if (result0 === null) {
3068
+ if (input.substr(pos, 2) === "nw") {
3069
+ result0 = "nw";
3070
+ pos += 2;
3071
+ } else {
3072
+ result0 = null;
3073
+ if (reportFailures === 0) {
3074
+ matchFailed("\"nw\"");
3075
+ }
3076
+ }
3077
+ if (result0 === null) {
3078
+ if (input.charCodeAt(pos) === 99) {
3079
+ result0 = "c";
3080
+ pos++;
3081
+ } else {
3082
+ result0 = null;
3083
+ if (reportFailures === 0) {
3084
+ matchFailed("\"c\"");
3085
+ }
3086
+ }
3087
+ if (result0 === null) {
3088
+ if (input.charCodeAt(pos) === 95) {
3089
+ result0 = "_";
3090
+ pos++;
3091
+ } else {
3092
+ result0 = null;
3093
+ if (reportFailures === 0) {
3094
+ matchFailed("\"_\"");
3095
+ }
3096
+ }
3097
+ }
3098
+ }
3099
+ }
3100
+ }
3101
+ }
3102
+ }
3103
+ }
3104
+ }
3105
+ }
3106
+ return result0;
3107
+ }
3108
+
3109
+ function parse_id() {
3110
+ var result0, result1, result2, result3, result4;
3111
+ var pos0, pos1, pos2, pos3;
3112
+
3113
+ reportFailures++;
3114
+ pos0 = pos;
3115
+ pos1 = pos;
3116
+ if (/^[a-zA-Z\u0200-\u0377_]/.test(input.charAt(pos))) {
3117
+ result0 = input.charAt(pos);
3118
+ pos++;
3119
+ } else {
3120
+ result0 = null;
3121
+ if (reportFailures === 0) {
3122
+ matchFailed("[a-zA-Z\\u0200-\\u0377_]");
3123
+ }
3124
+ }
3125
+ if (result0 !== null) {
3126
+ result1 = [];
3127
+ if (/^[a-zA-Z\u0200-\u0377_0-9]/.test(input.charAt(pos))) {
3128
+ result2 = input.charAt(pos);
3129
+ pos++;
3130
+ } else {
3131
+ result2 = null;
3132
+ if (reportFailures === 0) {
3133
+ matchFailed("[a-zA-Z\\u0200-\\u0377_0-9]");
3134
+ }
3135
+ }
3136
+ while (result2 !== null) {
3137
+ result1.push(result2);
3138
+ if (/^[a-zA-Z\u0200-\u0377_0-9]/.test(input.charAt(pos))) {
3139
+ result2 = input.charAt(pos);
3140
+ pos++;
3141
+ } else {
3142
+ result2 = null;
3143
+ if (reportFailures === 0) {
3144
+ matchFailed("[a-zA-Z\\u0200-\\u0377_0-9]");
3145
+ }
3146
+ }
3147
+ }
3148
+ if (result1 !== null) {
3149
+ result0 = [result0, result1];
3150
+ } else {
3151
+ result0 = null;
3152
+ pos = pos1;
3153
+ }
3154
+ } else {
3155
+ result0 = null;
3156
+ pos = pos1;
3157
+ }
3158
+ if (result0 !== null) {
3159
+ result0 = (function(offset, fst, rest) { return fst + rest.join(""); })(pos0, result0[0], result0[1]);
3160
+ }
3161
+ if (result0 === null) {
3162
+ pos = pos0;
3163
+ }
3164
+ if (result0 === null) {
3165
+ pos0 = pos;
3166
+ pos1 = pos;
3167
+ if (input.charCodeAt(pos) === 45) {
3168
+ result0 = "-";
3169
+ pos++;
3170
+ } else {
3171
+ result0 = null;
3172
+ if (reportFailures === 0) {
3173
+ matchFailed("\"-\"");
3174
+ }
3175
+ }
3176
+ result0 = result0 !== null ? result0 : "";
3177
+ if (result0 !== null) {
3178
+ if (input.charCodeAt(pos) === 46) {
3179
+ result1 = ".";
3180
+ pos++;
3181
+ } else {
3182
+ result1 = null;
3183
+ if (reportFailures === 0) {
3184
+ matchFailed("\".\"");
3185
+ }
3186
+ }
3187
+ if (result1 !== null) {
3188
+ if (/^[0-9]/.test(input.charAt(pos))) {
3189
+ result3 = input.charAt(pos);
3190
+ pos++;
3191
+ } else {
3192
+ result3 = null;
3193
+ if (reportFailures === 0) {
3194
+ matchFailed("[0-9]");
3195
+ }
3196
+ }
3197
+ if (result3 !== null) {
3198
+ result2 = [];
3199
+ while (result3 !== null) {
3200
+ result2.push(result3);
3201
+ if (/^[0-9]/.test(input.charAt(pos))) {
3202
+ result3 = input.charAt(pos);
3203
+ pos++;
3204
+ } else {
3205
+ result3 = null;
3206
+ if (reportFailures === 0) {
3207
+ matchFailed("[0-9]");
3208
+ }
3209
+ }
3210
+ }
3211
+ } else {
3212
+ result2 = null;
3213
+ }
3214
+ if (result2 !== null) {
3215
+ result0 = [result0, result1, result2];
3216
+ } else {
3217
+ result0 = null;
3218
+ pos = pos1;
3219
+ }
3220
+ } else {
3221
+ result0 = null;
3222
+ pos = pos1;
3223
+ }
3224
+ } else {
3225
+ result0 = null;
3226
+ pos = pos1;
3227
+ }
3228
+ if (result0 !== null) {
3229
+ result0 = (function(offset, sign, dot, after) { return sign + dot + after.join(""); })(pos0, result0[0], result0[1], result0[2]);
3230
+ }
3231
+ if (result0 === null) {
3232
+ pos = pos0;
3233
+ }
3234
+ if (result0 === null) {
3235
+ pos0 = pos;
3236
+ pos1 = pos;
3237
+ if (input.charCodeAt(pos) === 45) {
3238
+ result0 = "-";
3239
+ pos++;
3240
+ } else {
3241
+ result0 = null;
3242
+ if (reportFailures === 0) {
3243
+ matchFailed("\"-\"");
3244
+ }
3245
+ }
3246
+ result0 = result0 !== null ? result0 : "";
3247
+ if (result0 !== null) {
3248
+ if (/^[0-9]/.test(input.charAt(pos))) {
3249
+ result2 = input.charAt(pos);
3250
+ pos++;
3251
+ } else {
3252
+ result2 = null;
3253
+ if (reportFailures === 0) {
3254
+ matchFailed("[0-9]");
3255
+ }
3256
+ }
3257
+ if (result2 !== null) {
3258
+ result1 = [];
3259
+ while (result2 !== null) {
3260
+ result1.push(result2);
3261
+ if (/^[0-9]/.test(input.charAt(pos))) {
3262
+ result2 = input.charAt(pos);
3263
+ pos++;
3264
+ } else {
3265
+ result2 = null;
3266
+ if (reportFailures === 0) {
3267
+ matchFailed("[0-9]");
3268
+ }
3269
+ }
3270
+ }
3271
+ } else {
3272
+ result1 = null;
3273
+ }
3274
+ if (result1 !== null) {
3275
+ pos2 = pos;
3276
+ if (input.charCodeAt(pos) === 46) {
3277
+ result2 = ".";
3278
+ pos++;
3279
+ } else {
3280
+ result2 = null;
3281
+ if (reportFailures === 0) {
3282
+ matchFailed("\".\"");
3283
+ }
3284
+ }
3285
+ if (result2 !== null) {
3286
+ result3 = [];
3287
+ if (/^[0-9]/.test(input.charAt(pos))) {
3288
+ result4 = input.charAt(pos);
3289
+ pos++;
3290
+ } else {
3291
+ result4 = null;
3292
+ if (reportFailures === 0) {
3293
+ matchFailed("[0-9]");
3294
+ }
3295
+ }
3296
+ while (result4 !== null) {
3297
+ result3.push(result4);
3298
+ if (/^[0-9]/.test(input.charAt(pos))) {
3299
+ result4 = input.charAt(pos);
3300
+ pos++;
3301
+ } else {
3302
+ result4 = null;
3303
+ if (reportFailures === 0) {
3304
+ matchFailed("[0-9]");
3305
+ }
3306
+ }
3307
+ }
3308
+ if (result3 !== null) {
3309
+ result2 = [result2, result3];
3310
+ } else {
3311
+ result2 = null;
3312
+ pos = pos2;
3313
+ }
3314
+ } else {
3315
+ result2 = null;
3316
+ pos = pos2;
3317
+ }
3318
+ result2 = result2 !== null ? result2 : "";
3319
+ if (result2 !== null) {
3320
+ result0 = [result0, result1, result2];
3321
+ } else {
3322
+ result0 = null;
3323
+ pos = pos1;
3324
+ }
3325
+ } else {
3326
+ result0 = null;
3327
+ pos = pos1;
3328
+ }
3329
+ } else {
3330
+ result0 = null;
3331
+ pos = pos1;
3332
+ }
3333
+ if (result0 !== null) {
3334
+ result0 = (function(offset, sign, before, after) { return sign + before.join("") + (after[0] || "") + (after[1] || []).join(""); })(pos0, result0[0], result0[1], result0[2]);
3335
+ }
3336
+ if (result0 === null) {
3337
+ pos = pos0;
3338
+ }
3339
+ if (result0 === null) {
3340
+ pos0 = pos;
3341
+ pos1 = pos;
3342
+ if (input.charCodeAt(pos) === 34) {
3343
+ result0 = "\"";
3344
+ pos++;
3345
+ } else {
3346
+ result0 = null;
3347
+ if (reportFailures === 0) {
3348
+ matchFailed("\"\\\"\"");
3349
+ }
3350
+ }
3351
+ if (result0 !== null) {
3352
+ result1 = [];
3353
+ pos2 = pos;
3354
+ if (input.substr(pos, 2) === "\\\"") {
3355
+ result2 = "\\\"";
3356
+ pos += 2;
3357
+ } else {
3358
+ result2 = null;
3359
+ if (reportFailures === 0) {
3360
+ matchFailed("\"\\\\\\\"\"");
3361
+ }
3362
+ }
3363
+ if (result2 !== null) {
3364
+ result2 = (function(offset) { return '"'; })(pos2);
3365
+ }
3366
+ if (result2 === null) {
3367
+ pos = pos2;
3368
+ }
3369
+ if (result2 === null) {
3370
+ pos2 = pos;
3371
+ pos3 = pos;
3372
+ if (input.charCodeAt(pos) === 92) {
3373
+ result2 = "\\";
3374
+ pos++;
3375
+ } else {
3376
+ result2 = null;
3377
+ if (reportFailures === 0) {
3378
+ matchFailed("\"\\\\\"");
3379
+ }
3380
+ }
3381
+ if (result2 !== null) {
3382
+ if (/^[^"]/.test(input.charAt(pos))) {
3383
+ result3 = input.charAt(pos);
3384
+ pos++;
3385
+ } else {
3386
+ result3 = null;
3387
+ if (reportFailures === 0) {
3388
+ matchFailed("[^\"]");
3389
+ }
3390
+ }
3391
+ if (result3 !== null) {
3392
+ result2 = [result2, result3];
3393
+ } else {
3394
+ result2 = null;
3395
+ pos = pos3;
3396
+ }
3397
+ } else {
3398
+ result2 = null;
3399
+ pos = pos3;
3400
+ }
3401
+ if (result2 !== null) {
3402
+ result2 = (function(offset, ch) { return "\\" + ch; })(pos2, result2[1]);
3403
+ }
3404
+ if (result2 === null) {
3405
+ pos = pos2;
3406
+ }
3407
+ if (result2 === null) {
3408
+ if (/^[^"]/.test(input.charAt(pos))) {
3409
+ result2 = input.charAt(pos);
3410
+ pos++;
3411
+ } else {
3412
+ result2 = null;
3413
+ if (reportFailures === 0) {
3414
+ matchFailed("[^\"]");
3415
+ }
3416
+ }
3417
+ }
3418
+ }
3419
+ while (result2 !== null) {
3420
+ result1.push(result2);
3421
+ pos2 = pos;
3422
+ if (input.substr(pos, 2) === "\\\"") {
3423
+ result2 = "\\\"";
3424
+ pos += 2;
3425
+ } else {
3426
+ result2 = null;
3427
+ if (reportFailures === 0) {
3428
+ matchFailed("\"\\\\\\\"\"");
3429
+ }
3430
+ }
3431
+ if (result2 !== null) {
3432
+ result2 = (function(offset) { return '"'; })(pos2);
3433
+ }
3434
+ if (result2 === null) {
3435
+ pos = pos2;
3436
+ }
3437
+ if (result2 === null) {
3438
+ pos2 = pos;
3439
+ pos3 = pos;
3440
+ if (input.charCodeAt(pos) === 92) {
3441
+ result2 = "\\";
3442
+ pos++;
3443
+ } else {
3444
+ result2 = null;
3445
+ if (reportFailures === 0) {
3446
+ matchFailed("\"\\\\\"");
3447
+ }
3448
+ }
3449
+ if (result2 !== null) {
3450
+ if (/^[^"]/.test(input.charAt(pos))) {
3451
+ result3 = input.charAt(pos);
3452
+ pos++;
3453
+ } else {
3454
+ result3 = null;
3455
+ if (reportFailures === 0) {
3456
+ matchFailed("[^\"]");
3457
+ }
3458
+ }
3459
+ if (result3 !== null) {
3460
+ result2 = [result2, result3];
3461
+ } else {
3462
+ result2 = null;
3463
+ pos = pos3;
3464
+ }
3465
+ } else {
3466
+ result2 = null;
3467
+ pos = pos3;
3468
+ }
3469
+ if (result2 !== null) {
3470
+ result2 = (function(offset, ch) { return "\\" + ch; })(pos2, result2[1]);
3471
+ }
3472
+ if (result2 === null) {
3473
+ pos = pos2;
3474
+ }
3475
+ if (result2 === null) {
3476
+ if (/^[^"]/.test(input.charAt(pos))) {
3477
+ result2 = input.charAt(pos);
3478
+ pos++;
3479
+ } else {
3480
+ result2 = null;
3481
+ if (reportFailures === 0) {
3482
+ matchFailed("[^\"]");
3483
+ }
3484
+ }
3485
+ }
3486
+ }
3487
+ }
3488
+ if (result1 !== null) {
3489
+ if (input.charCodeAt(pos) === 34) {
3490
+ result2 = "\"";
3491
+ pos++;
3492
+ } else {
3493
+ result2 = null;
3494
+ if (reportFailures === 0) {
3495
+ matchFailed("\"\\\"\"");
3496
+ }
3497
+ }
3498
+ if (result2 !== null) {
3499
+ result0 = [result0, result1, result2];
3500
+ } else {
3501
+ result0 = null;
3502
+ pos = pos1;
3503
+ }
3504
+ } else {
3505
+ result0 = null;
3506
+ pos = pos1;
3507
+ }
3508
+ } else {
3509
+ result0 = null;
3510
+ pos = pos1;
3511
+ }
3512
+ if (result0 !== null) {
3513
+ result0 = (function(offset, id) { return id.join(""); })(pos0, result0[1]);
3514
+ }
3515
+ if (result0 === null) {
3516
+ pos = pos0;
3517
+ }
3518
+ }
3519
+ }
3520
+ }
3521
+ reportFailures--;
3522
+ if (reportFailures === 0 && result0 === null) {
3523
+ matchFailed("identifier");
3524
+ }
3525
+ return result0;
3526
+ }
3527
+
3528
+ function parse_node() {
3529
+ var result0;
3530
+ var pos0;
3531
+
3532
+ pos0 = pos;
3533
+ if (input.substr(pos, 4).toLowerCase() === "node") {
3534
+ result0 = input.substr(pos, 4);
3535
+ pos += 4;
3536
+ } else {
3537
+ result0 = null;
3538
+ if (reportFailures === 0) {
3539
+ matchFailed("\"node\"");
3540
+ }
3541
+ }
3542
+ if (result0 !== null) {
3543
+ result0 = (function(offset, k) { return k.toLowerCase(); })(pos0, result0);
3544
+ }
3545
+ if (result0 === null) {
3546
+ pos = pos0;
3547
+ }
3548
+ return result0;
3549
+ }
3550
+
3551
+ function parse_edge() {
3552
+ var result0;
3553
+ var pos0;
3554
+
3555
+ pos0 = pos;
3556
+ if (input.substr(pos, 4).toLowerCase() === "edge") {
3557
+ result0 = input.substr(pos, 4);
3558
+ pos += 4;
3559
+ } else {
3560
+ result0 = null;
3561
+ if (reportFailures === 0) {
3562
+ matchFailed("\"edge\"");
3563
+ }
3564
+ }
3565
+ if (result0 !== null) {
3566
+ result0 = (function(offset, k) { return k.toLowerCase(); })(pos0, result0);
3567
+ }
3568
+ if (result0 === null) {
3569
+ pos = pos0;
3570
+ }
3571
+ return result0;
3572
+ }
3573
+
3574
+ function parse_graph() {
3575
+ var result0;
3576
+ var pos0;
3577
+
3578
+ pos0 = pos;
3579
+ if (input.substr(pos, 5).toLowerCase() === "graph") {
3580
+ result0 = input.substr(pos, 5);
3581
+ pos += 5;
3582
+ } else {
3583
+ result0 = null;
3584
+ if (reportFailures === 0) {
3585
+ matchFailed("\"graph\"");
3586
+ }
3587
+ }
3588
+ if (result0 !== null) {
3589
+ result0 = (function(offset, k) { return k.toLowerCase(); })(pos0, result0);
3590
+ }
3591
+ if (result0 === null) {
3592
+ pos = pos0;
3593
+ }
3594
+ return result0;
3595
+ }
3596
+
3597
+ function parse_digraph() {
3598
+ var result0;
3599
+ var pos0;
3600
+
3601
+ pos0 = pos;
3602
+ if (input.substr(pos, 7).toLowerCase() === "digraph") {
3603
+ result0 = input.substr(pos, 7);
3604
+ pos += 7;
3605
+ } else {
3606
+ result0 = null;
3607
+ if (reportFailures === 0) {
3608
+ matchFailed("\"digraph\"");
3609
+ }
3610
+ }
3611
+ if (result0 !== null) {
3612
+ result0 = (function(offset, k) { return k.toLowerCase(); })(pos0, result0);
3613
+ }
3614
+ if (result0 === null) {
3615
+ pos = pos0;
3616
+ }
3617
+ return result0;
3618
+ }
3619
+
3620
+ function parse_subgraph() {
3621
+ var result0;
3622
+ var pos0;
3623
+
3624
+ pos0 = pos;
3625
+ if (input.substr(pos, 8).toLowerCase() === "subgraph") {
3626
+ result0 = input.substr(pos, 8);
3627
+ pos += 8;
3628
+ } else {
3629
+ result0 = null;
3630
+ if (reportFailures === 0) {
3631
+ matchFailed("\"subgraph\"");
3632
+ }
3633
+ }
3634
+ if (result0 !== null) {
3635
+ result0 = (function(offset, k) { return k.toLowerCase(); })(pos0, result0);
3636
+ }
3637
+ if (result0 === null) {
3638
+ pos = pos0;
3639
+ }
3640
+ return result0;
3641
+ }
3642
+
3643
+ function parse_strict() {
3644
+ var result0;
3645
+ var pos0;
3646
+
3647
+ pos0 = pos;
3648
+ if (input.substr(pos, 6).toLowerCase() === "strict") {
3649
+ result0 = input.substr(pos, 6);
3650
+ pos += 6;
3651
+ } else {
3652
+ result0 = null;
3653
+ if (reportFailures === 0) {
3654
+ matchFailed("\"strict\"");
3655
+ }
3656
+ }
3657
+ if (result0 !== null) {
3658
+ result0 = (function(offset, k) { return k.toLowerCase(); })(pos0, result0);
3659
+ }
3660
+ if (result0 === null) {
3661
+ pos = pos0;
3662
+ }
3663
+ return result0;
3664
+ }
3665
+
3666
+ function parse_graphType() {
3667
+ var result0;
3668
+ var pos0;
3669
+
3670
+ result0 = parse_graph();
3671
+ if (result0 === null) {
3672
+ pos0 = pos;
3673
+ result0 = parse_digraph();
3674
+ if (result0 !== null) {
3675
+ result0 = (function(offset, graph) {
3676
+ directed = graph === "digraph";
3677
+ return graph;
3678
+ })(pos0, result0);
3679
+ }
3680
+ if (result0 === null) {
3681
+ pos = pos0;
3682
+ }
3683
+ }
3684
+ return result0;
3685
+ }
3686
+
3687
+ function parse_whitespace() {
3688
+ var result0, result1;
3689
+
3690
+ reportFailures++;
3691
+ if (/^[ \t\r\n]/.test(input.charAt(pos))) {
3692
+ result1 = input.charAt(pos);
3693
+ pos++;
3694
+ } else {
3695
+ result1 = null;
3696
+ if (reportFailures === 0) {
3697
+ matchFailed("[ \\t\\r\\n]");
3698
+ }
3699
+ }
3700
+ if (result1 !== null) {
3701
+ result0 = [];
3702
+ while (result1 !== null) {
3703
+ result0.push(result1);
3704
+ if (/^[ \t\r\n]/.test(input.charAt(pos))) {
3705
+ result1 = input.charAt(pos);
3706
+ pos++;
3707
+ } else {
3708
+ result1 = null;
3709
+ if (reportFailures === 0) {
3710
+ matchFailed("[ \\t\\r\\n]");
3711
+ }
3712
+ }
3713
+ }
3714
+ } else {
3715
+ result0 = null;
3716
+ }
3717
+ reportFailures--;
3718
+ if (reportFailures === 0 && result0 === null) {
3719
+ matchFailed("whitespace");
3720
+ }
3721
+ return result0;
3722
+ }
3723
+
3724
+ function parse_comment() {
3725
+ var result0, result1, result2, result3;
3726
+ var pos0, pos1, pos2;
3727
+
3728
+ reportFailures++;
3729
+ pos0 = pos;
3730
+ if (input.substr(pos, 2) === "//") {
3731
+ result0 = "//";
3732
+ pos += 2;
3733
+ } else {
3734
+ result0 = null;
3735
+ if (reportFailures === 0) {
3736
+ matchFailed("\"//\"");
3737
+ }
3738
+ }
3739
+ if (result0 !== null) {
3740
+ result1 = [];
3741
+ if (/^[^\n]/.test(input.charAt(pos))) {
3742
+ result2 = input.charAt(pos);
3743
+ pos++;
3744
+ } else {
3745
+ result2 = null;
3746
+ if (reportFailures === 0) {
3747
+ matchFailed("[^\\n]");
3748
+ }
3749
+ }
3750
+ while (result2 !== null) {
3751
+ result1.push(result2);
3752
+ if (/^[^\n]/.test(input.charAt(pos))) {
3753
+ result2 = input.charAt(pos);
3754
+ pos++;
3755
+ } else {
3756
+ result2 = null;
3757
+ if (reportFailures === 0) {
3758
+ matchFailed("[^\\n]");
3759
+ }
3760
+ }
3761
+ }
3762
+ if (result1 !== null) {
3763
+ result0 = [result0, result1];
3764
+ } else {
3765
+ result0 = null;
3766
+ pos = pos0;
3767
+ }
3768
+ } else {
3769
+ result0 = null;
3770
+ pos = pos0;
3771
+ }
3772
+ if (result0 === null) {
3773
+ pos0 = pos;
3774
+ if (input.substr(pos, 2) === "/*") {
3775
+ result0 = "/*";
3776
+ pos += 2;
3777
+ } else {
3778
+ result0 = null;
3779
+ if (reportFailures === 0) {
3780
+ matchFailed("\"/*\"");
3781
+ }
3782
+ }
3783
+ if (result0 !== null) {
3784
+ result1 = [];
3785
+ pos1 = pos;
3786
+ pos2 = pos;
3787
+ reportFailures++;
3788
+ if (input.substr(pos, 2) === "*/") {
3789
+ result2 = "*/";
3790
+ pos += 2;
3791
+ } else {
3792
+ result2 = null;
3793
+ if (reportFailures === 0) {
3794
+ matchFailed("\"*/\"");
3795
+ }
3796
+ }
3797
+ reportFailures--;
3798
+ if (result2 === null) {
3799
+ result2 = "";
3800
+ } else {
3801
+ result2 = null;
3802
+ pos = pos2;
3803
+ }
3804
+ if (result2 !== null) {
3805
+ if (input.length > pos) {
3806
+ result3 = input.charAt(pos);
3807
+ pos++;
3808
+ } else {
3809
+ result3 = null;
3810
+ if (reportFailures === 0) {
3811
+ matchFailed("any character");
3812
+ }
3813
+ }
3814
+ if (result3 !== null) {
3815
+ result2 = [result2, result3];
3816
+ } else {
3817
+ result2 = null;
3818
+ pos = pos1;
3819
+ }
3820
+ } else {
3821
+ result2 = null;
3822
+ pos = pos1;
3823
+ }
3824
+ while (result2 !== null) {
3825
+ result1.push(result2);
3826
+ pos1 = pos;
3827
+ pos2 = pos;
3828
+ reportFailures++;
3829
+ if (input.substr(pos, 2) === "*/") {
3830
+ result2 = "*/";
3831
+ pos += 2;
3832
+ } else {
3833
+ result2 = null;
3834
+ if (reportFailures === 0) {
3835
+ matchFailed("\"*/\"");
3836
+ }
3837
+ }
3838
+ reportFailures--;
3839
+ if (result2 === null) {
3840
+ result2 = "";
3841
+ } else {
3842
+ result2 = null;
3843
+ pos = pos2;
3844
+ }
3845
+ if (result2 !== null) {
3846
+ if (input.length > pos) {
3847
+ result3 = input.charAt(pos);
3848
+ pos++;
3849
+ } else {
3850
+ result3 = null;
3851
+ if (reportFailures === 0) {
3852
+ matchFailed("any character");
3853
+ }
3854
+ }
3855
+ if (result3 !== null) {
3856
+ result2 = [result2, result3];
3857
+ } else {
3858
+ result2 = null;
3859
+ pos = pos1;
3860
+ }
3861
+ } else {
3862
+ result2 = null;
3863
+ pos = pos1;
3864
+ }
3865
+ }
3866
+ if (result1 !== null) {
3867
+ if (input.substr(pos, 2) === "*/") {
3868
+ result2 = "*/";
3869
+ pos += 2;
3870
+ } else {
3871
+ result2 = null;
3872
+ if (reportFailures === 0) {
3873
+ matchFailed("\"*/\"");
3874
+ }
3875
+ }
3876
+ if (result2 !== null) {
3877
+ result0 = [result0, result1, result2];
3878
+ } else {
3879
+ result0 = null;
3880
+ pos = pos0;
3881
+ }
3882
+ } else {
3883
+ result0 = null;
3884
+ pos = pos0;
3885
+ }
3886
+ } else {
3887
+ result0 = null;
3888
+ pos = pos0;
3889
+ }
3890
+ }
3891
+ reportFailures--;
3892
+ if (reportFailures === 0 && result0 === null) {
3893
+ matchFailed("comment");
3894
+ }
3895
+ return result0;
3896
+ }
3897
+
3898
+ function parse__() {
3899
+ var result0;
3900
+
3901
+ result0 = parse_whitespace();
3902
+ if (result0 === null) {
3903
+ result0 = parse_comment();
3904
+ }
3905
+ return result0;
3906
+ }
3907
+
3908
+
3909
+ function cleanupExpected(expected) {
3910
+ expected.sort();
3911
+
3912
+ var lastExpected = null;
3913
+ var cleanExpected = [];
3914
+ for (var i = 0; i < expected.length; i++) {
3915
+ if (expected[i] !== lastExpected) {
3916
+ cleanExpected.push(expected[i]);
3917
+ lastExpected = expected[i];
3918
+ }
3919
+ }
3920
+ return cleanExpected;
3921
+ }
3922
+
3923
+ function computeErrorPosition() {
3924
+ /*
3925
+ * The first idea was to use |String.split| to break the input up to the
3926
+ * error position along newlines and derive the line and column from
3927
+ * there. However IE's |split| implementation is so broken that it was
3928
+ * enough to prevent it.
3929
+ */
3930
+
3931
+ var line = 1;
3932
+ var column = 1;
3933
+ var seenCR = false;
3934
+
3935
+ for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
3936
+ var ch = input.charAt(i);
3937
+ if (ch === "\n") {
3938
+ if (!seenCR) { line++; }
3939
+ column = 1;
3940
+ seenCR = false;
3941
+ } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
3942
+ line++;
3943
+ column = 1;
3944
+ seenCR = true;
3945
+ } else {
3946
+ column++;
3947
+ seenCR = false;
3948
+ }
3949
+ }
3950
+
3951
+ return { line: line, column: column };
3952
+ }
3953
+
3954
+
3955
+ var directed;
3956
+
3957
+ function rightBiasedMerge(lhs, rhs) {
3958
+ var result = {};
3959
+ for (var k in lhs) {
3960
+ result[k] = lhs[k];
3961
+ }
3962
+ for (var k in rhs) {
3963
+ result[k] = rhs[k];
3964
+ }
3965
+ return result;
3966
+ }
3967
+
3968
+
3969
+ var result = parseFunctions[startRule]();
3970
+
3971
+ /*
3972
+ * The parser is now in one of the following three states:
3973
+ *
3974
+ * 1. The parser successfully parsed the whole input.
3975
+ *
3976
+ * - |result !== null|
3977
+ * - |pos === input.length|
3978
+ * - |rightmostFailuresExpected| may or may not contain something
3979
+ *
3980
+ * 2. The parser successfully parsed only a part of the input.
3981
+ *
3982
+ * - |result !== null|
3983
+ * - |pos < input.length|
3984
+ * - |rightmostFailuresExpected| may or may not contain something
3985
+ *
3986
+ * 3. The parser did not successfully parse any part of the input.
3987
+ *
3988
+ * - |result === null|
3989
+ * - |pos === 0|
3990
+ * - |rightmostFailuresExpected| contains at least one failure
3991
+ *
3992
+ * All code following this comment (including called functions) must
3993
+ * handle these states.
3994
+ */
3995
+ if (result === null || pos !== input.length) {
3996
+ var offset = Math.max(pos, rightmostFailuresPos);
3997
+ var found = offset < input.length ? input.charAt(offset) : null;
3998
+ var errorPosition = computeErrorPosition();
3999
+
4000
+ throw new this.SyntaxError(
4001
+ cleanupExpected(rightmostFailuresExpected),
4002
+ found,
4003
+ offset,
4004
+ errorPosition.line,
4005
+ errorPosition.column
4006
+ );
4007
+ }
4008
+
4009
+ return result;
4010
+ },
4011
+
4012
+ /* Returns the parser source code. */
4013
+ toSource: function() { return this._source; }
4014
+ };
4015
+
4016
+ /* Thrown when a parser encounters a syntax error. */
4017
+
4018
+ result.SyntaxError = function(expected, found, offset, line, column) {
4019
+ function buildMessage(expected, found) {
4020
+ var expectedHumanized, foundHumanized;
4021
+
4022
+ switch (expected.length) {
4023
+ case 0:
4024
+ expectedHumanized = "end of input";
4025
+ break;
4026
+ case 1:
4027
+ expectedHumanized = expected[0];
4028
+ break;
4029
+ default:
4030
+ expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
4031
+ + " or "
4032
+ + expected[expected.length - 1];
4033
+ }
4034
+
4035
+ foundHumanized = found ? quote(found) : "end of input";
4036
+
4037
+ return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
4038
+ }
4039
+
4040
+ this.name = "SyntaxError";
4041
+ this.expected = expected;
4042
+ this.found = found;
4043
+ this.message = buildMessage(expected, found);
4044
+ this.offset = offset;
4045
+ this.line = line;
4046
+ this.column = column;
4047
+ };
4048
+
4049
+ result.SyntaxError.prototype = Error.prototype;
4050
+
4051
+ return result;
4052
+ })();
4053
+ })();