]>
git.kianting.info Git - uann/blob - src/index.js
23320ac6471bd64cf15a6771802a5234bf85f354
2 Object
.defineProperty(exports
, "__esModule", { value
: true });
3 exports
.tokenize
= exports
.zeroOrOnceDo
= exports
.notDo
= exports
.zeroOrMoreDo
= exports
.orDo
= exports
.thenDo
= exports
.charToCodepoint
= exports
.matchRange
= exports
.matchAny
= exports
.match1Char
= void 0;
4 var fs
= require('fs');
6 * wrap a x in a `Some(T)`
7 * @param x : variable to be wrapped.
8 * @returns wrapped `x`.
11 return { _tag
: "Some", value
: x
};
15 * it returns a function which test if the first char of the `remained` part of
16 * the argument of the function is `c`, if it's true, update the `MatchedPair` wrapped
17 * in `Some`. Otherwise, it returns `None`.
18 * * @param c : the char to be test.
19 * @returns the updated `MatchedPair` wrapped in `Some(x)` or `None`.
21 function match1Char(c
) {
23 if (m
.remained
.length
== 0) {
24 return { _tag
: "None" };
26 const charToBeMatched
= m
.remained
[0];
27 if (charToBeMatched
=== c
) {
28 return { _tag
: "Some", value
: {
29 matched
: m
.matched
+ charToBeMatched
,
30 remained
: m
.remained
.substring(1)
34 return { _tag
: "None" };
38 exports
.match1Char
= match1Char
;
42 * @param m : the `MatcheePair` to be consumed.
43 * @returns if the length of `m.remained` >= 1; consumes the matchee by 1 char and wraps it in `Some`,
44 * otherwise, returns `None`.
46 function matchAny(m
) {
47 if (m
.remained
.length
>= 1) {
48 return { _tag
: "Some", value
: {
49 matched
: m
.matched
+ m
.remained
[0],
50 remained
: m
.remained
.substring(1)
54 return { _tag
: "None" };
57 exports
.matchAny
= matchAny
;
60 * it returns a function which test if the first char of the `remained` part of
61 * the argument of the function is between `l` and `u`, if it's true, update the `MatchedPair` wrapped
62 * in `Some`. Otherwise, it returns `None`.
63 * * @param l : lower bound char, 1-char string
64 * * @param u : upper bound char, 1-char string
65 * @returns the updated `MatchedPair` wrapped in `Some(x)` or `None`.
67 function matchRange(l
, u
) {
68 let lCodepoint
= charToCodepoint(l
);
69 let uCodepoint
= charToCodepoint(u
);
71 throw new Error("Error: the codepoint of `" + l
+ "` is not smaller than `" + u
+ "`)");
74 if (m
.remained
.length
< 1) {
75 return { _tag
: "None" };
77 const charToBeMatched
= m
.remained
[0];
78 const codePointToBeMatched
= charToCodepoint(charToBeMatched
);
79 if (codePointToBeMatched
>= lCodepoint
&& codePointToBeMatched
<= uCodepoint
) {
80 return { _tag
: "Some", value
: {
81 matched
: m
.matched
+ charToBeMatched
,
82 remained
: m
.remained
.substring(1)
86 return { _tag
: "None" };
90 exports
.matchRange
= matchRange
;
93 * convert the one-char string to codepoint.
94 * @param s : the string to code point.
95 * @returns if `s.length > 1` return error; otherwise, return the codepoint of `s`.
97 function charToCodepoint(s
) {
99 throw new Error("Error: the length of input string for " + s
+ "is " + s
.length
+ `,
100 however, it should be 1.`);
103 return s
.charCodeAt(0);
106 exports
.charToCodepoint
= charToCodepoint
;
108 * @description thendo(input, f, ...) like
110 * @param input: the wrapped input.
111 * @param f: the function to be applied.
113 * @returns:the applied wrapped result `MatcheePair`.
115 function thenDo(input
, f
) {
116 if (input
._tag
== "None") {
120 let inner
= input
.value
;
124 exports
.thenDo
= thenDo
;
126 * @description "or", like the regex `( f1 | f2 )` .
127 * It returns a function `f` of which the argument is`x`.
128 * if `f1(x)` is None, then `f` returns `f2(x)`. Otherwise,
129 * `F` returns `f1(x)`.
130 * @param f1 : 1st function to be compared
131 * @param f2 : 2nd function to be compared
132 * @returns:the combined function
134 function orDo(f1
, f2
) {
138 if (f1x
._tag
== "None") {
149 * @description repeating matching function `f`
150 * zero or more times, like the asterisk `*` in regex `f*` .
151 * @param f : the function to be repeated 0+ times.
152 * @returns:the combined function
154 function zeroOrMoreDo(f
) {
156 var wrapped_old_x
= { _tag
: "Some", value
: x
};
157 var wrapped_new_x
= wrapped_old_x
;
158 while (wrapped_new_x
._tag
!= "None") {
159 wrapped_old_x
= wrapped_new_x
;
160 wrapped_new_x
= thenDo(wrapped_old_x
, f
);
163 return wrapped_old_x
;
166 exports
.zeroOrMoreDo
= zeroOrMoreDo
;
168 * @description Not. like the `^` inside regex of [^f].
169 * returns a function `F(x)` such that if `f(x)` is `None`,
170 * returns the x consuming a char; if `f(x)` is not None, F(x)
172 * @param f: the function forbidden to be matched.
173 * @returns: combined function `F`.
181 let f_x
= thenDo(wrapped_x
, f
);
182 if (f_x
._tag
!= "None") {
183 return { _tag
: "None" };
186 return thenDo(wrapped_x
, matchAny
);
190 exports
.notDo
= notDo
;
192 * if `x` is matched by `f` once, returns `f(x)`. Otherwise,
194 * similar to `?` in regex `f?`.
195 * @param f : the function to be matched
196 * @returns return wrapped f(x)
198 function zeroOrOnceDo(f
) {
200 var wrapped_old_x
= { _tag
: "Some", value
: x
};
201 var wrapped_new_x
= thenDo(wrapped_old_x
, f
);
202 if (wrapped_new_x
._tag
!= "None") {
203 return wrapped_new_x
;
206 return wrapped_old_x
;
210 exports
.zeroOrOnceDo
= zeroOrOnceDo
;
211 function tokenize(input
) {
212 var input_matchee_pair
= toSome({ matched
: "",
214 // integer = ([+]|[-])\d\d?
215 let integer
= (x
) => {
216 let wrapped_x
= toSome(x
);
217 let plusMinus
= orDo(match1Char('+'), match1Char('-')); // ([+]|[-])
218 let d
= matchRange('0', '9'); // \d
219 return thenDo(thenDo(thenDo(wrapped_x
, zeroOrOnceDo(plusMinus
)), d
), zeroOrMoreDo(d
));
221 console
.log(input
+ ", result: ");
222 console
.log(thenDo(input_matchee_pair
, integer
));
223 // TODO: id, string, space, basic operator, 3 marks: @, {, }.
225 exports
.tokenize
= tokenize
;