UNPKG

defscript-embedded-react

Version:
463 lines (462 loc) 11.4 kB
const {min, max} = Math; const {freeze} = Object; const gotoStart = 10; const translations = map({ '$$$': 10, 'dom': 11, '$__1': 12, 'dom.attributes': 13, '$__2': 14, 'dom.node': 15, 'dom.attributes.string': 16, 'dom.attributes.attribute': 17, 'dom.attributes.attribute.value': 18, '$': 0, '<': 1, 'id': 2, '>': 3, '/': 4, 'text': 5, 'code': 6, 'simple-string': 7, 'rich-string': 8, '=': 9 }); const productions = [ [ 10, 1 ], [ 11, 1 ], [ 12, 0 ], [ 12, 1 ], [ 12, 2 ], [ 13, 1 ], [ 14, 0 ], [ 14, 1 ], [ 14, 2 ], [ 15, 9 ], [ 15, 5 ], [ 15, 1 ], [ 15, 1 ], [ 16, 1 ], [ 16, 1 ], [ 17, 3 ], [ 18, 1 ], [ 18, 1 ] ]; const reducers = map({ 0: function ($, $loc, $rule) { return $[0]; }, 2: function ($, $loc, $rule) { return []; }, 3: function ($, $loc, $rule) { return [$[0]]; }, 4: function ($, $loc, $rule) { var slice$ = [].slice, arrayFrom$ = Array.from || function (x) { return slice$.call(x); }; return arrayFrom$($[0]).concat([$[1]]); }, 6: function ($, $loc, $rule) { return []; }, 7: function ($, $loc, $rule) { return [$[0]]; }, 8: function ($, $loc, $rule) { var slice$ = [].slice, arrayFrom$ = Array.from || function (x) { return slice$.call(x); }; return arrayFrom$($[0]).concat([$[1]]); }, 9: function ($, $loc, $rule) { return this.node('dom-node', { name: $[1], attributes: $[2], children: $[4], single: false }); }, 10: function ($, $loc, $rule) { return this.node('dom-node', { name: $[1], attributes: $[2], children: [], single: true }); }, 11: function ($, $loc, $rule) { return this.node('text-node', { text: $[0] }); }, 12: function ($, $loc, $rule) { return this.node('code-node', { code: this.parseEmbedded($[0].slice(1, -1)) }); }, 15: function ($, $loc, $rule) { return this.node('attribute', { name: $[0], value: $[2] }); }, 16: function ($, $loc, $rule) { return this.node('code', { code: this.parseEmbedded($[0]) }); }, 17: function ($, $loc, $rule) { return this.node('code', { code: this.parseEmbedded($[0].slice(1, -1)) }); } }, parseInt); const lrTable = { action: map({ '0-1': 's3', '0-5': 's4', '0-6': 's5', '1-0': 'r0', '2-0': 'r1', '3-2': 's6', '4-0': 'r11', '5-0': 'r12', '6-3': 'r2', '6-2': 's10', '6-4': 'r2', '7-3': 's11', '7-4': 's12', '8-3': 'r5', '8-4': 'r5', '8-2': 's10', '9-3': 'r3', '9-2': 'r3', '9-4': 'r3', '10-9': 's14', '11-1': 's17', '11-5': 's18', '11-6': 's19', '12-3': 's20', '13-3': 'r4', '13-2': 'r4', '13-4': 'r4', '14-6': 's23', '14-7': 's24', '14-8': 's25', '15-1': 's26', '15-5': 's18', '15-6': 's19', '16-1': 'r7', '16-5': 'r7', '16-6': 'r7', '17-2': 's28', '18-1': 'r11', '18-5': 'r11', '18-6': 'r11', '19-1': 'r12', '19-5': 'r12', '19-6': 'r12', '20-0': 'r10', '21-3': 'r15', '21-2': 'r15', '21-4': 'r15', '22-3': 'r16', '22-2': 'r16', '22-4': 'r16', '23-3': 'r17', '23-2': 'r17', '23-4': 'r17', '24-3': 'r13', '24-2': 'r13', '24-4': 'r13', '25-3': 'r14', '25-2': 'r14', '25-4': 'r14', '26-4': 's29', '26-2': 's28', '27-1': 'r8', '27-5': 'r8', '27-6': 'r8', '28-3': 'r2', '28-2': 's10', '28-4': 'r2', '29-2': 's31', '30-3': 's32', '30-4': 's33', '31-3': 's34', '32-1': 's17', '32-5': 's18', '32-6': 's19', '33-3': 's36', '34-0': 'r9', '35-1': 's37', '35-5': 's18', '35-6': 's19', '36-1': 'r10', '36-5': 'r10', '36-6': 'r10', '37-4': 's38', '37-2': 's28', '38-2': 's39', '39-3': 's40', '40-1': 'r9', '40-5': 'r9', '40-6': 'r9' }), goto: map({ '0-11': 1, '0-15': 2, '6-13': 7, '6-12': 8, '6-17': 9, '8-17': 13, '11-14': 15, '11-15': 16, '14-18': 21, '14-16': 22, '15-15': 27, '28-13': 30, '28-12': 8, '28-17': 9, '32-14': 35, '32-15': 16, '35-15': 27 }) }; function map(obj, kFunc = k => k) { const mp = new Map(); for (let key in obj) if (obj.hasOwnProperty(key)) mp.set(kFunc(key), obj[key]); return mp; } export function untranslate(n) { for (const [key, value] of translations) { if (value === n) return key; } } export function accepts(token) { return translations.has(token) && translations.get(token) < gotoStart; } export const defaults = {}; class ParsingError extends Error { constructor(parsing, message = '') { super(); const [type] = this.constructor.name.split('$'); this.type = type; this.message = `${ this.type }: ${ message }`; this.parsing = parsing; this.loc = parsing.lastPosition; } } class UnexpectedTokenError extends ParsingError { constructor(parsing, token, message = `Unexpected "${ token.type }" token`) { super(parsing, message); this.loc = parsing._locateToken(token); this.token = token; } } class UnexpectedEndError extends ParsingError { constructor(parsing, message = 'Encountered EOF but expected more tokens') { super(parsing, message); } } class InvalidTokenError extends UnexpectedTokenError { constructor(parsing, token, message = `Invalid token type: "${ token.type }"`) { super(parsing, token, message); } } export class Parser { constructor(options = {}) { const {context = {}, tokenTranslator = token => token.value} = options; this.context = context; this.tokenTranslator = tokenTranslator; this.states = [0]; this.stack = []; this.values = []; this.positions = []; this.onreducestart = null; this.onreduceend = null; this.lastPosition = { row: 1, column: 0 }; this.settings = { locate: false }; } _state() { return this.states[this.states.length - 1]; } _fire(eventType, data) { const fn = this[`on${ eventType }`]; const internal = true; if (typeof fn === 'function') { fn.apply(this, [ data, internal ]); } } _locate(positions) { if (positions.length === 0) { return freeze({ start: this.lastPosition, end: this.lastPosition }); } else { const {start} = positions[0]; const {end} = positions[positions.length - 1]; return freeze({ start, end }); } } _locateToken(token) { if (token.loc == null) { return freeze({ start: this.lastPosition, end: this.lastPosition }); } else { return token.loc; } } _reduce(rule) { ; const [symbol, length] = productions[rule]; const nodes = this.values.splice(-length || this.values.length); const positions = this.positions.splice(-length || this.positions.length); const loc = this._locate(positions); this._fire('reducestart', { rule, nodes, positions, loc }); if (reducers.has(rule)) { const fn = reducers.get(rule); this.values.push(fn.apply(this.context, [ nodes, loc, rule ])); } else { this.values.push(nodes.length > 0 ? nodes[0] : []); } this._fire('reduceend', { loc, rule, nodes, positions, node: this.values.length > 0 ? this.values[this.values.length - 1] : null }); this.states.splice(-length || this.states.length); this.states.push(lrTable.goto.get(`${ this._state() }-${ symbol }`)); this.stack.splice(-length || this.stack.length); this.stack.push(symbol); this.positions.push(loc); } addSource(txt) { this.source += txt; } push(token, logger = null) { if (!translations.has(token.type) || translations.get(token.type) >= gotoStart) throw new InvalidTokenError(this, token); else { const type = translations.get(token.type); while (true) { const key = `${ this._state() }-${ type }`; if (lrTable.action.has(key)) { const val = lrTable.action.get(key); const action = val[0]; const number = parseInt(val.slice(1)); if (action === 's') { const loc = this._locateToken(token); this.states.push(number); this.stack.push(type); this.values.push(this.tokenTranslator(token)); this.positions.push(loc); this.lastPosition = loc.end; return; } if (action === 'r') { this._reduce(number); continue; } } else { throw new UnexpectedTokenError(this, token); } } } } finish(logger = null) { const type = translations.get('$'); while (true) { const key = `${ this._state() }-${ type }`; if (lrTable.action.has(key)) { const val = lrTable.action.get(key); const action = val[0]; const number = parseInt(val.slice(1)); if (action !== 'r') throw new UnexpectedEndError(this); if (number === 0) return this.values[0]; else { this._reduce(number); continue; } } else { throw new UnexpectedEndError(this); } } } }