chevrotain
Version:
Chevrotain is a high performance fault tolerant javascript parsing DSL for building recursive decent parsers
250 lines • 11.2 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var tokens_public_1 = require("../../scan/tokens_public");
var utils_1 = require("../../utils/utils");
var lang_extensions_1 = require("../../lang/lang_extensions");
var keys_1 = require("../grammar/keys");
var gast_public_1 = require("../grammar/gast/gast_public");
var gast_visitor_public_1 = require("../grammar/gast/gast_visitor_public");
function addTerminalToCst(node, token, tokenTypeName) {
;
node.children[tokenTypeName].push(token);
}
exports.addTerminalToCst = addTerminalToCst;
function addNoneTerminalToCst(node, ruleName, ruleResult) {
;
node.children[ruleName].push(ruleResult);
}
exports.addNoneTerminalToCst = addNoneTerminalToCst;
var NamedDSLMethodsCollectorVisitor = /** @class */ (function (_super) {
__extends(NamedDSLMethodsCollectorVisitor, _super);
function NamedDSLMethodsCollectorVisitor(ruleIdx) {
var _this = _super.call(this) || this;
_this.result = [];
_this.ruleIdx = ruleIdx;
return _this;
}
NamedDSLMethodsCollectorVisitor.prototype.collectNamedDSLMethod = function (node, newNodeConstructor, methodIdx) {
// TODO: better hack to copy what we need here...
if (!utils_1.isUndefined(node.name)) {
// copy without name so this will indeed be processed later.
var nameLessNode = void 0;
if (node instanceof gast_public_1.Option ||
node instanceof gast_public_1.Repetition ||
node instanceof gast_public_1.RepetitionMandatory ||
node instanceof gast_public_1.Alternation) {
nameLessNode = new newNodeConstructor({
definition: node.definition,
idx: node.idx
});
}
else if (node instanceof gast_public_1.RepetitionMandatoryWithSeparator ||
node instanceof gast_public_1.RepetitionWithSeparator) {
nameLessNode = new newNodeConstructor({
definition: node.definition,
idx: node.idx,
separator: node.separator
});
}
else {
/* istanbul ignore next */
throw Error("non exhaustive match");
}
var def = [nameLessNode];
var key = keys_1.getKeyForAutomaticLookahead(this.ruleIdx, methodIdx, node.idx);
this.result.push({ def: def, key: key, name: node.name, orgProd: node });
}
};
NamedDSLMethodsCollectorVisitor.prototype.visitOption = function (node) {
this.collectNamedDSLMethod(node, gast_public_1.Option, keys_1.OPTION_IDX);
};
NamedDSLMethodsCollectorVisitor.prototype.visitRepetition = function (node) {
this.collectNamedDSLMethod(node, gast_public_1.Repetition, keys_1.MANY_IDX);
};
NamedDSLMethodsCollectorVisitor.prototype.visitRepetitionMandatory = function (node) {
this.collectNamedDSLMethod(node, gast_public_1.RepetitionMandatory, keys_1.AT_LEAST_ONE_IDX);
};
NamedDSLMethodsCollectorVisitor.prototype.visitRepetitionMandatoryWithSeparator = function (node) {
this.collectNamedDSLMethod(node, gast_public_1.RepetitionMandatoryWithSeparator, keys_1.AT_LEAST_ONE_SEP_IDX);
};
NamedDSLMethodsCollectorVisitor.prototype.visitRepetitionWithSeparator = function (node) {
this.collectNamedDSLMethod(node, gast_public_1.RepetitionWithSeparator, keys_1.MANY_SEP_IDX);
};
NamedDSLMethodsCollectorVisitor.prototype.visitAlternation = function (node) {
var _this = this;
this.collectNamedDSLMethod(node, gast_public_1.Alternation, keys_1.OR_IDX);
var hasMoreThanOneAlternative = node.definition.length > 1;
utils_1.forEach(node.definition, function (currFlatAlt, altIdx) {
if (!utils_1.isUndefined(currFlatAlt.name)) {
var def = currFlatAlt.definition;
if (hasMoreThanOneAlternative) {
def = [new gast_public_1.Option({ definition: currFlatAlt.definition })];
}
else {
// mandatory
def = currFlatAlt.definition;
}
var key = keys_1.getKeyForAltIndex(_this.ruleIdx, keys_1.OR_IDX, node.idx, altIdx);
_this.result.push({
def: def,
key: key,
name: currFlatAlt.name,
orgProd: currFlatAlt
});
}
});
};
return NamedDSLMethodsCollectorVisitor;
}(gast_visitor_public_1.GAstVisitor));
exports.NamedDSLMethodsCollectorVisitor = NamedDSLMethodsCollectorVisitor;
function analyzeCst(topRules, fullToShortName) {
var result = { dictDef: new lang_extensions_1.HashTable(), allRuleNames: [] };
utils_1.forEach(topRules, function (currTopRule) {
var currChildrenNames = buildChildDictionaryDef(currTopRule.definition);
var currTopRuleShortName = fullToShortName.get(currTopRule.name);
result.dictDef.put(currTopRuleShortName, buildInitDefFunc(currChildrenNames));
result.allRuleNames.push(currTopRule.name);
var namedCollectorVisitor = new NamedDSLMethodsCollectorVisitor(currTopRuleShortName);
currTopRule.accept(namedCollectorVisitor);
utils_1.forEach(namedCollectorVisitor.result, function (_a) {
var def = _a.def, key = _a.key, name = _a.name;
var currNestedChildrenNames = buildChildDictionaryDef(def);
result.dictDef.put(key, buildInitDefFunc(currNestedChildrenNames));
result.allRuleNames.push(currTopRule.name + name);
});
});
return result;
}
exports.analyzeCst = analyzeCst;
function buildInitDefFunc(childrenNames) {
var funcString = "return {\n";
funcString += utils_1.map(childrenNames, function (currName) { return "\"" + currName + "\" : []"; }).join(",\n");
funcString += "}";
// major performance optimization, faster to create the children dictionary this way
// versus iterating over the childrenNames each time.
return Function(funcString);
}
function buildChildDictionaryDef(initialDef) {
var result = [];
var possiblePaths = [];
possiblePaths.push({ def: initialDef });
var currDef;
var currInIteration;
var currInOption;
var currResult;
function addSingleItemToResult(itemName) {
result.push(itemName);
var nextPath = {
def: utils_1.drop(currDef),
inIteration: currInIteration,
inOption: currInOption,
currResult: utils_1.cloneObj(currResult)
};
possiblePaths.push(nextPath);
}
while (!utils_1.isEmpty(possiblePaths)) {
var currPath = possiblePaths.pop();
currDef = currPath.def;
currInIteration = currPath.inIteration;
currInOption = currPath.inOption;
currResult = currPath.currResult;
// For Example: an empty path could exist in a valid grammar in the case of an EMPTY_ALT
if (utils_1.isEmpty(currDef)) {
continue;
}
var prod = currDef[0];
if (prod instanceof gast_public_1.Terminal) {
var terminalName = tokens_public_1.tokenName(prod.terminalType);
addSingleItemToResult(terminalName);
}
else if (prod instanceof gast_public_1.NonTerminal) {
var nonTerminalName = prod.nonTerminalName;
addSingleItemToResult(nonTerminalName);
}
else if (prod instanceof gast_public_1.Option) {
if (!utils_1.isUndefined(prod.name)) {
addSingleItemToResult(prod.name);
}
else {
var nextPathWith = {
def: prod.definition.concat(utils_1.drop(currDef))
};
possiblePaths.push(nextPathWith);
}
}
else if (prod instanceof gast_public_1.RepetitionMandatory ||
prod instanceof gast_public_1.Repetition) {
if (!utils_1.isUndefined(prod.name)) {
addSingleItemToResult(prod.name);
}
else {
var nextDef = prod.definition.concat(utils_1.drop(currDef));
var nextPath = {
def: nextDef
};
possiblePaths.push(nextPath);
}
}
else if (prod instanceof gast_public_1.RepetitionMandatoryWithSeparator ||
prod instanceof gast_public_1.RepetitionWithSeparator) {
if (!utils_1.isUndefined(prod.name)) {
addSingleItemToResult(prod.name);
}
else {
var separatorGast = new gast_public_1.Terminal({
terminalType: prod.separator
});
var secondIteration = new gast_public_1.Repetition({
definition: [separatorGast].concat(prod.definition),
idx: prod.idx
});
// Hack: X (, X)* --> (, X) because it is identical in terms of identifying "isCollection?"
var nextDef = [secondIteration].concat(utils_1.drop(currDef));
var nextPath = {
def: nextDef
};
possiblePaths.push(nextPath);
}
}
else if (prod instanceof gast_public_1.Alternation) {
/* istanbul ignore else */
// IGNORE ABOVE ELSE
if (!utils_1.isUndefined(prod.name)) {
addSingleItemToResult(prod.name);
}
else {
// the order of alternatives is meaningful, FILO (Last path will be traversed first).
for (var i = prod.definition.length - 1; i >= 0; i--) {
var currAlt = prod.definition[i];
// named alternatives
if (!utils_1.isUndefined(currAlt.name)) {
addSingleItemToResult(currAlt.name);
}
else {
var newDef = currAlt.definition.concat(utils_1.drop(currDef));
var currAltPath = {
def: newDef
};
possiblePaths.push(currAltPath);
}
}
}
}
else {
/* istanbul ignore next */ throw Error("non exhaustive match");
}
}
return result;
}
exports.buildChildDictionaryDef = buildChildDictionaryDef;
//# sourceMappingURL=cst.js.map