UNPKG

xtemplate

Version:

eXtensible Template Engine lib on browser and nodejs. support async control, inheritance, include, logic expression, custom function and more.

2,660 lines (2,658 loc) 140 kB
var XTemplate = (function(){ var module = {}; /* combined modules: xtemplate xtemplate/runtime xtemplate/runtime/util xtemplate/runtime/commands xtemplate/runtime/scope xtemplate/runtime/linked-buffer xtemplate/compiler xtemplate/compiler/parser xtemplate/compiler/ast */ var xtemplateRuntimeUtil, xtemplateRuntimeScope, xtemplateRuntimeLinkedBuffer, xtemplateCompilerParser, xtemplateCompilerAst, xtemplateRuntimeCommands, xtemplateRuntime, xtemplateCompiler, xtemplate; xtemplateRuntimeUtil = function (exports) { // http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet // http://wonko.com/post/html-escaping var htmlEntities = { '&': '&amp;', '>': '&gt;', '<': '&lt;', '`': '&#x60;', '/': '&#x2F;', '"': '&quot;', /*jshint quotmark:false*/ '\'': '&#x27;' }; var possibleEscapeHtmlReg = /[&<>"'`]/; var escapeHtmlReg = getEscapeReg(); var SUBSTITUTE_REG = /\\?\{([^{}]+)\}/g; var win = typeof global !== 'undefined' ? global : window; function getEscapeReg() { var str = ''; for (var entity in htmlEntities) { str += entity + '|'; } str = str.slice(0, -1); escapeHtmlReg = new RegExp(str, 'g'); return escapeHtmlReg; } var util; var toString = Object.prototype.toString; exports = util = { isArray: Array.isArray || function (obj) { return toString.call(obj) === '[object Array]'; }, keys: Object.keys || function (o) { var result = []; var p; for (p in o) { if (o.hasOwnProperty(p)) { result.push(p); } } return result; }, each: function (object, fn, context) { if (object) { var key, val, keys; var i = 0; var length = object && object.length; var isObj = length === undefined || Object.prototype.toString.call(object) === '[object Function]'; context = context || null; if (isObj) { keys = util.keys(object); for (; i < keys.length; i++) { key = keys[i]; if (fn.call(context, object[key], key, object) === false) { break; } } } else { for (val = object[0]; i < length; val = object[++i]) { if (fn.call(context, val, i, object) === false) { break; } } } } return object; }, mix: function (t, s) { for (var p in s) { t[p] = s[p]; } return t; }, globalEval: function (data) { if (win.execScript) { win.execScript(data); } else { (function (data) { win['eval'].call(win, data); }(data)); } }, substitute: function (str, o, regexp) { if (typeof str !== 'string' || !o) { return str; } return str.replace(regexp || SUBSTITUTE_REG, function (match, name) { if (match.charAt(0) === '\\') { return match.slice(1); } return o[name] === undefined ? '' : o[name]; }); }, escapeHtml: function (str) { str = '' + str; if (!possibleEscapeHtmlReg.test(str)) { return str; } return (str + '').replace(escapeHtmlReg, function (m) { return htmlEntities[m]; }); }, log: function () { if (typeof console !== 'undefined') { console.log.apply(console, arguments); } } }; return exports; }(); xtemplateRuntimeScope = function (exports) { function Scope(data) { if (data !== undefined) { this.data = data; } else { this.data = {}; } this.root = this; this.parent = undefined; this.affix = undefined; } Scope.prototype = { isScope: 1, setParent: function (parentScope) { this.parent = parentScope; this.root = parentScope.root; }, set: function (name, value) { if (!this.affix) { this.affix = {}; } this.affix[name] = value; }, setData: function (data) { this.data = data; }, getData: function () { return this.data; }, mix: function (v) { var affix = this.affix; if (!affix) { affix = this.affix = {}; } for (var name in v) { affix[name] = v[name]; } }, get: function (name) { var data = this.data; var v; var affix = this.affix; if (data != null) { v = data[name]; } if (v !== undefined) { return v; } v = affix && affix[name]; return v; }, resolve: function (parts, depth) { var self = this; var v; if (!depth && parts.length === 1) { v = self.get(parts[0]); if (v !== undefined) { return v; } else { depth = 1; } } var len = parts.length; var scope = self; var i; var part0 = parts[0]; if (depth) { while (scope && depth--) { scope = scope.parent; } } if (!scope) { return undefined; } if (part0 === 'this') { v = scope.data; } else if (part0 === 'root') { scope = scope.root; v = scope.data; } else if (part0) { do { v = scope.get(part0); } while (v === undefined && (scope = scope.parent)); } else { return scope.data; } for (i = 1; v && i < len; i++) { v = v[parts[i]]; } return v; } }; exports = Scope; return exports; }(); xtemplateRuntimeLinkedBuffer = function (exports) { var util = xtemplateRuntimeUtil; function Buffer(list, next) { this.list = list; this.init(); this.next = next; this.ready = false; } Buffer.prototype = { constructor: Buffer, isBuffer: 1, init: function () { this.data = ''; }, append: function (data) { this.data += data; return this; }, write: function (data) { if (data != null) { this.append(data); } return this; }, writeEscaped: function (data) { if (data != null) { this.append(util.escapeHtml(data)); } return this; }, async: function (fn) { var self = this; var list = self.list; var nextFragment = new Buffer(list, self.next); var asyncFragment = new Buffer(list, nextFragment); self.next = asyncFragment; self.ready = true; fn(asyncFragment); return nextFragment; }, error: function (reason) { var callback = this.list.callback; if (callback) { callback(reason, undefined); this.list.callback = null; } }, end: function () { var self = this; if (self.list.callback) { self.ready = true; self.list.flush(); } return self; } }; function LinkedBuffer(callback, config) { var self = this; self.config = config; self.head = new Buffer(self, undefined); self.callback = callback; this.init(); } LinkedBuffer.prototype = { constructor: LinkedBuffer, init: function () { this.data = ''; }, append: function (data) { this.data += data; }, end: function () { this.callback(null, this.data); this.callback = null; }, flush: function () { var self = this; var fragment = self.head; while (fragment) { if (fragment.ready) { this.append(fragment.data); } else { self.head = fragment; return; } fragment = fragment.next; } self.end(); } }; LinkedBuffer.Buffer = Buffer; exports = LinkedBuffer; return exports; }(); xtemplateCompilerParser = function (exports) { var parser = function (undefined) { var parser = {}; var GrammarConst = { 'SHIFT_TYPE': 1, 'REDUCE_TYPE': 2, 'ACCEPT_TYPE': 0, 'TYPE_INDEX': 0, 'PRODUCTION_INDEX': 1, 'TO_INDEX': 2 }; function peekStack(stack, n) { n = n || 1; return stack[stack.length - n]; } function mix(to, from) { for (var f in from) { to[f] = from[f]; } } function isArray(obj) { return '[object Array]' === Object.prototype.toString.call(obj); } function each(object, fn, context) { if (object) { var key, val, length, i = 0; context = context || null; if (!isArray(object)) { for (key in object) { if (fn.call(context, object[key], key, object) === false) { break; } } } else { length = object.length; for (val = object[0]; i < length; val = object[++i]) { if (fn.call(context, val, i, object) === false) { break; } } } } } function inArray(item, arr) { for (var i = 0, l = arr.length; i < l; i++) { if (arr[i] === item) { return true; } } return false; } var Lexer = function Lexer(cfg) { var self = this; self.rules = []; mix(self, cfg); self.resetInput(self.input); }; Lexer.prototype = { 'resetInput': function (input) { mix(this, { input: input, matched: '', stateStack: [Lexer.STATIC.INITIAL], match: '', text: '', firstLine: 1, lineNumber: 1, lastLine: 1, firstColumn: 1, lastColumn: 1 }); }, 'getCurrentRules': function () { var self = this, currentState = self.stateStack[self.stateStack.length - 1], rules = []; if (self.mapState) { currentState = self.mapState(currentState); } each(self.rules, function (r) { var state = r.state || r[3]; if (!state) { if (currentState === Lexer.STATIC.INITIAL) { rules.push(r); } } else if (inArray(currentState, state)) { rules.push(r); } }); return rules; }, 'pushState': function (state) { this.stateStack.push(state); }, 'popState': function (num) { num = num || 1; var ret; while (num--) { ret = this.stateStack.pop(); } return ret; }, 'showDebugInfo': function () { var self = this, DEBUG_CONTEXT_LIMIT = Lexer.STATIC.DEBUG_CONTEXT_LIMIT, matched = self.matched, match = self.match, input = self.input; matched = matched.slice(0, matched.length - match.length); var past = (matched.length > DEBUG_CONTEXT_LIMIT ? '...' : '') + matched.slice(0 - DEBUG_CONTEXT_LIMIT).replace(/\n/g, ' '), next = match + input; next = next.slice(0, DEBUG_CONTEXT_LIMIT).replace(/\n/g, ' ') + (next.length > DEBUG_CONTEXT_LIMIT ? '...' : ''); return past + next + '\n' + new Array(past.length + 1).join('-') + '^'; }, 'mapSymbol': function mapSymbolForCodeGen(t) { return this.symbolMap[t]; }, 'mapReverseSymbol': function (rs) { var self = this, symbolMap = self.symbolMap, i, reverseSymbolMap = self.reverseSymbolMap; if (!reverseSymbolMap && symbolMap) { reverseSymbolMap = self.reverseSymbolMap = {}; for (i in symbolMap) { reverseSymbolMap[symbolMap[i]] = i; } } if (reverseSymbolMap) { return reverseSymbolMap[rs]; } else { return rs; } }, 'lex': function () { var self = this, input = self.input, i, rule, m, ret, lines, rules = self.getCurrentRules(); self.match = self.text = ''; if (!input) { return self.mapSymbol(Lexer.STATIC.END_TAG); } for (i = 0; i < rules.length; i++) { rule = rules[i]; var regexp = rule.regexp || rule[1], token = rule.token || rule[0], action = rule.action || rule[2] || undefined; if (m = input.match(regexp)) { lines = m[0].match(/\n.*/g); if (lines) { self.lineNumber += lines.length; } mix(self, { firstLine: self.lastLine, lastLine: self.lineNumber, firstColumn: self.lastColumn, lastColumn: lines ? lines[lines.length - 1].length - 1 : self.lastColumn + m[0].length }); var match; match = self.match = m[0]; self.matches = m; self.text = match; self.matched += match; ret = action && action.call(self); if (ret === undefined) { ret = token; } else { ret = self.mapSymbol(ret); } input = input.slice(match.length); self.input = input; if (ret) { return ret; } else { return self.lex(); } } } } }; Lexer.STATIC = { 'INITIAL': 'I', 'DEBUG_CONTEXT_LIMIT': 20, 'END_TAG': '$EOF' }; var lexer = new Lexer({ 'rules': [ [ 0, /^[\s\S]*?(?={{)/, function () { var self = this, text = self.text, m, n = 0; if (m = text.match(/\\+$/)) { n = m[0].length; } if (n % 2) { self.pushState('et'); text = text.slice(0, -1); } else { self.pushState('t'); } if (n) { text = text.replace(/\\+$/g, function (m) { return new Array(m.length / 2 + 1).join('\\'); }); } self.text = text; return 'CONTENT'; } ], [ 'b', /^[\s\S]+/, 0 ], [ 'b', /^[\s\S]{2,}?(?:(?={{)|$)/, function popState() { this.popState(); }, ['et'] ], [ 'c', /^{{{?(?:#|@)/, function () { var self = this, text = self.text; if (text.length === 4) { self.pushState('p'); } else { self.pushState('e'); } }, ['t'] ], [ 'd', /^{{{?\//, function () { var self = this, text = self.text; if (text.length === 4) { self.pushState('p'); } else { self.pushState('e'); } }, ['t'] ], [ 'e', /^{{\s*else\s*}}/, function popState() { this.popState(); }, ['t'] ], [ 0, /^{{![\s\S]*?}}/, function popState() { this.popState(); }, ['t'] ], [ 'b', /^{{%([\s\S]*?)%}}/, function () { this.text = this.matches[1] || ''; this.popState(); }, ['t'] ], [ 'f', /^{{{?/, function () { var self = this, text = self.text; if (text.length === 3) { self.pushState('p'); } else { self.pushState('e'); } }, ['t'] ], [ 0, /^\s+/, 0, [ 'p', 'e' ] ], [ 'g', /^,/, 0, [ 'p', 'e' ] ], [ 'h', /^}}}/, function () { this.popState(2); }, ['p'] ], [ 'h', /^}}/, function () { this.popState(2); }, ['e'] ], [ 'i', /^\(/, 0, [ 'p', 'e' ] ], [ 'j', /^\)/, 0, [ 'p', 'e' ] ], [ 'k', /^\|\|/, 0, [ 'p', 'e' ] ], [ 'l', /^&&/, 0, [ 'p', 'e' ] ], [ 'm', /^===/, 0, [ 'p', 'e' ] ], [ 'n', /^!==/, 0, [ 'p', 'e' ] ], [ 'o', /^>=/, 0, [ 'p', 'e' ] ], [ 'p', /^<=/, 0, [ 'p', 'e' ] ], [ 'q', /^>/, 0, [ 'p', 'e' ] ], [ 'r', /^</, 0, [ 'p', 'e' ] ], [ 's', /^\+/, 0, [ 'p', 'e' ] ], [ 't', /^-/, 0, [ 'p', 'e' ] ], [ 'u', /^\*/, 0, [ 'p', 'e' ] ], [ 'v', /^\//, 0, [ 'p', 'e' ] ], [ 'w', /^%/, 0, [ 'p', 'e' ] ], [ 'x', /^!/, 0, [ 'p', 'e' ] ], [ 'y', /^"(\\[\s\S]|[^\\"\n])*"/, function () { this.text = this.text.slice(1, -1).replace(/\\"/g, '"'); }, [ 'p', 'e' ] ], [ 'y', /^'(\\[\s\S]|[^\\'\n])*'/, function () { this.text = this.text.slice(1, -1).replace(/\\'/g, '\''); }, [ 'p', 'e' ] ], [ 'z', /^\d+(?:\.\d+)?(?:e-?\d+)?/i, 0, [ 'p', 'e' ] ], [ 'aa', /^=/, 0, [ 'p', 'e' ] ], [ 'ab', /^\.\./, function () { this.pushState('ws'); }, [ 'p', 'e' ] ], [ 'ac', /^\//, function popState() { this.popState(); }, ['ws'] ], [ 'ac', /^\./, 0, [ 'p', 'e' ] ], [ 'ad', /^\[/, 0, [ 'p', 'e' ] ], [ 'ae', /^\]/, 0, [ 'p', 'e' ] ], [ 'af', /^\{/, 0, [ 'p', 'e' ] ], [ 'ag', /^\:/, 0, [ 'p', 'e' ] ], [ 'ah', /^\}/, 0, [ 'p', 'e' ] ], [ 'ab', /^[a-zA-Z_$][a-zA-Z0-9_$]*/, 0, [ 'p', 'e' ] ] ] }); parser.lexer = lexer; lexer.symbolMap = { '$EOF': 'a', 'CONTENT': 'b', 'OPEN_BLOCK': 'c', 'OPEN_CLOSE_BLOCK': 'd', 'INVERSE': 'e', 'OPEN_TPL': 'f', 'COMMA': 'g', 'CLOSE': 'h', 'L_PAREN': 'i', 'R_PAREN': 'j', 'OR': 'k', 'AND': 'l', 'LOGIC_EQUALS': 'm', 'LOGIC_NOT_EQUALS': 'n', 'GE': 'o', 'LE': 'p', 'GT': 'q', 'LT': 'r', 'PLUS': 's', 'MINUS': 't', 'MULTIPLY': 'u', 'DIVIDE': 'v', 'MODULUS': 'w', 'NOT': 'x', 'STRING': 'y', 'NUMBER': 'z', 'EQUALS': 'aa', 'ID': 'ab', 'SEP': 'ac', 'L_BRACKET': 'ad', 'R_BRACKET': 'ae', 'L_BRACE': 'af', 'COLON': 'ag', 'R_BRACE': 'ah', '$START': 'ai', 'program': 'aj', 'statements': 'ak', 'statement': 'al', 'function': 'am', 'id': 'an', 'expression': 'ao', 'params': 'ap', 'hash': 'aq', 'param': 'ar', 'conditionalOrExpression': 'as', 'listExpression': 'at', 'jsonExpression': 'au', 'jsonPart': 'av', 'conditionalAndExpression': 'aw', 'equalityExpression': 'ax', 'relationalExpression': 'ay', 'additiveExpression': 'az', 'multiplicativeExpression': 'ba', 'unaryExpression': 'bb', 'primaryExpression': 'bc', 'hashSegment': 'bd', 'idSegments': 'be' }; parser.productions = [ [ 'ai', ['aj'] ], [ 'aj', [ 'ak', 'e', 'ak' ], function () { return new this.yy.ProgramNode({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1, this.$3); } ], [ 'aj', ['ak'], function () { return new this.yy.ProgramNode({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1); } ], [ 'ak', ['al'], function () { return [this.$1]; } ], [ 'ak', [ 'ak', 'al' ], function () { this.$1.push(this.$2); } ], [ 'al', [ 'c', 'am', 'h', 'aj', 'd', 'an', 'h' ], function () { return new this.yy.BlockStatement({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$2, this.$4, this.$6, this.$1.length !== 4); } ], [ 'al', [ 'f', 'ao', 'h' ], function () { return new this.yy.ExpressionStatement({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$2, this.$1.length !== 3); } ], [ 'al', ['b'], function () { return new this.yy.ContentStatement({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1); } ], [ 'am', [ 'an', 'i', 'ap', 'g', 'aq', 'j' ], function () { return new this.yy.Function({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1, this.$3, this.$5); } ], [ 'am', [ 'an', 'i', 'ap', 'j' ], function () { return new this.yy.Function({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1, this.$3); } ], [ 'am', [ 'an', 'i', 'aq', 'j' ], function () { return new this.yy.Function({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1, null, this.$3); } ], [ 'am', [ 'an', 'i', 'j' ], function () { return new this.yy.Function({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1); } ], [ 'ap', [ 'ap', 'g', 'ar' ], function () { this.$1.push(this.$3); } ], [ 'ap', ['ar'], function () { return [this.$1]; } ], [ 'ar', ['ao'] ], [ 'ao', ['as'] ], [ 'ao', [ 'ad', 'at', 'ae' ], function () { return new this.yy.ArrayExpression(this.$2); } ], [ 'ao', [ 'af', 'au', 'ah' ], function () { return new this.yy.JsonExpression(this.$2); } ], [ 'av', [ 'y', 'ag', 'ao' ], function () { return [ this.$1, this.$3 ]; } ], [ 'av', [ 'ab', 'ag', 'ao' ], function () { return [ this.$1, this.$3 ]; } ], [ 'au', ['av'], function () { return [this.$1]; } ], [ 'au', [ 'au', 'g', 'av' ], function () { this.$1.push(this.$3); } ], [ 'at', ['ao'], function () { return [this.$1]; } ], [ 'at', [ 'at', 'g', 'ao' ], function () { this.$1.push(this.$3); } ], [ 'as', ['aw'] ], [ 'as', [ 'as', 'k', 'aw' ], function () { return new this.yy.ConditionalOrExpression(this.$1, this.$3); } ], [ 'aw', ['ax'] ], [ 'aw', [ 'aw', 'l', 'ax' ], function () { return new this.yy.ConditionalAndExpression(this.$1, this.$3); } ], [ 'ax', ['ay'] ], [ 'ax', [ 'ax', 'm', 'ay' ], function () { return new this.yy.EqualityExpression(this.$1, '===', this.$3); } ], [ 'ax', [ 'ax', 'n', 'ay' ], function () { return new this.yy.EqualityExpression(this.$1, '!==', this.$3); } ], [ 'ay', ['az'] ], [ 'ay', [ 'ay', 'r', 'az' ], function () { return new this.yy.RelationalExpression(this.$1, '<', this.$3); } ], [ 'ay', [ 'ay', 'q', 'az' ], function () { return new this.yy.RelationalExpression(this.$1, '>', this.$3); } ], [ 'ay', [ 'ay', 'p', 'az' ], function () { return new this.yy.RelationalExpression(this.$1, '<=', this.$3); } ], [ 'ay', [ 'ay', 'o', 'az' ], function () { return new this.yy.RelationalExpression(this.$1, '>=', this.$3); } ], [ 'az', ['ba'] ], [ 'az', [ 'az', 's', 'ba' ], function () { return new this.yy.AdditiveExpression(this.$1, '+', this.$3); } ], [ 'az', [ 'az', 't', 'ba' ], function () { return new this.yy.AdditiveExpression(this.$1, '-', this.$3); } ], [ 'ba', ['bb'] ], [ 'ba', [ 'ba', 'u', 'bb' ], function () { return new this.yy.MultiplicativeExpression(this.$1, '*', this.$3); } ], [ 'ba', [ 'ba', 'v', 'bb' ], function () { return new this.yy.MultiplicativeExpression(this.$1, '/', this.$3); } ], [ 'ba', [ 'ba', 'w', 'bb' ], function () { return new this.yy.MultiplicativeExpression(this.$1, '%', this.$3); } ], [ 'bb', [ 'x', 'bb' ], function () { return new this.yy.UnaryExpression(this.$1, this.$2); } ], [ 'bb', [ 't', 'bb' ], function () { return new this.yy.UnaryExpression(this.$1, this.$2); } ], [ 'bb', ['bc'] ], [ 'bc', ['am'] ], [ 'bc', ['y'], function () { return new this.yy.String({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1); } ], [ 'bc', ['z'], function () { return new this.yy.Number({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1); } ], [ 'bc', ['an'] ], [ 'bc', [ 'i', 'ao', 'j' ], function () { return this.$2; } ], [ 'aq', [ 'aq', 'g', 'bd' ], function () { var hash = this.$1, seg = this.$3; hash.value[seg[0]] = seg[1]; } ], [ 'aq', ['bd'], function () { var hash = new this.yy.Hash({ line: this.lexer.firstLine, col: this.lexer.firstColumn }), $1 = this.$1; hash.value[$1[0]] = $1[1]; return hash; } ], [ 'bd', [ 'ab', 'aa', 'ao' ], function () { return [ this.$1, this.$3 ]; } ], [ 'an', ['be'], function () { return new this.yy.Id({ line: this.lexer.firstLine, col: this.lexer.firstColumn }, this.$1); } ], [ 'be', [ 'be', 'ac', 'ab' ], function () { this.$1.push(this.$3); } ], [ 'be', [ 'be', 'ad', 'ao', 'ae' ], function () { this.$1.push(this.$3); } ], [ 'be', ['ab'], function () { return [this.$1]; } ] ]; parser.table = { 'gotos': { '0': { 'aj': 4, 'ak': 5, 'al': 6 }, '2': { 'am': 8, 'an': 9, 'be': 10 }, '3': { 'am': 18, 'an': 19, 'ao': 20, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '5': { 'al': 30 }, '11': { 'am': 18, 'an': 19, 'ao': 35, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '12': { 'am': 18, 'an': 19, 'bb': 36, 'bc': 28, 'be': 10 }, '13': { 'am': 18, 'an': 19, 'bb': 37, 'bc': 28, 'be': 10 }, '16': { 'am': 18, 'an': 19, 'ao': 38, 'as': 21, 'at': 39, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '17': { 'au': 42, 'av': 43 }, '29': { 'ak': 58, 'al': 6 }, '31': { 'aj': 59, 'ak': 5, 'al': 6 }, '32': { 'am': 18, 'an': 19, 'ao': 62, 'ap': 63, 'aq': 64, 'ar': 65, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'bd': 66, 'be': 10 }, '34': { 'am': 18, 'an': 19, 'ao': 68, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '45': { 'am': 18, 'an': 19, 'aw': 76, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '46': { 'am': 18, 'an': 19, 'ax': 77, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '47': { 'am': 18, 'an': 19, 'ay': 78, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '48': { 'am': 18, 'an': 19, 'ay': 79, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '49': { 'am': 18, 'an': 19, 'az': 80, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '50': { 'am': 18, 'an': 19, 'az': 81, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '51': { 'am': 18, 'an': 19, 'az': 82, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '52': { 'am': 18, 'an': 19, 'az': 83, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '53': { 'am': 18, 'an': 19, 'ba': 84, 'bb': 27, 'bc': 28, 'be': 10 }, '54': { 'am': 18, 'an': 19, 'ba': 85, 'bb': 27, 'bc': 28, 'be': 10 }, '55': { 'am': 18, 'an': 19, 'bb': 86, 'bc': 28, 'be': 10 }, '56': { 'am': 18, 'an': 19, 'bb': 87, 'bc': 28, 'be': 10 }, '57': { 'am': 18, 'an': 19, 'bb': 88, 'bc': 28, 'be': 10 }, '58': { 'al': 30 }, '70': { 'am': 18, 'an': 19, 'ao': 96, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '72': { 'am': 18, 'an': 19, 'ao': 97, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '73': { 'am': 18, 'an': 19, 'ao': 98, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '74': { 'av': 99 }, '89': { 'an': 100, 'be': 10 }, '90': { 'am': 18, 'an': 19, 'ao': 101, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'be': 10 }, '91': { 'am': 18, 'an': 19, 'ao': 62, 'aq': 102, 'ar': 103, 'as': 21, 'aw': 22, 'ax': 23, 'ay': 24, 'az': 25, 'ba': 26, 'bb': 27, 'bc': 28, 'bd': 66, 'be': 10 }, '93': { 'bd': 105 } }, 'action': { '0': { 'b': [ 1, undefined, 1 ], 'c': [ 1, undefined, 2 ], 'f': [ 1, undefined, 3 ] }, '1': { 'a': [ 2, 7 ], 'e': [ 2, 7 ], 'c': [ 2, 7 ], 'f': [ 2, 7 ], 'b': [ 2, 7 ], 'd': [ 2, 7 ] }, '2': { 'ab': [ 1, undefined, 7 ] }, '3': { 'i': [ 1, undefined, 11 ], 't': [ 1, undefined, 12 ], 'x': [ 1, undefined, 13 ], 'y': [ 1, undefined, 14 ], 'z': [ 1, undefined, 15 ], 'ab': [ 1, undefined, 7 ], 'ad': [ 1, undefined, 16 ], 'af': [ 1, undefined, 17 ] }, '4': { 'a': [0] }, '5': { 'a': [ 2, 2 ], 'd': [ 2, 2 ], 'b': [ 1, undefined, 1 ], 'c': [ 1, undefined, 2 ], 'e': [ 1, undefined, 29 ], 'f': [ 1, undefined, 3 ] }, '6': { 'a': [ 2, 3 ], 'e': [ 2, 3 ], 'c': [ 2, 3 ], 'f': [ 2, 3 ], 'b': [ 2, 3 ], 'd': [ 2, 3 ] }, '7': { 'i': [ 2, 57 ], 'ac': [ 2, 57 ], 'ad': [ 2, 57 ], 'h': [ 2, 57 ], 'k': [ 2, 57 ], 'l': [ 2, 57 ], 'm': [ 2, 57 ], 'n': [ 2, 57 ], 'o': [ 2, 57 ], 'p': [ 2, 57 ], 'q': [ 2, 57 ], 'r': [ 2, 57 ], 's': [ 2, 57 ], 't': [ 2, 57 ], 'u': [ 2, 57 ], 'v': [ 2, 57 ], 'w': [ 2, 57 ], 'j': [ 2, 57 ], 'ae': [ 2, 57 ], 'g': [ 2, 57 ], 'ah': [ 2, 57 ] }, '8': { 'h': [ 1, undefined, 31 ] }, '9': { 'i': [ 1, undefined, 32 ] }, '10': { 'i': [ 2, 54 ], 'h': [ 2, 54 ], 'k': [ 2, 54 ], 'l': [ 2, 54 ], 'm': [ 2, 54 ], 'n': [ 2, 54 ], 'o': [ 2, 54 ], 'p': [ 2, 54 ], 'q': [ 2, 54 ], 'r': [ 2, 54 ], 's': [ 2, 54 ], 't': [ 2, 54 ], 'u': [ 2, 54 ], 'v': [ 2, 54 ], 'w': [ 2, 54 ], 'j': [ 2, 54 ], 'ae': [ 2, 54 ], 'g': [ 2, 54 ], 'ah': [ 2, 54 ], 'ac': [ 1, undefined, 33 ], 'ad': [ 1, undefined, 34 ] }, '11': { 'i': [ 1, undefined, 11 ], 't': [ 1, undefined, 12 ], 'x': [ 1, undefined, 13 ], 'y': [ 1, undefined, 14 ], 'z': [ 1, undefined, 15 ], 'ab': [ 1, undefined, 7 ], 'ad': [ 1, undefined, 16 ], 'af': [ 1, undefined, 17 ] }, '12': { 'i': [ 1, undefined, 11 ], 't': [ 1, undefined, 12 ], 'x': [ 1, undefined, 13 ], 'y': [ 1, undefined, 14 ], 'z': [ 1, undefined, 15 ], 'ab': [ 1, undefined, 7 ] }, '13': { 'i': [ 1, undefined, 11 ], 't': [ 1, undefined, 12 ], 'x': [ 1, undefined, 13 ], 'y': [ 1, undefined, 14 ], 'z': [ 1, undefined, 15 ], 'ab': [ 1, undefined, 7 ] }, '14': { 'h': [ 2, 47 ], 'k': [ 2, 47 ], 'l': [ 2, 47 ], 'm': [ 2, 47 ], 'n': [ 2, 47 ], 'o': [ 2, 47 ], 'p': [ 2, 47 ], 'q': [ 2, 47 ], 'r': [ 2, 47 ], 's': [ 2, 47 ], 't': [ 2, 47 ], 'u': [ 2, 47 ], 'v': [ 2, 47 ], 'w': [ 2, 47 ], 'j': [ 2, 47 ], 'ae': [ 2, 47 ], 'g': [ 2, 47 ], 'ah': [ 2, 47 ] }, '15': { 'h': [ 2, 48 ], 'k': [ 2, 48 ], 'l': [ 2, 48 ], 'm': [ 2, 48 ], 'n': [ 2, 48 ], 'o': [ 2, 48 ], 'p': [ 2, 48 ], 'q': [ 2, 48 ], 'r': [ 2, 48 ], 's': [ 2, 48 ], 't': [ 2, 48 ], 'u': [ 2, 48 ], 'v': [ 2, 48 ], 'w': [ 2, 48 ], 'j': [ 2, 48 ], 'ae': [ 2, 48 ], 'g': [ 2, 48 ], 'ah': [ 2, 48 ] }, '16': { 'i': [ 1, undefined, 11 ], 't': [ 1, undefined, 12 ], 'x': [ 1, undefined, 13 ], 'y': [ 1, undefined, 14 ], 'z': [ 1, undefined, 15 ], 'ab': [ 1, undefined, 7 ], 'ad': [ 1, undefined, 16 ], 'af': [ 1, undefined, 17 ] }, '17': { 'y': [ 1, undefined, 40 ], 'ab': [ 1, undefined, 41 ] }, '18': { 'h': [ 2, 46 ], 'k': [ 2, 46 ], 'l': [ 2, 46 ], 'm': [ 2, 46 ], 'n': [ 2, 46 ], 'o': [ 2, 46 ], 'p': [ 2, 46 ], 'q': [ 2, 46 ], 'r': [ 2, 46 ], 's': [ 2, 46 ], 't': [ 2, 46 ], 'u': [ 2, 46 ], 'v': [ 2, 46 ], 'w': [ 2, 46 ], 'j': [ 2, 46 ], 'ae': [ 2, 46 ], 'g': [ 2, 46 ], 'ah': [ 2, 46 ] }, '19': { 'h': [ 2, 49 ], 'k': [ 2, 49 ], 'l': [ 2, 49 ], 'm': [ 2, 49 ], 'n': [ 2, 49 ], 'o': [ 2, 49 ], 'p': [ 2, 49 ], 'q': [ 2, 49 ], 'r': [ 2, 49 ], 's': [ 2, 49 ], 't': [ 2, 49 ], 'u': [ 2, 49 ], 'v': [ 2, 49 ], 'w': [ 2, 49 ], 'j': [ 2, 49 ], 'ae': [ 2, 49 ], 'g': [ 2, 49 ], 'ah': [ 2, 49 ], 'i': [ 1, undefined, 32 ] }, '20': { 'h': [ 1, undefined, 44 ] }, '21': { 'h': [ 2, 15 ], 'j': [ 2, 15 ], 'ae': [ 2, 15 ], 'g': [ 2, 15 ], 'ah': [ 2, 15 ], 'k': [