Error handling for asPreserves
This commit is contained in:
parent
d568fc56ce
commit
c9fa9c590b
|
@ -282,25 +282,30 @@ export class Reader extends ReaderBase<never> {
|
|||
export interface AsPreservesOptions<T extends Embeddable> {
|
||||
onGroup?: (g: Positioned<Group>) => Value<T>;
|
||||
onEmbedded?: (v: Value<T>) => Value<T>;
|
||||
error?: (tag: string, position: Position) => Value<T>;
|
||||
}
|
||||
|
||||
export function asPreserves<T extends Embeddable>(
|
||||
p: Positioned<Expr>,
|
||||
options: AsPreservesOptions<T> = {},
|
||||
): Value<T> {
|
||||
const error = options.error ?? ((tag, position) => {
|
||||
throw new Error(formatPosition(position) + ": " + tag);
|
||||
});
|
||||
|
||||
function nonCommas(p: Compound): Positioned<Expr>[] {
|
||||
return Array.from(p).filter(p => !Punct.isComma(p.item));
|
||||
}
|
||||
|
||||
function walk(p: Positioned<Expr>): Value<T> {
|
||||
if (p.item instanceof Punct) {
|
||||
throw new Error(formatPosition(p.position) + ": Invalid punctuation: " + p.item.text);
|
||||
return error('invalid-punctuation', p.position);
|
||||
} else if (p.item instanceof Embedded) {
|
||||
const e = walk({ position: p.position, item: p.item.expr });
|
||||
if (options.onEmbedded) {
|
||||
return options.onEmbedded(e);
|
||||
} else {
|
||||
throw new Error(formatPosition(p.position) + ": Cannot convert embedded values");
|
||||
return error('unexpected-embedded', p.position);
|
||||
}
|
||||
} else if (p.item instanceof Compound) {
|
||||
switch (p.item.variant) {
|
||||
|
@ -309,7 +314,7 @@ export function asPreserves<T extends Embeddable>(
|
|||
case 'record': {
|
||||
const vs = nonCommas(p.item).map(walk);
|
||||
if (vs.length < 1) {
|
||||
throw new Error(formatPosition(p.position) + ": Invalid record");
|
||||
return error('invalid-record', p.position);
|
||||
}
|
||||
const r = vs.slice(1) as unknown as VRecord<Value<T>, Value<T>[], T>;
|
||||
r.label = vs[0];
|
||||
|
@ -319,11 +324,11 @@ export function asPreserves<T extends Embeddable>(
|
|||
const d = new DictionaryMap<T>();
|
||||
const vs = nonCommas(p.item);
|
||||
if ((vs.length % 3) !== 0) {
|
||||
throw new Error(formatPosition(p.position) + ": Invalid dictionary: invalid length");
|
||||
return error('invalid-dictionary', p.position);
|
||||
}
|
||||
for (let i = 0; i < vs.length; i += 3) {
|
||||
if (!Punct.isColon(vs[i + 1].item)) {
|
||||
throw new Error(formatPosition(vs[i + 1].position) + ": Expected colon");
|
||||
return error('missing-colon', vs[i + 1].position);
|
||||
}
|
||||
const k = walk(vs[i]);
|
||||
const v = walk(vs[i + 2]);
|
||||
|
@ -335,7 +340,7 @@ export function asPreserves<T extends Embeddable>(
|
|||
if (options.onGroup) {
|
||||
return options.onGroup(p as Positioned<Group>);
|
||||
} else {
|
||||
throw new Error(formatPosition(p.position) + ": Unexpected group");
|
||||
return error('unexpected-group', p.position);
|
||||
}
|
||||
}
|
||||
case 'set':
|
||||
|
|
Loading…
Reference in New Issue