diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db5683..602b33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ ### Bugfixes --> +## 0.7.1 (2022/08/11) + +### Bugfixes +- (#12) Inference of type in parser.map() fails caused by T.alt not returning a Parser type. ## 0.7.0 (2022/08/11) diff --git a/examples/json/package.json b/examples/json/package.json index 5d4b394..0c0a319 100644 --- a/examples/json/package.json +++ b/examples/json/package.json @@ -12,6 +12,6 @@ "typescript": "4.7.4" }, "dependencies": { - "terrario": "0.4.0" + "terrario": "0.7.0" } } diff --git a/examples/json/src/index.ts b/examples/json/src/index.ts index ae8e22a..089d3fa 100644 --- a/examples/json/src/index.ts +++ b/examples/json/src/index.ts @@ -1,6 +1,6 @@ import * as T from 'terrario'; -const spaces = T.regexp(/[ \t\r\n]*/); +const spaces = T.str(/[ \t\r\n]*/); const lang = T.createLanguage({ value: r => T.alt([ @@ -17,7 +17,7 @@ const lang = T.createLanguage({ bool: r => T.alt([ T.str('true'), T.str('false'), - ]).map((value: 'true' | 'false') => { + ]).map(value => { return (value === 'true'); }), @@ -31,20 +31,18 @@ const lang = T.createLanguage({ ], 1), number: r => T.alt([ - T.regexp(/[+-]?[0-9]+\.[0-9]+/), - T.regexp(/[+-]?[0-9]+/), - ]).map((value: string) => { - return parseFloat(value); - }), + T.str(/[+-]?[0-9]+\.[0-9]+/), + T.str(/[+-]?[0-9]+/), + ]).map(value => Number(value)), object: r => { const entry = T.seq([ - r.string, + r.string as T.Parser, spaces, T.str(':'), spaces, - r.value, - ]).map((value: unknown[]) => { + r.value as T.Parser, + ]).map((value) => { return { key: value[0], value: value[4] }; }); const separator = T.seq([ @@ -58,7 +56,7 @@ const lang = T.createLanguage({ T.sep(entry, separator, 1).option(), spaces, T.str('}'), - ], 2).map((value: { key: string, value: unknown }[] | null) => { + ], 2).map(value => { if (value == null) { return {}; } @@ -79,10 +77,10 @@ const lang = T.createLanguage({ return T.seq([ T.str('['), spaces, - T.sep(r.value, separator, 1).option(), + T.sep(r.value as T.Parser, separator, 1).option(), spaces, T.str(']'), - ], 2).map((value: unknown[] | null) => { + ], 2).map((value) => { return (value != null ? value : []); }); }, diff --git a/package.json b/package.json index 7f727b0..e985d5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "terrario", - "version": "0.7.0", + "version": "0.7.1", "description": "A simple parser combinator library with TypeScript.", "main": "./built/index.js", "types": "./built/index.d.ts", diff --git a/src/index.ts b/src/index.ts index 58c4246..84160d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,9 @@ export type Failure = { export type Result = Success | Failure; export type ParserHandler = (input: string, index: number, state: any) => Result; +type ParserResult = T extends Parser ? R : never; +type ParserResults = T extends [infer Head, ...infer Tail] ? [ParserResult, ...ParserResults] : []; + export function success(index: number, value: T): Success { return { success: true, @@ -148,16 +151,13 @@ function strWithRegExp(pattern: RegExp): Parser { }); } -type SeqResultItem = T extends Parser ? R : never; -type SeqResult = T extends [infer Head, ...infer Tail] ? [SeqResultItem, ...SeqResult] : []; - -export function seq[]>(parsers: [...T]): Parser> +export function seq[]>(parsers: [...T]): Parser> export function seq[], U extends number>(parsers: [...T], select: U): T[U] export function seq(parsers: Parser[], select?: number) { return (select == null) ? seqAll(parsers) : seqSelect(parsers, select); } -function seqAll[]>(parsers: [...T]): Parser> { +function seqAll[]>(parsers: [...T]): Parser> { return new Parser((input, index, state) => { let result; let latestIndex = index; @@ -170,7 +170,7 @@ function seqAll[]>(parsers: [...T]): Parser)); + return success(latestIndex, (accum as ParserResults<[...T]>)); }); } @@ -178,11 +178,11 @@ function seqSelect[], U extends number>(parsers: [...T], s return seqAll(parsers).map(values => values[select]); } -export function alt[]>(parsers: T): T[number] { +export function alt[]>(parsers: [...T]): Parser[number]> { return new Parser((input, index, state) => { let result; for (let i = 0; i < parsers.length; i++) { - result = parsers[i].handler(input, index, state); + result = parsers[i].handler(input, index, state) as Result[number]>; if (result.success) { return result; }