81 lines
3.0 KiB
TypeScript
81 lines
3.0 KiB
TypeScript
import { Dictionary, KeyedDictionary, Record, Value, preserves } from '@preserves/core';
|
|
|
|
export type Input = Value<never>;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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('/');
|
|
export const ___Boolean = Symbol.for('Boolean');
|
|
export const ___ByteString = Symbol.for('ByteString');
|
|
export const ___Double = Symbol.for('Double');
|
|
export const ___Float = Symbol.for('Float');
|
|
export const ___SignedInteger = Symbol.for('SignedInteger');
|
|
export const ___String = Symbol.for('String');
|
|
export const ___Symbol = Symbol.for('Symbol');
|
|
export const ___and = Symbol.for('and');
|
|
export const ___atom = Symbol.for('atom');
|
|
export const ___dict = Symbol.for('dict');
|
|
export const ___dictof = Symbol.for('dictof');
|
|
export const ___lit = Symbol.for('lit');
|
|
export const ___named = Symbol.for('named');
|
|
export const ___or = Symbol.for('or');
|
|
export const ___pointer = Symbol.for('pointer');
|
|
export const ___rec = Symbol.for('rec');
|
|
export const ___ref = Symbol.for('ref');
|
|
export const ___schema = Symbol.for('schema');
|
|
export const ___setof = Symbol.for('setof');
|
|
export const ___tuple = Symbol.for('tuple');
|
|
export const ___tuple_STAR_ = Symbol.for('tuple*');
|
|
export const ___version = Symbol.for('version');
|
|
|
|
export type Environment = Array<Schema>;
|
|
|
|
export const Schema = Record.makeConstructor<{
|
|
version: number,
|
|
definitions: KeyedDictionary<symbol, Pattern, never>,
|
|
}>()(Symbol.for('schema'), ['version', 'definitions']);
|
|
export type Schema = ReturnType<typeof Schema>;
|
|
|
|
export type AtomKind =
|
|
| typeof ___Boolean
|
|
| typeof ___Float
|
|
| typeof ___Double
|
|
| typeof ___SignedInteger
|
|
| typeof ___String
|
|
| typeof ___ByteString
|
|
| typeof ___Symbol;
|
|
|
|
export type Pattern =
|
|
| Record<typeof ___atom, [AtomKind], never>
|
|
| Record<typeof ___lit, [Input], never>
|
|
| Record<typeof ___ref, [symbol], never>
|
|
| Record<typeof ___or, [Array<Pattern>], never>
|
|
| Record<typeof ___and, [Array<Pattern>], never>
|
|
| Record<typeof ___pointer, [], never>
|
|
| Record<typeof ___rec, [Pattern, Pattern], never>
|
|
| Record<typeof ___tuple, [Array<NamedPattern>], never>
|
|
| Record<typeof ___tuple_STAR_, [Array<NamedPattern>, NamedPattern], never>
|
|
| Record<typeof ___setof, [Pattern], never>
|
|
| Record<typeof ___dictof, [Pattern, Pattern], never>
|
|
| Record<typeof ___dict, [Dictionary<Pattern, never>], never>;
|
|
|
|
export type NamedPattern = Record<typeof ___named, [symbol, Pattern], never> | Pattern;
|
|
|
|
export function lookup(env: Environment, name: symbol): Pattern {
|
|
for (const s of env) {
|
|
const p = Schema._.definitions(s).get(name);
|
|
if (p !== void 0) return p;
|
|
}
|
|
throw new Error(preserves`Schema: unbound name ${name}`);
|
|
}
|