]> git.kianting.info Git - uann/blob - src/index.ts
add matchRange
[uann] / src / index.ts
1 var fs = require('fs');
2
3 type Some<T> = { _tag: "Some"; value: T };
4 type None = {_tag: "None"};
5
6 /**
7 * @description Like the `Some(a)` and `None` in Rust.
8 *
9 * @example
10 * ```ts
11 * let exam1 : Maybe<Number> = { _tag: "Some", value: 12 };
12 * let exam2 : Maybe<Number> = None;
13 * ```
14 */
15 export type Maybe<T> = Some<T> | None;
16
17
18 /**
19 * @description
20 * the pair of the string to be matched later and the string that have been matched
21 * @param matched : string have been matched
22 * @param remained : string will be tested whether it'll be matched.
23 */
24 export type MatcheePair = {matched : string; remained : string};
25
26 /**
27 * @description
28 * it returns a function which test if the first char of the `remained` part of
29 * the argument of the function is `c`, if it's true, update the `MatchedPair` wrapped
30 * in `Some`. Otherwise, it returns `None`.
31 * * @param c : the char to be test.
32 * @returns the updated `MatchedPair` wrapped in `Some(x)` or `None`.
33 */
34 export function match1Char(c : string) : (m: MatcheePair) => Maybe<MatcheePair> {
35 return (m : MatcheePair)=>{
36 const charToBeMatched = m.remained[0];
37 if (charToBeMatched === c){
38 return {_tag: "Some", value :{
39 matched : m.matched + charToBeMatched,
40 remained : m.remained.substring(1)}};
41 }
42 else{
43 return {_tag: "None"};
44 }
45 }
46 };
47
48 /**
49 * @description
50 * it returns a function which test if the first char of the `remained` part of
51 * the argument of the function is between `l` and `u`, if it's true, update the `MatchedPair` wrapped
52 * in `Some`. Otherwise, it returns `None`.
53 * * @param l : lower bound char, 1-char string
54 * * @param u : upper bound char, 1-char string
55 * @returns the updated `MatchedPair` wrapped in `Some(x)` or `None`.
56 */
57 export function matchRange(l : string, u : string) : (m: MatcheePair) => Maybe<MatcheePair> {
58 let lCodepoint = charToCodepoint(l);
59 let uCodepoint = charToCodepoint(u);
60 if (l > u){
61 throw new Error("Error: the codepoint of `"+l+"` is not smaller than `"+u+"`)");
62 }
63 return (m : MatcheePair)=>{
64
65 const charToBeMatched = m.remained[0];
66 const codePointToBeMatched = charToCodepoint(charToBeMatched);
67 if (codePointToBeMatched >= lCodepoint && codePointToBeMatched <= uCodepoint){
68 return {_tag: "Some", value :{
69 matched : m.matched + charToBeMatched,
70 remained : m.remained.substring(1)}};
71 }
72 else{
73 return {_tag: "None"};
74 }
75 }
76 };
77
78 /**
79 * convert the one-char string to codepoint.
80 * @param s : the string to code point.
81 * @returns if `s.length > 1` return error; otherwise, return the codepoint of `s`.
82 */
83 export function charToCodepoint(s : string): number{
84 if (s.length > 1){
85 throw new Error("Error: the length of input string for "+s+ "is "+s.length+`,
86 however, it should be 1.`);
87 }else{
88 return s.charCodeAt(0);
89 }
90 }
91
92 /**
93 * @description thendo(input, f, ...) like
94 * a ==> f
95 */
96 export function thenDo<T>(input : Maybe<T>, f : Function) : Maybe<T>{
97 if (input._tag == "None"){
98 return input;
99 }
100 else{
101 let inner = input.value;
102 return f(inner);
103 }
104 }