Skip to content

Commit 13fbe6d

Browse files
committed
impl type transformers
1 parent c3905a6 commit 13fbe6d

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

src/sifter/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { CmdVerb } from './types.ts';
1111

1212
export * from './parser.js';
1313
export * from './state.js';
14+
export * from './transforms.js';
1415
export type * from './types.ts';
1516

1617

src/sifter/transforms.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { ParseContext } from './state.js';
2+
import type { Transformer } from './types.ts';
3+
4+
/**
5+
* A raw string parser.
6+
* @returns A cmd token transformer.
7+
*/
8+
export function stringType()
9+
{
10+
return (ctx: ParseContext): string => {
11+
return ctx.consumeToken();
12+
};
13+
}
14+
15+
/**
16+
* A float parser.
17+
* @returns A cmd token transformer.
18+
*/
19+
export function floatType()
20+
{
21+
return (ctx: ParseContext): number => {
22+
let tok = ctx.consumeToken();
23+
const sign = tok[0] == '-' ? -1 : 1;
24+
if ('+-'.includes(tok[0]))
25+
tok = tok.slice(1);
26+
27+
if (tok == 'inf') return sign * Infinity;
28+
if (tok == 'nan') return NaN;
29+
30+
if (!/^[0-9]*(\.[0-9]+)?$/.test(tok))
31+
throw 'invalid float: ' + tok;
32+
33+
const val = parseFloat(tok);
34+
if (isNaN(val))
35+
throw 'couldn\'t parse float: ' + tok;
36+
return val * sign;
37+
};
38+
}
39+
40+
/**
41+
* A boolean parser.
42+
* @returns A cmd token transformer.
43+
*/
44+
export function boolType()
45+
{
46+
return (ctx: ParseContext): boolean => {
47+
let tok = ctx.consumeToken();
48+
const idx = ['false', 'true'].indexOf(tok);
49+
50+
if (idx == -1)
51+
throw 'invalid boolean: ' + tok;
52+
return !!idx;
53+
};
54+
}
55+
56+
/**
57+
* An integer parser.
58+
* @returns A cmd token transformer.
59+
*/
60+
export function intType()
61+
{
62+
return (ctx: ParseContext): number => {
63+
const tok = ctx.consumeToken();
64+
const val = parseInt(tok);
65+
66+
if (isNaN(val))
67+
throw 'invalid integer: ' + tok;
68+
return val;
69+
};
70+
}
71+
72+
/**
73+
* A rest argument parser.
74+
* @param parser The parser to transform values.
75+
* @returns A cmd token transformer.
76+
*/
77+
export function restType<T>(parser: Transformer<T>)
78+
{
79+
return (ctx: ParseContext): T[] => {
80+
const vals: T[] = [];
81+
82+
while (!ctx.isEndOfTokens)
83+
vals.push(parser(ctx));
84+
return vals;
85+
};
86+
}
87+
88+
/**
89+
* An enumeration parser.
90+
* @param opts The enum options.
91+
* @returns The selected value.
92+
*/
93+
export function enumType(...opts: string[])
94+
{
95+
return (ctx: ParseContext): any => {
96+
const tok = ctx.consumeToken();
97+
98+
if (opts.includes(tok))
99+
throw 'unknown enum option: ' + tok + '\n' +
100+
'expected one of: ' + opts.join(', ');
101+
102+
return tok;
103+
};
104+
}

0 commit comments

Comments
 (0)