core/converters/grammar.converter.ts

core/converters/grammar.converter.ts is a file in Bane's Lab Site. 53 lines of code and 14 definitions.

import type { GrammarRule, KeywordBlock } from "#types/grammar.types";
import { missingKeywordCategory, missingProductionGroup, missingTemplate } from "#configuration/strings/report.strings";
import { LINE_BREAK } from "#configuration/constants/code.constants";
import { ONTOLOGY } from "#core/generated/ontology.generated";

const HEADING = "# ";
const GAP = "\n\n";
const PRODUCES = " ::= ";
const OPEN = "<";
const CLOSE = ">";

export const joinRules = function joinRules(rules: readonly GrammarRule[]): string {
    return rules.map((rule) => HEADING + rule.title + LINE_BREAK + rule.grammar).join(GAP);
};

const rolesIn = function rolesIn(category: string, primary: boolean): KeywordBlock["keywords"] {
    return ONTOLOGY.grammar.categories.flatMap((group) =>
        group.keywords.flatMap((keyword) =>
            keyword.roles
                .filter((role, index) => role.category === category && (index === 0) === primary)
                .map((role) => ({ description: role.meaning, example: role.example, name: keyword.name })),
        ),
    );
};

export const keywordsOf = function keywordsOf(category: string): KeywordBlock {
    const keywords = [...rolesIn(category, true), ...rolesIn(category, false)];
    if (keywords.length === 0) {
        throw new Error(missingKeywordCategory(category));
    }
    return { keywords, kind: "keyword" };
};

export const productionsOf = function productionsOf(group: string, title: string): GrammarRule {
    const found = ONTOLOGY.grammar.groups.find((entry) => entry.group === group);
    if (found === undefined) {
        throw new Error(missingProductionGroup(group));
    }
    return {
        grammar: found.productions
            .map((production) => OPEN + production.lhs + CLOSE + PRODUCES + production.rhs)
            .join(LINE_BREAK),
        title,
    };
};

const templateOf = function templateOf(type: string): (typeof ONTOLOGY.grammar.templates)[number] {
    const found = ONTOLOGY.grammar.templates.find((template) => template.type === type);
    if (found === undefined) {
        throw new Error(missingTemplate(type));
    }
    return found;
};

export const templateBodyOf = function templateBodyOf(type: string): string {
    return templateOf(type).body;
};

export const templateConstraintsOf = function templateConstraintsOf(type: string): readonly string[] {
    return templateOf(type).constraints;
};