tscc-compiler
Version:
An LALR(1) compiler compiler written in Typescript
1,339 lines (1,316 loc) • 356 kB
JavaScript
(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)) {