fruitsconfits
Version:
FruitsConfits - A well typed and sugared parser combinator framework for TypeScript/JavaScript.
83 lines (70 loc) • 3.2 kB
text/typescript
// Copyright (c) 2019 Shellyl_N and Authors
// license: ISC
// https://github.com/shellyln
export interface ParserInputWithCtx<T extends ArrayLike<T[number]>, C> {
src: T;
start: number;
end: number;
context: C;
templateArgs?: any[]; // For "template strings". NOTE: For backword compatibility, this is optional.
templateArgsPos?: number[]; // For "template strings". NOTE: For backword compatibility, this is optional.
}
export type ParserInput<T extends ArrayLike<T[number]>> = ParserInputWithCtx<T, undefined>;
export type StringParserInputWithCtx<C> = ParserInputWithCtx<string, C>;
export type StringParserInput = StringParserInputWithCtx<undefined>;
export class ParseError<T extends ArrayLike<T[number]>, C, R> extends Error {
public result: ParserFnFailedResult<T, C, R>;
constructor(result: ParserFnFailedResult<T, C, R>) {
super(result.message);
this.result = result;
}
}
export function parserInput<T extends ArrayLike<T[number]>>(src: T): ParserInputWithCtx<T, undefined>;
export function parserInput<T extends ArrayLike<T[number]>, C>(src: T, context: C): ParserInputWithCtx<T, C>;
export function parserInput<T extends ArrayLike<T[number]>, C>(src: T, context?: C): ParserInputWithCtx<T, C> {
return ({
src,
start: 0,
end: src.length,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
context: context as any,
templateArgs: [],
templateArgsPos: [],
});
}
export function templateStringsParserInput<C>(strings: TemplateStringsArray, values: any[], context?: C): ParserInputWithCtx<string, C> {
const templateArgsPos: number[] = [];
let pos = 0;
if (values.length) {
for (let i = 0; i < strings.length; i++) {
const x = strings[i];
if (i < values.length) {
templateArgsPos.push(pos + x.length);
pos += x.length + 1;
}
}
}
const joined = strings.join('\x00');
return ({
src: joined,
start: 0,
end: joined.length,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
context: context as any,
templateArgs: values,
templateArgsPos,
});
}
// tslint:disable-next-line: interface-over-type-literal
export type ParserFnSucceededResult<T extends ArrayLike<T[number]>, C, R> =
{succeeded: true, next: ParserInputWithCtx<T, C>, tokens: R[]};
// tslint:disable-next-line: interface-over-type-literal
export type ParserFnFailedResult<T extends ArrayLike<T[number]>, C, R> =
{succeeded: false, error: boolean, src: T, pos: number, message: string};
export type ParserFnWithCtx<T extends ArrayLike<T[number]>, C, R> =
(input: ParserInputWithCtx<T, C>) =>
ParserFnSucceededResult<T, C, R> |
ParserFnFailedResult<T, C, R>;
export type ParserFn<T extends ArrayLike<T[number]>, R> = ParserFnWithCtx<T, undefined, R>;
export type StringParserFnWithCtx<C, R> = ParserFnWithCtx<string, C, R>;
export type StringParserFn<R> = StringParserFnWithCtx<undefined, R>;