chevrotain
Version:
Chevrotain is a high performance fault tolerant javascript parsing DSL for building recursive decent parsers
111 lines • 5.33 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.RestWalker = void 0;
var utils_1 = require("../../utils/utils");
var gast_public_1 = require("./gast/gast_public");
/**
* A Grammar Walker that computes the "remaining" grammar "after" a productions in the grammar.
*/
var RestWalker = /** @class */ (function () {
function RestWalker() {
}
RestWalker.prototype.walk = function (prod, prevRest) {
var _this = this;
if (prevRest === void 0) { prevRest = []; }
utils_1.forEach(prod.definition, function (subProd, index) {
var currRest = utils_1.drop(prod.definition, index + 1);
/* istanbul ignore else */
if (subProd instanceof gast_public_1.NonTerminal) {
_this.walkProdRef(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.Terminal) {
_this.walkTerminal(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.Alternative) {
_this.walkFlat(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.Option) {
_this.walkOption(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.RepetitionMandatory) {
_this.walkAtLeastOne(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.RepetitionMandatoryWithSeparator) {
_this.walkAtLeastOneSep(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.RepetitionWithSeparator) {
_this.walkManySep(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.Repetition) {
_this.walkMany(subProd, currRest, prevRest);
}
else if (subProd instanceof gast_public_1.Alternation) {
_this.walkOr(subProd, currRest, prevRest);
}
else {
throw Error("non exhaustive match");
}
});
};
RestWalker.prototype.walkTerminal = function (terminal, currRest, prevRest) { };
RestWalker.prototype.walkProdRef = function (refProd, currRest, prevRest) { };
RestWalker.prototype.walkFlat = function (flatProd, currRest, prevRest) {
// ABCDEF => after the D the rest is EF
var fullOrRest = currRest.concat(prevRest);
this.walk(flatProd, fullOrRest);
};
RestWalker.prototype.walkOption = function (optionProd, currRest, prevRest) {
// ABC(DE)?F => after the (DE)? the rest is F
var fullOrRest = currRest.concat(prevRest);
this.walk(optionProd, fullOrRest);
};
RestWalker.prototype.walkAtLeastOne = function (atLeastOneProd, currRest, prevRest) {
// ABC(DE)+F => after the (DE)+ the rest is (DE)?F
var fullAtLeastOneRest = [
new gast_public_1.Option({ definition: atLeastOneProd.definition })
].concat(currRest, prevRest);
this.walk(atLeastOneProd, fullAtLeastOneRest);
};
RestWalker.prototype.walkAtLeastOneSep = function (atLeastOneSepProd, currRest, prevRest) {
// ABC DE(,DE)* F => after the (,DE)+ the rest is (,DE)?F
var fullAtLeastOneSepRest = restForRepetitionWithSeparator(atLeastOneSepProd, currRest, prevRest);
this.walk(atLeastOneSepProd, fullAtLeastOneSepRest);
};
RestWalker.prototype.walkMany = function (manyProd, currRest, prevRest) {
// ABC(DE)*F => after the (DE)* the rest is (DE)?F
var fullManyRest = [
new gast_public_1.Option({ definition: manyProd.definition })
].concat(currRest, prevRest);
this.walk(manyProd, fullManyRest);
};
RestWalker.prototype.walkManySep = function (manySepProd, currRest, prevRest) {
// ABC (DE(,DE)*)? F => after the (,DE)* the rest is (,DE)?F
var fullManySepRest = restForRepetitionWithSeparator(manySepProd, currRest, prevRest);
this.walk(manySepProd, fullManySepRest);
};
RestWalker.prototype.walkOr = function (orProd, currRest, prevRest) {
var _this = this;
// ABC(D|E|F)G => when finding the (D|E|F) the rest is G
var fullOrRest = currRest.concat(prevRest);
// walk all different alternatives
utils_1.forEach(orProd.definition, function (alt) {
// wrapping each alternative in a single definition wrapper
// to avoid errors in computing the rest of that alternative in the invocation to computeInProdFollows
// (otherwise for OR([alt1,alt2]) alt2 will be considered in 'rest' of alt1
var prodWrapper = new gast_public_1.Alternative({ definition: [alt] });
_this.walk(prodWrapper, fullOrRest);
});
};
return RestWalker;
}());
exports.RestWalker = RestWalker;
function restForRepetitionWithSeparator(repSepProd, currRest, prevRest) {
var repSepRest = [
new gast_public_1.Option({
definition: [new gast_public_1.Terminal({ terminalType: repSepProd.separator })].concat(repSepProd.definition)
})
];
var fullRepSepRest = repSepRest.concat(currRest, prevRest);
return fullRepSepRest;
}
//# sourceMappingURL=rest.js.map
;