pyret-npm 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2687 @@
1
+ define("jglr/rnglr", ["jglr/cyclicJSON"], function(cycle) {
2
+ function SrcLoc(startRow, startCol, startChar, endRow, endCol, endChar) {
3
+ this.startRow = startRow;
4
+ this.startCol = startCol;
5
+ this.startChar = startChar;
6
+ this.endRow = endRow;
7
+ this.endCol = endCol;
8
+ this.endChar = endChar;
9
+ }
10
+ SrcLoc.cache = {};
11
+ SrcLoc.reset = function() { SrcLoc.cache = {}; }
12
+ SrcLoc.make = function(startRow, startCol, startChar, endRow, endCol, endChar) {
13
+ var byStartChar = SrcLoc.cache[startChar];
14
+ if (byStartChar === undefined)
15
+ byStartChar = SrcLoc.cache[startChar] = {};
16
+ var byEndChar = byStartChar[endChar];
17
+ if (byEndChar === undefined)
18
+ byEndChar = byStartChar[endChar] = new SrcLoc(startRow, startCol, startChar, endRow, endCol, endChar);
19
+ return byEndChar;
20
+ }
21
+ SrcLoc.prototype.toString = function(show_span) {
22
+ var ret = this.startRow + ":" + this.startCol;
23
+ if (show_span)
24
+ ret += "-" + this.endRow + ":" + this.endCol;
25
+ return ret;
26
+ }
27
+ SrcLoc.prototype.combine = function(that) {
28
+ if (this.startChar < that.startChar) {
29
+ if (this.endChar < that.endChar) {
30
+ return SrcLoc.make(this.startRow, this.startCol, this.startChar, that.endRow, that.endCol, that.endChar);
31
+ } else {
32
+ return SrcLoc.make(this.startRow, this.startCol, this.startChar, this.endRow, this.endCol, this.endChar);
33
+ }
34
+ } else {
35
+ if (this.endChar < that.endChar) {
36
+ return SrcLoc.make(that.startRow, that.startCol, that.startChar, that.endRow, that.endCol, that.endChar);
37
+ } else {
38
+ return SrcLoc.make(that.startRow, that.startCol, that.startChar, this.endRow, this.endCol, this.endChar);
39
+ }
40
+ }
41
+ }
42
+ SrcLoc.prototype.posAtStart = function() {
43
+ return SrcLoc.make(this.startRow, this.startCol, this.startChar, this.startRow, this.startCol, this.startChar);
44
+ }
45
+ SrcLoc.prototype.posAtEnd = function() {
46
+ return SrcLoc.make(this.endRow, this.endCol, this.endChar, this.endRow, this.endCol, this.endChar);
47
+ }
48
+
49
+ //////////////////////////////////
50
+ ////////// Various Sets //////////
51
+ //////////////////////////////////
52
+ function IntSet(items) {
53
+ this.elements = {};
54
+ this.ordered = [];
55
+ if (items instanceof IntSet) {
56
+ for (var i = 0; i < items.ordered.length; i++)
57
+ this.add(items.ordered[i]);
58
+ } else if (items) {
59
+ for (var i = 0; i < items.length; i++)
60
+ this.add(items[i]);
61
+ }
62
+ }
63
+ IntSet.prototype.add = function(item) {
64
+ if (this.elements[item] === undefined) {
65
+ this.elements[item] = item;
66
+ this.ordered.push(item);
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+ IntSet.prototype.contains = function(item) { return this.elements[item] !== undefined; }
72
+ IntSet.prototype.size = function() { return this.ordered.length; }
73
+ IntSet.prototype.get = function(index) { return this.ordered[index]; }
74
+ IntSet.prototype.toString = function() {
75
+ var items = this.ordered.slice(0);
76
+ items.sort();
77
+ return "{" + JSON.stringify(items) + "}";
78
+ }
79
+ IntSet.prototype.equals = function(that) {
80
+ if (this.size() !== that.size()) return false;
81
+ if (!(that instanceof IntSet)) return false;
82
+ for (var i = 0; i < this.ordered.length; i++)
83
+ if (that.elements[this.ordered[i]] === undefined)
84
+ return false;
85
+ return true;
86
+ }
87
+
88
+
89
+ function KeyedSet(key, items) {
90
+ this.elements = {};
91
+ this.ordered = [];
92
+ this.uniqueId = "KS" + (++KeyedSet.nextSetId);
93
+ this.byKey = key;
94
+ if (key instanceof KeyedSet) {
95
+ items = key;
96
+ this.byKey = items.byKey;
97
+ for (var i = 0; i < items.ordered.length; i++)
98
+ this.add(items.ordered[i]);
99
+ } else if (items) {
100
+ for (var i = 0; i < items.length; i++)
101
+ this.add(items[i]);
102
+ }
103
+ }
104
+ KeyedSet.nextSetId = 0;
105
+ KeyedSet.equals = function(thiz, that) { return thiz.equals(that); }
106
+ KeyedSet.prototype.add = function(item) {
107
+ var key = item[this.byKey];
108
+ if (this.elements[key] === undefined) {
109
+ this.elements[key] = item;
110
+ this.ordered.push(item);
111
+ return true;
112
+ }
113
+ return false;
114
+ }
115
+ KeyedSet.prototype.size = function() { return this.ordered.length; }
116
+ KeyedSet.prototype.contains = function(item) { return this.elements[item[this.byKey]] !== undefined; }
117
+ KeyedSet.prototype.equals = function(that) {
118
+ if (this.size() !== that.size()) return false;
119
+ if (this.byKey !== that.byKey) return false;
120
+ for (var i = 0; i < this.ordered.length; i++)
121
+ if (that.elements[this.ordered[i][this.byKey]] === undefined)
122
+ return false;
123
+ return true;
124
+ }
125
+ KeyedSet.prototype.get = function(index) { return this.ordered[index]; }
126
+ KeyedSet.prototype.itemForKey = function(key) { return this.elements[key]; }
127
+ KeyedSet.prototype.merge = function(that) {
128
+ var ret = false;
129
+ for (var i = 0; i < that.ordered.length; i++)
130
+ ret = this.add(that.ordered[i]) || ret;
131
+ return ret;
132
+ }
133
+ KeyedSet.prototype.toString = function() {
134
+ var keys = [];
135
+ for (var i = 0; i < this.ordered.length; i++)
136
+ keys.push(this.ordered[i][this.byKey]);
137
+ keys.sort();
138
+ var s = "";
139
+ for (var i = 0; i < keys.length; i++) {
140
+ if (s !== "") s += ", ";
141
+ var elt = this.elements[keys[i]];
142
+ s += elt.asString ? elt.asString : elt.toString();
143
+ }
144
+ return "{" + s + "}";
145
+ }
146
+
147
+ function LR1Set(rules) {
148
+ this.uniqueId = "LR" + ++LR1Set.nextId;
149
+ this.ruleIdx = {}; // maps rules-as-strings to indices in coreRules
150
+ this.coreRules = []; // array of core rules
151
+ this.core = []; // maps indices to sets of lookahead tokens
152
+ this.noLook = []; // true iff we have an LR0 item in this set
153
+ if (rules instanceof KeyedSet) {
154
+ for (var i = 0; i < rules.size(); i++)
155
+ this.addRule(rules.get(i));
156
+ } else if (rules instanceof Array) {
157
+ for (var i = 0; i < rules.length; i++)
158
+ this.addRule(rules[i]);
159
+ } else if (rules instanceof LR1Set) {
160
+ this.coreRules = rules.coreRules.slice(0);
161
+ this.noLook = rules.noLook.slice(0);
162
+ for (var r in rules.ruleIdx)
163
+ this.ruleIdx[r] = rules.ruleIdx[r];
164
+ for (var i = 0; i < rules.core.length; i++)
165
+ this.core[i] = new KeyedSet(rules.core[i]);
166
+ }
167
+ }
168
+ LR1Set.nextId = 0;
169
+ LR1Set.prototype.exhaustive = function() {
170
+ var ret = [];
171
+ for (var i = 0; i < this.coreRules.length; i++) {
172
+ if (this.noLook[i])
173
+ ret.push(this.coreRules[i]);
174
+ for (var j = 0; j < this.core[i].size(); j++) {
175
+ ret.push(this.coreRules[i].withLookahead(this.core[i].get(j)));
176
+ }
177
+ }
178
+ return ret;
179
+ }
180
+ LR1Set.prototype.coreSize = function() { return this.coreRules.length; }
181
+ LR1Set.prototype.getCore = function(i) { return this.coreRules[i]; }
182
+ LR1Set.prototype.getLookaheads = function(i) { return this.core[i]; }
183
+ LR1Set.prototype.addRule = function(rule) {
184
+ var ret = false;
185
+ var noLookahead = rule.withLookahead(undefined);
186
+ ruleKey = noLookahead.toString();
187
+ var idx = this.ruleIdx[ruleKey];
188
+ if (idx === undefined) {
189
+ ret = true;
190
+ idx = this.ruleIdx[ruleKey] = this.coreRules.push(noLookahead) - 1;
191
+ }
192
+ if (rule.lookahead === undefined) {
193
+ ret = ret || !this.noLook[idx];
194
+ this.noLook[idx] = true;
195
+ } else {
196
+ if (this.core[idx] === undefined)
197
+ this.core[idx] = new KeyedSet("key");
198
+ ret = this.core[idx].add(rule.lookahead) || ret;
199
+ }
200
+ return ret; // Return true if something's been added
201
+ }
202
+ LR1Set.prototype.addRuleWithLookaheads = function(rule, lookaheads) {
203
+ var noLookahead = rule.withLookahead(undefined);
204
+ ruleKey = noLookahead.toString();
205
+ var idx = this.ruleIdx[ruleKey];
206
+ if (idx === undefined) {
207
+ idx = this.ruleIdx[ruleKey] = this.coreRules.push(noLookahead) - 1;
208
+ }
209
+ if (lookaheads.size() === 0) {
210
+ this.noLook[idx] = true;
211
+ } else {
212
+ if (this.core[idx] === undefined)
213
+ this.core[idx] = new KeyedSet("key");
214
+ this.core[idx].merge(lookaheads);
215
+ }
216
+ }
217
+ LR1Set.prototype.toString = function(multiLine) {
218
+ var s = "";
219
+ var sep = (multiLine ? "\n" : ", ");
220
+ var leader = (multiLine ? " " : "");
221
+ for (var i = 0; i < this.coreRules.length; i++) {
222
+ if (this.noLook[i]) {
223
+ if (s !== "") s += sep;
224
+ s += leader + this.coreRules[i].toString();
225
+ }
226
+ if (this.core[i] !== undefined) {
227
+ if (s !== "") s += sep;
228
+ s += leader + "[" + this.coreRules[i].toString() + ", " + this.core[i].toString() + "]";
229
+ }
230
+ }
231
+ return "{" + (multiLine ? "\n" : "") + s + "}";
232
+ }
233
+ LR1Set.equals = function(thiz, that) { return thiz.equalsCore(that); }
234
+ LR1Set.prototype.equalsCore = function(that) {
235
+ ret = true
236
+ if (this.core.length !== that.core.length) ret = false;
237
+ for (var r in this.ruleIdx)
238
+ if (that.ruleIdx[r] === undefined) ret = false;
239
+ return ret;
240
+ }
241
+
242
+
243
+ function SetOfSets(items, comparison) {
244
+ this.ordered = [];
245
+ this.comparison = comparison
246
+ if (items instanceof SetOfSets) {
247
+ if (!this.comparison)
248
+ this.comparison = items.comparison;
249
+ for (var i = 0; i < items.ordered.length; i++)
250
+ this.add(items.ordered[i]);
251
+ } else if (items) {
252
+ for (var i = 0; i < items.length; i++)
253
+ this.add(items[i]);
254
+ }
255
+ }
256
+ SetOfSets.prototype.toString = function(sep_lines, sorted) {
257
+ var s = "";
258
+ var items_strs = []
259
+ for (var i = 0; i < this.ordered.length; i++)
260
+ items_strs[i] = this.ordered[i].toString();
261
+ if (sorted)
262
+ items_strs.sort();
263
+ for (var i = 0; i < items_strs.length; i++) {
264
+ if (s == "")
265
+ s += "{" + items_strs[i]
266
+ else
267
+ s += (sep_lines ? ",\n " : ", ") + items_strs[i];
268
+ }
269
+ if (s == "")
270
+ return "{}";
271
+ return s + "}";
272
+ }
273
+ SetOfSets.prototype.add = function(item) {
274
+ var key = item.toString();
275
+ if (this.indexOf(item) === -1) {
276
+ this.ordered.push(item);
277
+ return true;
278
+ }
279
+ return false;
280
+ }
281
+ SetOfSets.prototype.indexOf = function(item) {
282
+ return this.indexOfHelp(this.ordered, item);
283
+ }
284
+ SetOfSets.prototype.indexOfHelp = function(items, item) {
285
+ for (var i = 0; i < items.length; i++) {
286
+ if ((this.comparison && this.comparison(items[i], item)) ||
287
+ ((!this.comparison) && (items[i] == item))) {
288
+ return i;
289
+ }
290
+ }
291
+ return -1;
292
+ }
293
+ SetOfSets.prototype.size = function() { return this.ordered.length; }
294
+ SetOfSets.prototype.get = function(index) { return this.ordered[index]; }
295
+
296
+ //////////////////////////////////
297
+ ///////////// Queues /////////////
298
+ //////////////////////////////////
299
+
300
+ function Queue(items) {
301
+ this.items = items.slice(0);
302
+ this.start = 0;
303
+ this.end = items.length;
304
+ this.length = items.length;
305
+ }
306
+ Queue.prototype.push = function(item) {
307
+ this.items[this.end] = item;
308
+ this.end++;
309
+ this.length++;
310
+ }
311
+ Queue.prototype.shift = function() {
312
+ if (this.length === 0) return undefined;
313
+ var ret = this.items[this.start];
314
+ this.start++;
315
+ this.length--;
316
+ return ret;
317
+ }
318
+ Queue.prototype.get = function(idx) {
319
+ if (this.start + idx < this.end) return this.items[this.start + idx];
320
+ return undefined;
321
+ }
322
+ Queue.prototype.insertAt = function(idx, item) {
323
+ if (this.start + idx < this.end) {
324
+ this.items.splice(this.start + idx, 0, item);
325
+ this.end++;
326
+ this.length++;
327
+ } else
328
+ this.push(item);
329
+ }
330
+ Queue.prototype.debugPrint = function() {
331
+ console.log("********** Debug print of queue: start = " + this.start + ", end = " + this.end + ", length = " + this.length);
332
+ for (var i = this.start; i < this.end; i++) {
333
+ if (this.end === i) console.log("<<-- END");
334
+ if (this.start === i) console.log("-->> START");
335
+ if (this.items[i].hasOwnProperty("debugPrint"))
336
+ console.log(i + ": " + this.items[i].debugPrint());
337
+ else
338
+ console.log(i + ": " + this.items[i].toString(true));
339
+ }
340
+ if (this.items.length === this.start) console.log("-->> START");
341
+ if (this.items.length === this.end) console.log("<<-- END");
342
+ }
343
+
344
+
345
+ //////////////////////////////////
346
+ ///////////// Atoms //////////////
347
+ //////////////////////////////////
348
+
349
+ function Atom() {}
350
+ Atom.equals = function(thiz, that) {
351
+ if (thiz === that) return true;
352
+ if ((thiz instanceof Nonterm) && (that instanceof Nonterm) && (thiz.name == that.name)) return true;
353
+ if ((thiz instanceof Token) && (that instanceof Token) && (thiz.name == that.name)) return true;
354
+ return false;
355
+ }
356
+ Atom.equals.toString = function() { return "Atom.equals" };
357
+ Atom.fromSerializable = function(obj) {
358
+ if (obj === undefined) return undefined;
359
+ if (typeof obj === "string") {
360
+ if (obj === "EOF") return EOF;
361
+ if (obj === "EPSILON") return EPSILON;
362
+ if (obj === "HASH") return HASH;
363
+ var c = obj.charAt(0);
364
+ if (c === "'") return new Token(obj.substring(1));
365
+ if (c === "@") return new Nonterm(obj.substring(1));
366
+ }
367
+ if (obj.type === "Nonterm") return new Nonterm(obj.name);
368
+ if (obj.type === "Token") return new Token(obj.name, obj.value);
369
+ if (obj.type === "EOF") return EOF;
370
+ if (obj.type === "EPSILON") return EPSILON;
371
+ if (obj.type === "HASH") return HASH;
372
+ return null;
373
+ }
374
+ function Nonterm(name) {
375
+ this.name = name;
376
+ this.key = "@" + this.name;
377
+ this.asString = this.name;
378
+ }
379
+ Nonterm.prototype = Object.create(Atom.prototype);
380
+ Nonterm.prototype.toString = function() { /*throw new Error("Don't call me!");*/ return this.name; }
381
+ Nonterm.prototype.toSerializable = function() { return this.key; }
382
+ function Token(name, value) {
383
+ this.name = name;
384
+ if (value !== undefined) {
385
+ this.value = value;
386
+ this.key = "'" + this.name + ":" + this.value;
387
+ this.asString = "'" + this.name;
388
+ } else {
389
+ this.value = name;
390
+ this.key = "'" + this.name;
391
+ this.asString = this.key;
392
+ }
393
+ }
394
+ Token.prototype = Object.create(Atom.prototype);
395
+ Token.prototype.toRepr = function(showVal) {
396
+ if (showVal && this.name !== this.value)
397
+ return "('" + this.name + " " + JSON.stringify(this.value) + ")";
398
+ else
399
+ return this.asString;
400
+ }
401
+ Token.prototype.toString = function() { /*throw new Error("Don't call me!");*/ return this.asString; }
402
+ Token.prototype.toSerializable = function() {
403
+ if (this.name !== this.value)
404
+ return {type: "Token", name: this.name, value: this.value};
405
+ else
406
+ return "'" + this.name;
407
+ }
408
+
409
+ const EOF = Object.create(Token.prototype,
410
+ {name: {enumerable: true, value: "EOF"},
411
+ asString: {enumerable: true, value: "$"},
412
+ toString: {value: function() { /*throw new Error("Don't call me!");*/ return "$"; }},
413
+ toRepr: {value: function(showVal) {
414
+ if (showVal) return "<end of file>";
415
+ return "$";
416
+ }},
417
+ key: {enumerable: true, value: "$"},
418
+ toSerializable: {value: function() { return "EOF"; } }});
419
+ const EPSILON = Object.create(Atom.prototype,
420
+ {name: {enumerable: true, value: "EPSILON"},
421
+ asString: {enumerable: true, value: "ε"},
422
+ toString: {value: function() { /*throw new Error("Don't call me!");*/ return this.key; }},
423
+ toRepr: {value: function() { return "ε"; }},
424
+ key: {enumerable: true, value: "ε"},
425
+ toSerializable: {value: function() { return "EPSILON"; } }});
426
+ const HASH = Object.create(Atom.prototype,
427
+ {name: {enumerable: true, value: "HASH"},
428
+ asString: {enumerable: true, value: "#"},
429
+ toString: {value: function() { /*throw new Error("Don't call me!");*/ return "#"; }},
430
+ toRepr: {value: function() { return "#"; }},
431
+ key: {enumerable: true, value: "#"},
432
+ toSerializable: {value: function() { return "HASH"; } }});
433
+
434
+ //////////////////////////////////
435
+ //////////// Actions /////////////
436
+ //////////////////////////////////
437
+
438
+ function Action() { }
439
+ Action.equals = function actionEquals(thiz, that) {
440
+ return (thiz.type === that.type && Rule.equals(thiz.rule, that.rule) && thiz.dest == that.dest);
441
+ }
442
+ Action.equals.toString = function() { return "Action.equals"; }
443
+ function ReduceAction(rule, f) {
444
+ this.type = "Reduce";
445
+ this.rule = rule;
446
+ this.f = f;
447
+ //assert.notEqual(f, undefined, "Bad f value for rule " + rule);
448
+ this.key = rule.id + "#" + f
449
+ }
450
+ ReduceAction.prototype = Object.create(Action.prototype);
451
+ ReduceAction.prototype.toString = function(hideRule) {
452
+ if (hideRule)
453
+ return "Reduce " + this.rule.id;
454
+ else
455
+ return "Reduce(" + this.rule.id + ":" + this.rule.asString + ", m" + this.rule.position + ", f" + this.f + ")";
456
+ }
457
+ ReduceAction.prototype.equals = function(that) { return (that instanceof ReduceAction) && (this.rule == that.rule); }
458
+
459
+ //////////////////////////////////
460
+ ///////////// Rules //////////////
461
+ //////////////////////////////////
462
+
463
+ // name :: string
464
+ // symbols :: array of Atoms
465
+ // lookahead :: Atom or undefined
466
+ // position :: Number or undefined
467
+ function Rule(name, symbols, lookahead, position) {
468
+ this.id = Rule.NextRuleId++;
469
+ this.name = name;
470
+ this.symbols = symbols;
471
+ this.lookahead = lookahead
472
+ this.position = position || 0;
473
+ var s = this.name.toString() + " =>";
474
+ var c = s
475
+ for (var i = 0; i < this.symbols.length; i++) {
476
+ if (i === this.position)
477
+ s += " .";
478
+ s += " " + this.symbols[i].asString;
479
+ c += " " + this.symbols[i].asString;
480
+ }
481
+ this.coreString = c;
482
+ if (this.position === this.symbols.length)
483
+ s += " .";
484
+ if (this.lookahead)
485
+ s = "[" + s + ", " + this.lookahead.asString + "]";
486
+ this.asString = s;
487
+ }
488
+ Rule.semanticActions = {};
489
+ Rule.defaultASTToString = function(show_pos) {
490
+ var toStr = "(" + this.name;
491
+ if (show_pos)
492
+ toStr += "@" + this.pos.toString(true);
493
+ for (var i = 0; i < this.kids.length; i++) {
494
+ if (this.kids[i].toRepr)
495
+ toStr += " " + this.kids[i].toRepr(true);
496
+ else if (this.kids[i].asString)
497
+ toStr += " " + this.kids[i].asString
498
+ else
499
+ toStr += " " + this.kids[i].toString(true);
500
+ }
501
+ toStr += ")";
502
+ return toStr;
503
+ }
504
+ Rule.defaultAction = function(kids, curPos, semActions) {
505
+ var useful_kids = [];
506
+ for (var i = 0; i < kids.length; i++) {
507
+ if (kids[i].shouldInline === true) useful_kids = useful_kids.concat(kids[i].kids);
508
+ else useful_kids.push(kids[i]);
509
+ }
510
+ var pos = (kids.length > 0 ? kids[0].pos.combine(kids[kids.length - 1].pos) : curPos);
511
+ if (semActions !== undefined && semActions[this.name] !== undefined)
512
+ return semActions[this.name](useful_kids, pos);
513
+ else
514
+ return { name: this.name, kids: useful_kids, toString: Rule.defaultASTToString, pos: pos };
515
+ }
516
+ Rule.defaultAction.toString = function() { return "Rule.defaultAction"; }
517
+ Rule.defaultAction.toSerializable = function() { return "dA"; }
518
+ Rule.semanticActions["dA"] = Rule.defaultAction;
519
+
520
+ Rule.ListSnoc = function(tl, hd, shouldInline) {
521
+ var ret = function(kids, curPos, ignoredSemActions) {
522
+ var useful_kids = [];
523
+ for (var i = 0; i < kids.length; i++) {
524
+ if (kids[i].name === hd) {
525
+ if (kids[i].shouldInline === true)
526
+ useful_kids = useful_kids.concat(kids[i].kids);
527
+ else
528
+ useful_kids.push(kids[i]);
529
+ } else if (kids[i].name === tl) useful_kids = useful_kids.concat(kids[i].kids);
530
+ }
531
+ var pos = (kids.length > 0 ? kids[0].pos.combine(kids[kids.length - 1].pos) : curPos);
532
+ return { name: tl, kids: useful_kids, toString: Rule.defaultASTToString, pos: pos,
533
+ shouldInline: shouldInline };
534
+ }
535
+ if (shouldInline) {
536
+ ret.toString = function() { return "Rule.ListSnoc(" + JSON.stringify(tl) + ", " + JSON.stringify(hd) + ", true)"; }
537
+ }
538
+ else {
539
+ ret.toString = function() { return "Rule.ListSnoc(" + JSON.stringify(tl) + ", " + JSON.stringify(hd) + ")"; }
540
+ }
541
+ ret.toSerializable = function() { return ["ListSnoc", tl, hd, shouldInline]; }
542
+ return ret;
543
+ }
544
+ Rule.semanticActions["ListSnoc"] = Rule.ListSnoc;
545
+
546
+ Rule.Inline = function(kids, curPos, semActions) {
547
+ var ret = Rule.defaultAction.call(this, kids, curPos, semActions);
548
+ ret.shouldInline = true;
549
+ return ret;
550
+ }
551
+ Rule.Inline.toString = function() { return "Rule.Inline"; }
552
+ Rule.Inline.toSerializable = function() { return "Inline"; }
553
+ Rule.semanticActions["Inline"] = Rule.Inline;
554
+
555
+ Rule.KeepOnly = function(names, shouldInline) {
556
+ var name_dict = {};
557
+ for (var i = 0; i < names.length; i++)
558
+ name_dict[names[i]] = true;
559
+ var ret = function(kids, curPos, ignoredSemActions) {
560
+ var useful_kids = [];
561
+ for (var i = 0; i < kids.length; i++) {
562
+ if (name_dict[kids[i].name] === true) {
563
+ if (kids[i].shouldInline === true)
564
+ useful_kids = useful_kids.concat(kids[i].kids);
565
+ else
566
+ useful_kids.push(kids[i]);
567
+ }
568
+ }
569
+ var pos = (kids.length > 0 ? kids[0].pos.combine(kids[kids.length - 1].pos) : curPos);
570
+ return { name: this.name, kids: useful_kids, toString: Rule.defaultASTToString, pos: pos,
571
+ shouldInline: shouldInline };
572
+ }
573
+ if (shouldInline) {
574
+ ret.toString = function() { return "Rule.KeepOnly(" + JSON.stringify(names) + ", true)"; };
575
+ } else {
576
+ ret.toString = function() { return "Rule.KeepOnly(" + JSON.stringify(names) + ")"; };
577
+ }
578
+ ret.toSerializable = function() { return ["KeepOnly", names, shouldInline]; }
579
+ return ret;
580
+ }
581
+ Rule.semanticActions["KeepOnly"] = Rule.KeepOnly;
582
+
583
+ var RuleFactory = {};
584
+ RuleFactory.cache = {};
585
+ RuleFactory.byId = {};
586
+ RuleFactory.make = function(name, symbols, lookahead, pos) {
587
+ pos = pos || 0;
588
+ var findByName = RuleFactory.cache[name];
589
+ var symbolsStr = "" + symbols.map((s) => s.asString);
590
+ if (findByName) {
591
+ var findBySymbols = findByName[symbolsStr];
592
+ if (findBySymbols) {
593
+ var findByLookahead = findBySymbols[lookahead ? lookahead.asString : undefined];
594
+ if (findByLookahead) {
595
+ var findByPos = findByLookahead[pos];
596
+ if (findByPos) return findByPos;
597
+ else {
598
+ var rule = new Rule(name, symbols, lookahead, pos);
599
+ RuleFactory.byId[rule.id] = rule;
600
+ findByLookahead[pos] = rule;
601
+ return rule;
602
+ }
603
+ } else {
604
+ var rule = new Rule(name, symbols, lookahead, pos);
605
+ RuleFactory.byId[rule.id] = rule;
606
+ var byPos = {}; byPos[pos] = rule;
607
+ findBySymbols[lookahead ? lookahead.asString : undefined] = byPos;
608
+ return rule;
609
+ }
610
+ } else {
611
+ var rule = new Rule(name, symbols, lookahead, pos);
612
+ RuleFactory.byId[rule.id] = rule;
613
+ var byPos = {}; byPos[pos] = rule;
614
+ var byLookahead = {}; byLookahead[lookahead ? lookahead.asString : undefined] = byPos;
615
+ findByName[symbolsStr] = byLookahead;
616
+ return rule;
617
+ }
618
+ } else {
619
+ var rule = new Rule(name, symbols, lookahead, pos);
620
+ RuleFactory.byId[rule.id] = rule;
621
+ var byPos = {}; byPos[pos] = rule;
622
+ var byLookahead = {}; byLookahead[lookahead ? lookahead.asString : undefined] = byPos;
623
+ var bySymbols = {}; bySymbols[symbolsStr] = byLookahead;
624
+ RuleFactory.cache[name] = {}; RuleFactory.cache[name] = bySymbols;
625
+ return rule;
626
+ }
627
+ }
628
+ Rule.fromSerializable = function(rulesByOldId, id) {
629
+ var obj = rulesByOldId[id];
630
+ if (obj.hasOwnProperty("like")) {
631
+ var base = Rule.fromSerializable(rulesByOldId, obj.like);
632
+ var lookahead = obj.lookahead;
633
+ var pos = obj.position;
634
+ return RuleFactory.make(base.name, base.symbols, Atom.fromSerializable(lookahead), pos);
635
+ } else {
636
+ var sym = [];
637
+ for (var i = 0; i < obj.symbols.length; i++) {
638
+ sym[i] = Atom.fromSerializable(obj.symbols[i]);
639
+ }
640
+ return RuleFactory.make(obj.name, sym, Atom.fromSerializable(obj.lookahead), obj.position);
641
+ }
642
+ }
643
+
644
+ Rule.NextRuleId = 0;
645
+ Rule.equals = function(thiz, that) {
646
+ if (thiz === that) return true;
647
+ if (thiz === undefined || that === undefined) return false;
648
+ if (thiz.id === that.id) return true;
649
+ if (!(thiz.name == that.name &&
650
+ thiz.symbols == that.symbols &&
651
+ thiz.lookahead == that.lookahead &&
652
+ thiz.position == that.position)) return false;
653
+ return true;
654
+ }
655
+ Rule.equalsCore = function(thiz, that) {
656
+ if (thiz === that) return true;
657
+ if (thiz === undefined || that === undefined) return false;
658
+ if (!(thiz.name == that.name &&
659
+ thiz.symbols == that.symbols &&
660
+ thiz.position == that.position)) return false;
661
+ return true;
662
+ }
663
+ Rule.prototype = {
664
+ toString: function() { return this.asString; },
665
+ withPosition: function(pos) {
666
+ return RuleFactory.make(this.name, this.symbols, this.lookahead, pos);
667
+ },
668
+ withLookahead: function(lookahead) {
669
+ return RuleFactory.make(this.name, this.symbols, lookahead, this.position);
670
+ },
671
+ withLookaheadPosition: function(lookahead, pos) {
672
+ return RuleFactory.make(this.name, this.symbols, lookahead, pos);
673
+ },
674
+ toSerializable: function() {
675
+ var ret = {};
676
+ if (this.lookahead || this.position) {
677
+ if (this.lookahead)
678
+ ret.lookahead = this.lookahead.toSerializable();
679
+ if (this.position)
680
+ ret.position = this.position;
681
+ ret.like = this.withLookaheadPosition(undefined, 0).id;
682
+ return ret;
683
+ }
684
+ ret.name = this.name;
685
+ if (this.position)
686
+ ret.position = this.position;
687
+ ret.symbols = [];
688
+ for (var i = 0; i < this.symbols.length; i++)
689
+ ret.symbols[i] = this.symbols[i].toSerializable();
690
+ return ret;
691
+ }
692
+ }
693
+
694
+
695
+
696
+ function Link(prev, val) {
697
+ this.prev = prev;
698
+ this.val = val;
699
+ this.linkId = Link.NextLinkId++;
700
+ }
701
+ Link.NextLinkId = 0;
702
+ Link.prototype.toString = function() {
703
+ return this.prev.state + "<-(" + this.linkId + (this.reduced ? "r" : "") + ")-" + this.val;
704
+ }
705
+
706
+
707
+
708
+ function ShiftPair(gssNode, state) {
709
+ this.gssNode = gssNode;
710
+ this.state = state;
711
+ }
712
+ ShiftPair.prototype.toString = function() { return "Shift(" + this.gssNode.toString() + ", " + this.state + ")"; }
713
+ function ReductionItem(gssNode, rule, m, f, label) {
714
+ this.gssNode = gssNode;
715
+ this.rule = rule;
716
+ this.m = m;
717
+ this.f = f;
718
+ this.label = label;
719
+ }
720
+ ReductionItem.prototype.toString = function() {
721
+ return "RedItem(" + this.gssNode + ", " + this.rule + ", " + this.m + ", " + this.f + ", " + this.label + ")";
722
+ }
723
+ function GSSNode(label) {
724
+ this.gssId = GSSNode.NextNodeId++;
725
+ this.label = label;
726
+ this.links = [];
727
+ // GSSNode.allNodes.push(this);
728
+ }
729
+ GSSNode.NextNodeId = 0;
730
+ // GSSNode.allNodes = [];
731
+ // GSSNode.reset = function() {
732
+ // GSSNode.NextNodeId = 0;
733
+ // GSSNode.allNodes = [];
734
+ // }
735
+ GSSNode.prototype.toString = function() {
736
+ return "GSSNode(#" + this.gssId + ",s" + this.parentSetId + ":st" + this.label + ")";
737
+ }
738
+ GSSNode.prototype.forPathsOfLength = function(len, callback) {
739
+ if (len === 0) {
740
+ callback({labels: [], leftSib: this});
741
+ } else {
742
+ //assert(this.links.length > 0, "Can't find any paths of length " + len + " from " + this)
743
+ for (var i = 0; i < this.links.length; i++)
744
+ pathLengthHelp(this.links[i], len, [], /*[this.toString()], */callback);
745
+ }
746
+ }
747
+ function pathLengthHelp(link, len, labels, /*stack, */callback) {
748
+ labels[len - 1] = link.val;
749
+ //stack.push(link.prev.toString());
750
+ if (len == 1) {
751
+ // console.log("Constructed path via [" + stack + "]");
752
+ // console.log("Calling callback with [" + labels + "] and leftSib.state " + link.prev.label);
753
+ callback({labels: labels, leftSib: link.prev});
754
+ } else {
755
+ var prev_links = link.prev.links;
756
+ //assert(prev_links.length > 0, "Can't find any paths of length " + len + " from " + this)
757
+ for (var i = 0; i < prev_links.length; i++)
758
+ pathLengthHelp(prev_links[i], len - 1, labels, /*stack, */callback);
759
+ }
760
+ //stack.pop();
761
+ }
762
+
763
+
764
+
765
+ var allowNull = false;
766
+ function SPPFNode(label, pos) {
767
+ //if (!allowNull)
768
+ //assert(pos !== undefined && pos !== null);
769
+ this.sppfId = SPPFNode.NextId++;
770
+ this.label = label;
771
+ this.pos = pos;
772
+ this.rule = undefined;
773
+ this.kids = undefined;
774
+ this.ambig = undefined;
775
+ // SPPFNode.allNodes.push(this);
776
+ }
777
+ SPPFNode.NextId = 0;
778
+ // SPPFNode.allNodes = [];
779
+ // SPPFNode.reset = function() {
780
+ // SPPFNode.NextId = 0;
781
+ // SPPFNode.allNodes = [];
782
+ // }
783
+ SPPFNode.prototype.toString = function() {
784
+ var posString = "null";
785
+ if (this.pos)
786
+ posString = this.pos.toString(true);
787
+ var ruleAmbig = "";
788
+ if (this.rule)
789
+ ruleAmbig = this.rule.toString();
790
+ else if (this.ambig)
791
+ ruleAmbig = "ambig";
792
+ else if (this.label instanceof Token)
793
+ ruleAmbig = "<Token " + this.label.toString(true) + ">";
794
+ else
795
+ ruleAmbig = "<unknown>";
796
+ return "SPPFNode(" + this.sppfId + ", " + this.label.toString(true) + "@" + posString + " " + ruleAmbig + ")";
797
+ }
798
+ SPPFNode.prototype.addChildren = function(rule, kids, grammar) {
799
+ if (this.kids === undefined && this.ambig === undefined) {
800
+ this.kids = kids;
801
+ this.rule = rule;
802
+ } else if (this.ambig === undefined) {
803
+ this.ambig = [];
804
+ this.ambig.push({kids: this.kids, rule: this.rule});
805
+ this.ambig.push({kids: kids, rule: rule});
806
+ delete this.kids; delete this.rule;
807
+ } else {
808
+ var ruleFlags = grammar.getFlags(rule);
809
+ var sortingFlag = grammar.ambiguitySortingFlag;
810
+ if (sortingFlag === undefined || ruleFlags === undefined || ruleFlags[sortingFlag] === undefined) {
811
+ this.ambig.push({kids: kids, rule: rule});
812
+ } else {
813
+ var newFlag = ruleFlags[sortingFlag];
814
+ for (var i = 0; i < this.ambig.length; i++) {
815
+ var flags = grammar.getFlags(this.ambig[i].rule);
816
+ var relevantFlag = flags ? flags[sortingFlag] : undefined;
817
+ if (relevantFlag > newFlag) {
818
+ this.ambig.splice(i, 0, {kids: kids, rule: rule});
819
+ return;
820
+ }
821
+ }
822
+ this.ambig.push({kids: kids, rule: rule});
823
+ }
824
+ }
825
+ }
826
+
827
+ //////////////////////////////////
828
+ //////////// Grammars ////////////
829
+ //////////////////////////////////
830
+
831
+ function Grammar(name, start) {
832
+ this.name = name;
833
+ this.rules = {};
834
+ this.actions = {};
835
+ this.flags = {};
836
+ this.start = start;
837
+ this.rnTable = [];
838
+ this.acceptStates = [];
839
+ this.atoms = new KeyedSet("key", [EOF, EPSILON]);
840
+ this.tokens = new KeyedSet("key", [EOF, EPSILON]);
841
+ this.nonterms = new KeyedSet("key");
842
+ }
843
+
844
+ Grammar.fromSerializable = function(obj) {
845
+ switch(obj.version || 0) {
846
+ case 1: return Grammar.fromSerializableV1(obj);
847
+ case 0:
848
+ default: return Grammar.fromSerializableV0(obj);
849
+ }
850
+ }
851
+ Grammar.fromSerializableV1 = function(obj) {
852
+ const rawTime = ((typeof process !== "undefined") && process.hrtime) ? process.hrtime
853
+ : (((typeof performance !== "undefined") && performance.now) ? performance.now.bind(performance) : Date.now);
854
+ var startTime = rawTime();
855
+ function getTime() { return rawTime(startTime); }
856
+ var times = []
857
+ times.push({"Start ": getTime()});
858
+ var g = new Grammar(obj.name, obj.start);
859
+ times.push({"Constr ": getTime()});
860
+ var rulesByOldId = {};
861
+ var actionsByOldId = {};
862
+ var flagsByOldId = {};
863
+ GSSNode.NextNodeId = 0;
864
+ Link.NextLinkId = 0;
865
+ SPPFNode.NextId = 0
866
+ for (var id in obj.rulesByOldId) {
867
+ rulesByOldId[id] = Rule.fromSerializable(obj.rulesByOldId, id);
868
+ var action = obj.actionsByOldId[id]
869
+ if (typeof action === "string" || action instanceof String) {
870
+ actionsByOldId[id] = Rule.semanticActions[action];
871
+ } else if (action instanceof Array) {
872
+ var actionMaker = Rule.semanticActions[action.shift()];
873
+ actionsByOldId[id] = actionMaker.apply(Rule, action);
874
+ }
875
+ flagsByOldId[id] = obj.flagsByOldId[id];
876
+ }
877
+ times.push({"rulesByOldId ": getTime()});
878
+ for (var i = 0; i < obj.rules.length; i++) {
879
+ g.addRule(rulesByOldId[obj.rules[i]], actionsByOldId[obj.rules[i]], flagsByOldId[obj.rules[i]]);
880
+ }
881
+ times.push({"addRules ": getTime()});
882
+ g.rnTable = [];
883
+ var reduceActions = [];
884
+ for (var i = 0; i < obj.reduceActions.length; i += 2)
885
+ reduceActions[i] = new ReduceAction(rulesByOldId[obj.reduceActions[i]], obj.reduceActions[i + 1]);
886
+ times.push({"new redActs ": getTime(), numRedActs: reduceActions.length});
887
+ var emptyActions = {push: undefined, reductions: new Set()};
888
+ for (var i = 0; i < obj.rnTable.length; i++) {
889
+ var tableRow = obj.rnTable[i];
890
+ var newRow = g.rnTable[i] = {};
891
+ for (var j = 0; j < g.atoms.size(); j++) {
892
+ var atom = g.atoms.get(j).asString;
893
+ if (atom in tableRow) {
894
+ var nr = newRow[atom] = {push: undefined, reductions: new Set()};
895
+ var tr = tableRow[atom];
896
+ if (tr[0] >= 0)
897
+ nr.push = tr[0];
898
+ var last = tr.length;
899
+ if (tr.length > 1 && tr[tr.length - 1] === -1) {
900
+ last--;
901
+ nr.accept = true;
902
+ }
903
+ for (var k = 1; k < last; k++) {
904
+ nr.reductions.add(reduceActions[tr[k]]);
905
+ }
906
+ } else {
907
+ newRow[atom] = emptyActions;
908
+ }
909
+ }
910
+ }
911
+ times.push({"rnTable ": getTime(), numAtoms: g.atoms.size(), tableLen: obj.rnTable.length});
912
+ g.acceptStates = [];
913
+ for (var i = 0; i < obj.acceptStates.length; i++)
914
+ g.acceptStates[obj.acceptStates[i]] = true;
915
+ g.ambiguitySortingFlag = obj.ambiguitySortingFlag;
916
+ g.mode = obj.mode;
917
+ g.eSPPFs = [];
918
+ g.I = obj.I;
919
+ allowNull = true;
920
+ for (var i = 0; i < obj.eSPPFs.length; i++) {
921
+ var label = obj.eSPPFs[i].label;
922
+ if (label === "EPSILON")
923
+ label = EPSILON;
924
+ g.eSPPFs[i] = {null: new SPPFNode(label, null)};
925
+ }
926
+ times.push({"bareSPPFs ": getTime()});
927
+ allowNull = false;
928
+ for (var i = 0; i < obj.eSPPFs.length; i++) {
929
+ var src = obj.eSPPFs[i];
930
+ var dest = g.eSPPFs[i].null;
931
+ if (src.kids) {
932
+ var kids = [];
933
+ for (var j = 0; j < src.kids.length; j++)
934
+ kids.push(g.eSPPFs[src.kids[j]].null);
935
+ dest.addChildren(rulesByOldId[src.rule], kids, this);
936
+ }
937
+ }
938
+ times.push({"finished ": getTime()});
939
+ var end = rawTime(startTime);
940
+ const NS_PER_SEC = 1e9;
941
+ var cur = 0;
942
+ for (var i = 0; i < times.length; i++) {
943
+ for (var k in times[i]) {
944
+ if (times[i][k] instanceof Array) {
945
+ var next = (times[i][k][0] * NS_PER_SEC + times[i][k][1]) / NS_PER_SEC;
946
+ times[i][k] = (next - cur).toFixed(10);
947
+ cur = next;
948
+ }
949
+ }
950
+ }
951
+ times.push({"TOTAL ": ((end[0] * NS_PER_SEC + end[1]) / NS_PER_SEC).toFixed(10)});
952
+ //console.log(times);
953
+ return g;
954
+ }
955
+
956
+ Grammar.fromSerializableV0 = function(obj) {
957
+ const rawTime = ((typeof process !== "undefined") && process.hrtime) ? process.hrtime
958
+ : (((typeof performance !== "undefined") && performance.now) ? performance.now.bind(performance) : Date.now);
959
+ var startTime = rawTime();
960
+ function getTime() { return rawTime(startTime); }
961
+ var g = new Grammar(obj.name, obj.start);
962
+ var rulesByOldId = {};
963
+ var actionsByOldId = {};
964
+ var flagsByOldId = {};
965
+ GSSNode.NextNodeId = 0;
966
+ Link.NextLinkId = 0;
967
+ SPPFNode.NextId = 0
968
+ for (var id in obj.rulesByOldId) {
969
+ rulesByOldId[id] = Rule.fromSerializable(obj.rulesByOldId, id);
970
+ actionsByOldId[id] = obj.actionsByOldId[id] ? eval(obj.actionsByOldId[id]) : undefined;
971
+ flagsByOldId[id] = obj.flagsByOldId[id];
972
+ }
973
+ for (var i = 0; i < obj.rules.length; i++) {
974
+ g.addRule(rulesByOldId[obj.rules[i]], actionsByOldId[obj.rules[i]], flagsByOldId[obj.rules[i]]);
975
+ }
976
+ g.rnTable = [];
977
+ for (var i = 0; i < obj.rnTable.length; i++) {
978
+ var tableRow = obj.rnTable[i];
979
+ var newRow = g.rnTable[i] = {};
980
+ for (var j = 0; j < g.atoms.size(); j++) {
981
+ var atom = g.atoms.get(j);
982
+ newRow[atom] = {push: undefined, reductions: new Set()};
983
+ if (atom in tableRow) {
984
+ if (tableRow[atom].accept)
985
+ newRow[atom].accept = true;
986
+ if (tableRow[atom].push) {
987
+ //assert.equal(newRow[atom].push, undefined, "Already have a push action for atom " + atom);
988
+ newRow[atom].push = tableRow[atom].push;
989
+ }
990
+ if (tableRow[atom].reductions) {
991
+ for (var k = 0; k < tableRow[atom].reductions.length; k++) {
992
+ var red = tableRow[atom].reductions[k];
993
+ newRow[atom].reductions.add(new ReduceAction(rulesByOldId[red[0]], red[1]));
994
+ }
995
+ }
996
+ }
997
+ }
998
+ }
999
+ g.acceptStates = [];
1000
+ for (var i = 0; i < obj.acceptStates.length; i++)
1001
+ g.acceptStates[obj.acceptStates[i]] = true;
1002
+ g.derivable = {};
1003
+ for (var name in obj.derivable) {
1004
+ g.derivable[name] = {};
1005
+ for (var i = 0; i < obj.derivable[name].length; i++)
1006
+ g.derivable[name][obj.derivable[name][i]] = true;
1007
+ }
1008
+ g.ambiguitySortingFlag = obj.ambiguitySortingFlag;
1009
+ g.mode = obj.mode;
1010
+ g.eSPPFs = [];
1011
+ g.I = obj.I;
1012
+ allowNull = true;
1013
+ for (var i = 0; i < obj.eSPPFs.length; i++) {
1014
+ var label = obj.eSPPFs[i].label;
1015
+ if (label === "EPSILON")
1016
+ label = EPSILON;
1017
+ g.eSPPFs[i] = {null: new SPPFNode(label, null)};
1018
+ }
1019
+ allowNull = false;
1020
+ for (var i = 0; i < obj.eSPPFs.length; i++) {
1021
+ var src = obj.eSPPFs[i];
1022
+ var dest = g.eSPPFs[i].null;
1023
+ if (src.kids) {
1024
+ var kids = [];
1025
+ for (var j = 0; j < src.kids.length; j++)
1026
+ kids.push(g.eSPPFs[src.kids[j]].null);
1027
+ dest.addChildren(rulesByOldId[src.rule], kids, this);
1028
+ }
1029
+ }
1030
+ var end = rawTime(startTime);
1031
+ const NS_PER_SEC = 1e9;
1032
+ var cur = 0;
1033
+ console.log({"TOTAL ": ((end[0] * NS_PER_SEC + end[1]) / NS_PER_SEC).toFixed(10)});
1034
+ return g;
1035
+ }
1036
+
1037
+
1038
+
1039
+ Grammar.prototype = {
1040
+ resetParser: function() {
1041
+ this.rnTable = [];
1042
+ this.acceptStates = [];
1043
+ delete this.first;
1044
+ delete this.nontermFirst;
1045
+ delete this.states;
1046
+ this.firstStringCache = {};
1047
+ this.closureCache = {};
1048
+ },
1049
+ initializeParser: function(verbose) {
1050
+ console.log("Initializing " + this.name);
1051
+ var new_start;
1052
+ if (!this.initialized) {
1053
+ new_start = "START";
1054
+ while (this.rules.hasOwnProperty(new_start))
1055
+ new_start += "_";
1056
+ this.addRule(new_start, [new Nonterm(this.start)]);
1057
+ this.start = new_start;
1058
+ this.initialized = true;
1059
+ }
1060
+ var orig_start = this.rules[this.start][0].symbols[0];
1061
+ if (verbose) {
1062
+ console.log("Grammar productions:");
1063
+ for (var name in this.rules)
1064
+ for (var i = 0; i < this.rules[name].length; i++)
1065
+ console.log(" " + this.rules[name][i].toString(true));
1066
+ }
1067
+ console.log("Computing first sets");
1068
+ this.resetParser();
1069
+ this.computeFirstSets();
1070
+ console.log("Computing derivability");
1071
+ this.computeDerivability();
1072
+ console.log("Computing states");
1073
+ this.computeStateKernels();
1074
+ console.log("Computing required nullable parts");
1075
+ this.computeRequiredNullableParts();
1076
+ console.log("Computing RN Table");
1077
+ this.computeRNTable();
1078
+ // console.log(this.printTables());
1079
+ this.mode = "RNGLR";
1080
+ console.log("Done initializing " + this.name);
1081
+ },
1082
+ parse: function(token_stream) {
1083
+ this.resetESPPFs();
1084
+ if (this.mode === "RNGLR")
1085
+ return this.parseRNGLR(token_stream);
1086
+ return "Unknown parsing mode -- can't actually parse!"
1087
+ },
1088
+ toString: function() {
1089
+ var s = "Grammar " + this.name + ": (initial rule " + this.start + ")\n";
1090
+ for (var name in this.rules) {
1091
+ var rules = this.rules[name];
1092
+ for (var i = 0; i < rules.length; i++)
1093
+ s += rules[i].toString() + "\n";
1094
+ }
1095
+ return s;
1096
+ },
1097
+ sortAmbiguitiesBy: function(s) {
1098
+ this.ambiguitySortingFlag = s;
1099
+ },
1100
+ toSerializable: function(version) {
1101
+ switch(version || 0) {
1102
+ case 1: return this.toSerializableV1();
1103
+ case 0:
1104
+ default: return this.toSerializableV0();
1105
+ }
1106
+ },
1107
+
1108
+
1109
+ toSerializableV1: function() {
1110
+ var ret = {};
1111
+ ret.version = 1;
1112
+ ret.start = this.start;
1113
+ ret.name = this.name;
1114
+ ret.acceptStates = [];
1115
+ for (var i = 0; i < this.acceptStates.length; i++)
1116
+ if (this.acceptStates[i])
1117
+ ret.acceptStates.push(i);
1118
+ if (this.ambiguitySortingFlag)
1119
+ ret.ambiguitySortingFlag = this.ambiguitySortingFlag;
1120
+ ret.mode = this.mode;
1121
+ ret.rulesByOldId = {};
1122
+ ret.actionsByOldId = {};
1123
+ ret.flagsByOldId = {};
1124
+ ret.rules = [];
1125
+ for (var name in this.rules) {
1126
+ for (var i = 0; i < this.rules[name].length; i++) {
1127
+ var rule = this.rules[name][i];
1128
+ var id = rule.id;
1129
+ ret.rulesByOldId[id] = rule.toSerializable();
1130
+ ret.rules.push(id);
1131
+ var rule_noLookahead = rule.withLookahead(undefined);
1132
+ ret.rulesByOldId[rule_noLookahead.id] = rule_noLookahead.toSerializable();
1133
+ ret.actionsByOldId[rule_noLookahead.id] = this.getAction(rule_noLookahead);
1134
+ if (ret.actionsByOldId[rule_noLookahead.id] !== undefined) {
1135
+ ret.actionsByOldId[rule_noLookahead.id] = ret.actionsByOldId[rule_noLookahead.id].toSerializable();
1136
+ }
1137
+ ret.flagsByOldId[rule_noLookahead.id] = this.getFlags(rule_noLookahead);
1138
+ }
1139
+ }
1140
+ ret.reduceActions = [];
1141
+ var reduceActionsCache = {};
1142
+ ret.rnTable = []; // TODO: Fix this
1143
+ for (var i = 0; i < this.rnTable.length; i++) {
1144
+ var tableRow = this.rnTable[i];
1145
+ ret.rnTable[i] = {};
1146
+ for (var name in tableRow) {
1147
+ if (tableRow[name].push === undefined && !tableRow[name].accept && tableRow[name].reductions.size === 0) {
1148
+ //ret.rnTable[i][name] = "empty";
1149
+ } else {
1150
+ var entry = tableRow[name];
1151
+ var dest = ret.rnTable[i][name] = [];
1152
+ dest.push(entry.push === undefined ? -1 : entry.push);
1153
+ entry.reductions.forEach(function(red) {
1154
+ if (reduceActionsCache[red.rule.id] === undefined)
1155
+ reduceActionsCache[red.rule.id] = {};
1156
+ if (reduceActionsCache[red.rule.id][red.f] === undefined) {
1157
+ reduceActionsCache[red.rule.id][red.f] = ret.reduceActions.length;
1158
+ ret.reduceActions.push(red.rule.id, red.f);
1159
+ }
1160
+ dest.push(reduceActionsCache[red.rule.id][red.f]);
1161
+ ret.rulesByOldId[red.rule.id] = red.rule.toSerializable();
1162
+ var rule_noLookahead = red.rule.withLookahead(undefined);
1163
+ ret.rulesByOldId[rule_noLookahead.id] = rule_noLookahead.toSerializable();
1164
+ });
1165
+ if (entry.accept) dest.push(-1);
1166
+ }
1167
+ }
1168
+ }
1169
+ ret.I = this.I;
1170
+ ret.eSPPFs = [];
1171
+ for (var i = 0; i < this.eSPPFs.length; i++) {
1172
+ var null_eSPPF = this.eSPPFs[i].null;
1173
+ var label = null_eSPPF.label;
1174
+ if (label === EPSILON) {
1175
+ label = "EPSILON";
1176
+ }
1177
+ if (null_eSPPF.kids) {
1178
+ var kids = [];
1179
+ for (var j = 0; j < null_eSPPF.kids.length; j++)
1180
+ kids.push(null_eSPPF.kids[j].sppfId);
1181
+ if (null_eSPPF.rule)
1182
+ ret.eSPPFs[i] = {label: label, kids: kids, rule: null_eSPPF.rule.id};
1183
+ else
1184
+ ret.eSPPFs[i] = {label: label, kids: kids};
1185
+ } else {
1186
+ if (null_eSPPF.rule)
1187
+ ret.eSPPFs[i] = {label: label, rule: null_eSPPF.rule.id};
1188
+ else
1189
+ ret.eSPPFs[i] = {label: label};
1190
+ }
1191
+ }
1192
+ return ret;
1193
+ },
1194
+
1195
+
1196
+ toSerializableV0: function() {
1197
+ var ret = {};
1198
+ ret.start = this.start;
1199
+ ret.name = this.name;
1200
+ ret.acceptStates = [];
1201
+ for (var i = 0; i < this.acceptStates.length; i++)
1202
+ if (this.acceptStates[i])
1203
+ ret.acceptStates.push(i);
1204
+ if (this.ambiguitySortingFlag)
1205
+ ret.ambiguitySortingFlag = this.ambiguitySortingFlag;
1206
+ ret.mode = this.mode;
1207
+ ret.derivable = {};
1208
+ for (var name in this.derivable) {
1209
+ ret.derivable[name] = [];
1210
+ for (var der in this.derivable[name])
1211
+ ret.derivable[name].push(der);
1212
+ }
1213
+ ret.rulesByOldId = {};
1214
+ ret.actionsByOldId = {};
1215
+ ret.flagsByOldId = {};
1216
+ ret.rules = [];
1217
+ for (var name in this.rules) {
1218
+ for (var i = 0; i < this.rules[name].length; i++) {
1219
+ var rule = this.rules[name][i];
1220
+ var id = rule.id;
1221
+ ret.rulesByOldId[id] = rule.toSerializable();
1222
+ ret.rules.push(id);
1223
+ var rule_noLookahead = rule.withLookahead(undefined);
1224
+ ret.rulesByOldId[rule_noLookahead.id] = rule_noLookahead.toSerializable();
1225
+ ret.actionsByOldId[rule_noLookahead.id] = this.getAction(rule_noLookahead);
1226
+ if (ret.actionsByOldId[rule_noLookahead.id] !== undefined) {
1227
+ ret.actionsByOldId[rule_noLookahead.id] = ret.actionsByOldId[rule_noLookahead.id].toString();
1228
+ }
1229
+ ret.flagsByOldId[rule_noLookahead.id] = this.getFlags(rule_noLookahead);
1230
+ }
1231
+ }
1232
+ ret.rnTable = []; // TODO: Fix this
1233
+ for (var i = 0; i < this.rnTable.length; i++) {
1234
+ var tableRow = this.rnTable[i];
1235
+ ret.rnTable[i] = {};
1236
+ for (var name in tableRow) {
1237
+ if (tableRow[name].push === undefined && !tableRow[name].accept && tableRow[name].reductions.size === 0) {
1238
+ //ret.rnTable[i][name] = "empty";
1239
+ } else {
1240
+ var entry = tableRow[name];
1241
+ var dest = ret.rnTable[i][name] = {};
1242
+ if (entry.accept) dest.accept = true;
1243
+ if (entry.push !== undefined) {
1244
+ dest.push = entry.push;
1245
+ }
1246
+ if (entry.reductions.size > 0) {
1247
+ dest.reductions = [];
1248
+ entry.reductions.forEach(function(red) {
1249
+ dest.reductions.push([red.rule.id, red.f]);
1250
+ ret.rulesByOldId[red.rule.id] = red.rule.toSerializable();
1251
+ var rule_noLookahead = red.rule.withLookahead(undefined);
1252
+ ret.rulesByOldId[rule_noLookahead.id] = rule_noLookahead.toSerializable();
1253
+ });
1254
+ }
1255
+ }
1256
+ }
1257
+ }
1258
+ ret.I = this.I;
1259
+ ret.eSPPFs = [];
1260
+ for (var i = 0; i < this.eSPPFs.length; i++) {
1261
+ var null_eSPPF = this.eSPPFs[i].null;
1262
+ var label = null_eSPPF.label;
1263
+ if (label === EPSILON) {
1264
+ label = "EPSILON";
1265
+ }
1266
+ if (null_eSPPF.kids) {
1267
+ var kids = [];
1268
+ for (var j = 0; j < null_eSPPF.kids.length; j++)
1269
+ kids.push(null_eSPPF.kids[j].sppfId);
1270
+ if (null_eSPPF.rule)
1271
+ ret.eSPPFs[i] = {label: label, kids: kids, rule: null_eSPPF.rule.id};
1272
+ else
1273
+ ret.eSPPFs[i] = {label: label, kids: kids};
1274
+ } else {
1275
+ if (null_eSPPF.rule)
1276
+ ret.eSPPFs[i] = {label: label, rule: null_eSPPF.rule.id};
1277
+ else
1278
+ ret.eSPPFs[i] = {label: label};
1279
+ }
1280
+ }
1281
+ return ret;
1282
+ },
1283
+
1284
+ addRule: function(name, symbols, action, flags) {
1285
+ var new_rule;
1286
+ if (name instanceof Rule) {
1287
+ new_rule = name;
1288
+ name = new_rule.name;
1289
+ flags = action; // slide arguments over by one
1290
+ action = symbols;
1291
+ symbols = new_rule.symbols;
1292
+ } else {
1293
+ new_rule = RuleFactory.make(name, symbols, undefined, undefined);
1294
+ }
1295
+ if (action === undefined)
1296
+ action = Rule.defaultAction;
1297
+ this.actions[new_rule.id] = action;
1298
+ this.flags[new_rule.id] = flags;
1299
+ if (!(this.rules.hasOwnProperty(name)))
1300
+ this.rules[name] = [];
1301
+ this.rules[name].push(new_rule);
1302
+ this.atoms.add(new Nonterm(name));
1303
+ this.nonterms.add(new Nonterm(name));
1304
+ for (var i = 0; i < symbols.length; i++) {
1305
+ this.atoms.add(symbols[i]);
1306
+ if (symbols[i] instanceof Nonterm)
1307
+ this.nonterms.add(symbols[i])
1308
+ else
1309
+ this.tokens.add(symbols[i])
1310
+ }
1311
+ return new_rule;
1312
+ },
1313
+
1314
+ getAction: function(rule) {
1315
+ var baseRule = rule.withLookaheadPosition(undefined, 0);
1316
+ var action = this.actions[baseRule.id];
1317
+ return action;
1318
+ },
1319
+ applyAction: function(rule, kids, pos, semActions) {
1320
+ var action = this.getAction(rule);
1321
+ return action.call(rule, kids, pos, semActions);
1322
+ },
1323
+ getFlags: function(rule) {
1324
+ return this.flags[rule.withLookaheadPosition(undefined, 0).id];
1325
+ },
1326
+
1327
+ //////////////////////////////////
1328
+ // Computes what nonterminals can derive other nonterminals in one or more steps,
1329
+ // i.e. A ->+ B for two nonterminals A and B (possibly the same)
1330
+ //////////////////////////////////
1331
+ computeDerivability: function() {
1332
+ this.derivable = {}
1333
+ for (var i = 0; i < this.nonterms.size(); i++)
1334
+ this.derivable[this.nonterms.get(i).asString] = {};
1335
+ var changed = true;
1336
+ while(changed) {
1337
+ changed = false;
1338
+ // console.log("\nNew loop...");
1339
+ for (var name in this.rules) {
1340
+ var rules = this.rules[name]
1341
+ for (var i = 0; i < rules.length; i++) {
1342
+ var rule = rules[i];
1343
+ // console.log("Processing rule [" + rule + "]");
1344
+ if (rule.symbols.length === 0) {
1345
+ // if (!this.derivable[name][EPSILON.asString])
1346
+ // console.log(" " + name + " can derive EPSILON via rule " + rule);
1347
+ changed = changed || (!this.derivable[name][EPSILON.asString]);
1348
+ this.derivable[name][EPSILON.asString] = true; // Rule <name> is nullable
1349
+ }
1350
+ for (var j = 0; j < rule.symbols.length; j++) {
1351
+ var sym = rule.symbols[j]
1352
+ if ((sym instanceof Token) && (sym !== EOF)) {
1353
+ // console.log(" Rule [" + rule + "] isn't nullable due to " + sym.asString + " so skipping rest");
1354
+ break; // A token in the RHS of a rule means it can't derive a nonterminal on its own
1355
+ }
1356
+ var restNullable = true;
1357
+ for (var k = j + 1; k < rule.symbols.length; k++) {
1358
+ if (rule.symbols[k] === EOF) continue;
1359
+ if ((rule.symbols[k] instanceof Token) ||
1360
+ (this.derivable[rule.symbols[k].asString][EPSILON.asString] !== true)) {
1361
+ restNullable = false;
1362
+ break;
1363
+ }
1364
+ }
1365
+ if (restNullable) {
1366
+ // if (!this.derivable[name][sym.asString])
1367
+ // console.log(" " + name + " can derive " + sym.asString + " via [" + rule + "]");
1368
+ changed = changed || (!this.derivable[name][sym.asString]);
1369
+ this.derivable[name][sym.asString] = true;
1370
+ }
1371
+ if ((!this.derivable[sym.asString]) || this.derivable[sym.asString][EPSILON.asString] !== true) {
1372
+ // console.log("Rule [" + rule + "] isn't nullable after " + sym.asString + " so skipping rest");
1373
+ break; // This nonterminal isn't nullable, so skip the rest of the rule
1374
+ }
1375
+ }
1376
+ }
1377
+ }
1378
+
1379
+ for (var i = 0; i < this.nonterms.size(); i++) {
1380
+ var term_i = this.nonterms.get(i).asString;
1381
+ for (var j = 0; j < this.nonterms.size(); j++) {
1382
+ var term_j = this.nonterms.get(j).asString;
1383
+ if (i == j || !this.derivable[term_i][term_j]) continue;
1384
+ if (this.derivable[term_j][EPSILON.asString] && !this.derivable[term_i][EPSILON.asString]) {
1385
+ // console.log(term_i + " can derive EPSILON via " + term_j);
1386
+ this.derivable[term_i][EPSILON.asString] = true;
1387
+ }
1388
+ for (var k = 0; k < this.nonterms.size(); k++) {
1389
+ var term_k = this.nonterms.get(k);
1390
+ if (j == k || !this.derivable[term_j][term_k]) continue;
1391
+ // if (!this.derivable[term_i][term_k])
1392
+ // console.log(term_i + " can derive " + term_k + " via " + term_j);
1393
+ changed = changed || (!this.derivable[term_i][term_k])
1394
+ this.derivable[term_i][term_k] = true;
1395
+ }
1396
+ }
1397
+ }
1398
+ }
1399
+ // console.log("Done");
1400
+ },
1401
+
1402
+ //////////////////////////////////
1403
+ // Computes the set of first tokens in a rule
1404
+ // If a rule is nullable, then EPSILON is one possible token
1405
+ //////////////////////////////////
1406
+ computeFirstSets: function() {
1407
+ var thiz = this;
1408
+ var changed = true;
1409
+ function addFirst(name, token) {
1410
+ var ret = !(token.asString in thiz.first[name])
1411
+ thiz.first[name][token.asString] = token;
1412
+ return ret;
1413
+ }
1414
+ function merge(dest, source) {
1415
+ var ret = false;
1416
+ for (var tok in thiz.first[source])
1417
+ if (thiz.first[source][tok] !== EPSILON)
1418
+ ret = addFirst(dest, thiz.first[source][tok]) || ret;
1419
+ return ret;
1420
+ }
1421
+ this.first = {};
1422
+ this.nontermFirst = {};
1423
+ for (var name in this.rules) {
1424
+ if (this.rules.hasOwnProperty(name)) {
1425
+ this.first[name] = {};
1426
+ this.nontermFirst[name] = new KeyedSet("key", [new Nonterm(name)]);
1427
+ for (var i = 0; i < this.rules[name].length; i++)
1428
+ if (this.rules[name][i].symbols.length === 0)
1429
+ addFirst(name, EPSILON);
1430
+ }
1431
+ }
1432
+ while (changed) {
1433
+ changed = false;
1434
+ for (var name in this.rules) {
1435
+ var name_rules = this.rules[name];
1436
+ for (var i = 0; i < name_rules.length; i++) {
1437
+ var name_rule = name_rules[i];
1438
+ var allNullable = true;
1439
+ for (var j = 0; j < name_rule.symbols.length; j++) {
1440
+ if (name_rule.symbols[j] instanceof Nonterm) {
1441
+ changed = merge(name, name_rule.symbols[j].asString) || changed;
1442
+ //if (this.nontermFirst[name_rule.symbols[j]] === undefined)
1443
+ //assert(false, "Couldn't find a nontermFirst for " + name_rule.symbols[j]);
1444
+ this.nontermFirst[name].merge(this.nontermFirst[name_rule.symbols[j].asString]);
1445
+ if (this.first[name_rule.symbols[j].asString][EPSILON.asString] !== EPSILON) {
1446
+ allNullable = false;
1447
+ break;
1448
+ }
1449
+ } else {
1450
+ changed = addFirst(name, name_rule.symbols[j]) || changed;
1451
+ allNullable = false;
1452
+ break;
1453
+ }
1454
+ }
1455
+ if (allNullable) {
1456
+ addFirst(name, EPSILON);
1457
+ }
1458
+ }
1459
+ }
1460
+ }
1461
+ },
1462
+
1463
+
1464
+ //////////////////////////////////
1465
+ // Computes the tokens that can immediately follow the specified position
1466
+ // in the current rule. This is a subset of the Follow set for the given
1467
+ // nonterminal, and is therefore more precise and less prone to producing
1468
+ // parsing conflicts.
1469
+ //////////////////////////////////
1470
+ computeFollowAtPosition: function(rule, pos) {
1471
+ if (rule.lookahead)
1472
+ return this.computeFirstOfStrings(rule.symbols.slice(pos).concat(rule.lookahead));
1473
+ else
1474
+ return this.computeFirstOfStrings(rule.symbols.slice(pos));
1475
+ },
1476
+
1477
+ //////////////////////////////////
1478
+ // Lifts the first relation from non-terminals to strings of grammar symbols
1479
+ computeFirstOfStrings: function(string) {
1480
+ var joinedStrings = "" + string.map((s) => s.asString);
1481
+ var ret = this.firstStringCache[joinedStrings];
1482
+ if (ret !== undefined) return ret;
1483
+ ret = this.firstStringCache[joinedStrings] = new KeyedSet("key");
1484
+ var nullable = true;
1485
+ // console.log("syms[" + i + "] = [" + string + "], length = " + string.length);
1486
+ for (var j = 0; j < string.length; j++) {
1487
+ if (string[j] instanceof Token || string[j] === HASH) { // Tokens aren't nullable, so we're done
1488
+ ret.add(string[j]);
1489
+ nullable = false;
1490
+ break;
1491
+ } else {
1492
+ var first = this.first[string[j].asString];
1493
+ if (first === undefined) {
1494
+ console.log("Internal error! string[j] = " + JSON.stringify(string[j]) + " but first is undefined");
1495
+ }
1496
+ for (var name in first) {
1497
+ if (first[name] !== EPSILON)
1498
+ ret.add(first[name]);
1499
+ }
1500
+ if (first[EPSILON.asString] === undefined) { // This nonterminal isn't nullable, so we're done
1501
+ nullable = false;
1502
+ break;
1503
+ }
1504
+ }
1505
+ }
1506
+ if (nullable)
1507
+ ret.add(EPSILON);
1508
+ return ret;
1509
+ },
1510
+
1511
+ //////////////////////////////////
1512
+ // Computes the LR(1) closure of a rule set:
1513
+ // For a given rule [A -> a.Bb, x] in the set, it adds [B -> .g, y]
1514
+ // for all [B -> g] in the grammar, and all y in FIRST(bx).
1515
+ //
1516
+ // If inline = true, then it mutates the provided argument
1517
+ // otherwise it constructs a new set and returns that.
1518
+ // Dragon book 2ed, p261
1519
+ completeClosure: function(lrSet, inline) {
1520
+ var ret = inline ? lrSet : new LR1Set(lrSet);
1521
+ var worklist = new Queue(ret.exhaustive());
1522
+ while (worklist.length > 0) {
1523
+ var rule = worklist.shift();
1524
+ if (rule.position < rule.symbols.length) {
1525
+ var next_symbol = rule.symbols[rule.position];
1526
+ if (next_symbol instanceof Nonterm) {
1527
+ var next = this.computeFollowAtPosition(rule, rule.position + 1);
1528
+ // console.log(" next(" + rule + ") = " + next);
1529
+ var rules_to_add = this.rules[next_symbol.asString]
1530
+ if (rules_to_add === undefined) {
1531
+ throw("No rules known for symbol " + next_symbol.asString);
1532
+ }
1533
+ for (var j = 0; j < rules_to_add.length; j++) {
1534
+ var rule_to_add = rules_to_add[j];
1535
+ for (var k = 0; k < next.size(); k++) {
1536
+ var new_rule = RuleFactory.make(rule_to_add.name, rule_to_add.symbols, next.get(k), 0)
1537
+ if (ret.addRule(new_rule)) {
1538
+ worklist.push(new_rule);
1539
+ }
1540
+ }
1541
+ }
1542
+ }
1543
+ }
1544
+ }
1545
+ return ret;
1546
+ },
1547
+
1548
+ //////////////////////////////////
1549
+ // Computes the kernel of the LR(1) Goto set for a given kernel and symbol
1550
+ // Dragon book 2ed, p261
1551
+ computeGotoKernel: function(setNum, lrSet, symbol) {
1552
+ // console.log("--> Rule_set #" + setNum + " = " + lrSet + ", symbol = " + symbol);
1553
+ var ret = new LR1Set();
1554
+ for (var i = 0; i < lrSet.coreSize(); i++) {
1555
+ var rule = lrSet.getCore(i);
1556
+ // console.log(" Processing rule " + rule);
1557
+ if (rule.position < rule.symbols.length && rule.symbols[rule.position].asString == symbol.asString) {
1558
+ // console.log(" Pushing " + symbol + " over in rule " + rule);
1559
+ var new_rule = rule.withPosition(rule.position + 1);
1560
+ // console.log(" new_rule = " + new_rule + " and lookaheads = " + lrSet.getLookaheads(i));
1561
+ ret.addRuleWithLookaheads(new_rule, lrSet.getLookaheads(i));
1562
+ }
1563
+ }
1564
+ this.completeClosure(ret, true);
1565
+ // console.log("<-- Result = " + ret);
1566
+ return ret;
1567
+ },
1568
+
1569
+ reducer: function(U, R, Q, N, i, cur_tok, skipped_WS_loc) {
1570
+ // cur_tok = token #i+1: i starts at index 0, and tokens start at index 1
1571
+ // U is an array of sets of GSS nodes
1572
+ // R is the worklist of pending reductions
1573
+ // Q is the set of (GSS node, token) pairs of pending shifts
1574
+ // N is the set of SPPF nodes created in this step
1575
+ // cur_tok is the current token
1576
+ var item = R.shift();
1577
+ // console.log("In reducer, i = " + i + ", cur_tok = " + cur_tok.toString(true) + ", and item = " + item);
1578
+ var v = item.gssNode; // GSS node from which the reduction is to be applied
1579
+ var X = item.rule.name; // the name of the reduction rule
1580
+ var m = item.m; // the length of the RHS of the reduction rule (maybe just item.rule.position?)
1581
+ var f = item.f; // the index of the required nullable part at the righthand end of the reduction
1582
+ // or 0 if the reduction isn't right-nullable
1583
+ var y = item.label; // the SPPF node labels the first edge of the path down which the reduction is applied
1584
+ // (if m = 0 then y = epsilon) [sic]
1585
+ var y_m = (m !== 0 ? y : undefined)
1586
+ var U_i = U[i]
1587
+ const thiz = this;
1588
+ v.forPathsOfLength(m > 0 ? (m - 1) : 0, function(p) {
1589
+ // console.log("Found path " + JSON.stringify(p, null, " "));
1590
+ // p.labels contain the edge labels of the path
1591
+ var u = p.leftSib;
1592
+ var k = u.label;
1593
+ var l = thiz.rnTable[k][X].push;
1594
+ if (l !== undefined) {
1595
+ // console.log("k = " + k + ", X = " + X + ", l = " + l);
1596
+ var z = undefined;
1597
+ if (m === 0)
1598
+ z = thiz.getEpsilonSPPF(f, cur_tok.pos.posAtStart());
1599
+ else {
1600
+ var c = u.parentSetId;
1601
+ var nodes_X = N[X];
1602
+ if (nodes_X === undefined)
1603
+ nodes_X = N[X] = {};
1604
+ z = nodes_X[c];
1605
+ if (z === undefined) {
1606
+ var pos;
1607
+ if (skipped_WS_loc !== undefined) {
1608
+ pos = skipped_WS_loc.posAtStart();
1609
+ } else {
1610
+ pos = cur_tok.pos;
1611
+ }
1612
+ if (p.labels.length > 0) {
1613
+ pos = pos.combine(p.labels[0].pos);
1614
+ }
1615
+ z = nodes_X[c] = new SPPFNode(X, pos);
1616
+ }
1617
+ }
1618
+ // console.log("z = " + z); // XXX Serializing of eSPPFs isn't working
1619
+ var w = U_i.itemForKey(l);
1620
+ if (w !== undefined) {
1621
+ // console.log("1. Adding link from " + w + " to " + u + " labelled " + z);
1622
+ if (thiz.addLink(/*from*/w, /*to*/u, /*labelled*/z)) {
1623
+ if (m !== 0) {
1624
+ var actions = thiz.getActions(l, cur_tok);
1625
+ if (actions !== undefined) {
1626
+ var reductions = actions.reductions;
1627
+ reductions.forEach(function(red) {
1628
+ if (red.rule.position !== 0)
1629
+ R.push(new ReductionItem(u, red.rule, red.rule.position, red.f, z));
1630
+ });
1631
+ } else {
1632
+ // Possibly shouldn't throw?
1633
+ // throw("No actions found in state " + l + " for token " + next_tok.toString(true) + " at " +
1634
+ // next_tok.pos.toString(true));
1635
+ }
1636
+ }
1637
+ }
1638
+ } else {
1639
+ w = new GSSNode(/*labelled*/l);
1640
+ w.parentSetId = U_i.id;
1641
+ U_i.add(w);
1642
+ // console.log("Added " + w + " to U[" + i + "] ==> " + U_i);
1643
+ // console.log("2. Adding link from " + w + " to " + u + " labelled " + z);
1644
+ thiz.addLink(/*from*/w,/*to*/u,/*labelled*/z);
1645
+ var actions = thiz.getActions(l, cur_tok);
1646
+ if (actions !== undefined) {
1647
+ var ph = actions.push;
1648
+ if (ph !== undefined)
1649
+ Q.push(new ShiftPair(w, ph));
1650
+ var reductions = actions.reductions;
1651
+ // console.log("reductions(" + l + ", " + cur_tok.toString(true) + ") = " + reductions);
1652
+ reductions.forEach(function(red) {
1653
+ if (red.rule.position === 0)
1654
+ // the label here is irrelevant, because m == 0 means the rest of the rule derives EPSILON
1655
+ R.push(new ReductionItem(w, red.rule, 0, red.f, EPSILON));
1656
+ });
1657
+ if (m !== 0) {
1658
+ reductions.forEach(function(red) {
1659
+ if (red.rule.position !== 0)
1660
+ R.push(new ReductionItem(u, red.rule, red.rule.position, red.f, z));
1661
+ });
1662
+ }
1663
+ } else {
1664
+ // Possibly shouldn't throw?
1665
+ // throw("No actions found in state " + l + " for token " + next_tok.toString(true) + " at " +
1666
+ // next_tok.pos.toString(true));
1667
+ }
1668
+ }
1669
+ // console.log("R.length = " + R.length);
1670
+ // R.debugPrint();
1671
+ if (m !== 0) {
1672
+ var labels = p.labels.slice(0);
1673
+ labels.push(y_m);
1674
+ thiz.addChildren(item.rule, z, labels, f, skipped_WS_loc !== undefined ? skipped_WS_loc.posAtStart() : cur_tok.pos.posAtStart());
1675
+ }
1676
+ }
1677
+ });
1678
+ },
1679
+
1680
+ addLink: function(rightSib, leftSib, val) {
1681
+ var link = undefined;
1682
+ for (var i = 0; i < rightSib.links.length; i++) {
1683
+ if (rightSib.links[i].prev === leftSib) {
1684
+ link = rightSib.links[i];
1685
+ break;
1686
+ }
1687
+ }
1688
+ if (link === undefined) {
1689
+ link = new Link(leftSib, val);
1690
+ rightSib.links.push(link);
1691
+ // console.log("Linking " + leftSib.toString() + " <-- " + rightSib.toString() + " with val " + val + "@" + val.pos);
1692
+ return link;
1693
+ } else {
1694
+ // console.log("Link already exists between " + leftSib.toString() + " <-- " + rightSib.toString());
1695
+ return undefined;
1696
+ }
1697
+ },
1698
+
1699
+ shifter: function(U, R, Q, N, i, cur_tok, next_tok) {
1700
+ // cur_tok = token #i+1: i starts at index 0, and tokens start at index 1
1701
+ // next_tok = token #i+2
1702
+ // U is an array of sets of GSS nodes
1703
+ // R is the worklist of pending reductions
1704
+ // Q is the set of (GSS node, token) pairs of pending shifts
1705
+ // N is the set of SPPF nodes created in this step
1706
+ var success = false;
1707
+ if (cur_tok !== EOF) { // if i != d, in the paper, where d is the last token number
1708
+ // Q.debugPrint();
1709
+ var Qprime = new Queue([]);
1710
+ var z = new SPPFNode(cur_tok, cur_tok.pos);
1711
+ var U_i1 = U[i+1] = new KeyedSet("label");
1712
+ U_i1.id = i + 1;
1713
+ while (Q.length > 0) {
1714
+ var item = Q.shift();
1715
+ var v = item.gssNode;
1716
+ var k = item.state;
1717
+ var w = U_i1.itemForKey(k);
1718
+ // console.log("item = " + item + ", k = " + k + " and therefore w = " + w);
1719
+ if (w !== undefined) {
1720
+ success = true;
1721
+ this.addLink(/*from*/w, /*to*/v, /*labelled*/z);
1722
+ var actions = this.getActions(k, next_tok);
1723
+ if (actions !== undefined) {
1724
+ var reductions = actions.reductions;
1725
+ reductions.forEach(function(red) {
1726
+ if (red.rule.position !== 0)
1727
+ R.push(new ReductionItem(v, red.rule, red.rule.position, red.f, z));
1728
+ });
1729
+ } else {
1730
+ // Possibly shouldn't throw?
1731
+ // throw("No actions found in state " + k + " for token " + next_tok.toString(true) + " at " +
1732
+ // next_tok.pos.toString(true));
1733
+ }
1734
+ } else {
1735
+ w = new GSSNode(/*labelled*/k);
1736
+ w.parentSetId = U_i1.id;
1737
+ U_i1.add(w);
1738
+ // console.log("Added " + w + " to U[" + (i + 1) + "] ==> " + U_i1);
1739
+ this.addLink(/*from*/w, /*to*/v, /*labelled*/z);
1740
+
1741
+ var actions = this.getActions(k, next_tok);
1742
+ // console.log("next_tok = " + next_tok.toString(true) + ", k = " + k + ", actions = " + JSON.stringify(actions));
1743
+ if (actions !== undefined) {
1744
+ success = true;
1745
+ var ph = actions.push;
1746
+ if (ph !== undefined) {
1747
+ var sp = new ShiftPair(w, ph);
1748
+ // console.log("Pushing " + sp + " onto Q'");
1749
+ Qprime.push(sp);
1750
+ }
1751
+ var reductions = actions.reductions;
1752
+ // console.log("Reductions for k = " + k + " next_tok = " + next_tok + " are " + reductions);
1753
+ reductions.forEach(function(red) {
1754
+ // console.log("red.f = " + red.f + ", red.rule.position = " + red.rule.position);
1755
+ if (red.rule.position !== 0) {
1756
+ R.push(new ReductionItem(v, red.rule, red.rule.position, red.f, z));
1757
+ }
1758
+ });
1759
+ reductions.forEach(function(red) {
1760
+ if (red.rule.position === 0) {
1761
+ // the label here is irrelevant, because m == 0 means the rest of the rule derives EPSILON
1762
+ R.push(new ReductionItem(w, red.rule, 0, red.f, EPSILON));
1763
+ }
1764
+ });
1765
+ // console.log("R = ");
1766
+ // R.debugPrint();
1767
+ } else {
1768
+ // Possibly shouldn't throw?
1769
+ // throw("No actions found in state " + k + " for token " + next_tok.toString(true) + " at " +
1770
+ // next_tok.pos.toString(true));
1771
+ }
1772
+ }
1773
+ }
1774
+ while (Qprime.length > 0)
1775
+ Q.push(Qprime.shift());
1776
+ // console.log("At the end of shifter(" + i + "), Q = ");
1777
+ // Q.debugPrint();
1778
+ }
1779
+ return success;
1780
+ },
1781
+
1782
+ addChildren: function(rule, y, kids, f, pos) {
1783
+ var lambda = kids.slice(0);
1784
+ if (f !== 0)
1785
+ lambda.push(this.getEpsilonSPPF(f, pos));
1786
+ // Find lambda in the kids of y
1787
+ function examine(y_rule, y_kids) {
1788
+ if (y_rule !== rule) return false;
1789
+ if (y_kids.length !== lambda.length) return false;
1790
+ for (var i = 0; i < y_kids.length; i++)
1791
+ if (y_kids[i] !== lambda[i]) return false;
1792
+ return true;
1793
+ }
1794
+ var found = false;
1795
+ if (y.kids) {
1796
+ found = examine(y.rule, y.kids);
1797
+ } else if (y.ambig) {
1798
+ for (var i = 0; i < y.ambig.length; i++)
1799
+ if (examine(y.ambig[i].rule, y.ambig[i].kids)) {
1800
+ found = true;
1801
+ break;
1802
+ }
1803
+ }
1804
+ if (!found)
1805
+ y.addChildren(rule, lambda, this);
1806
+ },
1807
+
1808
+ getActions: function(state, tok) {
1809
+ var tableRow = this.rnTable[state];
1810
+ var actions1 = tableRow[tok.asString];
1811
+ return actions1;
1812
+ },
1813
+ /*
1814
+ printSPPFasDot: function() {
1815
+ var ret = [];
1816
+ ret.push("digraph " + this.name + "_SPPF {");
1817
+ ret.push(" rankdir=RL; clusterrank=local;");
1818
+ ret.push(" // Nodes");
1819
+ for (var i = 0; i < SPPFNode.allNodes.length; i++) {
1820
+ var node = SPPFNode.allNodes[i];
1821
+ var style = "";
1822
+ if (node.inline)
1823
+ style = ", style=dashed";
1824
+ var label = "SPPFNode #" + node.sppfId;
1825
+ if (node.inline)
1826
+ label += "\nInlined e-SPPF for " + node.label;
1827
+ else
1828
+ label += "\nLabel: " + node.label.toString(true);
1829
+ if (node.rule)
1830
+ label += "\nRule: " + node.rule.toString();
1831
+ else if (node.ambig)
1832
+ label += "\nMultiple derivations";
1833
+
1834
+ ret.push(" " + node.sppfId + " [label=" + JSON.stringify(label) + style + "];");
1835
+ if (node.ambig !== undefined) {
1836
+ for (var j = 0; j < node.ambig.length; j++) {
1837
+ ret.push(" \"" + node.sppfId + "_" + j
1838
+ + "\" [label=" + JSON.stringify(node.ambig[j].rule.toString()) +", shape=box];");
1839
+ }
1840
+ }
1841
+ }
1842
+ ret.push(" // Edges");
1843
+ for (var i = 0; i < SPPFNode.allNodes.length; i++) {
1844
+ var node = SPPFNode.allNodes[i];
1845
+ if (node.kids !== undefined)
1846
+ for (var j = 0; j < node.kids.length; j++)
1847
+ ret.push(" " + node.sppfId + " -> " + node.kids[j].sppfId
1848
+ + " [label=\"" + j + "\"];");
1849
+ else if (node.ambig !== undefined) {
1850
+ for (var j = 0; j < node.ambig.length; j++) {
1851
+ ret.push(" " + node.sppfId + " -> \"" + node.sppfId + "_" + j + "\";");
1852
+ for (var k = 0; k < node.ambig[j].kids.length; k++)
1853
+ ret.push(" \"" + node.sppfId + "_" + j + "\" -> " + node.ambig[j].kids[k].sppfId
1854
+ + " [label=\"" + k + "\"];");
1855
+ }
1856
+ }
1857
+ }
1858
+ ret.push("}");
1859
+ return ret.join("\n");
1860
+ },
1861
+
1862
+ printGSSasDot: function() {
1863
+ var ret = [];
1864
+ ret.push("digraph " + this.name + "_GSS {");
1865
+ ret.push(" rankdir=RL; clusterrank=local;");
1866
+ ret.push(" // Nodes");
1867
+ for (var i = 0; i < GSSNode.allNodes.length; i++) {
1868
+ var node = GSSNode.allNodes[i];
1869
+ ret.push(" " + node.gssId + "[label=" + JSON.stringify(node.toString()) + "];");
1870
+ }
1871
+ ret.push(" // Ranks");
1872
+ for (var i = 0; i < this.U.length; i++) {
1873
+ var s = "";
1874
+ for (var j = 0; j < this.U[i].size(); j++)
1875
+ s += " " + this.U[i].get(j).gssId + ";";
1876
+ ret.push(" subgraph cluster" + i + " {");
1877
+ ret.push(" rank = same; color=black;");
1878
+ if (i > 0)
1879
+ ret.push(" label=\"Token " + i + "\"");
1880
+ ret.push(" " + s);
1881
+ ret.push(" }");
1882
+ }
1883
+ ret.push(" // Edges");
1884
+ for (var i = 0; i < GSSNode.allNodes.length; i++) {
1885
+ var node = GSSNode.allNodes[i];
1886
+ for (var j = 0; j < node.links.length; j++)
1887
+ ret.push(" " + node.gssId + " -> " + node.links[j].prev.gssId
1888
+ + "[label=" + JSON.stringify(node.links[j].val.toString()) + "]"
1889
+ //+ "[label=" + JSON.stringify(JSON.decycle(node.links[j].val), null, " ") + "]"
1890
+ + ";");
1891
+ }
1892
+ ret.push("}");
1893
+ return ret.join("\n");
1894
+ },
1895
+ */
1896
+
1897
+ //////////////////////////////////
1898
+ // The RNGLR algorithm
1899
+ // Following Scott & Johnstone '06, TOPLAS 28:4
1900
+ //////////////////////////////////
1901
+ parseRNGLR: function(token_source) {
1902
+ if (token_source.isEmpty()) {
1903
+ if (this.acceptStates[0])
1904
+ return this.getEpsilonSPPF(this.I[this.start.asString], SrcLoc.make(0,0,0,0,0,0));
1905
+ else {
1906
+ console.log("There are zero tokens available, but the grammar does not accept the empty string");
1907
+ return undefined;
1908
+ }
1909
+ } else {
1910
+ var v0 = new GSSNode(0);
1911
+ var U0 = new KeyedSet("label", [v0]);
1912
+ U0.id = 0;
1913
+ v0.parentSetId = U0.id;
1914
+ this.U = [];
1915
+ this.U[0] = U0;
1916
+ var R = new Queue([]);
1917
+ var Q = new Queue([]);
1918
+ var hasNext = true;
1919
+ var cur_tok = token_source.next(); // need to peek at first token
1920
+ var actions = this.getActions(0, cur_tok);
1921
+ // console.log("Actions[0][" + cur_tok.toRepr(true) + "] = " + JSON.stringify(actions));
1922
+ if (actions !== undefined) {
1923
+ var pk = actions.push;
1924
+ if (pk !== undefined)
1925
+ Q.push(new ShiftPair(v0, pk));
1926
+ // console.log("Q = ");
1927
+ // Q.debugPrint();
1928
+ var reductions = actions.reductions;
1929
+ reductions.forEach(function(red) {
1930
+ if (red.rule.position === 0)
1931
+ // Again, label shouldn't matter because length is 0
1932
+ R.push(new ReductionItem(v0, red.rule, 0, red.f, EPSILON));
1933
+ });
1934
+ }
1935
+ // console.log("R = ");
1936
+ // R.debugPrint();
1937
+ var i = 0;
1938
+ // try {
1939
+ while (hasNext && this.U[i].size() > 0) {
1940
+ var N = new Queue([]);
1941
+ // console.log("Phase 1: reducing due to token #" + i + ": " + cur_tok.toRepr(true));
1942
+ while (R.length > 0) {
1943
+ this.reducer(this.U, R, Q, N, i, cur_tok, token_source.skippedWhitespace);
1944
+ }
1945
+ hasNext = token_source.hasNext();
1946
+ var next_tok = hasNext ? token_source.next() : undefined;
1947
+ // console.log("Phase 2: shifting token #" + i + ": " + cur_tok.toRepr(true));
1948
+ hasNext = this.shifter(this.U, R, Q, N, i, cur_tok, next_tok) && hasNext;
1949
+ if (hasNext) {
1950
+ cur_tok = next_tok;
1951
+ } else {
1952
+ token_source.unshiftToken(cur_tok);
1953
+ }
1954
+ i++;
1955
+ }
1956
+ // console.log("DONE WITH LOOP, i = " + i
1957
+ // + ", last token = " + cur_tok.toString(true) + "@" + cur_tok.pos.toString(true)
1958
+ // + ", hasNext = " + hasNext + ", final set emptied out: " + (this.U[i].size() == 0));
1959
+ if (!hasNext) i--;
1960
+ // console.log("Finalizing: i = " + i + " and U[i] = " + this.U[i]);
1961
+ for (var acc = 0; acc < this.acceptStates.length; acc++) {
1962
+ if (this.acceptStates[acc]) {
1963
+ //console.log("Searching for " + acc);
1964
+ var t = this.U[i].itemForKey(acc);
1965
+ if (t !== undefined) {
1966
+ //console.log("Parse success!");
1967
+ var link = undefined;
1968
+ for (var j = 0; j < t.links.length; j++) {
1969
+ if (t.links[j].prev === v0) {
1970
+ link = t.links[j];
1971
+ break;
1972
+ }
1973
+ }
1974
+ if (link !== undefined) {
1975
+ return link.val;
1976
+ } else
1977
+ console.log("Couldn't find correct link in " + JSON.stringify(JSON.decycle(t), null, " "));
1978
+ } else {
1979
+ //console.log("Parse failure");
1980
+ }
1981
+ }
1982
+ }
1983
+ // // Collect error information
1984
+ // if (i > 0) {
1985
+ // var acc = undefined;
1986
+ // for (var j = 0; j < this.U[i - 1].size(); j++) {
1987
+ // var head = this.U[i - 1].get(j);
1988
+ // console.log("For token " + i + ", " + cur_tok + ", head is in state " + head.label);
1989
+ // acc = this.plausibleTokensForState(head.label, acc);
1990
+ // }
1991
+ // throw(acc);
1992
+ // }
1993
+ // } catch(e) {
1994
+ // console.log(e);
1995
+ // return undefined;
1996
+ // }
1997
+ }
1998
+ },
1999
+
2000
+ plausibleTokensForState: function(state, ret) {
2001
+ if (ret === undefined)
2002
+ ret = {};
2003
+ for (var j = 0; j < this.tokens.size(); j++) {
2004
+ var tok = this.tokens.get(j);
2005
+ var actions = this.getActions(state, tok);
2006
+ if (tok !== EPSILON && actions !== undefined &&
2007
+ (actions.push !== undefined || (actions.reductions !== undefined && actions.reductions.size > 0))) {
2008
+ console.log("In state " + state + " for token " + tok + ", actions = " + JSON.stringify([...actions.reductions]));
2009
+ ret[tok] = true;
2010
+ }
2011
+ }
2012
+ return ret;
2013
+ },
2014
+
2015
+ constructAllParses: function(sppfNode, semActions) {
2016
+ if (sppfNode === undefined) return undefined;
2017
+ if (sppfNode.label instanceof Token) {
2018
+ return [sppfNode.label];
2019
+ }
2020
+ var options = undefined;
2021
+ if (sppfNode.ambig)
2022
+ options = sppfNode.ambig;
2023
+ else
2024
+ options = [{kids: sppfNode.kids, rule: sppfNode.rule}];
2025
+ var ret = [];
2026
+ for (var i = 0; i < options.length; i++) {
2027
+ var kids = options[i].kids;
2028
+ var rule = options[i].rule;
2029
+ var kidsParses = [];
2030
+ for (var j = 0; j < kids.length; j++) {
2031
+ if (kids[j].rule === undefined && kids[j].ambig === undefined && kids[j].inline === true) {
2032
+ for (var k = 0; k < kids[j].kids.length; k++) {
2033
+ kidsParses.push([this.applyAction(kids[j].kids[k].rule, kids[j].kids[k].kids, kids[j].kids[k].pos, semActions)]);
2034
+ }
2035
+ } else if (kids[j].rule === undefined && kids[j].kids !== undefined && kids[j].label.indexOf(',') > -1) {
2036
+ for (var k = 0; k < kids[j].kids.length; k++) {
2037
+ kidsParses.push(this.constructAllParses(kids[j].kids[k], semActions));
2038
+ }
2039
+ } else {
2040
+ kidsParses.push(this.constructAllParses(kids[j], semActions));
2041
+ }
2042
+ }
2043
+ const thiz = this;
2044
+ ret = ret.concat(this.cartesian(kidsParses, 0, [],
2045
+ function(kids) { return thiz.applyAction(rule, kids, sppfNode.pos, semActions); }));
2046
+ }
2047
+ return ret;
2048
+ },
2049
+ cartesian: function(arrays, idx, arr, callback) {
2050
+ if (arrays.length == idx) return callback(arr);
2051
+ var ret = [];
2052
+ for (var i = 0; i < arrays[idx].length; i++) {
2053
+ ret = ret.concat(this.cartesian(arrays, idx+1, arr.concat(arrays[idx][i]), callback));
2054
+ }
2055
+ return ret;
2056
+ },
2057
+
2058
+ countAllParses: function(sppfNode) {
2059
+ if (sppfNode === undefined) return 0;
2060
+ var todo = [[[sppfNode]]]; // stack of alternate lists of children
2061
+ var count = [[[]], [[]]]; // stack of sums of factors
2062
+ while (todo.length > 0) {
2063
+ var top = todo[todo.length - 1];
2064
+ var topCount = count[count.length - 1];
2065
+ if (top.length === 0) { // done with all parses of a given node
2066
+ todo.pop();
2067
+ count.pop();
2068
+ var tot = 0;
2069
+ for (var i = 0; i < topCount.length; i++) {
2070
+ var prod = 1;
2071
+ for (var j = 0; j < topCount[i].length; j++)
2072
+ prod *= topCount[i][j];
2073
+ tot += prod;
2074
+ }
2075
+ var newTopCount = count[count.length - 1];
2076
+ newTopCount[newTopCount.length - 1].push(tot);
2077
+ } else if (top[top.length - 1].length === 0) { // done with one alternative
2078
+ top.pop();
2079
+ if (top.length > 0) {
2080
+ topCount.push([]);
2081
+ }
2082
+ } else {
2083
+ var node = top[top.length - 1].pop();
2084
+ if (node.label instanceof Token) {
2085
+ topCount[topCount.length - 1].push(1);
2086
+ } else if (node.ambig && node.ambig.length > 0) {
2087
+ count.push([[]]);
2088
+ todo.push(node.ambig.map(function(d) { return d.kids.slice(0); }));
2089
+ } else if (node.kids && node.kids.length > 0) {
2090
+ count.push([[]]);
2091
+ todo.push([node.kids.slice(0)]);
2092
+ }
2093
+ }
2094
+ }
2095
+ if (count.length > 0 && count[0].length > 0 && count[0][0].length > 0)
2096
+ return count[0][0][0];
2097
+ else
2098
+ throw count;
2099
+ },
2100
+
2101
+ constructUniqueParse: function(sppfNode, semActions) {
2102
+ if (sppfNode === undefined) return undefined;
2103
+ // Each stack item is a pair {todo, done}, where todo is a list of children
2104
+ // in reverse order (so that pop goes from left-to-right in actual tree order)
2105
+ // and done is a list of children in tree order
2106
+ // If there are nodes todo:
2107
+ // We examine the pop()ed node from stack[TOP].todo:
2108
+ // if it has kids, we push a new stack item
2109
+ // otherwise, we move it over
2110
+ // Otherwise we reduce
2111
+ var stack = [{todo: [sppfNode], done: []}];
2112
+ while (stack.length > 0 && stack[0].todo.length > 0) {
2113
+ var curr = stack[stack.length - 1];
2114
+ if (curr.todo.length > 0) {
2115
+ var next = curr.todo[curr.todo.length - 1];
2116
+ if (next.label instanceof Token) {
2117
+ curr.todo.pop();
2118
+ curr.done.push(next.label);
2119
+ } else if (next.ambig) {
2120
+ throw("Not a unique parse");
2121
+ } else if (next.rule === undefined && next.label.indexOf(',') > -1) {
2122
+ curr.todo.pop();
2123
+ for (var k = next.kids.length - 1; k >= 0; k--)
2124
+ curr.todo.unshift(next.kids[k]);
2125
+ } else if (next.kids.length == 0) {
2126
+ // Optimization for nullary nonterminals
2127
+ curr.todo.pop();
2128
+ var pos = curr.done.length > 0 ? curr.done[curr.done.length - 1].pos : next.pos;
2129
+ curr.done.push(this.applyAction(next.rule, [], pos, semActions))
2130
+ } else {
2131
+ stack.push({todo: next.kids.slice(0).reverse(), done: []});
2132
+ }
2133
+ } else {
2134
+ if (stack.length > 1) {
2135
+ stack.pop();
2136
+ var prev = stack[stack.length - 1];
2137
+ var toReduce = prev.todo.pop();
2138
+ if (toReduce.rule === undefined) {
2139
+ function jsonPos(key, value) {
2140
+ if (key === "pos") { return "SrcLoc(" + value.toString(true) + ")"; }
2141
+ else { return value; }
2142
+ }
2143
+ throw("Cannot find a reduction rule on " + JSON.stringify(toReduce, jsonPos, " "));
2144
+ } else {
2145
+ prev.done.push(this.applyAction(toReduce.rule, curr.done, toReduce.pos, semActions));
2146
+ }
2147
+ }
2148
+ }
2149
+ }
2150
+ return stack[0].done[0];
2151
+ },
2152
+
2153
+ constructNextParse: function(sppfNode, semActions, directions) {
2154
+ if (sppfNode === undefined) return undefined;
2155
+ // Directions contains an array of pairs {choice, of}
2156
+ // saying which index choice (out of how many choices) at an ambig node
2157
+ // was taken by the previous parse.
2158
+ // To compute the next parse, remove all trailing pairs for which choice == of,
2159
+ // then increment the last remaining choice
2160
+ var newDirs = [];
2161
+ if (directions) {
2162
+ var lastIndex = directions.length - 1;
2163
+ while (lastIndex >= directions[lastIndex].choice == directions[lastIndex].of)
2164
+ lastIndex--;
2165
+ if (lastIndex < 0) return undefined;
2166
+ for (var i = 0; i < lastIndex; i++)
2167
+ newDirs[i] = directions[i];
2168
+ newDirs[lastIndex] = {choice: directions[i].choice + 1, of: directions[i].of};
2169
+ }
2170
+ var stack = [{todo: [sppfNode], done: []}];
2171
+ var curDir = 0;
2172
+ while (stack.length > 0 && stack[0].todo.length > 0) {
2173
+ var curr = stack[stack.length - 1];
2174
+ if (curr.todo.length > 0) {
2175
+ var next = curr.todo[curr.todo.length - 1];
2176
+ if (next.label instanceof Token) {
2177
+ curr.todo.pop();
2178
+ curr.done.push(next.label);
2179
+ } else if (next.rule === undefined && next.label.indexOf(',') > -1) {
2180
+ curr.todo.pop();
2181
+ for (var k = next.kids.length - 1; k >= 0; k--)
2182
+ curr.todo.unshift(next.kids[k]);
2183
+ } else if (next.ambig) {
2184
+ if (curDir < newDirs.length) {
2185
+ next = next.ambig[newDirs[curDir++].choice];
2186
+ } else {
2187
+ newDirs.push({choice: 0, of: next.ambig.length})
2188
+ next = next.ambig[0];
2189
+ }
2190
+ if (next.kids.length == 0) {
2191
+ // Optimization for nullary nonterminals
2192
+ curr.todo.pop();
2193
+ var pos = curr.done.length > 0 ? curr.done[curr.done.length - 1].pos : next.pos;
2194
+ curr.done.push(this.applyAction(next.rule, [], pos, semActions))
2195
+ } else {
2196
+ stack.push({todo: next.kids.slice(0).reverse(), done: []});
2197
+ }
2198
+ } else if (next.kids.length == 0) {
2199
+ // Optimization for nullary nonterminals
2200
+ curr.todo.pop();
2201
+ var pos = curr.done.length > 0 ? curr.done[curr.done.length - 1].pos : next.pos;
2202
+ curr.done.push(this.applyAction(next.rule, [], pos, semActions))
2203
+ } else {
2204
+ stack.push({todo: next.kids.slice(0).reverse(), done: []});
2205
+ }
2206
+ } else {
2207
+ if (stack.length > 1) {
2208
+ stack.pop();
2209
+ var prev = stack[stack.length - 1];
2210
+ var toReduce = prev.todo.pop();
2211
+ if (toReduce.rule === undefined) {
2212
+ function jsonPos(key, value) {
2213
+ if (key === "pos") { return "SrcLoc(" + value.toString(true) + ")"; }
2214
+ else { return value; }
2215
+ }
2216
+ throw("Cannot find a reduction rule on " + JSON.stringify(toReduce, jsonPos, " "));
2217
+ } else {
2218
+ prev.done.push(this.applyAction(toReduce.rule, curr.done, toReduce.pos, semActions));
2219
+ }
2220
+ }
2221
+ }
2222
+ }
2223
+ return {parse: stack[0].done[0], directions: newDirs};
2224
+ },
2225
+ checkPositionContainment: function(sppfNode) {
2226
+ if (sppfNode === undefined) return undefined;
2227
+ var violations = [];
2228
+ //var worklist = [sppfNode];
2229
+ function helper(node) {
2230
+ var pos = node.pos;
2231
+ if (node.kids) {
2232
+ for (var i = 0; i < node.kids.length; i++) {
2233
+ var kidPos = node.kids[i].pos;
2234
+ if (kidPos.startChar < pos.startChar || kidPos.endChar > pos.endChar) {
2235
+ violations.push(node);
2236
+ break;
2237
+ }
2238
+ }
2239
+ } else if (node.ambig) {
2240
+ for (var i = 0; i < node.ambig.length; i++) {
2241
+ var kids = node.ambig[i].kids;
2242
+ var shouldBreak = false
2243
+ for (var j = 0; j < kids.length; j++) {
2244
+ var kidPos = kids[j].pos;
2245
+ if (kidPos.startChar < pos.startChar || kidPos.endChar > pos.endChar) {
2246
+ violations.push(node);
2247
+ shouldBreak = true;
2248
+ break;
2249
+ }
2250
+ }
2251
+ if (shouldBreak) break;
2252
+ }
2253
+ }
2254
+ }
2255
+ helper(sppfNode);
2256
+ if (violations.length > 0) return violations;
2257
+ return false;
2258
+ },
2259
+
2260
+ computeRequiredNullableParts: function() {
2261
+ // The I dictionary is an index of all nullable nonterminals and (nonempty) strings of
2262
+ // nonterminals that appear as right-hand tails in rules in the grammar.
2263
+ // The eSPPFs table is a dictionary indexed first by I value and second by position.
2264
+ // We already ensure that position objects are singletons, and this second-level
2265
+ // dictionary ensures that e-SPPFs are singletons too, for each position in the
2266
+ // parse tree for which they are needed. This helps ensure that finding existing links
2267
+ // doesn't create duplicates and therefore does't cause duplicate parses, later.
2268
+ allowNull = true;
2269
+ this.I = {};
2270
+ this.I[EPSILON.asString] = 0;
2271
+ this.eSPPFs = [];
2272
+ this.eSPPFs[0] = {null: new SPPFNode(EPSILON, null)};
2273
+ // Initialize all eSPPFs to empty nodes
2274
+ for (var name in this.rules) {
2275
+ if (this.derivable[name][EPSILON.asString] !== true) continue;
2276
+ var name_eSPPF = new SPPFNode(name, null);
2277
+ this.I[name] = this.eSPPFs.length;
2278
+ this.eSPPFs.push({null: name_eSPPF});
2279
+ }
2280
+ // Compute the e-closure of the rules
2281
+ for (var name in this.rules) {
2282
+ if (this.derivable[name][EPSILON.asString] !== true) continue;
2283
+ var rules_name = this.rules[name];
2284
+ var name_eSPPF = this.eSPPFs[this.I[name]].null;
2285
+ for (var i = 0; i < rules_name.length; i++) {
2286
+ var rule = rules_name[i];
2287
+ if (this.computeFirstOfStrings(rule.symbols).contains(EPSILON)) {
2288
+ var kids = [];
2289
+ for (var j = 0; j < rule.symbols.length; j++) {
2290
+ kids.push(this.eSPPFs[this.I[rule.symbols[j].asString]].null);
2291
+ }
2292
+ name_eSPPF.addChildren(rule, kids, this);
2293
+ }
2294
+ }
2295
+ }
2296
+ // Compute required nullable parts
2297
+ for (var name in this.rules) {
2298
+ var rules_name = this.rules[name];
2299
+ for (var i = 0; i < rules_name.length; i++) {
2300
+ var rule = rules_name[i];
2301
+ for (var j = 1/*note: not 0*/; j < rule.symbols.length; j++) {
2302
+ var slice = rule.symbols.slice(j);
2303
+ var sliceStrs = slice.map((s) => s.asString);
2304
+ var sliceStr = "" + sliceStrs;
2305
+ if (this.computeFirstOfStrings(slice).contains(EPSILON) && this.I[sliceStr] === undefined) {
2306
+ var eSPPF_slice = new SPPFNode(sliceStr, null);
2307
+ eSPPF_slice.inline = true;
2308
+ var kids = [];
2309
+ for (var k = 0; k < slice.length; k++)
2310
+ kids[k] = this.eSPPFs[this.I[sliceStrs[k]]].null;
2311
+ eSPPF_slice.kids = kids;
2312
+ this.I[sliceStrs] = this.eSPPFs.length;
2313
+ this.eSPPFs.push({null: eSPPF_slice});
2314
+ }
2315
+ }
2316
+ }
2317
+ }
2318
+ allowNull = false;
2319
+ },
2320
+ getI: function(rule) {
2321
+ var ret = undefined;
2322
+ if (rule.position === 0) ret = this.I[rule.name];
2323
+ else if (rule.position === rule.symbols.length) ret = this.I[EPSILON.asString];
2324
+ else ret = this.I[rule.symbols.slice(rule.position).map((s) => s.asString)];
2325
+ return ret;
2326
+ },
2327
+ getEpsilonSPPF: function(i, pos) {
2328
+ function find(node, cache) {
2329
+ for (var i = 0; i < cache.length; i++) {
2330
+ if (cache[i].key === node) {
2331
+ return cache[i].value;
2332
+ }
2333
+ }
2334
+ return undefined;
2335
+ }
2336
+ function clone(node, cache) {
2337
+ var ret = find(node, cache);
2338
+ if (ret !== undefined) return ret;
2339
+ ret = {};
2340
+ cache.push({key: node, value: ret});
2341
+ ret.sppfId = node.sppfId;
2342
+ ret.name = node.name;
2343
+ ret.label = node.label;
2344
+ ret.pos = pos;
2345
+ ret.toString = node.toString;
2346
+ ret.rule = node.rule;
2347
+ ret.inline = node.inline;
2348
+ if (node.kids !== undefined) {
2349
+ ret.kids = [];
2350
+ for (var i = 0; i < node.kids.length; i++) {
2351
+ ret.kids[i] = clone(node.kids[i], cache);
2352
+ }
2353
+ } else if (node.ambig !== undefined) {
2354
+ ret.ambig = [];
2355
+ for (var i = 0; i < node.ambig.length; i++) {
2356
+ var kids = [];
2357
+ ret.ambig.push({kids: kids, rule: node.ambig[i].rule});
2358
+ for (var j = 0; j < node.ambig[i].kids.length; j++) {
2359
+ kids[j] = clone(node.ambig[i].kids[j], cache);
2360
+ }
2361
+ }
2362
+ }
2363
+ return ret;
2364
+ }
2365
+ var byI = this.eSPPFs[i];
2366
+ var ret = byI[pos];
2367
+ if (ret === undefined)
2368
+ ret = byI[pos] = clone(byI[null], []);
2369
+ return ret;
2370
+ },
2371
+ resetESPPFs: function() {
2372
+ for (var i = 0; i < this.eSPPFs.length; i++) {
2373
+ this.eSPPFs[i] = {null: this.eSPPFs[i].null};
2374
+ }
2375
+ },
2376
+
2377
+ computeRNTable: function() {
2378
+ const thiz = this;
2379
+ function initTables(index) {
2380
+ var tableRow = thiz.rnTable[index];
2381
+ if (tableRow === undefined)
2382
+ tableRow = thiz.rnTable[index] = {};
2383
+ for (var k = 0; k < thiz.atoms.size(); k++) {
2384
+ if (tableRow[thiz.atoms.get(k).asString] === undefined)
2385
+ tableRow[thiz.atoms.get(k).asString] = {push: undefined, reductions: new Set()};
2386
+ }
2387
+ }
2388
+
2389
+
2390
+ initTables(0);
2391
+ // This doesn't seem to be needed, because we always explicitly shift the EOF token
2392
+ // if (this.derivable[this.start][EPSILON] === true) {
2393
+ // this.acceptStates[0] = true;
2394
+ // this.rnTable[0][EOF].accept = true;
2395
+ // }
2396
+ for (var i = 0; i < this.states.size(); i++) {
2397
+ var state_i = this.states.get(i);
2398
+ initTables(i);
2399
+ // console.log("State " + i + " = " + state_i.toString());
2400
+ var full_state = this.completeClosure(state_i);
2401
+ // console.log("FullState " + i + " = " + full_state.toString());
2402
+ for (var j = 0; j < full_state.coreSize(); j++) {
2403
+ var rule_j = full_state.getCore(j);
2404
+ if (rule_j.name === this.start) {
2405
+ if (rule_j.position === rule_j.symbols.length && full_state.getLookaheads(j).contains(EOF)) {
2406
+ this.acceptStates[i] = true;
2407
+ this.rnTable[i][EOF.asString].accept = true;
2408
+ }
2409
+ } else {
2410
+ if (this.computeFollowAtPosition(rule_j, rule_j.position).contains(EPSILON)) {
2411
+ var lookaheads = full_state.getLookaheads(j);
2412
+ for (var k = 0; k < lookaheads.size(); k++) {
2413
+ if (this.rnTable[i][lookaheads.get(k).asString] === undefined) {
2414
+ throw("Can't get rnTable actions for i = " + i + " and symbol = " + lookaheads.get(k).asString + " in rule " + rule_j.toString(true));
2415
+ }
2416
+ this.rnTable[i][lookaheads.get(k).asString].reductions.add(new ReduceAction(rule_j, this.getI(rule_j)));
2417
+ }
2418
+ }
2419
+ }
2420
+ }
2421
+ }
2422
+ },
2423
+
2424
+ //////////////////////////////////
2425
+ //
2426
+
2427
+
2428
+ //////////////////////////////////
2429
+ // Algorithm 4.13 (p242-243) in Dragon book
2430
+ computeStateKernels: function() {
2431
+ var init_rule = this.rules[this.start][0].withLookahead(EOF);
2432
+ this.init_set = new LR1Set([init_rule]);
2433
+ this.completeClosure(this.init_set, true);
2434
+ var kernelStates = new SetOfSets([this.init_set], LR1Set.equals);
2435
+ this.rnTable = [];
2436
+ // Step 1
2437
+ var worklist = new Queue([this.init_set]);
2438
+ var state_num = -1;
2439
+ while (worklist.length > 0) {
2440
+ var set = worklist.shift();
2441
+ state_num++;
2442
+ this.rnTable[state_num] = undefined;
2443
+ for (var j = 0; j < this.atoms.size(); j++) {
2444
+ var atom_j = this.atoms.get(j);
2445
+ var new_set = this.computeGotoKernel(state_num, set, atom_j);
2446
+ if (new_set.coreSize() > 0) {
2447
+ var gotoStateNum = undefined;
2448
+ if (kernelStates.add(new_set)) {
2449
+ gotoStateNum = kernelStates.size() - 1;
2450
+ // console.log("\nAdded new_set at index " + gotoStateNum + ": " + new_set.toString() + "\n");
2451
+ // console.log("Added new_set at index " + gotoStateNum);
2452
+ worklist.push(new_set);
2453
+ } else {
2454
+ gotoStateNum = kernelStates.indexOf(new_set);
2455
+ // console.log("Set already exists at index " + gotoStateNum + ": " + new_set.toString());
2456
+ }
2457
+ // console.log(state_num + ":" + set + " goes to " + gotoStateNum + ":" + new_set + " via symbol " + atom_j);
2458
+ var tableRow = this.rnTable[state_num];
2459
+ if (tableRow === undefined)
2460
+ tableRow = this.rnTable[state_num] = {};
2461
+ var tableCell = tableRow[atom_j.asString];
2462
+ if (tableCell === undefined)
2463
+ tableCell = tableRow[atom_j.asString] = {push: undefined, reductions: new Set()};
2464
+ if (tableCell.push !== undefined && tableCell.push !== gotoStateNum)
2465
+ throw ("Already have a push action for atom " + atom_j.asString + " in state " + state_num + ": supposed to goto state " + tableCell.push + " and now need to go to " + gotoStateNum);
2466
+ tableCell.push = gotoStateNum;
2467
+ }
2468
+ }
2469
+ }
2470
+ console.log("Done with step 1");
2471
+ // console.log("There are " + kernelStates.size() + " kernel states");
2472
+ // console.log(kernelStates.toString(true));
2473
+ // Step 2
2474
+ this.states = [];
2475
+ var spontLookaheads = {}; // Map from goto state number -> rule id -> setOf(lookaheads)
2476
+ var propLookaheads = {}; // Map from state number -> goto state num -> rule id -> setOf(rule ids)
2477
+ for (var i = 0; i < kernelStates.size(); i++) {
2478
+ this.states.push(new LR1Set());
2479
+ spontLookaheads[i] = {};
2480
+ propLookaheads[i] = {};
2481
+ }
2482
+ init_rule = this.rules[this.start][0];
2483
+ spontLookaheads[0][init_rule.id] = new KeyedSet("key", [EOF]);
2484
+ for (var i = 0; i < kernelStates.size(); i++) {
2485
+ // if (i > 0 && i % 100 == 0) { console.log("Processing state " + i); }
2486
+ this.applyLookaheads(spontLookaheads, propLookaheads, kernelStates.get(i), i, this.atoms.get(j));
2487
+ }
2488
+ console.log("Done with step 2");
2489
+ // Step 3
2490
+ var allLookaheads = {}; // Map from goto state num -> rule id -> setOf(lookaheads)
2491
+ for (var i = 0; i < kernelStates.size(); i++) {
2492
+ allLookaheads[i] = {};
2493
+ for (var j in spontLookaheads[i]) {
2494
+ // console.log("i = " + i + ", j = " + j + ", spontLookaheads[i][j] = " + spontLookaheads[i][j]);
2495
+ allLookaheads[i][j] = new KeyedSet(spontLookaheads[i][j]);
2496
+ }
2497
+ }
2498
+ console.log("Done with step 3");
2499
+ // Step 4
2500
+ // console.log("\n\n\n");
2501
+ function printSets(k, v) {
2502
+ if (v instanceof KeyedSet || v instanceof IntSet || v instanceof LR1Set)
2503
+ return v.toString();
2504
+ else
2505
+ return v;
2506
+ }
2507
+ // console.log("spontLookaheads = " + JSON.stringify(spontLookaheads, printSets, " "));
2508
+ // console.log("propLookaheads = " + JSON.stringify(propLookaheads, printSets, " "));
2509
+ var changed = true;
2510
+ var pass = 0;
2511
+ while (changed) {
2512
+ changed = false;
2513
+ pass++;
2514
+ for (var i = 0; i < kernelStates.size(); i++) {
2515
+ var state_i = kernelStates.get(i);
2516
+ var rnTable_i = this.rnTable[i];
2517
+ for (var x in rnTable_i) {
2518
+ var gotoState = rnTable_i[x].push;
2519
+ if (gotoState !== undefined) {
2520
+ for (var j = 0; j < state_i.coreSize(); j++) {
2521
+ var rule_j = state_i.getCore(j);
2522
+ var prop = propLookaheads[i][gotoState] ? propLookaheads[i][gotoState][rule_j.id] : undefined;
2523
+ var look = allLookaheads[i][rule_j.id];
2524
+ if (prop !== undefined && look !== undefined) {
2525
+ // console.log("Propagating " + look + " from state " + i + " to all rules " + prop.toString() + " in state " + gotoState);
2526
+ for (var k = 0; k < prop.size(); k++) {
2527
+ var id_k = prop.get(k);
2528
+ if (allLookaheads[gotoState][id_k] === undefined)
2529
+ allLookaheads[gotoState][id_k] = new KeyedSet("key");
2530
+ changed = allLookaheads[gotoState][id_k].merge(look) || changed;
2531
+ }
2532
+ }
2533
+ }
2534
+ }
2535
+ }
2536
+ }
2537
+ }
2538
+ console.log("Done with step 4");
2539
+ // console.log("allLookaheads = " + JSON.stringify(allLookaheads, printSets, " "));
2540
+ // console.log("All rules:")
2541
+ // for (var r in RuleFactory.byId)
2542
+ // console.log(r + ": " + RuleFactory.byId[r]);
2543
+ // Step 5 -- expand
2544
+ for (var i = 0; i < kernelStates.size(); i++) {
2545
+ var kernelState_i = kernelStates.get(i);
2546
+ var state_i = this.states[i];
2547
+ for (var j = 0; j < kernelState_i.coreSize(); j++) {
2548
+ var rule_j = kernelState_i.getCore(j);
2549
+ var lookahead = allLookaheads[i][rule_j.id];
2550
+ // console.log("Lookaheads in state " + i + " for rule #" + rule_j.id + " " + rule_j.toString(true) + ": " + lookahead);
2551
+ if (lookahead) {
2552
+ state_i.addRuleWithLookaheads(rule_j, lookahead);
2553
+ // for (var k = 0; k < lookahead.size(); k++)
2554
+ // state_i.addRule(RuleFactory.make(rule_j.name, rule_j.symbols, lookahead.get(k), rule_j.position));
2555
+ }
2556
+ }
2557
+ }
2558
+ this.states = new SetOfSets(this.states, LR1Set.equals);
2559
+ },
2560
+
2561
+ //////////////////////////////////
2562
+ // Algorithm 4.12 (p242) in Dragon book
2563
+ applyLookaheads: function(spont, prop, rule_set, set_num) {
2564
+ // console.log("-----------------------------\nRuleSet #" + set_num + " = " + rule_set);
2565
+ for (var i = 0; i < rule_set.coreSize(); i++) {
2566
+ var rule = rule_set.getCore(i);
2567
+ var jPrime_rule = RuleFactory.make(rule.name, rule.symbols, HASH, rule.position);
2568
+ var jPrime = this.closureCache[jPrime_rule];
2569
+ if (jPrime === undefined)
2570
+ jPrime = this.closureCache[jPrime_rule] = this.completeClosure(new LR1Set([jPrime_rule]), true);
2571
+ // console.log("\nClosure(" + jPrime_rule.toString(true) + ") = " + jPrime.toString());
2572
+ for (var a = 0; a < this.atoms.size(); a++) {
2573
+ var symbol = this.atoms.get(a);
2574
+ if (this.rnTable[set_num] === undefined || this.rnTable[set_num][symbol.asString] === undefined) {
2575
+ continue;
2576
+ }
2577
+ var goto_set_num = this.rnTable[set_num][symbol.asString].push;
2578
+ // console.log("GOTO(" + set_num + ", " + symbol + ") = " + goto_set_num);
2579
+
2580
+ for (var j = 0; j < jPrime.coreSize(); j++) {
2581
+ var rule_j = jPrime.getCore(j);
2582
+ if (rule_j.position < rule_j.symbols.length && rule_j.symbols[rule_j.position].asString == symbol.asString) {
2583
+ var lookaheads = jPrime.getLookaheads(j);
2584
+ if (lookaheads !== undefined) {
2585
+ for (var k = 0; k < lookaheads.size(); k++) {
2586
+ if (lookaheads.get(k) !== HASH) {
2587
+ var new_rule = RuleFactory.make(rule_j.name, rule_j.symbols, undefined, rule_j.position + 1);
2588
+ if (spont[goto_set_num][new_rule.id] === undefined)
2589
+ spont[goto_set_num][new_rule.id] = new KeyedSet("key");
2590
+ if (spont[goto_set_num][new_rule.id].add(lookaheads.get(k))) {
2591
+ // console.log("Added " + lookaheads.get(k) + " to rule " + new_rule + " in set " + goto_set_num);
2592
+ }
2593
+ } else {
2594
+ var new_rule = RuleFactory.make(rule_j.name, rule_j.symbols, undefined, rule_j.position + 1);
2595
+ if (prop[set_num][goto_set_num] === undefined)
2596
+ prop[set_num][goto_set_num] = {};
2597
+ if (prop[set_num][goto_set_num][rule.id] === undefined)
2598
+ prop[set_num][goto_set_num][rule.id] = new IntSet();
2599
+ if (prop[set_num][goto_set_num][rule.id].add(new_rule.id)) {
2600
+ // console.log("Propagating from " + rule + " in state " + set_num + " to " + new_rule + " in state " + goto_set_num);
2601
+ }
2602
+ }
2603
+ }
2604
+ }
2605
+ }
2606
+ }
2607
+ }
2608
+ }
2609
+ },
2610
+
2611
+
2612
+
2613
+
2614
+ printTables: function() {
2615
+ var ret = "";
2616
+ for (var i = 0; i < this.rnTable.length; i++) {
2617
+ var str_action = ""
2618
+ rnTable_i = this.rnTable[i];
2619
+ if (rnTable_i === undefined) {
2620
+ var state = this.states.get(i);
2621
+ ret += "No actions in state #" + i + ":" + (state ? state.toString() : "undefined!") + "\n";
2622
+ continue;
2623
+ }
2624
+ for (var j = 0; j < this.atoms.size(); j++) {
2625
+ actions = this.rnTable[i][this.atoms.get(j)]
2626
+ if (actions.accept)
2627
+ str_action += "\n On " + this.atoms.get(j) + ", accept";
2628
+ if (actions.push !== undefined)
2629
+ str_action += "\n On " + this.atoms.get(j) + ", " + actions.push;
2630
+ if (actions.reductions && actions.reductions.size > 0)
2631
+ str_action += "\n On " + this.atoms.get(j) + ", " + [...actions.reductions];
2632
+ }
2633
+ var s = "In state #" + i + ":" + this.states.get(i).toString();
2634
+ if (this.acceptStates[i])
2635
+ s += " (ACCEPT STATE)";
2636
+ if (str_action)
2637
+ s += "\n Actions:" + str_action;
2638
+ if (s !== "") s += "\n";
2639
+ ret += s;
2640
+ }
2641
+ return ret;
2642
+ },
2643
+
2644
+ checkForCycles: function() {
2645
+ var cyclic = []
2646
+ for (var name in this.rules)
2647
+ if (this.derivable[name][name])
2648
+ cyclic.push(name);
2649
+ if (cyclic.length === 0) return false;
2650
+ return cyclic;
2651
+ }
2652
+
2653
+ // //////////////////////////////////
2654
+ // // A LALR(1) ambiguity is a state/token pair that has multiple enabled actions
2655
+ // // Returns a list of warning messages
2656
+ // //////////////////////////////////
2657
+ // checkForLALRAmbiguity: function() {
2658
+ // var ambiguities = []
2659
+ // for (var i = 0; i < this.rnTable.length; i++) {
2660
+ // var tableRow = this.rnTable[i];
2661
+ // for (var name in tableRow) {
2662
+ // if (tableRow.hasOwnProperty(name)) {
2663
+ // var actions = tableRow[name];
2664
+ // if (actions.size() > 1) {
2665
+ // ambiguities.push("In state #" + i + ", conflicting actions on token " + name + ": " + actions);
2666
+ // }
2667
+ // }
2668
+ // }
2669
+ // }
2670
+ // return ambiguities;
2671
+ // },
2672
+
2673
+ }
2674
+
2675
+
2676
+ return {
2677
+ Atom: Atom,
2678
+ Nonterm: Nonterm,
2679
+ Token: Token,
2680
+ Rule: Rule,
2681
+ Grammar: Grammar,
2682
+ SetOfSets: SetOfSets,
2683
+ EOF: EOF,
2684
+ EPSILON: EPSILON,
2685
+ SrcLoc: SrcLoc
2686
+ };
2687
+ });