UNPKG

pegisland

Version:

General PEG-based parser supporting island grammars with lake symbols

192 lines 6.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Recognizer = void 0; // Copyright (C) 2022- Katsumi Okuda. All rights reserved. const assert_1 = require("assert"); const ParseTree_1 = require("./ParseTree"); const Position_1 = require("./Position"); class Recognizer { constructor(env) { this.env = env; } visitNonterminal(pe, pos) { const result = this.env.parseRule(pe.rule, pos); if (result === null || pe.name === '') { return result; } const [, end] = result; const value = this.env.s.substring(pos.offset, end.offset).trim(); if (!this.env.has(pe.name)) { this.env.register(pe.name, value); } else if (value !== this.env.lookup(pe.name)) { return null; } return result; } visitTerminal(pe, pos) { pe.regex.lastIndex = pos.offset; const m = this.env.s.match(pe.regex); if (m === null) { return null; } const [text] = m; const { length } = text; const nextOffset = pos.offset + length; const lines = text.split('\n'); const baseCol = lines.length === 1 ? pos.column : 1; const nextPos = new Position_1.Position(nextOffset, pos.line + lines.length - 1, baseCol + lines[lines.length - 1].length); return [new ParseTree_1.NodeTerminal(new ParseTree_1.Range(pos, nextPos), pe.regex, text), nextPos]; } visitZeroOrMore(pe, pos) { const values = []; let prevPos = null; let nextPos = pos; while (nextPos !== prevPos) { prevPos = nextPos; const result = this.env.parse(pe.operand, nextPos); if (!result) { break; } const [value] = result; [, nextPos] = result; values.push(value); } return [new ParseTree_1.NodeZeroOrMore(new ParseTree_1.Range(pos, nextPos), values), nextPos]; } visitOneOrMore(pe, pos) { let prevPos = pos; const result = this.env.parse(pe.operand, pos); if (!result) { return null; } let [value, nextPos] = result; const values = [value]; while (nextPos !== prevPos) { prevPos = nextPos; const result = this.env.parse(pe.operand, nextPos); if (!result) { break; } [value, nextPos] = result; values.push(value); } return [new ParseTree_1.NodeOneOrMore(new ParseTree_1.Range(pos, nextPos), values), nextPos]; } visitOptional(pe, pos) { const values = []; let nextPos = pos; const result = this.env.parse(pe.operand, nextPos); if (result) { const [value] = result; [, nextPos] = result; values.push(value); } return [new ParseTree_1.NodeOptional(new ParseTree_1.Range(pos, nextPos), values), nextPos]; } visitAnd(pe, pos) { const result = this.env.parse(pe.operand, pos); if (result === null) { return null; } const [value, nextPos] = result; return [new ParseTree_1.NodeAnd(new ParseTree_1.Range(pos, nextPos), value), pos]; } visitNot(pe, pos) { const result = this.env.parse(pe.operand, pos); if (result !== null) { return null; } return [new ParseTree_1.NodeNot(new ParseTree_1.Range(pos, pos)), pos]; } visitSequence(pe, pos) { const values = []; let nextPos = pos; for (const operand of pe.operands) { const result = this.env.parse(operand, nextPos); if (result === null) { return null; } const [value] = result; [, nextPos] = result; values.push(value); } return [new ParseTree_1.NodeSequence(new ParseTree_1.Range(pos, nextPos), values), nextPos]; } visitOrderedChoice(pe, pos) { for (let i = 0; i < pe.operands.length; i++) { const result = this.env.parse(pe.operands[i], pos); if (result !== null) { const [value, nextPos] = result; return [ new ParseTree_1.NodeOrderedChoice(new ParseTree_1.Range(pos, nextPos), value, i), nextPos, ]; } } return null; } visitGrouping(pe, pos) { const result = this.env.parse(pe.operand, pos); if (result === null) { return null; } const [childNode, nextPos] = result; return [new ParseTree_1.NodeGrouping(new ParseTree_1.Range(pos, nextPos), childNode), nextPos]; } visitRewriting(pe, pos) { const result = this.env.parse(pe.operand, pos); if (result === null) { return null; } const [childNode, nextPos] = result; return [ new ParseTree_1.NodeRewriting(new ParseTree_1.Range(pos, nextPos), childNode, this), nextPos, ]; } visitColon(pe, pos) { const lhsResult = this.env.parse(pe.lhs, pos); if (lhsResult === null) { return null; } const [, lhsNextPos] = lhsResult; const rhsResult = this.env.parse(pe.rhs, pos); if (rhsResult === null) { return null; } const [, rhsNextPos] = rhsResult; if (lhsNextPos.offset !== rhsNextPos.offset) { return null; } return rhsResult; } visitColonNot(pe, pos) { const lhsResult = this.env.parse(pe.lhs, pos); if (lhsResult === null) { return null; } const rhsResult = this.env.parse(pe.rhs, pos); if (rhsResult !== null) { const [, lhsNextPos] = lhsResult; const [, rhsNextPos] = rhsResult; if (lhsNextPos.offset === rhsNextPos.offset) { return null; } } return lhsResult; } visitLake(pe, pos) { const result = this.env.parse(pe.operand, pos); (0, assert_1.strict)(result !== null, 'Lake should not fail since it accepts an empty string'); const [childNode, nextPos] = result; const zeroOrMore = childNode; const islands = zeroOrMore.childNodes .map((group) => group.childNodes[0]) .filter((childNode) => childNode.index === 0) .map((childNode) => childNode.childNodes[0]); return [new ParseTree_1.NodeLake(new ParseTree_1.Range(pos, nextPos), islands, pe), nextPos]; } } exports.Recognizer = Recognizer; //# sourceMappingURL=Recognizer.js.map