UNPKG

xast

Version:
148 lines 5.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Parser = void 0; const Location_1 = require("./Location"); const TokenKind_1 = require("./TokenKind"); const schema_1 = require("./parsers/schema"); const ANY_KEYWORD = Symbol('@@any'); class Parser { constructor(lexer, options = {}) { this.lexer = lexer; this._options = options; this._tokenCounter = 0; this._parsersMap = new Map; } parseSchema() { return this.expectParse(schema_1.schemaParser); } add(nodeParser) { var _a, _b; if (nodeParser.trigger) { if (!this._parsersMap.has(nodeParser.trigger.kind)) { this._parsersMap.set(nodeParser.trigger.kind, new Map); } const parsersKindMap = this._parsersMap.get(nodeParser.trigger.kind); const keyword = (_a = nodeParser.trigger.keyword) !== null && _a !== void 0 ? _a : ANY_KEYWORD; if (!(parsersKindMap === null || parsersKindMap === void 0 ? void 0 : parsersKindMap.has(keyword))) { parsersKindMap === null || parsersKindMap === void 0 ? void 0 : parsersKindMap.set(keyword, []); } (_b = parsersKindMap === null || parsersKindMap === void 0 ? void 0 : parsersKindMap.get(keyword)) === null || _b === void 0 ? void 0 : _b.push(nodeParser); } } parseToken(token) { if (this._parsersMap.has(token.kind)) { const parsersKindMap = this._parsersMap.get(token.kind); for (const keyword of [token.value, ANY_KEYWORD]) { const nodeParsers = (parsersKindMap === null || parsersKindMap === void 0 ? void 0 : parsersKindMap.get(keyword)) || []; for (const nodeParser of nodeParsers) { const node = nodeParser.parse(this); if (node) { return node; } } } } } optionalParse(nodeParser) { return nodeParser.parse(this); } expectParse(nodeParser) { const node = nodeParser.parse(this); if (node) { return node; } throw this.lexer.source.syntaxError(this.lexer.token.start, `Expected ${nodeParser.kind}, found ${this.lexer.token.getDescription()}.`); } node(startToken, node) { if (this._options.enableLocation) { node.loc = new Location_1.Location(startToken, this.lexer.lastToken, this.lexer.source); } return node; } peek(kind) { return this.lexer.token.kind === kind; } expectToken(kind) { const token = this.lexer.token; if (token.kind === kind) { this.advanceLexer(); return token; } throw this.lexer.source.syntaxError(token.start, `Expected ${(0, TokenKind_1.getTokenKindDescription)(kind)}, found ${token.getDescription()}.`); } expectOptionalToken(kind) { const token = this.lexer.token; if (token.kind === kind) { this.advanceLexer(); return true; } return false; } expectKeyword(value) { const token = this.lexer.token; if (token.kind === TokenKind_1.TokenKind.NAME && token.value === value) { this.advanceLexer(); } else { throw this.lexer.source.syntaxError(token.start, `Expected "${value}", found ${token.getDescription()}.`); } } expectOptionalKeyword(value) { const token = this.lexer.token; if (token.kind === TokenKind_1.TokenKind.NAME && token.value === value) { this.advanceLexer(); return true; } return false; } unexpected(atToken) { const token = atToken !== null && atToken !== void 0 ? atToken : this.lexer.token; return this.lexer.source.syntaxError(token.start, `Unexpected ${token.getDescription()}.`); } any(openKind, nodeParser, closeKind) { this.expectToken(openKind); const nodes = []; while (!this.expectOptionalToken(closeKind)) { nodes.push(this.expectParse(nodeParser)); } return nodes; } many(openKind, nodeParser, closeKind) { this.expectToken(openKind); const nodes = []; do { nodes.push(this.expectParse(nodeParser)); } while (!this.expectOptionalToken(closeKind)); return nodes; } optionalMany(openKind, nodeParser, closeKind) { if (this.expectOptionalToken(openKind)) { const nodes = []; do { nodes.push(this.expectParse(nodeParser)); } while (!this.expectOptionalToken(closeKind)); return nodes; } return []; } delimitedMany(delimiterKind, nodeParser) { this.expectOptionalToken(delimiterKind); const nodes = []; do { nodes.push(this.expectParse(nodeParser)); } while (this.expectOptionalToken(delimiterKind)); return nodes; } advanceLexer() { const { maxTokens } = this._options; const token = this.lexer.advance(); if (maxTokens !== undefined && token.kind !== TokenKind_1.TokenKind.EOF) { ++this._tokenCounter; if (this._tokenCounter > maxTokens) { throw this.lexer.source.syntaxError(token.start, `Schema contains more than ${maxTokens} tokens.`); } } } } exports.Parser = Parser; //# sourceMappingURL=Parser.js.map