First commit.

Signed-off-by: Chen Xiao <abigwc@gmail.com>
This commit is contained in:
Chen Xiao
2026-05-08 14:43:16 +08:00
commit 0b64e2de94
10989 changed files with 2253791 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
import {
AbstractProduction,
Alternation,
Alternative,
NonTerminal,
Option,
Repetition,
RepetitionMandatory,
RepetitionMandatoryWithSeparator,
RepetitionWithSeparator,
Rule,
Terminal,
} from "./model.js";
import type { IProduction, IProductionWithOccurrence } from "@chevrotain/types";
export function isSequenceProd(
prod: IProduction,
): prod is { definition: IProduction[] } & IProduction {
return (
prod instanceof Alternative ||
prod instanceof Option ||
prod instanceof Repetition ||
prod instanceof RepetitionMandatory ||
prod instanceof RepetitionMandatoryWithSeparator ||
prod instanceof RepetitionWithSeparator ||
prod instanceof Terminal ||
prod instanceof Rule
);
}
export function isOptionalProd(
prod: IProduction,
alreadyVisited: NonTerminal[] = [],
): boolean {
const isDirectlyOptional =
prod instanceof Option ||
prod instanceof Repetition ||
prod instanceof RepetitionWithSeparator;
if (isDirectlyOptional) {
return true;
}
// note that this can cause infinite loop if one optional empty TOP production has a cyclic dependency with another
// empty optional top rule
// may be indirectly optional ((A?B?C?) | (D?E?F?))
if (prod instanceof Alternation) {
// for OR its enough for just one of the alternatives to be optional
return (<Alternation>prod).definition.some((subProd: IProduction) => {
return isOptionalProd(subProd, alreadyVisited);
});
} else if (prod instanceof NonTerminal && alreadyVisited.includes(prod)) {
// avoiding stack overflow due to infinite recursion
return false;
} else if (prod instanceof AbstractProduction) {
if (prod instanceof NonTerminal) {
alreadyVisited.push(prod);
}
return (<AbstractProduction>prod).definition.every(
(subProd: IProduction) => {
return isOptionalProd(subProd, alreadyVisited);
},
);
} else {
return false;
}
}
export function isBranchingProd(
prod: IProduction,
): prod is { definition: IProduction[] } & IProduction {
return prod instanceof Alternation;
}
export function getProductionDslName(prod: IProductionWithOccurrence): string {
/* istanbul ignore else */
if (prod instanceof NonTerminal) {
return "SUBRULE";
} else if (prod instanceof Option) {
return "OPTION";
} else if (prod instanceof Alternation) {
return "OR";
} else if (prod instanceof RepetitionMandatory) {
return "AT_LEAST_ONE";
} else if (prod instanceof RepetitionMandatoryWithSeparator) {
return "AT_LEAST_ONE_SEP";
} else if (prod instanceof RepetitionWithSeparator) {
return "MANY_SEP";
} else if (prod instanceof Repetition) {
return "MANY";
} else if (prod instanceof Terminal) {
return "CONSUME";
/* c8 ignore next 3 */
} else {
throw Error("non exhaustive match");
}
}