UNPKG

@stackpress/idea-parser

Version:

Parses ideas to AST and readable JSON.

220 lines (219 loc) 7.88 kB
import { data, scan } from '../definitions.js'; import AbstractTree from './AbstractTree.js'; export default class TypeTree extends AbstractTree { static data = [...data, 'CapitalIdentifier']; static definitions(lexer) { super.definitions(lexer); lexer.define('Type', (code, index) => { const regexp = /^[A-Z][a-zA-Z0-9_]*((\[\])|\?)?/; const results = scan('Literal', regexp, code, index); if (results) { const square = code.substring(results.end, results.end + 2); if (results.end > index && square === '[]') { results.end += 2; results.value += square; } results.raw = `"${results.value}"`; } return results; }); lexer.define('TypeWord', (code, index) => scan('_TypeWord', /^type/, code, index)); return lexer; } static parse(code, start = 0) { return new this().parse(code, start); } parse(code, start = 0) { this._lexer.load(code, start); return this.type(); } parameter() { const key = this._lexer.expect('AttributeIdentifier'); key.name = key.name.slice(1); const elements = []; if (this._lexer.optional('(')) { this.noncode(); const data = this.constructor.data; let results; do { results = this._lexer.optional(data); if (results) { elements.push(results); this.noncode(); continue; } } while (results); this._lexer.expect(')'); } return { type: 'Property', kind: 'init', start: key.start, end: this._lexer.index, method: false, shorthand: false, computed: false, key, value: elements.length ? { type: 'ArrayExpression', start: key.start, end: this._lexer.index, elements } : { type: 'Literal', start: key.start, end: this._lexer.index, value: true, raw: 'true' } }; } property() { const key = this._lexer.expect('CamelIdentifier'); this._lexer.expect('whitespace'); const value = this._lexer.expect('Type'); this._lexer.expect('whitespace'); const properties = []; this.dotry(() => { properties.push(this.parameter()); this.noncode(); }); return { type: 'Property', kind: 'init', start: key.start, end: this._lexer.index, method: false, shorthand: false, computed: false, key, value: { type: 'ObjectExpression', start: value.start, end: this._lexer.index, properties: [ { type: 'Property', kind: 'init', start: value.start, end: value.end, method: false, shorthand: false, computed: false, key: { type: 'Identifier', start: value.start, end: value.end, name: 'type', }, value }, { type: 'Property', kind: 'init', start: value.start, end: this._lexer.index, method: false, shorthand: false, computed: false, key: { type: 'Identifier', start: value.start, end: value.end, name: 'attributes', }, value: { type: 'ObjectExpression', start: value.start, end: value.end, properties } } ] } }; } type() { const type = this._lexer.expect('TypeWord'); this._lexer.expect('whitespace'); const id = this._lexer.expect('CapitalIdentifier'); const final = this._lexer.optional('!'); this._lexer.expect('whitespace'); const properties = []; this.dotry(() => { properties.push(this.parameter()); this.noncode(); }); this.noncode(); this._lexer.expect('{'); this.noncode(); const columns = []; this.dotry(() => { columns.push(this.property()); }); this._lexer.expect('}'); return { type: 'VariableDeclaration', kind: 'type', mutable: !Boolean(final), start: type.start, end: this._lexer.index, declarations: [{ type: 'VariableDeclarator', start: type.start, end: this._lexer.index, id, init: { type: 'ObjectExpression', start: type.start, end: this._lexer.index, properties: [ { type: 'Property', kind: 'init', start: type.start, end: this._lexer.index, method: false, shorthand: false, computed: false, key: { type: 'Identifier', start: type.start, end: type.end, name: 'attributes', }, value: { type: 'ObjectExpression', start: type.start, end: type.end, properties } }, { type: 'Property', kind: 'init', start: type.start, end: this._lexer.index, method: false, shorthand: false, computed: false, key: { type: 'Identifier', start: type.start, end: type.end, name: 'columns', }, value: { type: 'ObjectExpression', start: type.start, end: type.end, properties: columns } } ] } }] }; } } ;