@fauton/cfg
Version:
A package to work with context free grammars and LL1 parsers
43 lines (42 loc) • 2.17 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateCfg = void 0;
/**
* Validates a cfg
* @param cfg Input cfg to validate
*/
function validateCfg(cfg) {
const { startVariable, terminals, productionRules, variables } = cfg;
// Check if all the variables is present in transition record
const productionRulesEntries = Object.entries(productionRules);
if (productionRulesEntries.length !== variables.length) {
throw new Error('All variables must be present in the transition record');
}
const terminalsSet = new Set(terminals);
const variablesSet = new Set(variables);
// Validate that all the keys of transition record are variables
productionRulesEntries.forEach(([productionRuleVariable, productionRuleSubstitutions]) => {
if (!variablesSet.has(productionRuleVariable)) {
throw new Error(`Transition record contains a variable ${productionRuleVariable}, that is not present in variables array`);
}
// Check if all the substitutions contain either variable or terminal
productionRuleSubstitutions.forEach((productionRuleSubstitution) => {
const tokens = productionRuleSubstitution.split(' ');
for (let index = 0; index < tokens.length; index += 1) {
const productionRuleSubstitutionToken = tokens[index];
// Check if the letter is a terminal
const isTerminal = terminalsSet.has(productionRuleSubstitutionToken);
// Check if the letter is a variable
const isVariable = variablesSet.has(productionRuleSubstitutionToken);
if (!isTerminal && !isVariable) {
throw new Error(`Transition record substitution chunk ${productionRuleSubstitutionToken} is neither a variable nor a terminal`);
}
}
});
});
// Check if the starting variable is part of variables
if (!variablesSet.has(startVariable)) {
throw new Error(`Starting variable must be part of variables array`);
}
}
exports.validateCfg = validateCfg;