UNPKG

pegisland

Version:

General PEG-based parser supporting island grammars with lake symbols

198 lines 6.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PikaParser = exports.PikaParsingEnv = void 0; // Copyright (C) 2022- Katsumi Okuda. All rights reserved. const heap_1 = __importDefault(require("heap")); const BeginningCalculator_1 = require("./set/BeginningCalculator"); const DepthFirstTraverser_1 = require("./DepthFirstTraverser"); const Indexer_1 = require("./Indexer"); const IParsingEnv_1 = require("./IParsingEnv"); const Position_1 = require("./Position"); const SetCalculator_1 = require("./set/SetCalculator"); const BottomUpParser_1 = require("./BottomUpParser"); class PikaParsingEnv extends IParsingEnv_1.BaseParsingEnv { constructor(s, peg) { super(s); this.peg = peg; this.parentsMap = createParentsMap(this.peg); this.createHeap = getHeapCreator(this.peg); } parseString(s, start) { this.fillMemoTable(s); const startRule = this.peg.rules.get(start); if (!startRule) { return Error(`${start} is not a valid nonterminal symbol.`); } const result = startRule.parse(this, new Position_1.Position(0, 1, 1)); if (result === null) { return Error(`Failed to recognize ${start}`); } return result; } parse(pe, pos) { // console.log('offset: ' + pos.offset); if (!this.memo[pos.offset].has(pe)) { this.memo[pos.offset].set(pe, null); // const result = pe.parse(this, pos); // assert(result == null, `${show(pe)} should be null`); // this.memo[pos.offset].set(pe, result); } return this.memo[pos.offset].get(pe); } grow(pe, pos) { const isFirstEval = !this.memo[pos.offset].has(pe); // console.log('grow ' + show(pe)); if (isFirstEval) { this.memo[pos.offset].set(pe, null); } const result = pe.accept(this.recognizer, pos); const oldResult = this.memo[pos.offset].get(pe); if (isFirstEval || (0, BottomUpParser_1.isGrowing)(result, oldResult)) { this.memo[pos.offset].set(pe, result); // console.log(result); return true; } return false; } fillMemoTable(s) { for (let pos = s.length; pos >= 0; pos--) { this.fillMemoEntry(pos); } } fillMemoEntry(pos) { const [heap] = this.createHeap(); const set = new Set(heap.toArray()); // console.log('heap was created for ' + pos, heap.size()); while (!heap.empty()) { const pe = heap.pop(); set.delete(pe); const isGrowing = this.grow(pe, new Position_1.Position(pos, -1, -1)); // XXX /* console.log( pos, heap.size(), show(pe) + indexMap.get(pe) + ' was poped!' + isGrowing ); */ if (!isGrowing) continue; const parents = this.parentsMap.get(pe); if (!parents) continue; parents .filter((parent) => !set.has(parent)) .forEach((parent) => { // console.log(show(parent) + ' was pushed!'); heap.push(parent); set.add(parent); }); } } } exports.PikaParsingEnv = PikaParsingEnv; class ParentsBuilder { constructor(beginning) { this.beginning = beginning; this.parents = new Map(); } build(peg) { const traverser = new DepthFirstTraverser_1.DepthFirstTraverser(this, (0, BottomUpParser_1.getTopLevelExpressions)(peg)); traverser.traverse(); return this.parents; } addParent(pe, parent) { if (!this.parents.has(pe)) { this.parents.set(pe, []); } const parents = this.parents.get(pe); parents.push(parent); } visitNonterminal(pe) { this.addParent(pe.rule.rhs, pe); } visitTerminal(_pe) { // Nothing to be done } visitZeroOrMore(pe) { this.addParent(pe.operand, pe); } visitOneOrMore(pe) { this.addParent(pe.operand, pe); } visitOptional(pe) { this.addParent(pe.operand, pe); } visitAnd(pe) { this.addParent(pe.operand, pe); } visitNot(pe) { this.addParent(pe.operand, pe); } visitSequence(pe) { for (const operand of pe.operands) { this.addParent(operand, pe); const beginningSet = this.beginning.get(operand); if (!beginningSet.has(SetCalculator_1.EPSILON)) { break; } } } visitOrderedChoice(pe) { pe.operands.forEach((operand) => { this.addParent(operand, pe); }); } visitGrouping(pe) { this.addParent(pe.operand, pe); } visitRewriting(pe) { this.addParent(pe.operand, pe); } visitColon(pe) { this.visitBinaryOperator(pe); } visitColonNot(pe) { this.visitBinaryOperator(pe); } visitLake(pe) { this.addParent(pe.operand, pe); } visitBinaryOperator(pe) { this.addParent(pe.lhs, pe); this.addParent(pe.rhs, pe); } } function getHeapCreator(peg) { const indexer = new Indexer_1.Indexer(); const [indexMap, terminals] = indexer.build(peg); /* console.log( 'terminals: ' + terminals.map((terminal) => (terminal as Terminal).source) ); */ const cmp = (a, b) => indexMap.get(a) - indexMap.get(b); return () => { const heap = new heap_1.default(cmp); terminals.forEach((terminal) => { heap.push(terminal); }); return [heap, indexMap]; }; } class PikaParser extends BottomUpParser_1.BottomUpParserBase { constructor(peg) { super(peg, PikaParsingEnv); } } exports.PikaParser = PikaParser; function createParentsMap(peg) { const beginningCalculator = new BeginningCalculator_1.BeginningCalculator(peg.rules); const beginningSets = beginningCalculator.calculate(); const parentsBuilder = new ParentsBuilder(beginningSets); const parentsMap = parentsBuilder.build(peg); return parentsMap; } //# sourceMappingURL=PikaParser.js.map