type-unlambda/src/parser.ts

51 lines
1.6 KiB
TypeScript
Raw Normal View History

2020-11-06 09:07:33 +00:00
/**
* parser.ts - Unlambda parser.
*
* @author CismonX <admin@cismon.net>
* @license MIT
*/
2021-06-03 13:27:35 +00:00
import { Expression, FuncChar, FuncNoChar, WhiteSpace } from './language';
2020-11-06 09:07:33 +00:00
/**
2021-06-03 13:27:35 +00:00
* Parse result is a tuple `[E, R]`, where `E` is the parsed expression,
* and `R` is the unparsed code fragment.
2020-11-06 09:07:33 +00:00
*
2021-06-03 13:27:35 +00:00
* If `E` is `never`, or `R` is more than whitespaces and comments,
* the Unlambda code given to the parser is malformed.
2020-11-06 09:07:33 +00:00
*/
export type ParseResult = [Expression, string];
/**
* Parse the given Unlambda code. Returns a `ParseResult`.
*/
export type Parse<Code extends string> =
// `C` is the first character of the code, `R` is the rest.
Code extends `${infer C}${infer R}` ?
// Trim comment line.
2021-06-03 13:27:35 +00:00
C extends '#' ? Parse<R extends `${any}\n${infer N}` ? N : ''>
2020-11-06 09:07:33 +00:00
// Trim whitespace.
2021-06-03 13:27:35 +00:00
: C extends WhiteSpace ? Parse<R>
2020-11-06 09:07:33 +00:00
// Apply the result of two consective parse.
: C extends '`' ? ParseApply<Parse<R>>
// A single character function.
: C extends FuncNoChar ? [C, R]
// A `.x` or `?x` function.
2021-06-03 13:27:35 +00:00
: R extends `${infer C1}${infer R1}` ?
`${C}${C1}` extends FuncChar ? [`${C}${C1}`, R1] : [never, R]
2020-11-06 09:07:33 +00:00
: [never, R]
: [never, Code];
/**
2021-06-03 13:27:35 +00:00
* Given the left part (the "operator") of an application, parse
* the right part (the "operand").
2020-11-06 09:07:33 +00:00
*/
type ParseApply<L extends ParseResult> = ParseApplyResult<L[0], Parse<L[1]>>;
/**
2021-06-03 13:27:35 +00:00
* Given the parse result of two parts of an application, return
* the final parse result.
2020-11-06 09:07:33 +00:00
*/
2021-06-03 13:27:35 +00:00
type ParseApplyResult<L extends Expression, R extends ParseResult> =
[[L, R[0]], R[1]];