preserves/implementations/javascript/packages/schema/src/meta.ts

66 lines
2.3 KiB
TypeScript
Raw Normal View History

import { Value, is, Position } from '@preserves/core';
2021-03-11 09:56:49 +00:00
import { ModulePath, Ref, Schema, Pattern, $thisModule, $definitions } from './gen/schema';
import { BASE } from './base';
import { SchemaSyntaxError } from './error';
2021-03-11 09:56:49 +00:00
export * from './gen/schema';
2021-03-09 14:59:40 +00:00
export type Input = Value<never>;
2021-03-09 15:45:57 +00:00
export function isValidToken(s: string, allowLeadingUnderscore = false): boolean {
if (allowLeadingUnderscore) {
return /^[a-zA-Z_][a-zA-Z_0-9]*$/.test(s);
} else {
return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s);
}
}
2021-03-09 14:59:40 +00:00
export const ANDSYM = Symbol.for('&');
export const DOT = Symbol.for('.');
export const DOTDOTDOT = Symbol.for('...');
export const EQUALS = Symbol.for('=');
export const ORSYM = Symbol.for('/');
2021-03-11 09:56:49 +00:00
export type SchemaEnvEntry = {
schemaModulePath: ModulePath,
typescriptModulePath: string | null, // null means it's $thisModule in disguise
schema: Schema,
};
export type Environment = Array<SchemaEnvEntry>;
2021-03-09 14:59:40 +00:00
export function lookup<R>(namePos: Position | null,
name: Ref,
2021-03-11 09:56:49 +00:00
env: Environment,
kLocal: (p: Pattern) => R,
kBase: (p: Pattern) => R,
kOther: (mod: string, modPath: string, p: Pattern) => R): R
{
for (const e of env) {
if (is(e.schemaModulePath, Ref._.module(name)) ||
(e.typescriptModulePath === null && Ref._.module(name) === $thisModule))
{
const p = Schema._.details(e.schema).get($definitions).get(Ref._.name(name));
if (p !== void 0) {
if (e.typescriptModulePath === null) {
return kLocal(p);
} else {
const modsym = '_i_' + e.schemaModulePath.map(s => s.description!).join('$');
return kOther(modsym, e.typescriptModulePath, p);
}
}
}
}
2021-03-09 14:59:40 +00:00
2021-03-11 09:56:49 +00:00
if (Ref._.module(name) === $thisModule) {
const p = Schema._.details(BASE).get($definitions).get(Ref._.name(name));
if (p !== void 0) return kBase(p);
2021-03-09 14:59:40 +00:00
}
2021-03-11 09:56:49 +00:00
throw new SchemaSyntaxError(`Undefined reference: ${formatRef(name)}`, namePos);
}
export function formatRef(r: Ref): string {
return [... r[0] === $thisModule ? [] : r[0], r[1]].map(s => s.description!).join('.');
2021-03-09 14:59:40 +00:00
}