UNPKG

@light0x00/parser-generator

Version:

A Parser Generator

351 lines (273 loc) 34.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStateSet_LR = getStateSet_LR; exports.LRAutomataTools = void 0; var _parserDefinition = require("@light0x00/parser-definition"); var _Definition = require("../../Definition"); var _Definition2 = require("../Definition"); var _shim = require("@light0x00/shim"); var _StateAutomata = require("../StateAutomata"); var _debug = _interopRequireDefault(require("debug")); 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:LR1:automata"); /* 1.何时应该展开 对于何时应该展开 需要考虑如下几种场景 1.1 「点」已经到了产生式的最末尾,形如A-> X· 1.2 展开符不是终结符 没有闭包,形如 A-> ·a 1.3 由别的项展开自己 S->A A->B | B𝜶 B->b I0 S->·A A->·B A->·B𝜶 B->·b $ B->·b 𝜶 如上状态集中,B被A的两个项分别引用, 由A->·B 可展开得到 B->·b $ 由A->·B𝜶 可展开得到 B->·b 𝜶 此种情况允许同一符号被多次展开✅ 1.4 自己展开自己 S->A A->AAb | a I0 S->·A A->·AAb A->·a 在项 A->·AAb 中,由于为左递归产生式,且「点」位于「左递归符号」前,因此不能再展开A.❌ I1 S->A· A->A·Ab 在项A->A·Ab中,虽然左递归,但「点」在左递归符号之后,因此可以展开A. I1继续加入如下项:✅ A->·AAb A->·a 此时,在项A->·AAb中,「点」位于左递归符号之前,因此不能再展开A❌ 结论 0. 存在展开符号,且展开符号为非终结符 1. 一个符号被不同的多个个项引用,可以重复展开多次 2. 左递归 且 展开符为最左符号 不得展开 , 形如 A->·AA𝜶 3. 左递归 但 展开符不是最左符号,可以展开,形如 A->A·A𝜶 2.如何展开(LR展望符集计算) 名词约定: - 展望符集,LR中每个项都有自己的展望符集,一个项的展望符集决定何时可以归约(后称lookaheadSet,有时简称lookSet) - 展开符号,例如项S->·E是可展开的,展开符号为E - Look(A->·𝜶) 表示项A->·𝜶的展望符集 对展望符的计算可分为3种情况 例: S->E E->E+F | E*F | F F->id I0 S->·E $ E->·E+F $ E->·E*F $ E->·F +,*,$ F->·id +,*,$ 2.1. 针对闭包项 2.1.1 展开符包含左递归产生式,初始状态I0中项S->·E产生如下3个闭包项: E->·E+F $,+,* E->·E*F $,+,* E->·F $,+,* 它们的lookSet计算方式如下 E->·E+F、E->·E*F、E->·F 均为左递归产生式,它们可能处于末端,也可能被嵌入另一个左递归产生式 例1 对于项E->·E+F而言 - 如果它处于末端,那么 lookSet(E·E+F)就应该有`$` (继承自 lookSet(S->·E)) - 如果它被嵌入E->·E*F,那么 lookSet(E->·E+F)就应该有`*` - 如果它被嵌入E->·E+F,那么 lookSet(E->·E+F)就应该有`+` - 要注意,它不可能被嵌入E->·F,所以 lookSet(E->·E+F)不包含`id` 例2 对于E->·F而言,虽然其本身没有左递归,但是由于它的兄弟项中存在左递归项,因此它仍然可能被嵌入其左递归的兄弟项 - 如果E->·F 直接作为S->·E的右侧,那么LookSet(E->·F)应包含`$` (继承自 lookSet(S->·E)) - 如果E->·F被嵌入E->·E+F,那么LookSet(E->·F)应包含`+` - 如果E->·F被嵌入E->·E*F,那么LookSet(E->·F)应包含`*` 更一般的讲,一个左递归项的LookSet应该包含它的「左递归兄弟项及其本身」的「最左非左递归符号」,以及继承的LookSet 在本例中,E->·E+F的「左递归兄弟项」是 E->·E*F,这个兄弟项的「最左非左递归符号」是`*`, 且E->·E+F继承了`$`. 2.1.2 展开符不包含左递归的产生式,由上一个项确定 的lookSet. - 如果项形如A->𝜶·B,由展开符B得到的项应为lookSet(A) - 如果项形如A->·B𝜶𝜷 - 若𝝴∉First(𝜶) 由展开符B得到的项的lookSet为First(𝜶) - 否则,应当继续加入First(B),重复以上过程,直到末尾时,如果仍包含𝝴,则加入lookSet(A) 此例中,E->·F, 由于展开符是最末符号,因此展开的项F->·id可继承lookSet(A) 2.2 针对前进项 如果只是单纯的项的「点」前进,那么可以直接继承. 例如,项E->·E+F 前进后得到项E->E·+F, 后者的lookSet应该继承前者. 3. 展开后的处理 3.1 如果项集中存在产生式相同,且「点」的位置相同的项, 应将它们合并. 例 A->·𝜶 $ A->·𝜶 𝜶 合并后: A->·𝜶 $,𝜶 */ /* 构造自动机所需要的方法 */ class LRAutomataTools { constructor(firstSetCalculator) { _defineProperty(this, "getFirstSet", void 0); this.getFirstSet = firstSetCalculator; } GOTO(I, inputSymbol) { let nextItemSet = new _Definition2.ItemSet(); for (let item of I) { if (!item.hasNext()) continue; if (item.nextSymbol() == inputSymbol) { nextItemSet.push(item.nextItem()); } } return this.closure(nextItemSet); } closure(itemSet) { let itemSetClosure = itemSet; //项集的每一个项 item for (let processedIdx = 0; processedIdx < itemSetClosure.length; processedIdx++) { let item = itemSetClosure[processedIdx]; if (!item.hasNext()) //issue 1.1 continue; let expandSym = item.nextSymbol(); if (!(expandSym instanceof _Definition.NonTerminal)) //issue 1.2 continue; if (item.prod[0] == item.prod.nonTerminal && item.dotPos == 0) { //issue 1.4 debug(`Stop expanding left recursion production ${expandSym}`); continue; } let lrps = this.getLeftRecursiveProds(expandSym); //issue 2.1.1.1 左递归产生式 let nlrlookSet = this.determineNonLeftRecursionLookSet(item); //issue 2.1.1 展开符包含左递归产生式的情况 if (lrps.length > 0) { let lrLookSet = this.determineLeftRecursionLookSet(item); //由所有左递归项带来的展望符集 for (let lrp of expandSym) { let unionLookSet = new Set(); (0, _shim.addAll_Set)(unionLookSet, lrLookSet); (0, _shim.addAll_Set)(unionLookSet, nlrlookSet); itemSetClosure.pushOrMerge(new _Definition2.Item(lrp, 0, unionLookSet)); } } //issue 2.1.2 展开符不包含递归产生式的情况 else { for (let prod of expandSym.prods) { let newItem = new _Definition2.Item(prod, 0, nlrlookSet); itemSetClosure.pushOrMerge(newItem); } } } return itemSetClosure; } /** ========展开符包含左递归产生式的处理======== 文法: S->A A->A𝜶 | A𝜷 | 𝝲 状态: S->·A ,$ A->·A𝜶,$ A->·A𝜷,$ A->·𝝲, ? 如何求「 A->𝝲 」的展望集? 若𝜶,𝜷不能推出𝝴,则 lookSet(A->·𝝲) = {𝜶,𝜷} 否则 lookSet(A->·𝝲) ={𝜶,𝜷,$} 形式化: 加入在A中的每一个左递归产生式中的「第一非A的符号的First集」,记为First(!A), 如果该集内存在𝝴,则一路向后直到末尾,如果仍存在𝝴,则加入 Look(A) 伪代码: for each lr-prod in A for each sym in lr-prod if sym != A add First(sym) if 𝝴 ∉ First(sym) break else if sym is rightmost add lookSet(S) 注: Look(S) 表示S的lookeheadSet * @param curItem */ determineLeftRecursionLookSet(curItem) { let target = curItem.nextSymbol(); (0, _shim.assert)(target instanceof _Definition.NonTerminal); let lookaheadSet = new Set(); //目标的所有左递归产生式 let lrProds = this.getLeftRecursiveProds(target); //每一个左递归产生式 for (let lr_prod of lrProds) { //每一个符号 let searching = false; for (let j = 0; j < lr_prod.length; j++) { if (lr_prod[j] != target && !searching) { continue; } // right-most if (j == lr_prod.length - 1) { (0, _shim.addAll_Set)(lookaheadSet, curItem.lookaheadSet); } else { let follower = lr_prod[j + 1]; let follower_first_set = this.getFirstSet(follower); (0, _shim.addAll_Set)(lookaheadSet, follower_first_set); // 𝝴 ∉ First(follower) if (!follower_first_set.has(_parserDefinition.NIL)) { break; } // 𝝴 ∈ First(follower) scan next one else { lookaheadSet.delete(_parserDefinition.NIL); searching = true; } } } } return lookaheadSet; } /** ========展开符不包含左递归产生式的处理======== 约定 - 将闭包项记为 closureItem ,例如S->·As - 将展开项计为 expandItem , 例如由展开符A得到的项 A->·a 形式化计算规则如下: 展开符位于item末端,形如A->·B lookSet(expandItem)=lookSet(prevItem) next非末端,形如A->·B𝜶𝜷 lookSet(expandItem)=First(𝜶) , 如果𝜶可推出𝝴,则继续向后寻找𝜷,重复这个过程, 如果𝜷为最末尾符号,且𝜷仍可推出𝝴,那么将lookSet(prevItem)放入lookSet(next) * @param prevItem */ determineNonLeftRecursionLookSet(prevItem) { let expandSym = prevItem.nextSymbol(); (0, _shim.assert)(expandSym instanceof _Definition.NonTerminal); let lookaheadSet = new Set(); for (let i = prevItem.dotPos; i < prevItem.prod.length; i++) { if (i == prevItem.prod.length - 1) { (0, _shim.addAll_Set)(lookaheadSet, prevItem.lookaheadSet); break; } else { let firstSetOfFollow = this.getFirstSet(prevItem.prod[i + 1]); (0, _shim.addAll_Set)(lookaheadSet, firstSetOfFollow); if (firstSetOfFollow.has(_parserDefinition.NIL)) { lookaheadSet.delete(_parserDefinition.NIL); } else { break; } } } return lookaheadSet; } getLeftRecursiveProds(non_terminal) { let lr_prods = []; //每一个产生式 for (let prod of non_terminal.prods) { //产生式中的每一个符号 for (let symbol of prod) { //若相等,,则表示prod存在左递归 if (symbol == non_terminal) { lr_prods.push(prod); break; } //若不相等 且First(symbol)不存在𝝴则中断,则表示prod没有左递归 else if (!this.getFirstSet(symbol).has(_parserDefinition.NIL)) { break; } } } debug(lr_prods.join(",")); return lr_prods; } getStartState(grammar) { return new _Definition2.State(0, this.closure(new _Definition2.ItemSet(new _Definition2.Item(grammar.prodOfStartNT, 0, new Set([_parserDefinition.EOF]))))); } } exports.LRAutomataTools = LRAutomataTools; function getStateSet_LR(grammar, getFirstSet) { return (0, _StateAutomata.getStateSet)(grammar, new LRAutomataTools(getFirstSet)); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9MUi9MUjEvQXV0b21hdGEudHMiXSwibmFtZXMiOlsiZGVidWciLCJMUkF1dG9tYXRhVG9vbHMiLCJjb25zdHJ1Y3RvciIsImZpcnN0U2V0Q2FsY3VsYXRvciIsImdldEZpcnN0U2V0IiwiR09UTyIsIkkiLCJpbnB1dFN5bWJvbCIsIm5leHRJdGVtU2V0IiwiSXRlbVNldCIsIml0ZW0iLCJoYXNOZXh0IiwibmV4dFN5bWJvbCIsInB1c2giLCJuZXh0SXRlbSIsImNsb3N1cmUiLCJpdGVtU2V0IiwiaXRlbVNldENsb3N1cmUiLCJwcm9jZXNzZWRJZHgiLCJsZW5ndGgiLCJleHBhbmRTeW0iLCJOb25UZXJtaW5hbCIsInByb2QiLCJub25UZXJtaW5hbCIsImRvdFBvcyIsImxycHMiLCJnZXRMZWZ0UmVjdXJzaXZlUHJvZHMiLCJubHJsb29rU2V0IiwiZGV0ZXJtaW5lTm9uTGVmdFJlY3Vyc2lvbkxvb2tTZXQiLCJsckxvb2tTZXQiLCJkZXRlcm1pbmVMZWZ0UmVjdXJzaW9uTG9va1NldCIsImxycCIsInVuaW9uTG9va1NldCIsIlNldCIsInB1c2hPck1lcmdlIiwiSXRlbSIsInByb2RzIiwibmV3SXRlbSIsImN1ckl0ZW0iLCJ0YXJnZXQiLCJsb29rYWhlYWRTZXQiLCJsclByb2RzIiwibHJfcHJvZCIsInNlYXJjaGluZyIsImoiLCJmb2xsb3dlciIsImZvbGxvd2VyX2ZpcnN0X3NldCIsImhhcyIsIk5pbCIsImRlbGV0ZSIsInByZXZJdGVtIiwiaSIsImZpcnN0U2V0T2ZGb2xsb3ciLCJub25fdGVybWluYWwiLCJscl9wcm9kcyIsInN5bWJvbCIsImpvaW4iLCJnZXRTdGFydFN0YXRlIiwiZ3JhbW1hciIsIlN0YXRlIiwicHJvZE9mU3RhcnROVCIsIkVPRiIsImdldFN0YXRlU2V0X0xSIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBOzs7Ozs7QUFDQSxJQUFJQSxLQUFLLEdBQUcsb0JBQVUsa0JBQVYsQ0FBWjtBQUVBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNEhBO0FBQ08sTUFBTUMsZUFBTixDQUErQztBQUVyREMsRUFBQUEsV0FBVyxDQUFDQyxrQkFBRCxFQUFxQztBQUFBOztBQUMvQyxTQUFLQyxXQUFMLEdBQW1CRCxrQkFBbkI7QUFDQTs7QUFFREUsRUFBQUEsSUFBSSxDQUFDQyxDQUFELEVBQWFDLFdBQWIsRUFBMkM7QUFDOUMsUUFBSUMsV0FBVyxHQUFHLElBQUlDLG9CQUFKLEVBQWxCOztBQUNBLFNBQUssSUFBSUMsSUFBVCxJQUFpQkosQ0FBakIsRUFBb0I7QUFDbkIsVUFBSSxDQUFDSSxJQUFJLENBQUNDLE9BQUwsRUFBTCxFQUNDOztBQUNELFVBQUlELElBQUksQ0FBQ0UsVUFBTCxNQUFxQkwsV0FBekIsRUFBc0M7QUFDckNDLFFBQUFBLFdBQVcsQ0FBQ0ssSUFBWixDQUFpQkgsSUFBSSxDQUFDSSxRQUFMLEVBQWpCO0FBQ0E7QUFDRDs7QUFDRCxXQUFPLEtBQUtDLE9BQUwsQ0FBYVAsV0FBYixDQUFQO0FBQ0E7O0FBRURPLEVBQUFBLE9BQU8sQ0FBQ0MsT0FBRCxFQUE0QjtBQUNsQyxRQUFJQyxjQUF1QixHQUFHRCxPQUE5QixDQURrQyxDQUVsQzs7QUFDQSxTQUFLLElBQUlFLFlBQVksR0FBRyxDQUF4QixFQUEyQkEsWUFBWSxHQUFHRCxjQUFjLENBQUNFLE1BQXpELEVBQWlFRCxZQUFZLEVBQTdFLEVBQWlGO0FBQ2hGLFVBQUlSLElBQUksR0FBR08sY0FBYyxDQUFDQyxZQUFELENBQXpCO0FBQ0EsVUFBSSxDQUFDUixJQUFJLENBQUNDLE9BQUwsRUFBTCxFQUFxQjtBQUNwQjtBQUNELFVBQUlTLFNBQVMsR0FBR1YsSUFBSSxDQUFDRSxVQUFMLEVBQWhCO0FBQ0EsVUFBSSxFQUFFUSxTQUFTLFlBQVlDLHVCQUF2QixDQUFKLEVBQXlDO0FBQ3hDOztBQUNELFVBQUlYLElBQUksQ0FBQ1ksSUFBTCxDQUFVLENBQVYsS0FBZ0JaLElBQUksQ0FBQ1ksSUFBTCxDQUFVQyxXQUExQixJQUF5Q2IsSUFBSSxDQUFDYyxNQUFMLElBQWUsQ0FBNUQsRUFBK0Q7QUFBRTtBQUNoRXhCLFFBQUFBLEtBQUssQ0FBRSw0Q0FBMkNvQixTQUFVLEVBQXZELENBQUw7QUFDQTtBQUNBOztBQUNELFVBQUlLLElBQUksR0FBRyxLQUFLQyxxQkFBTCxDQUEyQk4sU0FBM0IsQ0FBWCxDQVhnRixDQVc5Qjs7QUFDbEQsVUFBSU8sVUFBVSxHQUFHLEtBQUtDLGdDQUFMLENBQXNDbEIsSUFBdEMsQ0FBakIsQ0FaZ0YsQ0FhaEY7O0FBQ0EsVUFBSWUsSUFBSSxDQUFDTixNQUFMLEdBQWMsQ0FBbEIsRUFBcUI7QUFDcEIsWUFBSVUsU0FBUyxHQUFHLEtBQUtDLDZCQUFMLENBQW1DcEIsSUFBbkMsQ0FBaEIsQ0FEb0IsQ0FDc0M7O0FBQzFELGFBQUssSUFBSXFCLEdBQVQsSUFBZ0JYLFNBQWhCLEVBQTJCO0FBQzFCLGNBQUlZLFlBQVksR0FBRyxJQUFJQyxHQUFKLEVBQW5CO0FBQ0EsZ0NBQVdELFlBQVgsRUFBeUJILFNBQXpCO0FBQ0EsZ0NBQVdHLFlBQVgsRUFBeUJMLFVBQXpCO0FBQ0FWLFVBQUFBLGNBQWMsQ0FBQ2lCLFdBQWYsQ0FBMkIsSUFBSUMsaUJBQUosQ0FBU0osR0FBVCxFQUFjLENBQWQsRUFBaUJDLFlBQWpCLENBQTNCO0FBQ0E7QUFDRCxPQVJELENBU0E7QUFUQSxXQVVLO0FBQ0osZUFBSyxJQUFJVixJQUFULElBQWlCRixTQUFTLENBQUNnQixLQUEzQixFQUFrQztBQUNqQyxnQkFBSUMsT0FBTyxHQUFHLElBQUlGLGlCQUFKLENBQVNiLElBQVQsRUFBZSxDQUFmLEVBQWtCSyxVQUFsQixDQUFkO0FBQ0FWLFlBQUFBLGNBQWMsQ0FBQ2lCLFdBQWYsQ0FBMkJHLE9BQTNCO0FBQ0E7QUFDRDtBQUNEOztBQUNELFdBQU9wQixjQUFQO0FBQ0E7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFrQ0FhLEVBQUFBLDZCQUE2QixDQUFDUSxPQUFELEVBQStCO0FBQzNELFFBQUlDLE1BQU0sR0FBR0QsT0FBTyxDQUFDMUIsVUFBUixFQUFiO0FBQ0Esc0JBQU8yQixNQUFNLFlBQVlsQix1QkFBekI7QUFFQSxRQUFJbUIsWUFBWSxHQUFHLElBQUlQLEdBQUosRUFBbkIsQ0FKMkQsQ0FLM0Q7O0FBQ0EsUUFBSVEsT0FBTyxHQUFHLEtBQUtmLHFCQUFMLENBQTJCYSxNQUEzQixDQUFkLENBTjJELENBTzNEOztBQUNBLFNBQUssSUFBSUcsT0FBVCxJQUFvQkQsT0FBcEIsRUFBNkI7QUFDNUI7QUFDQSxVQUFJRSxTQUFTLEdBQUcsS0FBaEI7O0FBQ0EsV0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHRixPQUFPLENBQUN2QixNQUE1QixFQUFvQ3lCLENBQUMsRUFBckMsRUFBeUM7QUFDeEMsWUFBSUYsT0FBTyxDQUFDRSxDQUFELENBQVAsSUFBY0wsTUFBZCxJQUF3QixDQUFDSSxTQUE3QixFQUF3QztBQUN2QztBQUNBLFNBSHVDLENBSXhDOzs7QUFDQSxZQUFJQyxDQUFDLElBQUlGLE9BQU8sQ0FBQ3ZCLE1BQVIsR0FBaUIsQ0FBMUIsRUFBNkI7QUFDNUIsZ0NBQVdxQixZQUFYLEVBQXlCRixPQUFPLENBQUNFLFlBQWpDO0FBQ0EsU0FGRCxNQUVPO0FBQ04sY0FBSUssUUFBUSxHQUFHSCxPQUFPLENBQUNFLENBQUMsR0FBRyxDQUFMLENBQXRCO0FBQ0EsY0FBSUUsa0JBQWtCLEdBQUcsS0FBSzFDLFdBQUwsQ0FBaUJ5QyxRQUFqQixDQUF6QjtBQUNBLGdDQUFXTCxZQUFYLEVBQXlCTSxrQkFBekIsRUFITSxDQUlOOztBQUNBLGNBQUksQ0FBQ0Esa0JBQWtCLENBQUNDLEdBQW5CLENBQXVCQyxxQkFBdkIsQ0FBTCxFQUFrQztBQUNqQztBQUNBLFdBRkQsQ0FHQTtBQUhBLGVBSUs7QUFDSlIsY0FBQUEsWUFBWSxDQUFDUyxNQUFiLENBQW9CRCxxQkFBcEI7QUFDQUwsY0FBQUEsU0FBUyxHQUFHLElBQVo7QUFDQTtBQUNEO0FBQ0Q7QUFDRDs7QUFDRCxXQUFPSCxZQUFQO0FBQ0E7QUFDRDs7Ozs7Ozs7Ozs7Ozs7OztBQWdCQVosRUFBQUEsZ0NBQWdDLENBQUNzQixRQUFELEVBQWdDO0FBQy9ELFFBQUk5QixTQUFTLEdBQUc4QixRQUFRLENBQUN0QyxVQUFULEVBQWhCO0FBQ0Esc0JBQU9RLFNBQVMsWUFBWUMsdUJBQTVCO0FBRUEsUUFBSW1CLFlBQVksR0FBRyxJQUFJUCxHQUFKLEVBQW5COztBQUVBLFNBQUssSUFBSWtCLENBQUMsR0FBR0QsUUFBUSxDQUFDMUIsTUFBdEIsRUFBOEIyQixDQUFDLEdBQUdELFFBQVEsQ0FBQzVCLElBQVQsQ0FBY0gsTUFBaEQsRUFBd0RnQyxDQUFDLEVBQXpELEVBQTZEO0FBQzVELFVBQUlBLENBQUMsSUFBSUQsUUFBUSxDQUFDNUIsSUFBVCxDQUFjSCxNQUFkLEdBQXVCLENBQWhDLEVBQW1DO0FBQ2xDLDhCQUFXcUIsWUFBWCxFQUF5QlUsUUFBUSxDQUFDVixZQUFsQztBQUNBO0FBQ0EsT0FIRCxNQUdPO0FBQ04sWUFBSVksZ0JBQWdCLEdBQUcsS0FBS2hELFdBQUwsQ0FBaUI4QyxRQUFRLENBQUM1QixJQUFULENBQWM2QixDQUFDLEdBQUcsQ0FBbEIsQ0FBakIsQ0FBdkI7QUFDQSw4QkFBV1gsWUFBWCxFQUF5QlksZ0JBQXpCOztBQUNBLFlBQUlBLGdCQUFnQixDQUFDTCxHQUFqQixDQUFxQkMscUJBQXJCLENBQUosRUFBK0I7QUFDOUJSLFVBQUFBLFlBQVksQ0FBQ1MsTUFBYixDQUFvQkQscUJBQXBCO0FBQ0EsU0FGRCxNQUVPO0FBQ047QUFDQTtBQUNEO0FBQ0Q7O0FBQ0QsV0FBT1IsWUFBUDtBQUNBOztBQUNEZCxFQUFBQSxxQkFBcUIsQ0FBQzJCLFlBQUQsRUFBNEI7QUFDaEQsUUFBSUMsUUFBc0IsR0FBRyxFQUE3QixDQURnRCxDQUVoRDs7QUFDQSxTQUFLLElBQUloQyxJQUFULElBQWlCK0IsWUFBWSxDQUFDakIsS0FBOUIsRUFBcUM7QUFDcEM7QUFDQSxXQUFLLElBQUltQixNQUFULElBQW1CakMsSUFBbkIsRUFBeUI7QUFDeEI7QUFDQSxZQUFJaUMsTUFBTSxJQUFJRixZQUFkLEVBQTRCO0FBQzNCQyxVQUFBQSxRQUFRLENBQUN6QyxJQUFULENBQWNTLElBQWQ7QUFDQTtBQUNBLFNBSEQsQ0FJQTtBQUpBLGFBS0ssSUFBSSxDQUFDLEtBQUtsQixXQUFMLENBQWlCbUQsTUFBakIsRUFBeUJSLEdBQXpCLENBQTZCQyxxQkFBN0IsQ0FBTCxFQUF3QztBQUM1QztBQUNBO0FBQ0Q7QUFDRDs7QUFDRGhELElBQUFBLEtBQUssQ0FBQ3NELFFBQVEsQ0FBQ0UsSUFBVCxDQUFjLEdBQWQsQ0FBRCxDQUFMO0FBQ0EsV0FBT0YsUUFBUDtBQUNBOztBQUNERyxFQUFBQSxhQUFhLENBQUNDLE9BQUQsRUFBNEI7QUFDeEMsV0FBTyxJQUFJQyxrQkFBSixDQUFVLENBQVYsRUFBYSxLQUFLNUMsT0FBTCxDQUFhLElBQUlOLG9CQUFKLENBQVksSUFBSTBCLGlCQUFKLENBQVN1QixPQUFPLENBQUNFLGFBQWpCLEVBQWdDLENBQWhDLEVBQW1DLElBQUkzQixHQUFKLENBQWtCLENBQUM0QixxQkFBRCxDQUFsQixDQUFuQyxDQUFaLENBQWIsQ0FBYixDQUFQO0FBQ0E7O0FBekxvRDs7OztBQTZML0MsU0FBU0MsY0FBVCxDQUF3QkosT0FBeEIsRUFBbUR0RCxXQUFuRCxFQUFnRjtBQUN0RixTQUFPLGdDQUFZc0QsT0FBWixFQUFxQixJQUFJekQsZUFBSixDQUFvQkcsV0FBcEIsQ0FBckIsQ0FBUDtBQUNBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTklMIGFzIE5pbCwgRU9GIH0gZnJvbSBcIkBsaWdodDB4MDAvcGFyc2VyLWRlZmluaXRpb25cIjtcbmltcG9ydCB7IFByb2R1Y3Rpb24sIE5vblRlcm1pbmFsLCBTeW1ib2wsIFRlcm1pbmFsLCB9IGZyb20gXCIuLi8uLi9EZWZpbml0aW9uXCI7XG5pbXBvcnQgeyBJdGVtU2V0LCBTdGF0ZSwgSXRlbSwgQXVnbWVudGVkR3JhbW1hciwgQXV0b21hdGFUb29scyB9IGZyb20gXCIuLi9EZWZpbml0aW9uXCI7XG5pbXBvcnQgeyBhZGRBbGxfU2V0LCBJRnVuY3Rpb24gfSBmcm9tIFwiQGxpZ2h0MHgwMC9zaGltXCI7XG5pbXBvcnQgeyBnZXRTdGF0ZVNldCB9IGZyb20gXCIuLi9TdGF0ZUF1dG9tYXRhXCI7XG5pbXBvcnQgeyBhc3NlcnQgfSBmcm9tIFwiQGxpZ2h0MHgwMC9zaGltXCI7XG5cbmltcG9ydCByb290RGVidWcgZnJvbSBcImRlYnVnXCI7XG5sZXQgZGVidWcgPSByb290RGVidWcoXCJBUFA6TFIxOmF1dG9tYXRhXCIpO1xuXG4vKlxuXG4xLuS9leaXtuW6lOivpeWxleW8gFxuXG4gICAg5a+55LqO5L2V5pe25bqU6K+l5bGV5byAIOmcgOimgeiAg+iZkeWmguS4i+WHoOenjeWcuuaZr1xuXG4gICAgMS4xIOOAjOeCueOAjeW3sue7j+WIsOS6huS6p+eUn+W8j+eahOacgOacq+WwvizlvaLlpoJBLT4gWMK3XG5cbiAgICAxLjIg5bGV5byA56ym5LiN5piv57uI57uT56ymIOayoeaciemXreWMhSzlvaLlpoIgQS0+IMK3YVxuXG4gICAgMS4zIOeUseWIq+eahOmhueWxleW8gOiHquW3sVxuICAgIFMtPkFcbiAgICBBLT5CIHwgQvCdnLZcbiAgICBCLT5iXG5cbiAgICBJMFxuICAgIFMtPsK3QVxuICAgIEEtPsK3QlxuICAgIEEtPsK3QvCdnLZcbiAgICBCLT7Ct2IgICAkXG4gICAgQi0+wrdiICAg8J2ctlxuXG4gICAg5aaC5LiK54q25oCB6ZuG5LitLELooqtB55qE5Lik5Liq6aG55YiG5Yir5byV55SoLFxuICAgICAgICDnlLFBLT7Ct0Ig5Y+v5bGV5byA5b6X5YiwIEItPsK3YiAgICRcbiAgICAgICAg55SxQS0+wrdC8J2ctiAg5Y+v5bGV5byA5b6X5YiwIEItPsK3YiAgIPCdnLZcbiAgICDmraTnp43mg4XlhrXlhYHorrjlkIzkuIDnrKblj7fooqvlpJrmrKHlsZXlvIDinIVcblxuICAgIDEuNCDoh6rlt7HlsZXlvIDoh6rlt7FcblxuICAgIFMtPkFcbiAgICBBLT5BQWIgfCBhXG5cbiAgICBJMFxuICAgIFMtPsK3QVxuICAgIEEtPsK3QUFiXG4gICAgQS0+wrdhXG5cbiAgICDlnKjpobkgQS0+wrdBQWIg5LitLOeUseS6juS4uuW3pumAkuW9kuS6p+eUn+W8jyzkuJTjgIzngrnjgI3kvY3kuo7jgIzlt6bpgJLlvZLnrKblj7fjgI3liY0s5Zug5q2k5LiN6IO95YaN5bGV5byAQS7inYxcblxuICAgIEkxXG4gICAgUy0+QcK3XG4gICAgQS0+QcK3QWJcblxuICAgIOWcqOmhuUEtPkHCt0Fi5LitLOiZveeEtuW3pumAkuW9kizkvYbjgIzngrnjgI3lnKjlt6bpgJLlvZLnrKblj7fkuYvlkI4s5Zug5q2k5Y+v5Lul5bGV5byAQS4gSTHnu6fnu63liqDlhaXlpoLkuIvpobk64pyFXG5cbiAgICBBLT7Ct0FBYlxuICAgIEEtPsK3YVxuXG4gICAg5q2k5pe2LOWcqOmhuUEtPsK3QUFi5LitLOOAjOeCueOAjeS9jeS6juW3pumAkuW9kuespuWPt+S5i+WJjSzlm6DmraTkuI3og73lho3lsZXlvIBB4p2MXG5cblxuICAgIOe7k+iuulxuICAgICAgICAwLiDlrZjlnKjlsZXlvIDnrKblj7cs5LiU5bGV5byA56ym5Y+35Li66Z2e57uI57uT56ymXG4gICAgICAgIDEuIOS4gOS4quespuWPt+iiq+S4jeWQjOeahOWkmuS4quS4qumhueW8leeUqCzlj6/ku6Xph43lpI3lsZXlvIDlpJrmrKFcbiAgICAgICAgMi4g5bem6YCS5b2SIOS4lCDlsZXlvIDnrKbkuLrmnIDlt6bnrKblj7cg5LiN5b6X5bGV5byAICwg5b2i5aaCIEEtPsK3QUHwnZy2XG4gICAgICAgIDMuIOW3pumAkuW9kiDkvYYg5bGV5byA56ym5LiN5piv5pyA5bem56ym5Y+3LOWPr+S7peWxleW8gCzlvaLlpoIgQS0+QcK3QfCdnLZcblxuXG4yLuWmguS9leWxleW8gChMUuWxleacm+espumbhuiuoeeulylcblxuICAgIOWQjeivjee6puWumjpcbiAgICAtIOWxleacm+espumbhixMUuS4reavj+S4qumhuemDveacieiHquW3seeahOWxleacm+espumbhizkuIDkuKrpobnnmoTlsZXmnJvnrKbpm4blhrPlrprkvZXml7blj6/ku6XlvZLnuqYo5ZCO56ewbG9va2FoZWFkU2V0LOacieaXtueugOensGxvb2tTZXQpXG5cdC0g5bGV5byA56ym5Y+3LOS+i+WmgumhuVMtPsK3ReaYr+WPr+WxleW8gOeahCzlsZXlvIDnrKblj7fkuLpFXG5cdC0gTG9vayhBLT7Ct/CdnLYpIOihqOekuumhuUEtPsK38J2ctueahOWxleacm+espumbhlxuXG4gICAg5a+55bGV5pyb56ym55qE6K6h566X5Y+v5YiG5Li6M+enjeaDheWGtVxuXG4gICAg5L6LOlxuICAgIFMtPkVcbiAgICBFLT5FK0YgfCBFKkYgfCBGXG4gICAgRi0+aWRcblxuICAgIEkwXG4gICAgUy0+wrdFICAgICAgICRcbiAgICBFLT7Ct0UrRiAgICAgJFxuICAgIEUtPsK3RSpGICAgICAkXG4gICAgRS0+wrdGICAgICAgICssKiwkXG4gICAgRi0+wrdpZCAgICAgICssKiwkXG5cbiAgICAyLjEuIOmSiOWvuemXreWMhemhuVxuICAgICAgICAyLjEuMSDlsZXlvIDnrKbljIXlkKvlt6bpgJLlvZLkuqfnlJ/lvI8s5Yid5aeL54q25oCBSTDkuK3poblTLT7Ct0XkuqfnlJ/lpoLkuIsz5Liq6Zet5YyF6aG5OlxuICAgICAgICAgICAgRS0+wrdFK0YgICAgICQsKywqXG4gICAgICAgICAgICBFLT7Ct0UqRiAgICAgJCwrLCpcbiAgICAgICAgICAgIEUtPsK3RiAgICAgICAkLCssKlxuICAgICAgICAgICAg5a6D5Lus55qEbG9va1NldOiuoeeul+aWueW8j+WmguS4i1xuXHRcdFx0XHRFLT7Ct0UrRuOAgUUtPsK3RSpG44CBRS0+wrdGIOWdh+S4uuW3pumAkuW9kuS6p+eUn+W8jyzlroPku6zlj6/og73lpITkuo7mnKvnq68s5Lmf5Y+v6IO96KKr5bWM5YWl5Y+m5LiA5Liq5bem6YCS5b2S5Lqn55Sf5byPXG5cblx0XHRcdFx05L6LMSDlr7nkuo7poblFLT7Ct0UrRuiAjOiogFxuXHRcdFx0XHRcdC0g5aaC5p6c5a6D5aSE5LqO5pyr56uvLOmCo+S5iCBsb29rU2V0KEXCt0UrRinlsLHlupTor6XmnIlgJGAgKOe7p+aJv+iHqiBsb29rU2V0KFMtPsK3RSkpXG5cdFx0XHRcdFx0LSDlpoLmnpzlroPooqvltYzlhaVFLT7Ct0UqRizpgqPkuYggbG9va1NldChFLT7Ct0UrRinlsLHlupTor6XmnIlgKmBcblx0XHRcdFx0XHQtIOWmguaenOWug+iiq+W1jOWFpUUtPsK3RStGLOmCo+S5iCBsb29rU2V0KEUtPsK3RStGKeWwseW6lOivpeaciWArYFxuXHRcdFx0XHRcdC0g6KaB5rOo5oSPLOWug+S4jeWPr+iDveiiq+W1jOWFpUUtPsK3RizmiYDku6UgbG9va1NldChFLT7Ct0UrRinkuI3ljIXlkKtgaWRgXG5cblx0XHRcdFx05L6LMiDlr7nkuo5FLT7Ct0bogIzoqIAs6Jm954S25YW25pys6Lqr5rKh5pyJ5bem6YCS5b2SLOS9huaYr+eUseS6juWug+eahOWFhOW8n+mhueS4reWtmOWcqOW3pumAkuW9kumhuSzlm6DmraTlroPku43nhLblj6/og73ooqvltYzlhaXlhbblt6bpgJLlvZLnmoTlhYTlvJ/poblcblx0XHRcdFx0XHQtIOWmguaenEUtPsK3RiDnm7TmjqXkvZzkuLpTLT7Ct0XnmoTlj7Pkvqcs6YKj5LmITG9va1NldChFLT7Ct0Yp5bqU5YyF5ZCrYCRgICjnu6fmib/oh6ogbG9va1NldChTLT7Ct0UpKVxuXHRcdFx0XHRcdC0g5aaC5p6cRS0+wrdG6KKr5bWM5YWlRS0+wrdFK0Ys6YKj5LmITG9va1NldChFLT7Ct0Yp5bqU5YyF5ZCrYCtgXG5cdFx0XHRcdFx0LSDlpoLmnpxFLT7Ct0booqvltYzlhaVFLT7Ct0UqRizpgqPkuYhMb29rU2V0KEUtPsK3RinlupTljIXlkKtgKmBcblxuXHRcdFx05pu05LiA6Iis55qE6K6yLOS4gOS4quW3pumAkuW9kumhueeahExvb2tTZXTlupTor6XljIXlkKvlroPnmoTjgIzlt6bpgJLlvZLlhYTlvJ/pobnlj4rlhbbmnKzouqvjgI3nmoTjgIzmnIDlt6bpnZ7lt6bpgJLlvZLnrKblj7fjgI0s5Lul5Y+K57un5om/55qETG9va1NldFxuXHRcdFx05Zyo5pys5L6L5LitLEUtPsK3RStG55qE44CM5bem6YCS5b2S5YWE5byf6aG544CN5pivIEUtPsK3RSpGLOi/meS4quWFhOW8n+mhueeahOOAjOacgOW3pumdnuW3pumAkuW9kuespuWPt+OAjeaYr2AqYCwg5LiURS0+wrdFK0bnu6fmib/kuoZgJGAuXG5cbiAgICAgICAgMi4xLjIg5bGV5byA56ym5LiN5YyF5ZCr5bem6YCS5b2S55qE5Lqn55Sf5byPLOeUseS4iuS4gOS4qumhueehruWumiDnmoRsb29rU2V0LlxuICAgICAgICAgICAgLSDlpoLmnpzpobnlvaLlpoJBLT7wnZy2wrdCLOeUseWxleW8gOespkLlvpfliLDnmoTpobnlupTkuLpsb29rU2V0KEEpXG4gICAgICAgICAgICAtIOWmguaenOmhueW9ouWmgkEtPsK3QvCdnLbwnZy3XG4gICAgICAgICAgICAgICAgLSDoi6XwnZ204oiJRmlyc3Qo8J2ctikg55Sx5bGV5byA56ymQuW+l+WIsOeahOmhueeahGxvb2tTZXTkuLpGaXJzdCjwnZy2KVxuICAgICAgICAgICAgICAgIC0g5ZCm5YiZLOW6lOW9k+e7p+e7reWKoOWFpUZpcnN0KEIpLOmHjeWkjeS7peS4iui/h+eoiyznm7TliLDmnKvlsL7ml7Ys5aaC5p6c5LuN5YyF5ZCr8J2dtCzliJnliqDlhaVsb29rU2V0KEEpXG4gICAgICAgICAgICDmraTkvovkuK0sRS0+wrdGLCDnlLHkuo7lsZXlvIDnrKbmmK/mnIDmnKvnrKblj7cs5Zug5q2k5bGV5byA55qE6aG5Ri0+wrdpZOWPr+e7p+aJv2xvb2tTZXQoQSlcblxuICAgIDIuMiDpkojlr7nliY3ov5vpoblcbiAgICAgICAg5aaC5p6c5Y+q5piv5Y2V57qv55qE6aG555qE44CM54K544CN5YmN6L+bLOmCo+S5iOWPr+S7peebtOaOpee7p+aJvy5cbiAgICAgICAg5L6L5aaCLOmhuUUtPsK3RStGIOWJjei/m+WQjuW+l+WIsOmhuUUtPkXCtytGLCDlkI7ogIXnmoRsb29rU2V05bqU6K+l57un5om/5YmN6ICFLlxuXG4zLiDlsZXlvIDlkI7nmoTlpITnkIZcblxuICAgIDMuMSDlpoLmnpzpobnpm4bkuK3lrZjlnKjkuqfnlJ/lvI/nm7jlkIws5LiU44CM54K544CN55qE5L2N572u55u45ZCM55qE6aG5LCDlupTlsIblroPku6zlkIjlubYuXG5cbiAgICDkvotcbiAgICBBLT7Ct/CdnLYgICAkXG4gICAgQS0+wrfwnZy2ICAg8J2ctlxuXG4gICAg5ZCI5bm25ZCOOlxuICAgIEEtPsK38J2ctiAgICQs8J2ctlxuKi9cbmV4cG9ydCB0eXBlIEZpcnN0U2V0R2V0dGVyID0gSUZ1bmN0aW9uPFN5bWJvbCwgU2V0PFRlcm1pbmFsPj47XG4vKiDmnoTpgKDoh6rliqjmnLrmiYDpnIDopoHnmoTmlrnms5UgKi9cbmV4cG9ydCBjbGFzcyBMUkF1dG9tYXRhVG9vbHMgaW1wbGVtZW50cyBBdXRvbWF0YVRvb2xzIHtcblx0Z2V0Rmlyc3RTZXQ6IEZpcnN0U2V0R2V0dGVyXG5cdGNvbnN0cnVjdG9yKGZpcnN0U2V0Q2FsY3VsYXRvcjogRmlyc3RTZXRHZXR0ZXIpIHtcblx0XHR0aGlzLmdldEZpcnN0U2V0ID0gZmlyc3RTZXRDYWxjdWxhdG9yO1xuXHR9XG5cblx0R09UTyhJOiBJdGVtU2V0LCBpbnB1dFN5bWJvbDogU3ltYm9sKTogSXRlbVNldCB7XG5cdFx0bGV0IG5leHRJdGVtU2V0ID0gbmV3IEl0ZW1TZXQoKTtcblx0XHRmb3IgKGxldCBpdGVtIG9mIEkpIHtcblx0XHRcdGlmICghaXRlbS5oYXNOZXh0KCkpXG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0aWYgKGl0ZW0ubmV4dFN5bWJvbCgpID09IGlucHV0U3ltYm9sKSB7XG5cdFx0XHRcdG5leHRJdGVtU2V0LnB1c2goaXRlbS5uZXh0SXRlbSgpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuY2xvc3VyZShuZXh0SXRlbVNldCk7XG5cdH1cblxuXHRjbG9zdXJlKGl0ZW1TZXQ6IEl0ZW1TZXQpOiBJdGVtU2V0IHtcblx0XHRsZXQgaXRlbVNldENsb3N1cmU6IEl0ZW1TZXQgPSBpdGVtU2V0O1xuXHRcdC8v6aG56ZuG55qE5q+P5LiA5Liq6aG5IGl0ZW1cblx0XHRmb3IgKGxldCBwcm9jZXNzZWRJZHggPSAwOyBwcm9jZXNzZWRJZHggPCBpdGVtU2V0Q2xvc3VyZS5sZW5ndGg7IHByb2Nlc3NlZElkeCsrKSB7XG5cdFx0XHRsZXQgaXRlbSA9IGl0ZW1TZXRDbG9zdXJlW3Byb2Nlc3NlZElkeF07XG5cdFx0XHRpZiAoIWl0ZW0uaGFzTmV4dCgpKSAvL2lzc3VlIDEuMVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdGxldCBleHBhbmRTeW0gPSBpdGVtLm5leHRTeW1ib2woKTtcblx0XHRcdGlmICghKGV4cGFuZFN5bSBpbnN0YW5jZW9mIE5vblRlcm1pbmFsKSkgLy9pc3N1ZSAxLjJcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRpZiAoaXRlbS5wcm9kWzBdID09IGl0ZW0ucHJvZC5ub25UZXJtaW5hbCAmJiBpdGVtLmRvdFBvcyA9PSAwKSB7IC8vaXNzdWUgMS40XG5cdFx0XHRcdGRlYnVnKGBTdG9wIGV4cGFuZGluZyBsZWZ0IHJlY3Vyc2lvbiBwcm9kdWN0aW9uICR7ZXhwYW5kU3ltfWApO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGxldCBscnBzID0gdGhpcy5nZXRMZWZ0UmVjdXJzaXZlUHJvZHMoZXhwYW5kU3ltKTsgLy9pc3N1ZSAyLjEuMS4xIOW3pumAkuW9kuS6p+eUn+W8j1xuXHRcdFx0bGV0IG5scmxvb2tTZXQgPSB0aGlzLmRldGVybWluZU5vbkxlZnRSZWN1cnNpb25Mb29rU2V0KGl0ZW0pO1xuXHRcdFx0Ly9pc3N1ZSAyLjEuMSDlsZXlvIDnrKbljIXlkKvlt6bpgJLlvZLkuqfnlJ/lvI/nmoTmg4XlhrVcblx0XHRcdGlmIChscnBzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0bGV0IGxyTG9va1NldCA9IHRoaXMuZGV0ZXJtaW5lTGVmdFJlY3Vyc2lvbkxvb2tTZXQoaXRlbSk7IC8v55Sx5omA5pyJ5bem6YCS5b2S6aG55bim5p2l55qE5bGV5pyb56ym6ZuGXG5cdFx0XHRcdGZvciAobGV0IGxycCBvZiBleHBhbmRTeW0pIHtcblx0XHRcdFx0XHRsZXQgdW5pb25Mb29rU2V0ID0gbmV3IFNldDxUZXJtaW5hbD4oKTtcblx0XHRcdFx0XHRhZGRBbGxfU2V0KHVuaW9uTG9va1NldCwgbHJMb29rU2V0KTtcblx0XHRcdFx0XHRhZGRBbGxfU2V0KHVuaW9uTG9va1NldCwgbmxybG9va1NldCk7XG5cdFx0XHRcdFx0aXRlbVNldENsb3N1cmUucHVzaE9yTWVyZ2UobmV3IEl0ZW0obHJwLCAwLCB1bmlvbkxvb2tTZXQpKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly9pc3N1ZSAyLjEuMiDlsZXlvIDnrKbkuI3ljIXlkKvpgJLlvZLkuqfnlJ/lvI/nmoTmg4XlhrVcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRmb3IgKGxldCBwcm9kIG9mIGV4cGFuZFN5bS5wcm9kcykge1xuXHRcdFx0XHRcdGxldCBuZXdJdGVtID0gbmV3IEl0ZW0ocHJvZCwgMCwgbmxybG9va1NldCk7XG5cdFx0XHRcdFx0aXRlbVNldENsb3N1cmUucHVzaE9yTWVyZ2UobmV3SXRlbSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGl0ZW1TZXRDbG9zdXJlO1xuXHR9XG5cblx0LyoqXG4gICAgPT09PT09PT3lsZXlvIDnrKbljIXlkKvlt6bpgJLlvZLkuqfnlJ/lvI/nmoTlpITnkIY9PT09PT09PVxuXG4gICAg5paH5rOVOlxuICAgIFMtPkFcbiAgICBBLT5B8J2ctiB8IEHwnZy3IHwg8J2dslxuXG4gICAg54q25oCBOlxuICAgIFMtPsK3QSAsJFxuICAgIEEtPsK3QfCdnLYsJFxuICAgIEEtPsK3QfCdnLcsJFxuICAgIEEtPsK38J2dsiwgP1xuXG4gICAg5aaC5L2V5rGC44CMIEEtPvCdnbIg44CN55qE5bGV5pyb6ZuGP1xuXG4gICAg6Iul8J2ctizwnZy35LiN6IO95o6o5Ye68J2dtCzliJkgbG9va1NldChBLT7Ct/CdnbIpID0ge/CdnLYs8J2ct31cbiAgICDlkKbliJkgbG9va1NldChBLT7Ct/CdnbIpID178J2ctizwnZy3LCR9XG5cbiAgICDlvaLlvI/ljJY6XG4gICAg5Yqg5YWl5ZyoQeS4reeahOavj+S4gOS4quW3pumAkuW9kuS6p+eUn+W8j+S4reeahOOAjOesrOS4gOmdnkHnmoTnrKblj7fnmoRGaXJzdOmbhuOAjSzorrDkuLpGaXJzdCghQSksIOWmguaenOivpembhuWGheWtmOWcqPCdnbQs5YiZ5LiA6Lev5ZCR5ZCO55u05Yiw5pyr5bC+LOWmguaenOS7jeWtmOWcqPCdnbQs5YiZ5Yqg5YWlIExvb2soQSlcblxuICAgIOS8quS7o+eggTpcbiAgICBmb3IgZWFjaCBsci1wcm9kIGluIEFcbiAgICAgICAgZm9yIGVhY2ggc3ltIGluIGxyLXByb2RcbiAgICAgICAgICAgIGlmIHN5bSAhPSBBXG4gICAgICAgICAgICAgICAgYWRkIEZpcnN0KHN5bSlcbiAgICAgICAgICAgICAgICBpZiDwnZ20IOKIiSBGaXJzdChzeW0pXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgZWxzZSBpZiBzeW0gaXMgcmlnaHRtb3N0XG4gICAgICAgICAgICAgICAgICAgIGFkZCBsb29rU2V0KFMpXG5cbiAgICDms6g6IExvb2soUykg6KGo56S6U+eahGxvb2tlaGVhZFNldFxuICAgICogQHBhcmFtIGN1ckl0ZW1cbiAgICAqL1xuXHRkZXRlcm1pbmVMZWZ0UmVjdXJzaW9uTG9va1NldChjdXJJdGVtOiBJdGVtKTogU2V0PFRlcm1pbmFsPiB7XG5cdFx0bGV0IHRhcmdldCA9IGN1ckl0ZW0ubmV4dFN5bWJvbCgpO1xuXHRcdGFzc2VydCh0YXJnZXQgaW5zdGFuY2VvZiBOb25UZXJtaW5hbCk7XG5cblx0XHRsZXQgbG9va2FoZWFkU2V0ID0gbmV3IFNldDxUZXJtaW5hbD4oKTtcblx0XHQvL+ebruagh+eahOaJgOacieW3pumAkuW9kuS6p+eUn+W8j1xuXHRcdGxldCBsclByb2RzID0gdGhpcy5nZXRMZWZ0UmVjdXJzaXZlUHJvZHModGFyZ2V0KTtcblx0XHQvL+avj+S4gOS4quW3pumAkuW9kuS6p+eUn+W8j1xuXHRcdGZvciAobGV0IGxyX3Byb2Qgb2YgbHJQcm9kcykge1xuXHRcdFx0Ly/mr4/kuIDkuKrnrKblj7dcblx0XHRcdGxldCBzZWFyY2hpbmcgPSBmYWxzZTtcblx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgbHJfcHJvZC5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRpZiAobHJfcHJvZFtqXSAhPSB0YXJnZXQgJiYgIXNlYXJjaGluZykge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdC8vIHJpZ2h0LW1vc3Rcblx0XHRcdFx0aWYgKGogPT0gbHJfcHJvZC5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdFx0YWRkQWxsX1NldChsb29rYWhlYWRTZXQsIGN1ckl0ZW0ubG9va2FoZWFkU2V0KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsZXQgZm9sbG93ZXIgPSBscl9wcm9kW2ogKyAxXTtcblx0XHRcdFx0XHRsZXQgZm9sbG93ZXJfZmlyc3Rfc2V0ID0gdGhpcy5nZXRGaXJzdFNldChmb2xsb3dlcik7XG5cdFx0XHRcdFx0YWRkQWxsX1NldChsb29rYWhlYWRTZXQsIGZvbGxvd2VyX2ZpcnN0X3NldCk7XG5cdFx0XHRcdFx0Ly8g8J2dtCDiiIkgRmlyc3QoZm9sbG93ZXIpXG5cdFx0XHRcdFx0aWYgKCFmb2xsb3dlcl9maXJzdF9zZXQuaGFzKE5pbCkpIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvLyDwnZ20IOKIiCBGaXJzdChmb2xsb3dlcikgIHNjYW4gbmV4dCBvbmVcblx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdGxvb2thaGVhZFNldC5kZWxldGUoTmlsKTtcblx0XHRcdFx0XHRcdHNlYXJjaGluZyA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBsb29rYWhlYWRTZXQ7XG5cdH1cblx0LyoqXG4gICAgPT09PT09PT3lsZXlvIDnrKbkuI3ljIXlkKvlt6bpgJLlvZLkuqfnlJ/lvI/nmoTlpITnkIY9PT09PT09PVxuXG4gICAg57qm5a6aXG4gICAgLSDlsIbpl63ljIXpobnorrDkuLogY2xvc3VyZUl0ZW0gLOS+i+WmglMtPsK3QXNcbiAgICAtIOWwhuWxleW8gOmhueiuoeS4uiBleHBhbmRJdGVtICwg5L6L5aaC55Sx5bGV5byA56ymQeW+l+WIsOeahOmhuSBBLT7Ct2FcblxuICAgIOW9ouW8j+WMluiuoeeul+inhOWImeWmguS4izpcbiAgICDlsZXlvIDnrKbkvY3kuo5pdGVt5pyr56uvLOW9ouWmgkEtPsK3QlxuICAgICAgICBsb29rU2V0KGV4cGFuZEl0ZW0pPWxvb2tTZXQocHJldkl0ZW0pXG4gICAgbmV4dOmdnuacq+erryzlvaLlpoJBLT7Ct0LwnZy28J2ct1xuICAgICAgICBsb29rU2V0KGV4cGFuZEl0ZW0pPUZpcnN0KPCdnLYpICxcbiAgICAgICAgICAgIOWmguaenPCdnLblj6/mjqjlh7rwnZ20LOWImee7p+e7reWQkeWQjuWvu+aJvvCdnLcs6YeN5aSN6L+Z5Liq6L+H56iLLFxuICAgICAgICAgICAg5aaC5p6c8J2ct+S4uuacgOacq+WwvuespuWPtyzkuJTwnZy35LuN5Y+v5o6o5Ye68J2dtCzpgqPkuYjlsIZsb29rU2V0KHByZXZJdGVtKeaUvuWFpWxvb2tTZXQobmV4dClcbiAgICAqIEBwYXJhbSBwcmV2SXRlbVxuICAgICovXG5cdGRldGVybWluZU5vbkxlZnRSZWN1cnNpb25Mb29rU2V0KHByZXZJdGVtOiBJdGVtKTogU2V0PFRlcm1pbmFsPiB7XG5cdFx0bGV0IGV4cGFuZFN5bSA9IHByZXZJdGVtLm5leHRTeW1ib2woKTtcblx0XHRhc3NlcnQoZXhwYW5kU3ltIGluc3RhbmNlb2YgTm9uVGVybWluYWwpO1xuXG5cdFx0bGV0IGxvb2thaGVhZFNldCA9IG5ldyBTZXQ8VGVybWluYWw+KCk7XG5cblx0XHRmb3IgKGxldCBpID0gcHJldkl0ZW0uZG90UG9zOyBpIDwgcHJldkl0ZW0ucHJvZC5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGkgPT0gcHJldkl0ZW0ucHJvZC5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdGFkZEFsbF9TZXQobG9va2FoZWFkU2V0LCBwcmV2SXRlbS5sb29rYWhlYWRTZXQpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxldCBmaXJzdFNldE9mRm9sbG93ID0gdGhpcy5nZXRGaXJzdFNldChwcmV2SXRlbS5wcm9kW2kgKyAxXSk7XG5cdFx0XHRcdGFkZEFsbF9TZXQobG9va2FoZWFkU2V0LCBmaXJzdFNldE9mRm9sbG93KTtcblx0XHRcdFx0aWYgKGZpcnN0U2V0T2ZGb2xsb3cuaGFzKE5pbCkpIHtcblx0XHRcdFx0XHRsb29rYWhlYWRTZXQuZGVsZXRlKE5pbCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGxvb2thaGVhZFNldDtcblx0fVxuXHRnZXRMZWZ0UmVjdXJzaXZlUHJvZHMobm9uX3Rlcm1pbmFsOiBOb25UZXJtaW5hbCkge1xuXHRcdGxldCBscl9wcm9kczogUHJvZHVjdGlvbltdID0gW107XG5cdFx0Ly/mr4/kuIDkuKrkuqfnlJ/lvI9cblx0XHRmb3IgKGxldCBwcm9kIG9mIG5vbl90ZXJtaW5hbC5wcm9kcykge1xuXHRcdFx0Ly/kuqfnlJ/lvI/kuK3nmoTmr4/kuIDkuKrnrKblj7dcblx0XHRcdGZvciAobGV0IHN5bWJvbCBvZiBwcm9kKSB7XG5cdFx0XHRcdC8v6Iul55u4562JLCzliJnooajnpLpwcm9k5a2Y5Zyo5bem6YCS5b2SXG5cdFx0XHRcdGlmIChzeW1ib2wgPT0gbm9uX3Rlcm1pbmFsKSB7XG5cdFx0XHRcdFx0bHJfcHJvZHMucHVzaChwcm9kKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0XHQvL+iLpeS4jeebuOetiSDkuJRGaXJzdChzeW1ib2wp5LiN5a2Y5Zyo8J2dtOWImeS4reaWrSzliJnooajnpLpwcm9k5rKh5pyJ5bem6YCS5b2SXG5cdFx0XHRcdGVsc2UgaWYgKCF0aGlzLmdldEZpcnN0U2V0KHN5bWJvbCkuaGFzKE5pbCkpIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRkZWJ1Zyhscl9wcm9kcy5qb2luKFwiLFwiKSk7XG5cdFx0cmV0dXJuIGxyX3Byb2RzO1xuXHR9XG5cdGdldFN0YXJ0U3RhdGUoZ3JhbW1hcjogQXVnbWVudGVkR3JhbW1hcikge1xuXHRcdHJldHVybiBuZXcgU3RhdGUoMCwgdGhpcy5jbG9zdXJlKG5ldyBJdGVtU2V0KG5ldyBJdGVtKGdyYW1tYXIucHJvZE9mU3RhcnROVCwgMCwgbmV3IFNldDxUZXJtaW5hbD4oW0VPRl0pKSkpKTtcblx0fVxuXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGF0ZVNldF9MUihncmFtbWFyOiBBdWdtZW50ZWRHcmFtbWFyLCBnZXRGaXJzdFNldDogRmlyc3RTZXRHZXR0ZXIpIHtcblx0cmV0dXJuIGdldFN0YXRlU2V0KGdyYW1tYXIsIG5ldyBMUkF1dG9tYXRhVG9vbHMoZ2V0Rmlyc3RTZXQpKTtcbn1cbiJdfQ==