spellu-core
Version:
Spellu is a parser combinator engine.
290 lines (288 loc) • 17.7 kB
TypeScript
declare namespace spellu {
type SourceFile = {
fileName: string;
path: string;
text: string;
};
type Token = {
type: string;
file?: SourceFile;
lineNo: number;
columnNo: number;
string: string;
value?: string | Token[];
};
}
declare namespace spellu {
interface Failable {
isFailure(): boolean;
}
interface Either<Left, Right> extends Failable {
extract(): Left | Right;
resolve<T>(left?: () => T, right?: () => T): T;
}
interface Maybe extends Failable {
}
interface Just extends Maybe {
}
interface Nothing extends Maybe {
}
interface Listable extends Failable {
}
interface List extends Listable {
}
interface Nil extends Listable {
}
}
declare namespace spellu {
type SourceStreamOption = {
normalize?: boolean;
inputLength?: number;
inputOffset?: number;
startingLineNo?: number;
startingColumnNo?: number;
};
type Location = {
lineNo: number;
columnNo: number;
};
class SourceStream implements ParserSource {
protected readonly _input: string;
protected readonly inputLength: number;
protected inputOffset: number;
protected lineNo: number;
protected columnNo: number;
constructor(input: string, option?: SourceStreamOption);
readonly input: string;
protected normalizeSource(string: string): string;
protected stripUtf8Bom(string: string): string;
protected normalizeNewLine(string: string): string;
protected addTrailNewLine(string: string): string;
location(): Location;
charCodeAt(offset?: number): number;
substring(length: number): string;
nowEol(): boolean;
nowEos(): boolean;
startsWith(pattern: string): boolean;
test(pattern: string | RegExp): boolean;
skip(pattern: string | RegExp): void;
consume(pattern: string | RegExp): boolean;
scan(type: string, pattern: string | RegExp, matchIndex?: number): Token | null;
scanBlock(type: string, openString: string, closeString: string, option?: {
allowRecursive?: boolean;
allowMultiline?: boolean;
innerPattern?: string;
}): Token | null;
read<T>(pattern: string | RegExp, converter: (result: RegExpExecArray) => T, defaultValue: T): T;
match<T>(pattern: string | RegExp, converter: (result: RegExpExecArray) => T, defaultValue: T, option?: {
locationUpdate?: boolean;
}): T;
protected regexp(stringOrPattern: string | RegExp): RegExp;
protected matchBlock(openString: string, closeString: string, innerPattern: string): number;
protected matchBlockRecursive(openString: string, closeString: string, innerPattern: string): number;
protected escapeForReadAhead(string: string): string;
token(type: string, location?: Location, string?: string, value?: string): Token;
protected updateLocation(string: string): void;
}
}
declare namespace spellu {
class Tokenizer {
readonly source: SourceStream;
protected token: Token;
constructor(source: Token | SourceStream);
available(): boolean;
setToken(token: Token): void;
chain(): Chain;
skip(pattern: RegExp): Chain;
consume(pattern: RegExp): Chain;
scan(type: string, pattern: string | RegExp, matchIndex?: number, innerTokenizer?: (source: SourceStream) => any): Chain;
scanBlock(type: string, openPattern: string, closePattern: string, option?: {}, innerTokenizer?: (source: SourceStream) => any): Chain;
expect(message: string): void;
error(code: string, message: string): never;
fail(): void;
fatal(message: string): void;
result(): Token;
}
class Chain {
protected tokenizer: Tokenizer;
protected source: SourceStream;
protected result?: boolean;
constructor(tokenizer: Tokenizer);
call(closure: (chain: this) => void): this;
skip(pattern: RegExp): this;
consume(pattern: RegExp): this;
scan(type: string, pattern: string | RegExp, matchIndex?: number, innerTokenizer?: (source: SourceStream) => any): this;
scanBlock(type: string, openPattern: string, closePattern: string, option?: {}, innerTokenizer?: (source: SourceStream) => any): this;
expect(message: string): this;
error(): void;
fail(message?: string): void;
fatal(message?: string): void;
ok(): boolean;
ng(): boolean;
}
}
declare namespace spellu {
interface ParserInputString {
nowEos(): boolean;
location(): Location;
scan(pattern: string): string | null;
scan(pattern: RegExp, matchIndex?: number): string | null;
}
interface ParserInputToken {
nowEos(): boolean;
location(): Location;
scan(type: string, pattern: string): Token | null;
scan(type: string, pattern: RegExp, matchIndex?: number): Token | null;
nextTokenIf(type: string): Token | null;
}
interface ParserSource {
nowEos(): boolean;
location(): Location;
skip(pattern: RegExp): void;
consume(pattern: RegExp): boolean;
scan(type: string, pattern: string | RegExp, matchIndex?: number): Token | null;
}
interface Diagnostic {
message: string;
lineNo?: number;
columnNo?: number;
}
type ParserResult<V> = ParserSuccess<V> | ParserFailure;
type ParserSuccess<V> = Success<ParserSource, V>;
type ParserFailure = Failure<ParserSource, Diagnostic>;
interface ParsedValue<C, S, F> extends Either<F, S> {
_: C;
isSuccess(): boolean;
isFailure(): boolean;
success(callback: (value: S) => void): ParsedValue<C, S, F>;
failure(callback: (diagnostics: F) => void): ParsedValue<C, S, F>;
extract(): S | F;
resolve<T>(left?: (diagnostics: F) => T, right?: (value: S) => T): T | null;
}
class Success<C, V> implements ParsedValue<C, V, never> {
_: C;
value: V;
constructor(_: C, value: V);
isSuccess(): boolean;
isFailure(): boolean;
success(callback: (value: V) => void): this;
failure(callback: (diagnostics: never) => void): this;
extract(): V;
resolve<T>(left?: (diagnostics: never) => T, right?: (value: V) => T): T | null;
}
class Failure<C, D> implements ParsedValue<C, never, D[]> {
_: C;
diagnostics: D[];
constructor(_: C, diagnostics?: D[]);
isSuccess(): boolean;
isFailure(): boolean;
success(callback: (value: never) => void): this;
failure(callback: (diagnostics: D[]) => void): this;
extract(): D[];
resolve<T>(left?: (diagnostics: D[]) => T, right?: (value: never) => T): T | null;
}
interface Parser<V> {
(_: ParserSource): ParserResult<V>;
many0: () => Parser<V[]>;
many1: () => Parser<V[]>;
optional: () => Parser<V | null>;
or: <W>(parser: Parser<W>) => Parser<V | W>;
times: (count: number) => Parser<V[]>;
timesMany: (min: number) => Parser<V[]>;
timesBetween: (min: number, max: number) => Parser<V[]>;
expect(callback: (value: V) => boolean, message: string): Parser<V>;
reduce<T>(callback: (value: V) => T): Parser<T>;
inspect(callback: (result: ParserResult<V>) => void): Parser<V>;
}
interface Combinator<V> {
(...args: any[]): Parser<V>;
}
function createParser<V>(evaluator: (_: ParserSource) => ParserResult<V>): Parser<V>;
function success<V>(_: ParserSource, value: V): ParserSuccess<V>;
function failure<V>(_: ParserSource, diagnostic: Diagnostic): ParserFailure;
function failure<V>(_: ParserSource, diagnostics: Diagnostic[]): ParserFailure;
function and<V>(): Parser<[never]>;
function and<V1>(p1: Parser<V1>): Parser<[V1]>;
function and<V1, V2>(p1: Parser<V1>, p2: Parser<V2>): Parser<[V1, V2]>;
function and<V1, V2, V3>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>): Parser<[V1, V2, V3]>;
function and<V1, V2, V3, V4>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>): Parser<[V1, V2, V3, V4]>;
function and<V1, V2, V3, V4, V5>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>): Parser<[V1, V2, V3, V4, V5]>;
function and<V1, V2, V3, V4, V5, V6>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>): Parser<[V1, V2, V3, V4, V5, V6]>;
function and<V1, V2, V3, V4, V5, V6, V7>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>): Parser<[V1, V2, V3, V4, V5, V6, V7]>;
function and<V1, V2, V3, V4, V5, V6, V7, V8>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8]>;
function and<V1, V2, V3, V4, V5, V6, V7, V8, V9>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>, p9: Parser<V9>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8, V9]>;
function and(...parsers: Parser<any>[]): Parser<any[]>;
function or<V>(): Parser<[never]>;
function or<V1>(p1: Parser<V1>): Parser<V1 | null>;
function or<V1, V2>(p1: Parser<V1>, p2: Parser<V2>): Parser<V1 | V2 | null>;
function or<V1, V2, V3>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>): Parser<V1 | V2 | V3 | null>;
function or<V1, V2, V3, V4>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>): Parser<V1 | V2 | V3 | V4 | null>;
function or<V1, V2, V3, V4, V5>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>): Parser<V1 | V2 | V3 | V4 | V5 | null>;
function or<V1, V2, V3, V4, V5, V6>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>): Parser<V1 | V2 | V3 | V4 | V5 | V6 | null>;
function or<V1, V2, V3, V4, V5, V6, V7>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>): Parser<V1 | V2 | V3 | V4 | V5 | V6 | V7 | null>;
function or<V1, V2, V3, V4, V5, V6, V7, V8>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>): Parser<V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | null>;
function or<V1, V2, V3, V4, V5, V6, V7, V8, V9>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>, p9: Parser<V9>): Parser<V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | null>;
function or<V>(...parsers: Parser<V>[]): Parser<V>;
function option<V>(parser: Parser<V>): Parser<V | null>;
function many<V>(parser: Parser<V>, min: number, max?: number): Parser<V[]>;
function $$<V1>(p1: Parser<V1>): Parser<[V1]>;
function $$<V1, V2>(p1: Parser<V1>, p2: Parser<V2>): Parser<[V1, V2]>;
function $$<V1, V2, V3>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>): Parser<[V1, V2, V3]>;
function $$<V1, V2, V3, V4>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>): Parser<[V1, V2, V3, V4]>;
function $$<V1, V2, V3, V4, V5>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>): Parser<[V1, V2, V3, V4, V5]>;
function $$<V1, V2, V3, V4, V5, V6>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>): Parser<[V1, V2, V3, V4, V5, V6]>;
function $$<V1, V2, V3, V4, V5, V6, V7>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>): Parser<[V1, V2, V3, V4, V5, V6, V7]>;
function $$<V1, V2, V3, V4, V5, V6, V7, V8>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8]>;
function $$<V1, V2, V3, V4, V5, V6, V7, V8, V9>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>, p9: Parser<V9>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8, V9]>;
function $$(...parsers: (string | Parser<any>)[]): Parser<any>;
function $0<V1>(p1: Parser<V1>): Parser<V1[]>;
function $0<V1, V2>(p1: Parser<V1>, p2: Parser<V2>): Parser<[V1, V2][]>;
function $0<V1, V2, V3>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>): Parser<[V1, V2, V3][]>;
function $0<V1, V2, V3, V4>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>): Parser<[V1, V2, V3, V4][]>;
function $0<V1, V2, V3, V4, V5>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>): Parser<[V1, V2, V3, V4, V5][]>;
function $0<V1, V2, V3, V4, V5, V6>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>): Parser<[V1, V2, V3, V4, V5, V6][]>;
function $0<V1, V2, V3, V4, V5, V6, V7>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>): Parser<[V1, V2, V3, V4, V5, V6, V7][]>;
function $0<V1, V2, V3, V4, V5, V6, V7, V8>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8][]>;
function $0<V1, V2, V3, V4, V5, V6, V7, V8, V9>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>, p9: Parser<V9>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8, V9][]>;
function $0(parser: Parser<any>, ...parsers: (string | Parser<any>)[]): Parser<any[][]>;
function $1<V1>(p1: Parser<V1>): Parser<V1[]>;
function $1<V1, V2>(p1: Parser<V1>, p2: Parser<V2>): Parser<[V1, V2][]>;
function $1<V1, V2, V3>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>): Parser<[V1, V2, V3][]>;
function $1<V1, V2, V3, V4>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>): Parser<[V1, V2, V3, V4][]>;
function $1<V1, V2, V3, V4, V5>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>): Parser<[V1, V2, V3, V4, V5][]>;
function $1<V1, V2, V3, V4, V5, V6>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>): Parser<[V1, V2, V3, V4, V5, V6][]>;
function $1<V1, V2, V3, V4, V5, V6, V7>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>): Parser<[V1, V2, V3, V4, V5, V6, V7][]>;
function $1<V1, V2, V3, V4, V5, V6, V7, V8>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8][]>;
function $1<V1, V2, V3, V4, V5, V6, V7, V8, V9>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>, p9: Parser<V9>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8, V9][]>;
function $1(parser: Parser<any>, ...parsers: (string | Parser<any>)[]): Parser<any[][]>;
function $_<V1>(p1: Parser<V1>): Parser<V1 | null>;
function $_<V1, V2>(p1: Parser<V1>, p2: Parser<V2>): Parser<[V1, V2] | null>;
function $_<V1, V2, V3>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>): Parser<[V1, V2, V3] | null>;
function $_<V1, V2, V3, V4>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>): Parser<[V1, V2, V3, V4] | null>;
function $_<V1, V2, V3, V4, V5>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>): Parser<[V1, V2, V3, V4, V5] | null>;
function $_<V1, V2, V3, V4, V5, V6>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>): Parser<[V1, V2, V3, V4, V5, V6] | null>;
function $_<V1, V2, V3, V4, V5, V6, V7>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>): Parser<[V1, V2, V3, V4, V5, V6, V7] | null>;
function $_<V1, V2, V3, V4, V5, V6, V7, V8>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8] | null>;
function $_<V1, V2, V3, V4, V5, V6, V7, V8, V9>(p1: Parser<V1>, p2: Parser<V2>, p3: Parser<V3>, p4: Parser<V4>, p5: Parser<V5>, p6: Parser<V6>, p7: Parser<V7>, p8: Parser<V8>, p9: Parser<V9>): Parser<[V1, V2, V3, V4, V5, V6, V7, V8, V9] | null>;
function $_(parser: Parser<any>, ...parsers: (string | Parser<any>)[]): Parser<any[] | null>;
function delay<V>(combinator: Combinator<V>, ...args: any[]): Parser<V>;
function always<T>(value?: T): Parser<T>;
function never<T>(message?: string): Parser<T>;
function parse<V>(parser: Parser<V>, input: string): ParserResult<V>;
}
declare namespace spellu {
function p<V>(def: (source: ParserSource) => V | Diagnostic | Diagnostic[]): Parser<V>;
const string: {
eos: () => Parser<string>;
string: (string: string) => Parser<string>;
regex: (pattern: RegExp) => Parser<string>;
};
}
declare namespace spellu {
const token: {
eos: (type: string) => Parser<Token>;
string: (type: string, string?: string) => Parser<Token>;
regex: (type: string, pattern: RegExp, matchIndex?: number) => Parser<Token>;
};
}
export = spellu;