pegisland
Version:
General PEG-based parser supporting island grammars with lake symbols
98 lines • 3.34 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PackratParsingEnv = exports.PackratParser = exports.ParsingError = void 0;
// Copyright (C) 2021- Katsumi Okuda. All rights reserved.
const line_column_1 = __importDefault(require("line-column"));
const IParsingEnv_1 = require("./IParsingEnv");
const Position_1 = require("./Position");
const Printer_1 = require("./Printer");
const Stats_1 = require("./Stats");
function makeErrorMessage(env) {
const finder = (0, line_column_1.default)(env.s);
const info = finder.fromIndex(env.maxIndex);
if (info) {
return [
`Parsing error at offset line ${info.line} column ${info.col}.`,
'when parsing with the following parsing expressions:',
...[...env.deepestStack.map(Printer_1.peToString)].reverse(),
].join('\n');
}
return `Parsing error at offset ${env.maxIndex}`;
}
class ParsingError extends Error {
constructor(env) {
super(makeErrorMessage(env));
this.env = env;
}
}
exports.ParsingError = ParsingError;
class PackratParser {
constructor(rules) {
this.rules = rules;
}
parse(s, startSymbol, stats) {
const rule = this.getStartRule(startSymbol);
if (rule instanceof Error) {
return rule;
}
const env = new PackratParsingEnv(s, stats);
const result = rule.parse(env, new Position_1.Position(0, 1, 1));
if (result === null) {
return new ParsingError(env);
}
const [tree, nextPos] = result;
if (nextPos.offset < s.length) {
return new ParsingError(env);
}
return tree;
}
getStartRule(startSymbol) {
let rule = this.rules.values().next().value;
if (startSymbol) {
if (this.rules.has(startSymbol)) {
rule = this.rules.get(startSymbol);
}
else {
return Error(`Nonterminal symbol ${startSymbol} does not exist in the grammar.`);
}
}
return rule;
}
}
exports.PackratParser = PackratParser;
class PackratParsingEnv extends IParsingEnv_1.BaseParsingEnv {
constructor(s, stats = new Stats_1.Stats()) {
super(s);
this.stats = stats;
this.deepestStack = [];
this.maxIndex = 0;
this.currentStack = [];
}
parseRule(rule, pos) {
if (!this.memo[pos.offset].has(rule)) {
this.stats.memoMissCount++;
this.memo[pos.offset].set(rule, rule.parse(this, pos));
}
this.stats.memoAccessCount++;
const result = this.memo[pos.offset].get(rule);
if (result === null) {
this.stats.failureCount++;
}
return result;
}
parse(pe, pos) {
this.currentStack.push(pe);
if (pos.offset >= this.maxIndex) {
this.maxIndex = pos.offset;
this.deepestStack = [...this.currentStack];
}
const result = pe.accept(this.recognizer, pos);
this.currentStack.pop();
return result;
}
}
exports.PackratParsingEnv = PackratParsingEnv;
//# sourceMappingURL=PackratParser.js.map