UNPKG

tscc-compiler

Version:

An LALR(1) compiler compiler written in Typescript

1,339 lines (1,316 loc) 356 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.tscc = {}))); }(this, (function (exports) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var OutputStream = (function () { function OutputStream() { this.endl = '\n'; } OutputStream.prototype.writeln = function (s) { s && this.write(s); this.write(this.endl); }; return OutputStream; }()); var StringOS = (function (_super) { __extends(StringOS, _super); function StringOS() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.s = ''; return _this; } StringOS.prototype.write = function (s) { this.s += s; }; StringOS.prototype.reset = function () { this.s = ''; }; return StringOS; }(OutputStream)); function StringIS(s) { var i = 0; return { peek: function () { return s.charAt(i) || null; }, next: function () { var ret = this.peek(); i++; return ret; } }; } function biss(iss) { var backup = []; return { peek: function () { return backup.length > 0 ? backup[backup.length - 1] : iss.peek(); }, next: function () { if (backup.length > 0) { return backup.pop(); } else { return iss.next(); } }, backup: function (c) { backup.push(c); } }; } var io = /*#__PURE__*/Object.freeze({ OutputStream: OutputStream, StringOS: StringOS, StringIS: StringIS, biss: biss }); var console$1 = { assert: function (expr) { if (!expr) { throw new Error('Assertion failed'); } }, log: function (s) { } }; function setDebugger(d) { return console$1.log = d.log; } var BSIZE = 32; var BitSet = (function () { function BitSet(_size) { this._size = _size; this._s = new Array(Math.ceil(_size / BSIZE)); for (var i = 0; i < this._s.length; i++) { this._s[i] = 0; } } BitSet.prototype.add = function (i) { var block = Math.floor(i / BSIZE); var offset = i - block * BSIZE; var orig = this._s[block]; this._s[block] |= (1 << offset); return orig !== this._s[block]; }; BitSet.prototype.addAll = function () { for (var i = 0; i < this._s.length; i++) { this._s[i] = ~0; } }; BitSet.prototype.remove = function (i) { var block = Math.floor(i / BSIZE); var offset = i - block * BSIZE; var orig = this._s[block]; this._s[block] &= ~(1 << offset); return orig !== this._s[block]; }; BitSet.prototype.removeAll = function () { for (var i = 0; i < this._s.length; i++) { this._s[i] = 0; } }; BitSet.prototype.contains = function (i) { var block = Math.floor(i / BSIZE); var offset = i - block * BSIZE; return (this._s[block] & (1 << offset)) !== 0; }; BitSet.prototype.union = function (set, mask) { var changed = false; for (var i = 0; i < this._s.length; i++) { var orig = this._s[i]; var source = set._s[i]; mask && (source &= mask._s[i]); this._s[i] |= source; changed = (this._s[i] !== orig) || changed; } return changed; }; BitSet.prototype.hasIntersection = function (set) { for (var i = 0; i < this._s.length; i++) { if ((this._s[i] & set._s[i]) !== 0) { return true; } } return false; }; BitSet.prototype.equals = function (set) { for (var i = 0; i < this._s.length; i++) { if (this._s[i] !== set._s[i]) { return false; } } return true; }; BitSet.prototype.forEach = function (cb) { for (var i = 0; i < this._size; i++) { this.contains(i) && cb(i); } }; BitSet.prototype.hash = function () { var ret = ''; for (var i = 0; i < this._s.length; i++) { ret += this._s[i].toString(16) + '-'; } return ret; }; return BitSet; }()); var TokenSet = (function (_super) { __extends(TokenSet, _super); function TokenSet(tcount) { return _super.call(this, tcount) || this; } TokenSet.prototype.toString = function (g) { var ret = ''; var first = true; if (this.contains(0)) { ret += '""'; first = false; } for (var i = 0; i < g.tokenCount; i++) { if (this.contains(i + 1)) { if (!first) { ret += ', '; } var tdef = g.tokens[i]; ret += tdef.alias === null ? "<" + tdef.sym + ">" : "\"" + tdef.alias + "\""; first = false; } } return ret; }; return TokenSet; }(BitSet)); var Action; (function (Action) { Action[Action["NONE"] = 1] = "NONE"; Action[Action["SHIFT"] = 2] = "SHIFT"; Action[Action["REDUCE"] = 3] = "REDUCE"; })(Action || (Action = {})); var Item = (function () { function Item(rule, ik) { this.marker = 0; this.shift = null; this.actionType = Action.NONE; this.changed = true; this.rule = rule; this.isKernel = ik; this.lah = new TokenSet(rule.g.tokenCount); } Item.prototype.canShift = function () { return this.rule.rhs.length > this.marker; }; Item.prototype.getShift = function () { return this.rule.rhs[this.marker]; }; Item.prototype.toString = function (opt) { var showlah = (opt && opt.showlah) || false; var showTrailer = (opt && opt.showTrailer) || false; var r = this.rule; var ret = '[ ' + this.rule.toString(this.marker) + (showlah ? ', { ' + this.lah.toString(this.rule.g) + ' }' : '') + ' ]'; this.isKernel && (ret += '*'); if (showTrailer) { switch (this.actionType) { case Action.NONE: ret += '(-)'; break; case Action.SHIFT: ret += '(s' + this.shift.stateIndex + ')'; break; case Action.REDUCE: ret += '(r)'; break; } } return ret; }; Item.prototype.hash = function () { return this.rule.index + '-' + this.marker; }; Item.prototype.hasRRConflictWith = function (i) { return this.actionType === Action.REDUCE && i.actionType === Action.REDUCE && this.rule.index !== i.rule.index && this.lah.hasIntersection(i.lah); }; Item.prototype.getFollowSet = function (set) { var g = this.rule.g; var i; for (i = this.marker + 1; i < this.rule.rhs.length; i++) { var mItem = this.rule.rhs[i]; if (g.isToken(mItem)) { set.add(mItem + 1); break; } else { var set1 = g.nts[-mItem - 1].firstSet; set.union(set1); set.remove(0); if (!set1.contains(0)) { break; } } } if (i === this.rule.rhs.length) { set.union(this.lah); } }; Item.NULL = {}; return Item; }()); var ItemSet = (function () { function ItemSet(g) { this.items = []; this.itemTable = []; this.reduces = []; this.complete = false; this.index = -1; this.stateIndex = 0; this.prev = null; this.next = null; this.merges = []; this.g = g; this.data = this; } ItemSet.prototype.add = function (rule, marker, ik, lah, reset) { var entry = this.itemTable[rule.index] = this.itemTable[rule.index] || []; var it = entry[marker]; if (it === undefined) { var n = new Item(rule, ik); n.marker = marker; if (lah) { n.lah.union(lah); } entry[marker] = n; this.items.push(n); marker === rule.rhs.length && this.reduces.push(n); return true; } else if (lah) { var ret = it.lah.union(lah); if (reset && ret && it.canShift()) { it.actionType = Action.NONE; } ret && (it.changed = true); return ret; } }; ItemSet.prototype.contains = function () { }; ItemSet.prototype.closure = function () { var changed = true; var tSet = new TokenSet(this.g.tokenCount); var cela = this; while (changed) { changed = false; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; if (item.changed && item.canShift()) { var ritem = item.getShift(); if (ritem < 0) { tSet.removeAll(); item.getFollowSet(tSet); this.g.forEachRuleOfNt(-ritem - 1, function (rule) { changed = cela.add(rule, 0, false, tSet, false) || changed; return false; }); } } item.changed = false; } } }; ItemSet.prototype.toString = function (opt) { var showlah = (opt && opt.showlah) || false; var showTrailer = (opt && opt.showTrailer) || false; var ret = 's' + this.stateIndex + ''; if (this.index !== null) { ret += '(i' + this.index; } else { ret += '(i?'; } if (this.merges.length > 0) { ret += ', merged from '; for (var i = 0; i < this.merges.length; i++) { if (i > 0) { ret += ', '; } ret += 'i' + this.merges[i]; } } ret += ')\n'; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; ret += item.toString(opt) + '\n'; } return ret; }; ItemSet.prototype.kernelHash = function () { var ret = 0; for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; if (item.isKernel) { ret += item.rule.index << 5 + item.rule.index + item.marker; } } return String(ret); }; ItemSet.prototype.forEach = function (cb) { for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var item = _a[_i]; cb(item); } }; ItemSet.prototype.canMergeTo = function (s) { var dup = true; for (var i = 0; i < this.g.rules.length; i++) { var t1 = this.itemTable[i], t2 = s.itemTable[i]; dup = dup && !!(t1 && t2 || !t1 && !t2); if (t1 || t2) { var rhs = this.g.rules[i].rhs; for (var j = 0; j <= rhs.length; j++) { if (t1 && t1[j] && t1[j].isKernel && (!t2 || !t2[j] || !t2[j].isKernel) || t2 && t2[j] && t2[j].isKernel && (!t1 || !t1[j] || !t1[j].isKernel)) { return false; } else { dup = dup && (!t1 && !t1 && !t1[j] && !t2[j] || t1 && t2 && t1[j] && t2[j] && t1[j].lah.equals(t2[j].lah)); } } } } if (!dup) { for (var _i = 0, _a = this.reduces; _i < _a.length; _i++) { var rit = _a[_i]; for (var _b = 0, _c = s.reduces; _b < _c.length; _b++) { var rit2 = _c[_b]; if (rit.rule !== rit2.rule && rit.lah.hasIntersection(rit2.lah)) { return false; } } } } return true; }; ItemSet.prototype.mergeTo = function (s) { var ret = false; for (var _i = 0, _a = s.items; _i < _a.length; _i++) { var it = _a[_i]; ret = this.add(it.rule, it.marker, it.isKernel, it.lah, true) || ret; } this.merges.push(s.index); return ret; }; return ItemSet; }()); var List = (function () { function List() { this.size = 0; this.head = { prev: null, next: null, data: null }; this.tail = { prev: null, next: null, data: null }; this.head.next = this.tail; this.tail.prev = this.head; } List.prototype.append = function (n) { n.prev = this.tail.prev; n.next = this.tail; this.tail.prev.next = n; this.tail.prev = n; this.size++; }; List.prototype.pull = function () { var n = this.head.next; this.head.next = n.next; n.next.prev = this.head; n.prev = n.next = null; this.size--; return n.data; }; List.prototype.isEmpty = function () { return this.size === 0; }; List.prototype.forEach = function (cb) { for (var a = this.head.next; a !== this.tail; a = a.next) { cb(a.data); } }; List.prototype.remove = function (n) { n.next.prev = n.prev; n.prev.next = n.next; this.size--; }; List.prototype.iterator = function () { var p = this.head; var cela = this; return function () { return p !== cela.tail ? (p = p.next, p.data) : null; }; }; return List; }()); (function (Assoc) { Assoc[Assoc["UNDEFINED"] = 0] = "UNDEFINED"; Assoc[Assoc["LEFT"] = 1] = "LEFT"; Assoc[Assoc["RIGHT"] = 2] = "RIGHT"; Assoc[Assoc["NON"] = 3] = "NON"; })(exports.Assoc || (exports.Assoc = {})); function convertTokenToString(t) { return t.alias === null ? "<" + t.sym + ">" : "\"" + t.alias + "\""; } function escapeString(s, escapes) { var ret = ''; for (var i = 0; i < s.length; i++) { var c = s.charAt(i); ret += escapes[c] || c; } return ret; } var Span = (function () { function Span() { this._s = []; } Span.prototype.append = function (content, escape) { if (escape === void 0) { escape = true; } if (this._s.length > 0 && this._s[this._s.length - 1].escape === escape) { this._s[this._s.length - 1].content += content; } else { this._s.push({ content: content, escape: escape }); } return this; }; Span.prototype.toString = function (escapes) { var ret = ''; for (var _i = 0, _a = this._s; _i < _a.length; _i++) { var it = _a[_i]; var s = it.content; if (escapes && it.escape) { s = escapeString(s, escapes); } ret += s; } return ret; }; return Span; }()); function printParseTable(os, cela, doneList, showlah, showFullItemsets, escapes) { var g = cela.g; var tokenCount = g.tokenCount; var ntCount = g.nts.length; var tab = ' '; function echo(s) { if (escapes) { s = escapeString(s, escapes); } os.writeln(s); } doneList.forEach(function (set) { var i = set.stateIndex; var shift = ''; var reduce = ''; var gotot = ''; echo("state " + i); set.forEach(function (item) { (showFullItemsets || item.isKernel) && echo(tab + item.toString({ showlah: showlah })); }); if (cela.defred[i] !== -1) { var def = cela.defred[i]; echo(tab + "default action: reduce with rule " + def + " (" + g.rules[def].lhs.sym + ")"); } else { echo(tab + 'no default action'); } for (var j = 0; j < tokenCount; j++) { var item = cela.lookupShift(i, j); if (item !== null && item !== Item.NULL) { if (item.actionType === Action.SHIFT) { shift += "" + tab + convertTokenToString(g.tokens[j]) + " : shift, and go to state " + item.shift.stateIndex + "\n"; } else { reduce += "" + tab + convertTokenToString(g.tokens[j]) + " : reduce with rule " + item.rule.index + " (" + item.rule.lhs.sym + ")\n"; } } } for (var j = 0; j < ntCount; j++) { var item = cela.lookupGoto(i, j); if (item !== null) { gotot += "" + tab + g.nts[j].sym + " : go to state " + item.shift.stateIndex + "\n"; } } var line = shift + reduce + gotot; echo(line); os.writeln(); }); } var ParseTable = (function () { function ParseTable(g, stateCount) { this.defred = null; this.g = g; var tokenCount = g.tokenCount; var ntCount = g.nts.length; this.stateCount = stateCount; this.shift = new Array(tokenCount * stateCount); this.gotot = new Array(ntCount * stateCount); for (var i = 0; i < this.shift.length; i++) { this.shift[i] = null; } for (var i = 0; i < this.gotot.length; i++) { this.gotot[i] = null; } } ParseTable.prototype.forEachShift = function (cb) { for (var state = 0; state < this.stateCount; state++) { for (var tk = 0; tk < this.g.tokens.length; tk++) { var item = this.lookupShift(state, tk); item && cb(item, state, tk); } } }; ParseTable.prototype.forEachGoto = function (cb) { for (var state = 0; state < this.stateCount; state++) { for (var nt = 0; nt < this.g.nts.length; nt++) { var item = this.lookupGoto(state, nt); item && cb(item, state, nt); } } }; ParseTable.prototype.lookupShift = function (state, token) { return this.shift[this.g.tokenCount * state + token]; }; ParseTable.prototype.lookupGoto = function (state, nt) { return this.gotot[this.g.nts.length * state + nt]; }; ParseTable.prototype._getDefRed = function (state, apool) { for (var i = 0; i < apool.length; i++) { apool[i] = 0; } for (var tk = 0; tk < this.g.tokenCount; tk++) { var item = this.lookupShift(state, tk); item && item.actionType === Action.REDUCE && apool[item.rule.index]++; } var ret = 0; for (var i = 0; i < apool.length; i++) { apool[i] > apool[ret] && (ret = i); } return apool[ret] > 0 ? ret : -1; }; ParseTable.prototype.findDefAct = function () { this.defred = new Array(this.stateCount); var apool = new Array(this.g.rules.length); for (var i = 0; i < this.stateCount; i++) { var def = this._getDefRed(i, apool); this.defred[i] = def; if (def !== -1) { for (var tk = 0; tk < this.g.tokens.length; tk++) { var item = this.lookupShift(i, tk); item && item.actionType === Action.REDUCE && item.rule.index === def && (this.shift[this.g.tokenCount * i + tk] = null); } } } }; return ParseTable; }()); var ConflictType; (function (ConflictType) { ConflictType[ConflictType["RR"] = 0] = "RR"; ConflictType[ConflictType["SR"] = 1] = "SR"; })(ConflictType || (ConflictType = {})); var Conflict = (function () { function Conflict() { } Conflict.prototype.toString = function () { return "state " + this.set.stateIndex + ", " + Conflict.cNames[this.type] + " conflict:\n" + (" token: " + convertTokenToString(this.token) + "\n") + (" used rule: " + this.used.toString() + "\n") + (" discarded rule: " + this.discarded.toString()); }; Conflict.cNames = ['reduce/reduce', 'shift/reduce']; return Conflict; }()); function genInitialSet(g) { var start = g.nts[0].rules[0]; var iset = new ItemSet(g); iset.index = 0; var set1 = new TokenSet(g.tokenCount); set1.add(1); iset.add(start, 0, true, set1, false); return iset; } function genItemSets(g) { var htable = {}; var iterations = 0; function addToTable(iset) { var h = iset.kernelHash(); if (htable[h] === undefined) { htable[h] = []; } htable[h].push(iset); } function forEachInBucket(set, cb) { var b = htable[set.kernelHash()]; if (b !== undefined) { for (var i = 0; i < b.length; i++) { if (cb(b[i])) break; } } } var index = 1; var todoList = new List(); var incList = new List(); var doneList = new List(); todoList.append(genInitialSet(g)); while (!todoList.isEmpty() || !incList.isEmpty()) { var comeFrom = null; if (!incList.isEmpty()) { var set = comeFrom = incList.pull(); set.forEach(function (item) { if (item.actionType === Action.NONE) { console$1.assert(item.canShift()); var shift = item.getShift(); var newSet = new ItemSet(g); newSet.index = index++; todoList.append(newSet); set.forEach(function (item1) { if (item1.canShift()) { var rItem = item1.getShift(); if (rItem === shift) { item1.actionType = Action.SHIFT; item1.shift = newSet; newSet.add(item1.rule, item1.marker + 1, true, item1.lah, false); } } }); } }); set.complete = true; doneList.append(set); } while (!todoList.isEmpty()) { var set = todoList.pull(); set.closure(); set.forEach(function (item) { if (!item.canShift()) { item.actionType = Action.REDUCE; } }); var merged = null; forEachInBucket(set, function (gSet) { if (gSet.canMergeTo(set)) { if (gSet.mergeTo(set)) { if (gSet.complete) { merged = gSet; } } if (comeFrom !== null) { comeFrom.forEach(function (sItem) { if (sItem.actionType === Action.SHIFT && sItem.shift === set) { sItem.shift = gSet; } }); } set = null; return true; } return false; }); if (merged !== null) { doneList.remove(merged); incList.append(merged); merged.complete = false; } else if (set !== null) { incList.append(set); addToTable(set); } } iterations++; } var i = 0; doneList.forEach(function (set) { set.stateIndex = i++; }); return { result: doneList, iterations: iterations }; } function genParseTable(g, doneList) { var conflicts = []; function resolveSRConflict(set, shift, reduce) { var token = g.tokens[shift.getShift()]; if (token.assoc !== exports.Assoc.UNDEFINED) { var ruleP = reduce.rule.pr; if (ruleP !== -1) { if (ruleP > token.pr) { return reduce; } else if (ruleP < token.pr) { return shift; } else { if (token.assoc === exports.Assoc.LEFT) { return reduce; } else if (token.assoc === exports.Assoc.RIGHT) { return shift; } else if (token.assoc === exports.Assoc.NON) { return Item.NULL; } else { console$1.assert(false); } } } } var cf = new Conflict(); cf.type = ConflictType.SR; cf.set = set; cf.token = token; cf.used = shift; cf.discarded = reduce; conflicts.push(cf); return shift; } function resolveRRConflict(set, r1, r2, token) { var tdef = g.tokens[token]; if (r1.rule.pr !== -1 && r2.rule.pr !== -1 && r1.rule.pr !== r2.rule.pr) { return r1.rule.pr > r2.rule.pr ? r1 : r2; } else { var used = r1.rule.index > r2.rule.index ? r2 : r1; var discarded = r1.rule.index > r2.rule.index ? r1 : r2; var cf = new Conflict(); cf.type = ConflictType.RR; cf.set = set; cf.token = tdef; cf.used = used; cf.discarded = discarded; conflicts.push(cf); return used; } } var ptable = new ParseTable(g, doneList.size); doneList.forEach(function (set) { set.forEach(function (item) { if (item.actionType === Action.SHIFT) { var sItem = item.getShift(); if (g.isToken(sItem)) { var tindex = set.stateIndex * g.tokenCount + sItem; var cItem = ptable.shift[tindex]; if (cItem !== null) { if (cItem.actionType === Action.REDUCE) { ptable.shift[tindex] = resolveSRConflict(set, item, cItem); } else { console$1.assert(cItem.shift === item.shift); } } else { ptable.shift[tindex] = item; } } else { var tindex = set.stateIndex * g.nts.length + (-sItem - 1); ptable.gotot[tindex] = item; } } else if (item.actionType === Action.REDUCE) { for (var i = 0; i < g.tokenCount; i++) { if (item.lah.contains(i + 1)) { var index = set.stateIndex * g.tokenCount + i; var cItem = ptable.shift[index]; if (cItem !== null) { if (cItem.actionType === Action.REDUCE) { ptable.shift[index] = resolveRRConflict(set, cItem, item, i); } else if (cItem.actionType === Action.SHIFT) { ptable.shift[index] = resolveSRConflict(set, cItem, item); } } else { ptable.shift[index] = item; } } } } else { console$1.assert(false); } }); }); return { result: ptable, conflicts: conflicts }; } function testParse(g, pt, tokens, onErr) { var tk = []; for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) { var tname = tokens_1[_i]; var tdef = void 0; if (/<[^>]+>/.test(tname)) { tdef = g.findTokenByName(tname.substr(1, tname.length - 2)); if (tdef === null) { onErr("cannot recognize " + tname + " as a token"); return []; } } else { var defs = g.findTokensByAlias(tname); if (defs.length === 0) { onErr("cannot recognize \"" + tname + "\" as a token"); return []; } if (defs.length > 1) { var msg = ''; for (var _a = 0, defs_1 = defs; _a < defs_1.length; _a++) { var def = defs_1[_a]; msg += "<" + def.sym + "> "; } onErr("cannot recognize \"" + tname + "\" as a token, since it can be " + msg); return []; } tdef = defs[0]; } tk.push(tdef); } var state = [0]; var stack = []; var ret = []; function s() { return state[state.length - 1]; } function shift(ns) { state.push(ns); var tdef = tk.shift(); stack.push(convertTokenToString(tdef)); } function reduce(rule) { state.length -= rule.rhs.length; stack.length -= rule.rhs.length; stack.push(rule.lhs.sym); var gotot = pt.lookupGoto(s(), rule.lhs.index).shift.stateIndex; state.push(gotot); } function dump() { var ret = ''; for (var _i = 0, stack_1 = stack; _i < stack_1.length; _i++) { var s_1 = stack_1[_i]; ret += s_1 + ' '; } ret += '| '; for (var _a = 0, tk_1 = tk; _a < tk_1.length; _a++) { var tdef = tk_1[_a]; ret += convertTokenToString(tdef); ret += ' '; } return ret; } ret.push(dump()); do { var item = pt.lookupShift(s(), tk[0] ? tk[0].index : 0); if (item !== null) { if (item === Item.NULL) { ret.push('syntax error!'); break; } else if (item.actionType === Action.SHIFT) { if (tk.length === 0) { ret.push('accepted!'); break; } shift(item.shift.stateIndex); } else if (item.actionType === Action.REDUCE) { if (reduce(item.rule)) { break; } } else { console.assert(false); } } else { var ri = pt.defred[s()]; if (ri !== -1) { reduce(g.rules[ri]); } else { ret.push('syntax error!'); break; } } ret.push(dump()); } while (true); return ret; } var JsccError = (function () { function JsccError(msg, type) { if (type === void 0) { type = 'Error'; } this.msg = msg; this.type = type; } JsccError.prototype.toString = function (opt) { if (opt === void 0) { opt = {}; } var ret = new Span(); if (opt.typeClass) { ret.append("<span class=\"" + opt.typeClass + "\">" + ret + "</span>", false); } else { ret.append(this.type); } ret.append(': '); ret.append(this.msg); return ret; }; return JsccError; }()); var CompilationError = (function (_super) { __extends(CompilationError, _super); function CompilationError(msg, line) { var _this = _super.call(this, msg, 'CompilationError') || this; _this.line = line; return _this; } CompilationError.prototype.toString = function (opt) { return _super.prototype.toString.call(this).append("(at line " + this.line + ")"); }; return CompilationError; }(JsccError)); var JsccWarning = (function (_super) { __extends(JsccWarning, _super); function JsccWarning(msg) { return _super.call(this, msg, 'Warning') || this; } return JsccWarning; }(JsccError)); function sorter(cmp) { var a = []; function insert(i, obj) { a.push(null); for (var j = a.length - 1; j > i; j--) { a[j] = a[j - 1]; } a[i] = obj; } return { add: function (b) { var i; for (i = 0; i < a.length; i++) { if ((i === 0 || cmp(b, a[i - 1]) >= 0) && cmp(b, a[i]) <= 0) { break; } } insert(i, b); }, done: function () { return a; } }; } var RowEntry = (function () { function RowEntry(emptyCount, row) { this.emptyCount = emptyCount; this.row = row; this.dp = 0; } return RowEntry; }()); function compress(source) { function empty(i, j) { j = j - sorted[i].dp; return j < 0 || j >= source.columns || source.isEmpty(sorted[i].row, j); } function fit(i, dp) { for (var j = 0; j < source.columns; j++) { if (!empty(i, j)) { for (var k = 0; k < i; k++) { if (!empty(k, j + dp)) { return false; } } } } return true; } function getFitdp(i) { var dp = 0; while (-dp < source.columns && source.isEmpty(sorted[i].row, -dp)) { dp--; } while (!fit(i, dp)) { dp++; } return dp; } var tmpsorted = sorter(function (a, b) { return a.emptyCount < b.emptyCount ? -1 : a.emptyCount > b.emptyCount ? 1 : 0; }); for (var i = 0; i < source.rows; i++) { tmpsorted.add(new RowEntry(source.emptyCount(i), i)); } var sorted = tmpsorted.done(); var maxdp = 0; var dps = new Array(source.rows); var initDp = 0; while (-initDp < source.columns && source.isEmpty(sorted[0].row, -initDp)) { initDp--; } dps[sorted[0].row] = sorted[0].dp = initDp; for (var i = 1; i < sorted.length; i++) { var row = sorted[i].row; var dp = getFitdp(i); dps[row] = sorted[i].dp = dp; dp > maxdp && (maxdp = dp); } return { dps: dps, len: maxdp + source.columns }; } function initArray(len, cb) { var ret = new Array(len); for (var i = 0; i < len; i++) { ret[i] = cb(i); } return ret; } function action(pt) { var emCount = []; for (var state = 0; state < pt.stateCount; state++) { emCount.push(0); for (var tk = 0; tk < pt.g.tokens.length; tk++) { pt.lookupShift(state, tk) === null && (emCount[state]++); } } return { rows: pt.stateCount, columns: pt.g.tokens.length, isEmpty: function (state, token) { return pt.lookupShift(state, token) === null; }, emptyCount: function (state) { return emCount[state]; } }; } function gotot(pt) { var emCount = []; for (var state = 0; state < pt.stateCount; state++) { emCount.push(0); for (var nt = 0; nt < pt.g.nts.length; nt++) { pt.lookupShift(state, nt) === null && (emCount[state]++); } } return { rows: pt.stateCount, columns: pt.g.nts.length, isEmpty: function (state, nt) { return pt.lookupGoto(state, nt) === null; }, emptyCount: function (nt) { return emCount[nt]; } }; } var CompressedPTable = (function () { function CompressedPTable(ptable) { this.g = ptable.g; this.defred = ptable.defred; this.stateCount = ptable.stateCount; var actionCResult = compress(action(ptable)); var gotoCResult = compress(gotot(ptable)); this.disact = actionCResult.dps; this.disgoto = gotoCResult.dps; this.pact = initArray(actionCResult.len, function () { return null; }); this.checkact = initArray(actionCResult.len, function () { return 0; }); var cela = this; ptable.forEachShift(function (it, state, token) { console$1.assert(cela.pact[cela.disact[state] + token] === null); cela.pact[cela.disact[state] + token] = it; cela.checkact[cela.disact[state] + token] = state; }); this.pgoto = initArray(gotoCResult.len, function () { return null; }); this.checkgoto = initArray(gotoCResult.len, function () { return 0; }); ptable.forEachGoto(function (it, state, nt) { console$1.assert(cela.pgoto[cela.disgoto[state] + nt] === null); cela.pgoto[cela.disgoto[state] + nt] = it; cela.checkgoto[cela.disgoto[state] + nt] = state; }); this._trim(); } CompressedPTable.prototype._trim = function () { while (this.pact[this.pact.length - 1] === null) { this.pact.pop(); this.checkact.pop(); } while (this.pgoto[this.pgoto.length - 1] === null) { this.pgoto.pop(); this.checkgoto.pop(); } }; CompressedPTable.prototype.lookupShift = function (state, token) { var index = this.disact[state] + token; if (index >= 0 && index < this.pact.length && this.checkact[index] === state) { return this.pact[this.disact[state] + token]; } else { return null; } }; CompressedPTable.prototype.lookupGoto = function (state, nt) { var index = this.disgoto[state] + nt; if (index >= 0 && index < this.pgoto.length && this.checkgoto[index] === state) { return this.pgoto[this.disgoto[state] + nt]; } else { return null; } }; return CompressedPTable; }()); var Rule = (function () { function Rule(g, lhs, pos) { this.g = g; this.lhs = lhs; this.pos = pos; this.pr = -1; this.rhs = []; this.action = null; this.index = 0; this.vars = {}; this.usedVars = {}; } Rule.prototype.calcPr = function () { if (this.pr === -1) { for (var i = this.rhs.length - 1; i >= 0; i--) { var item = this.rhs[i]; if (item >= 0) { this.g.tokens[item].assoc !== exports.Assoc.UNDEFINED && (this.pr = this.g.tokens[item].pr); } } } }; Rule.prototype.getVarSp = function (v, ecb) { if (this.lhs.parents.length !== 1) { if (this.lhs.parents.length > 1) { ecb("LHS of the rule is referenced by more than one rule"); } else { ecb("this rule is unreachable"); } return null; } var ret = this.rhs.length; var pos = this.lhs.parents[0].pos; var rule = this.lhs.parents[0].rule; while (true) { var vdef = rule.vars[v]; if (vdef !== undefined && vdef.val < pos) { ret += pos - vdef.val; return ret; } if (rule.lhs.parents.length !== 1) { if (rule.lhs.parents.length > 1) { ecb("\"" + rule.lhs.sym + "\" is referenced by more than one rule or unreachable"); } else { ecb("variable is undefined"); } return null; } ret += pos; pos = rule.lhs.parents[0].pos; rule = rule.lhs.parents[0].rule; } }; Rule.prototype.toString = function (marker) { var ret = this.index + ': ' + this.lhs.sym + ' =>'; for (var i = 0; i < this.rhs.length; i++) { var r = this.rhs[i]; if (marker === i) { ret += ' .'; } if (r >= 0) { ret += ' ' + convertTokenToString(this.g.tokens[r]); } else { ret += ' ' + this.g.nts[-r - 1].sym; } } if (marker === this.rhs.length) { ret += ' .'; } return ret; }; return Rule; }()); var Grammar = (function () { function Grammar() { this.tokens = []; this.tokenCount = 0; this.nts = []; this.rules = []; } Grammar.prototype.isToken = function (t) { return t >= 0; }; Grammar.prototype.forEachRule = function (cb) { for (var i = 0; i < this.nts.length; i++) { var rules = this.nts[i].rules; for (var j = 0; j < rules.length; j++) { cb(i, rules[j]); } } }; Grammar.prototype.forEachRuleOfNt = function (lhs, cb) { var rules = this.nts[lhs].rules; for (var j = 0; j < rules.length; j++) { if (cb(rules[j])) { break; } } }; Grammar.prototype.genFirstSets = function () { var changed = true; var mask = new TokenSet(this.tokens.length); mask.addAll(); mask.remove(0); while (changed) { changed = false; for (var nt = 0; nt < this.nts.length; nt++) { var rules = this.nts[nt].rules; var firstSet = this.nts[nt].firstSet; for (var j = 0; j < rules.length; j++) { var rule = rules[j]; for (var k = 0; k < rule.rhs.length; k++) { var ritem = rule.rhs[k]; if (this.isToken(ritem)) {