@stackpress/idea-parser
Version:
Parses ideas to AST and readable JSON.
114 lines (113 loc) • 3.57 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Exception_js_1 = __importDefault(require("./Exception.js"));
class Lexer {
constructor() {
this._code = '';
this._index = 0;
this._dictionary = {};
}
get dictionary() {
return Object.assign({}, this._dictionary);
}
get index() {
return this._index;
}
clone() {
const lexer = new Lexer();
lexer.load(this._code, this._index);
for (const key in this._dictionary) {
lexer.define(key, this._dictionary[key].reader);
}
return lexer;
}
define(key, reader) {
this._dictionary[key] = { key, reader };
}
expect(keys) {
if (!Array.isArray(keys)) {
keys = [keys];
}
const definitions = keys.map(key => {
const reader = this.get(key);
if (!reader) {
throw Exception_js_1.default.for('Unknown definition %s', key);
}
return reader;
}).filter(Boolean);
if (!definitions.length) {
throw Exception_js_1.default.for('Unknown definitions %s', keys.join(', '));
}
const match = this.match(this._code, this._index, keys);
if (!match) {
if (this._code[this._index + 10]) {
throw Exception_js_1.default.for('Unexpected %s ... expecting %s', this._code
.substring(this._index, this._index + 10)
.replace(/[\n\r]/g, ' ')
.trim(), keys.join(' or ')).withPosition(this._index, this.nextSpace());
}
else {
throw Exception_js_1.default.for('Unexpected %s expecting %s', this._code.substring(this._index, this._index + 10), keys.join(' or ')).withPosition(this._index, this.nextSpace());
}
}
this._index = match.end;
return match;
}
get(key) {
return this._dictionary[key];
}
load(code, index = 0) {
this._code = code;
this._index = index;
return this;
}
match(code, start, keys) {
keys = keys || Object.keys(this._dictionary);
for (let i = 0; i < keys.length; i++) {
if (!this._dictionary[keys[i]]) {
throw Exception_js_1.default.for('Unknown definition %s', keys[i]);
}
const results = this._dictionary[keys[i]].reader(code, start, this);
if (results && results.end > start) {
return results;
}
}
return null;
}
next(names) {
const start = this._index;
try {
this.expect(names);
this._index = start;
return true;
}
catch (error) {
this._index = start;
return false;
}
}
optional(names) {
const start = this._index;
try {
return this.expect(names);
}
catch (error) {
this._index = start;
return undefined;
}
}
read() {
return this.optional(Object.keys(this.dictionary));
}
substring(start, end) {
return this._code.substring(start, end);
}
nextSpace() {
const index = this._code.indexOf(' ', this._index);
return index === -1 ? this._code.length : index;
}
}
exports.default = Lexer;