@light0x00/parser-generator
Version:
A Parser Generator
157 lines (120 loc) • 16.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildLLParser = buildLLParser;
exports.LLParser = void 0;
var _parserDefinition = require("@light0x00/parser-definition");
var _Definition = require("../Definition");
var _shim = require("@light0x00/shim");
var _debug = _interopRequireDefault(require("debug"));
var _First = require("../First");
var _Follow = require("../Follow");
var _Toolkit = require("../Toolkit");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
let debug = (0, _debug.default)("APP:LLParser");
class LLParser {
constructor(grammar, firstTable, followTable) {
_defineProperty(this, "startNT", void 0);
_defineProperty(this, "firstTable", void 0);
_defineProperty(this, "followTable", void 0);
this.startNT = grammar.startNT();
this.firstTable = firstTable;
this.followTable = followTable;
checkAmbiguity(firstTable, followTable);
}
accumulate(accStack, ele) {
if (accStack.size() > 0) {
let parentEntry = accStack.peek();
if (ele != null) parentEntry.astNode.appendElement(ele);
--parentEntry.accNum;
if (parentEntry.accNum == 0) {
accStack.pop();
}
}
}
parse(lexer) {
let symStack = new _shim.Stack();
symStack.push(_parserDefinition.EOF);
symStack.push(this.startNT);
let rootAST;
let astAccStack = new _shim.Stack();
let lookahead = lexer.nextToken();
while (symStack.size() > 0) {
// debug(symStack.join(" "));
let symbol = symStack.pop();
let lookaheadKey = lookahead.tableKey(); //非终结符
if (symbol instanceof _Definition.NonTerminal) {
let nt_key = symbol.name;
let firstSet = this.firstTable.get(nt_key);
let followSet = this.followTable.get(nt_key);
let candidate_prod = firstSet.get(lookaheadKey); //如果当前非终结符存在 对lookahead的非ε推导
if (candidate_prod != null) {
//将候选式符号倒序压入栈
for (let i = candidate_prod.length - 1; i >= 0; i--) symStack.push(candidate_prod[i]);
/* 分析树 */
let ast = candidate_prod.makeAST();
if (rootAST == undefined && symbol == this.startNT) rootAST = ast;
this.accumulate(astAccStack, ast);
astAccStack.push({
astNode: ast,
accNum: candidate_prod.length
});
} //否则
else {
//检查当前非终结符是否可推出ε, 并且lookahead存在于followSet
if (firstSet.has(_parserDefinition.NIL) && followSet.has(lookaheadKey)) {
//ok
/* 分析树 */
this.accumulate(astAccStack);
} else {
throw new _Toolkit.MismatchError(firstSet.keys(), lookahead);
}
}
} //终结符
else {
if (lookaheadKey != symbol) throw new _Toolkit.MismatchError(symbol, lookahead);
debug(`matched ${lookahead}`);
/* 分析树 */
if (lookahead != _parserDefinition.EOF) this.accumulate(astAccStack, lookahead);
lookahead = lexer.nextToken();
}
}
debug("success!");
return rootAST;
}
}
exports.LLParser = LLParser;
function buildLLParser(grammar) {
let firstSetCalculator = new _First.FirstSetCalculator(grammar);
let follow = new _Follow.FollowSetCalculator(grammar, firstSetCalculator);
return new LLParser(grammar, firstSetCalculator.getFirstTable(), follow.getFollowTable());
}
/*
1. 二义性
如果一个非终结符A可以推出ε,那么必须满足 First(A) ∩ Follow(A)=∅, 否则就存在二义性
S->Aa
A->a|ε
First(A)={a,ε}
Follow(A)={a}
预测表:
+------+--------------+
| | a |
+------+--------------+
|A | A->a,A->ε |
+------+--------------+
在输入串为「a」时,分别选择A->a,A->ε,前者将匹配失败,而后者匹配成功. 无法确定一个唯一的选择.
*/
function checkAmbiguity(firstTable, followTable) {
/* issue: 1. 二义性 */
for (let [pname, firstMap] of firstTable) {
if (firstMap.has(_parserDefinition.NIL)) {
let followSet = followTable.get(pname);
for (let v of firstMap.keys()) {
if (followSet.has(v)) throw new Error(`Found ambiguity in grammar. There is conflict between the First-set(${pname}) and Follow-Set(${pname}) on ${v}`);
}
}
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MTC9QYXJzZXIudHMiXSwibmFtZXMiOlsiZGVidWciLCJMTFBhcnNlciIsImNvbnN0cnVjdG9yIiwiZ3JhbW1hciIsImZpcnN0VGFibGUiLCJmb2xsb3dUYWJsZSIsInN0YXJ0TlQiLCJjaGVja0FtYmlndWl0eSIsImFjY3VtdWxhdGUiLCJhY2NTdGFjayIsImVsZSIsInNpemUiLCJwYXJlbnRFbnRyeSIsInBlZWsiLCJhc3ROb2RlIiwiYXBwZW5kRWxlbWVudCIsImFjY051bSIsInBvcCIsInBhcnNlIiwibGV4ZXIiLCJzeW1TdGFjayIsIlN0YWNrIiwicHVzaCIsIkVPRiIsInJvb3RBU1QiLCJhc3RBY2NTdGFjayIsImxvb2thaGVhZCIsIm5leHRUb2tlbiIsInN5bWJvbCIsImxvb2thaGVhZEtleSIsInRhYmxlS2V5IiwiTm9uVGVybWluYWwiLCJudF9rZXkiLCJuYW1lIiwiZmlyc3RTZXQiLCJnZXQiLCJmb2xsb3dTZXQiLCJjYW5kaWRhdGVfcHJvZCIsImkiLCJsZW5ndGgiLCJhc3QiLCJtYWtlQVNUIiwidW5kZWZpbmVkIiwiaGFzIiwiTklMIiwiTWlzbWF0Y2hFcnJvciIsImtleXMiLCJidWlsZExMUGFyc2VyIiwiZmlyc3RTZXRDYWxjdWxhdG9yIiwiRmlyc3RTZXRDYWxjdWxhdG9yIiwiZm9sbG93IiwiRm9sbG93U2V0Q2FsY3VsYXRvciIsImdldEZpcnN0VGFibGUiLCJnZXRGb2xsb3dUYWJsZSIsInBuYW1lIiwiZmlyc3RNYXAiLCJ2IiwiRXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBR0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7OztBQUNBLElBQUlBLEtBQUssR0FBRyxvQkFBVSxjQUFWLENBQVo7O0FBSU8sTUFBTUMsUUFBTixDQUFrQztBQU94Q0MsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQW9CQyxVQUFwQixFQUE0Q0MsV0FBNUMsRUFBeUU7QUFBQTs7QUFBQTs7QUFBQTs7QUFDbkYsU0FBS0MsT0FBTCxHQUFlSCxPQUFPLENBQUNHLE9BQVIsRUFBZjtBQUNBLFNBQUtGLFVBQUwsR0FBa0JBLFVBQWxCO0FBQ0EsU0FBS0MsV0FBTCxHQUFtQkEsV0FBbkI7QUFFQUUsSUFBQUEsY0FBYyxDQUFDSCxVQUFELEVBQWFDLFdBQWIsQ0FBZDtBQUNBOztBQUVERyxFQUFBQSxVQUFVLENBQUNDLFFBQUQsRUFBd0NDLEdBQXhDLEVBQTBEO0FBQ25FLFFBQUlELFFBQVEsQ0FBQ0UsSUFBVCxLQUFrQixDQUF0QixFQUF5QjtBQUN4QixVQUFJQyxXQUFXLEdBQUdILFFBQVEsQ0FBQ0ksSUFBVCxFQUFsQjtBQUNBLFVBQUlILEdBQUcsSUFBSSxJQUFYLEVBQ0NFLFdBQVcsQ0FBQ0UsT0FBWixDQUFvQkMsYUFBcEIsQ0FBa0NMLEdBQWxDO0FBQ0QsUUFBRUUsV0FBVyxDQUFDSSxNQUFkOztBQUNBLFVBQUlKLFdBQVcsQ0FBQ0ksTUFBWixJQUFzQixDQUExQixFQUE2QjtBQUM1QlAsUUFBQUEsUUFBUSxDQUFDUSxHQUFUO0FBQ0E7QUFDRDtBQUNEOztBQUVEQyxFQUFBQSxLQUFLLENBQUNDLEtBQUQsRUFBd0I7QUFDNUIsUUFBSUMsUUFBUSxHQUFHLElBQUlDLFdBQUosRUFBZjtBQUNBRCxJQUFBQSxRQUFRLENBQUNFLElBQVQsQ0FBY0MscUJBQWQ7QUFDQUgsSUFBQUEsUUFBUSxDQUFDRSxJQUFULENBQWMsS0FBS2hCLE9BQW5CO0FBRUEsUUFBSWtCLE9BQUo7QUFDQSxRQUFJQyxXQUFXLEdBQUcsSUFBSUosV0FBSixFQUFsQjtBQUVBLFFBQUlLLFNBQVMsR0FBR1AsS0FBSyxDQUFDUSxTQUFOLEVBQWhCOztBQUNBLFdBQU9QLFFBQVEsQ0FBQ1QsSUFBVCxLQUFrQixDQUF6QixFQUE0QjtBQUMzQjtBQUNBLFVBQUlpQixNQUFNLEdBQUdSLFFBQVEsQ0FBQ0gsR0FBVCxFQUFiO0FBQ0EsVUFBSVksWUFBWSxHQUFHSCxTQUFTLENBQUNJLFFBQVYsRUFBbkIsQ0FIMkIsQ0FJM0I7O0FBQ0EsVUFBSUYsTUFBTSxZQUFZRyx1QkFBdEIsRUFBbUM7QUFDbEMsWUFBSUMsTUFBTSxHQUFHSixNQUFNLENBQUNLLElBQXBCO0FBQ0EsWUFBSUMsUUFBUSxHQUFHLEtBQUs5QixVQUFMLENBQWdCK0IsR0FBaEIsQ0FBb0JILE1BQXBCLENBQWY7QUFDQSxZQUFJSSxTQUFTLEdBQUcsS0FBSy9CLFdBQUwsQ0FBaUI4QixHQUFqQixDQUFxQkgsTUFBckIsQ0FBaEI7QUFFQSxZQUFJSyxjQUFjLEdBQUdILFFBQVEsQ0FBQ0MsR0FBVCxDQUFhTixZQUFiLENBQXJCLENBTGtDLENBTWxDOztBQUNBLFlBQUlRLGNBQWMsSUFBSSxJQUF0QixFQUE0QjtBQUMzQjtBQUNBLGVBQUssSUFBSUMsQ0FBQyxHQUFHRCxjQUFjLENBQUNFLE1BQWYsR0FBd0IsQ0FBckMsRUFBd0NELENBQUMsSUFBSSxDQUE3QyxFQUFnREEsQ0FBQyxFQUFqRCxFQUNDbEIsUUFBUSxDQUFDRSxJQUFULENBQWNlLGNBQWMsQ0FBQ0MsQ0FBRCxDQUE1QjtBQUVEOzs7QUFDQSxjQUFJRSxHQUFHLEdBQUdILGNBQWMsQ0FBQ0ksT0FBZixFQUFWO0FBRUEsY0FBSWpCLE9BQU8sSUFBSWtCLFNBQVgsSUFBd0JkLE1BQU0sSUFBSSxLQUFLdEIsT0FBM0MsRUFDQ2tCLE9BQU8sR0FBR2dCLEdBQVY7QUFFRCxlQUFLaEMsVUFBTCxDQUFnQmlCLFdBQWhCLEVBQTZCZSxHQUE3QjtBQUNBZixVQUFBQSxXQUFXLENBQUNILElBQVosQ0FBaUI7QUFBRVIsWUFBQUEsT0FBTyxFQUFFMEIsR0FBWDtBQUFnQnhCLFlBQUFBLE1BQU0sRUFBRXFCLGNBQWMsQ0FBQ0U7QUFBdkMsV0FBakI7QUFFQSxTQWRELENBZUE7QUFmQSxhQWdCSztBQUNKO0FBQ0EsZ0JBQUlMLFFBQVEsQ0FBQ1MsR0FBVCxDQUFhQyxxQkFBYixLQUFxQlIsU0FBUyxDQUFDTyxHQUFWLENBQWNkLFlBQWQsQ0FBekIsRUFBc0Q7QUFDckQ7O0FBRUE7QUFDQSxtQkFBS3JCLFVBQUwsQ0FBZ0JpQixXQUFoQjtBQUNBLGFBTEQsTUFLTztBQUNOLG9CQUFNLElBQUlvQixzQkFBSixDQUFrQlgsUUFBUSxDQUFDWSxJQUFULEVBQWxCLEVBQW1DcEIsU0FBbkMsQ0FBTjtBQUNBO0FBQ0Q7QUFDRCxPQWxDRCxDQW1DQTtBQW5DQSxXQW9DSztBQUNKLGNBQUlHLFlBQVksSUFBSUQsTUFBcEIsRUFDQyxNQUFNLElBQUlpQixzQkFBSixDQUFrQmpCLE1BQWxCLEVBQTBCRixTQUExQixDQUFOO0FBQ0QxQixVQUFBQSxLQUFLLENBQUUsV0FBVTBCLFNBQVUsRUFBdEIsQ0FBTDtBQUVBOztBQUNBLGNBQUlBLFNBQVMsSUFBSUgscUJBQWpCLEVBQ0MsS0FBS2YsVUFBTCxDQUFnQmlCLFdBQWhCLEVBQTZCQyxTQUE3QjtBQUVEQSxVQUFBQSxTQUFTLEdBQUdQLEtBQUssQ0FBQ1EsU0FBTixFQUFaO0FBQ0E7QUFDRDs7QUFDRDNCLElBQUFBLEtBQUssQ0FBQyxVQUFELENBQUw7QUFDQSxXQUFPd0IsT0FBUDtBQUNBOztBQTNGdUM7Ozs7QUFnR2xDLFNBQVN1QixhQUFULENBQXVCNUMsT0FBdkIsRUFBK0M7QUFDckQsTUFBSTZDLGtCQUFrQixHQUFHLElBQUlDLHlCQUFKLENBQXVCOUMsT0FBdkIsQ0FBekI7QUFDQSxNQUFJK0MsTUFBTSxHQUFHLElBQUlDLDJCQUFKLENBQXdCaEQsT0FBeEIsRUFBaUM2QyxrQkFBakMsQ0FBYjtBQUNBLFNBQU8sSUFBSS9DLFFBQUosQ0FBYUUsT0FBYixFQUFzQjZDLGtCQUFrQixDQUFDSSxhQUFuQixFQUF0QixFQUEwREYsTUFBTSxDQUFDRyxjQUFQLEVBQTFELENBQVA7QUFDQTtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBLFNBQVM5QyxjQUFULENBQXdCSCxVQUF4QixFQUFnREMsV0FBaEQsRUFBNkU7QUFDNUU7QUFDQSxPQUFLLElBQUksQ0FBQ2lELEtBQUQsRUFBUUMsUUFBUixDQUFULElBQThCbkQsVUFBOUIsRUFBMEM7QUFDekMsUUFBSW1ELFFBQVEsQ0FBQ1osR0FBVCxDQUFhQyxxQkFBYixDQUFKLEVBQXVCO0FBQ3RCLFVBQUlSLFNBQVMsR0FBRy9CLFdBQVcsQ0FBQzhCLEdBQVosQ0FBZ0JtQixLQUFoQixDQUFoQjs7QUFDQSxXQUFLLElBQUlFLENBQVQsSUFBY0QsUUFBUSxDQUFDVCxJQUFULEVBQWQsRUFBK0I7QUFDOUIsWUFBSVYsU0FBUyxDQUFDTyxHQUFWLENBQWNhLENBQWQsQ0FBSixFQUNDLE1BQU0sSUFBSUMsS0FBSixDQUFXLHVFQUFzRUgsS0FBTSxvQkFBbUJBLEtBQU0sUUFBT0UsQ0FBRSxFQUF6SCxDQUFOO0FBQ0Q7QUFDRDtBQUNEO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuTm9ucmVjdXJzaXZlIExMIFByZWRpY3RpdmUgUGFyc2luZ1xuKi9cbmltcG9ydCB7IEVPRiwgTklMLCBBU1RyZWUsIEFTVEVsZW1lbnQsSUxleGVyIH0gZnJvbSBcIkBsaWdodDB4MDAvcGFyc2VyLWRlZmluaXRpb25cIjtcbmltcG9ydCB7IFRlcm1pbmFsLCBOb25UZXJtaW5hbCwgUHJvZHVjdGlvbiwgU3ltYm9sLCBJR3JhbW1hciwgSVBhcnNlciwgQWN0aW9uR3JhbW1hciB9IGZyb20gXCIuLi9EZWZpbml0aW9uXCI7XG5pbXBvcnQgeyAgU3RhY2sgfSBmcm9tIFwiQGxpZ2h0MHgwMC9zaGltXCI7XG5pbXBvcnQgcm9vdERlYnVnIGZyb20gXCJkZWJ1Z1wiO1xuaW1wb3J0IHsgRmlyc3RUYWJsZSwgRmlyc3RTZXRDYWxjdWxhdG9yIH0gZnJvbSBcIi4uL0ZpcnN0XCI7XG5pbXBvcnQgeyBGb2xsb3dTZXRUYWJsZSwgRm9sbG93U2V0Q2FsY3VsYXRvciB9IGZyb20gXCIuLi9Gb2xsb3dcIjtcbmltcG9ydCB7IE1pc21hdGNoRXJyb3IgfSBmcm9tIFwiLi4vVG9vbGtpdFwiO1xubGV0IGRlYnVnID0gcm9vdERlYnVnKFwiQVBQOkxMUGFyc2VyXCIpO1xuXG50eXBlIEFTVEFjY3VtdWxhdGlvbkVudHJ5ID0geyBhc3ROb2RlOiBBU1RyZWUsIGFjY051bTogbnVtYmVyIH1cblxuZXhwb3J0IGNsYXNzIExMUGFyc2VyIGltcGxlbWVudHMgSVBhcnNlciB7XG5cblx0c3RhcnROVDogTm9uVGVybWluYWxcblx0Zmlyc3RUYWJsZTogTWFwPHN0cmluZywgTWFwPFRlcm1pbmFsLCBQcm9kdWN0aW9uPj5cblx0Zm9sbG93VGFibGU6IE1hcDxzdHJpbmcsIFNldDxUZXJtaW5hbD4+XG5cblxuXHRjb25zdHJ1Y3RvcihncmFtbWFyOiBJR3JhbW1hciwgZmlyc3RUYWJsZTogRmlyc3RUYWJsZSwgZm9sbG93VGFibGU6IEZvbGxvd1NldFRhYmxlKSB7XG5cdFx0dGhpcy5zdGFydE5UID0gZ3JhbW1hci5zdGFydE5UKCk7XG5cdFx0dGhpcy5maXJzdFRhYmxlID0gZmlyc3RUYWJsZTtcblx0XHR0aGlzLmZvbGxvd1RhYmxlID0gZm9sbG93VGFibGU7XG5cblx0XHRjaGVja0FtYmlndWl0eShmaXJzdFRhYmxlLCBmb2xsb3dUYWJsZSk7XG5cdH1cblxuXHRhY2N1bXVsYXRlKGFjY1N0YWNrOiBTdGFjazxBU1RBY2N1bXVsYXRpb25FbnRyeT4sIGVsZT86IEFTVEVsZW1lbnQpIHtcblx0XHRpZiAoYWNjU3RhY2suc2l6ZSgpID4gMCkge1xuXHRcdFx0bGV0IHBhcmVudEVudHJ5ID0gYWNjU3RhY2sucGVlaygpO1xuXHRcdFx0aWYgKGVsZSAhPSBudWxsKVxuXHRcdFx0XHRwYXJlbnRFbnRyeS5hc3ROb2RlLmFwcGVuZEVsZW1lbnQoZWxlKTtcblx0XHRcdC0tcGFyZW50RW50cnkuYWNjTnVtO1xuXHRcdFx0aWYgKHBhcmVudEVudHJ5LmFjY051bSA9PSAwKSB7XG5cdFx0XHRcdGFjY1N0YWNrLnBvcCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHBhcnNlKGxleGVyOiBJTGV4ZXIpOiBBU1RyZWUge1xuXHRcdGxldCBzeW1TdGFjayA9IG5ldyBTdGFjazxTeW1ib2w+KCk7XG5cdFx0c3ltU3RhY2sucHVzaChFT0YpO1xuXHRcdHN5bVN0YWNrLnB1c2godGhpcy5zdGFydE5UKTtcblxuXHRcdGxldCByb290QVNUO1xuXHRcdGxldCBhc3RBY2NTdGFjayA9IG5ldyBTdGFjazxBU1RBY2N1bXVsYXRpb25FbnRyeT4oKTtcblxuXHRcdGxldCBsb29rYWhlYWQgPSBsZXhlci5uZXh0VG9rZW4oKTtcblx0XHR3aGlsZSAoc3ltU3RhY2suc2l6ZSgpID4gMCkge1xuXHRcdFx0Ly8gZGVidWcoc3ltU3RhY2suam9pbihcIiBcIikpO1xuXHRcdFx0bGV0IHN5bWJvbCA9IHN5bVN0YWNrLnBvcCgpITtcblx0XHRcdGxldCBsb29rYWhlYWRLZXkgPSBsb29rYWhlYWQudGFibGVLZXkoKTtcblx0XHRcdC8v6Z2e57uI57uT56ymXG5cdFx0XHRpZiAoc3ltYm9sIGluc3RhbmNlb2YgTm9uVGVybWluYWwpIHtcblx0XHRcdFx0bGV0IG50X2tleSA9IHN5bWJvbC5uYW1lO1xuXHRcdFx0XHRsZXQgZmlyc3RTZXQgPSB0aGlzLmZpcnN0VGFibGUuZ2V0KG50X2tleSkhO1xuXHRcdFx0XHRsZXQgZm9sbG93U2V0ID0gdGhpcy5mb2xsb3dUYWJsZS5nZXQobnRfa2V5KSE7XG5cblx0XHRcdFx0bGV0IGNhbmRpZGF0ZV9wcm9kID0gZmlyc3RTZXQuZ2V0KGxvb2thaGVhZEtleSk7XG5cdFx0XHRcdC8v5aaC5p6c5b2T5YmN6Z2e57uI57uT56ym5a2Y5ZyoIOWvuWxvb2thaGVhZOeahOmdns615o6o5a+8XG5cdFx0XHRcdGlmIChjYW5kaWRhdGVfcHJvZCAhPSBudWxsKSB7XG5cdFx0XHRcdFx0Ly/lsIblgJnpgInlvI/nrKblj7flgJLluo/ljovlhaXmoIhcblx0XHRcdFx0XHRmb3IgKGxldCBpID0gY2FuZGlkYXRlX3Byb2QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pXG5cdFx0XHRcdFx0XHRzeW1TdGFjay5wdXNoKGNhbmRpZGF0ZV9wcm9kW2ldKTtcblxuXHRcdFx0XHRcdC8qIOWIhuaekOagkSAqL1xuXHRcdFx0XHRcdGxldCBhc3QgPSBjYW5kaWRhdGVfcHJvZC5tYWtlQVNUKCk7XG5cblx0XHRcdFx0XHRpZiAocm9vdEFTVCA9PSB1bmRlZmluZWQgJiYgc3ltYm9sID09IHRoaXMuc3RhcnROVClcblx0XHRcdFx0XHRcdHJvb3RBU1QgPSBhc3Q7XG5cblx0XHRcdFx0XHR0aGlzLmFjY3VtdWxhdGUoYXN0QWNjU3RhY2ssIGFzdCk7XG5cdFx0XHRcdFx0YXN0QWNjU3RhY2sucHVzaCh7IGFzdE5vZGU6IGFzdCwgYWNjTnVtOiBjYW5kaWRhdGVfcHJvZC5sZW5ndGggfSk7XG5cblx0XHRcdFx0fVxuXHRcdFx0XHQvL+WQpuWImVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHQvL+ajgOafpeW9k+WJjemdnue7iOe7k+espuaYr+WQpuWPr+aOqOWHus61LCDlubbkuJRsb29rYWhlYWTlrZjlnKjkuo5mb2xsb3dTZXRcblx0XHRcdFx0XHRpZiAoZmlyc3RTZXQuaGFzKE5JTCkgJiYgZm9sbG93U2V0Lmhhcyhsb29rYWhlYWRLZXkpKSB7XG5cdFx0XHRcdFx0XHQvL29rXG5cblx0XHRcdFx0XHRcdC8qIOWIhuaekOagkSAqL1xuXHRcdFx0XHRcdFx0dGhpcy5hY2N1bXVsYXRlKGFzdEFjY1N0YWNrKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IE1pc21hdGNoRXJyb3IoZmlyc3RTZXQua2V5cygpLCBsb29rYWhlYWQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly/nu4jnu5PnrKZcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRpZiAobG9va2FoZWFkS2V5ICE9IHN5bWJvbClcblx0XHRcdFx0XHR0aHJvdyBuZXcgTWlzbWF0Y2hFcnJvcihzeW1ib2wsIGxvb2thaGVhZCk7XG5cdFx0XHRcdGRlYnVnKGBtYXRjaGVkICR7bG9va2FoZWFkfWApO1xuXG5cdFx0XHRcdC8qIOWIhuaekOagkSAqL1xuXHRcdFx0XHRpZiAobG9va2FoZWFkICE9IEVPRilcblx0XHRcdFx0XHR0aGlzLmFjY3VtdWxhdGUoYXN0QWNjU3RhY2ssIGxvb2thaGVhZCk7XG5cblx0XHRcdFx0bG9va2FoZWFkID0gbGV4ZXIubmV4dFRva2VuKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGRlYnVnKFwic3VjY2VzcyFcIik7XG5cdFx0cmV0dXJuIHJvb3RBU1QgYXMgQVNUcmVlO1xuXHR9XG5cbn1cblxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRMTFBhcnNlcihncmFtbWFyOiBBY3Rpb25HcmFtbWFyKSB7XG5cdGxldCBmaXJzdFNldENhbGN1bGF0b3IgPSBuZXcgRmlyc3RTZXRDYWxjdWxhdG9yKGdyYW1tYXIpO1xuXHRsZXQgZm9sbG93ID0gbmV3IEZvbGxvd1NldENhbGN1bGF0b3IoZ3JhbW1hciwgZmlyc3RTZXRDYWxjdWxhdG9yKTtcblx0cmV0dXJuIG5ldyBMTFBhcnNlcihncmFtbWFyLCBmaXJzdFNldENhbGN1bGF0b3IuZ2V0Rmlyc3RUYWJsZSgpLCBmb2xsb3cuZ2V0Rm9sbG93VGFibGUoKSk7XG59XG5cbi8qXG5cbjEuIOS6jOS5ieaAp1xu5aaC5p6c5LiA5Liq6Z2e57uI57uT56ymQeWPr+S7peaOqOWHus61LOmCo+S5iOW/hemhu+a7oei2syBGaXJzdChBKSDiiKkgRm9sbG93KEEpPeKIhSwg5ZCm5YiZ5bCx5a2Y5Zyo5LqM5LmJ5oCnXG5cblMtPkFhXG5BLT5hfM61XG5cbkZpcnN0KEEpPXthLM61fVxuRm9sbG93KEEpPXthfVxuXG7pooTmtYvooag6XG4rLS0tLS0tKy0tLS0tLS0tLS0tLS0tK1xufCAgICAgIHwgYSAgICAgICAgICAgIHxcbistLS0tLS0rLS0tLS0tLS0tLS0tLS0rXG58QSAgICAgfCBBLT5hLEEtPs61ICAgIHxcbistLS0tLS0rLS0tLS0tLS0tLS0tLS0rXG5cbuWcqOi+k+WFpeS4suS4uuOAjGHjgI3ml7Ys5YiG5Yir6YCJ5oupQS0+YSxBLT7OtSzliY3ogIXlsIbljLnphY3lpLHotKUs6ICM5ZCO6ICF5Yy56YWN5oiQ5YqfLiDml6Dms5Xnoa7lrprkuIDkuKrllK/kuIDnmoTpgInmi6kuXG4qL1xuZnVuY3Rpb24gY2hlY2tBbWJpZ3VpdHkoZmlyc3RUYWJsZTogRmlyc3RUYWJsZSwgZm9sbG93VGFibGU6IEZvbGxvd1NldFRhYmxlKSB7XG5cdC8qIGlzc3VlOiAxLiDkuozkuYnmgKcgKi9cblx0Zm9yIChsZXQgW3BuYW1lLCBmaXJzdE1hcF0gb2YgZmlyc3RUYWJsZSkge1xuXHRcdGlmIChmaXJzdE1hcC5oYXMoTklMKSkge1xuXHRcdFx0bGV0IGZvbGxvd1NldCA9IGZvbGxvd1RhYmxlLmdldChwbmFtZSkhO1xuXHRcdFx0Zm9yIChsZXQgdiBvZiBmaXJzdE1hcC5rZXlzKCkpIHtcblx0XHRcdFx0aWYgKGZvbGxvd1NldC5oYXModikpXG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGb3VuZCBhbWJpZ3VpdHkgaW4gZ3JhbW1hci4gVGhlcmUgaXMgY29uZmxpY3QgYmV0d2VlbiB0aGUgRmlyc3Qtc2V0KCR7cG5hbWV9KSBhbmQgRm9sbG93LVNldCgke3BuYW1lfSkgb24gJHt2fWApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSJdfQ==