]> git.kianting.info Git - uann/blob - src/index.js
23320ac6471bd64cf15a6771802a5234bf85f354
[uann] / src / index.js
1 "use strict";
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');
5 /**
6 * wrap a x in a `Some(T)`
7 * @param x : variable to be wrapped.
8 * @returns wrapped `x`.
9 */
10 function toSome(x) {
11 return { _tag: "Some", value: x };
12 }
13 /**
14 * @description
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`.
20 */
21 function match1Char(c) {
22 return (m) => {
23 if (m.remained.length == 0) {
24 return { _tag: "None" };
25 }
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)
31 } };
32 }
33 else {
34 return { _tag: "None" };
35 }
36 };
37 }
38 exports.match1Char = match1Char;
39 ;
40 /**
41 *
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`.
45 */
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)
51 } };
52 }
53 else {
54 return { _tag: "None" };
55 }
56 }
57 exports.matchAny = matchAny;
58 /**
59 * @description
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`.
66 */
67 function matchRange(l, u) {
68 let lCodepoint = charToCodepoint(l);
69 let uCodepoint = charToCodepoint(u);
70 if (l > u) {
71 throw new Error("Error: the codepoint of `" + l + "` is not smaller than `" + u + "`)");
72 }
73 return (m) => {
74 if (m.remained.length < 1) {
75 return { _tag: "None" };
76 }
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)
83 } };
84 }
85 else {
86 return { _tag: "None" };
87 }
88 };
89 }
90 exports.matchRange = matchRange;
91 ;
92 /**
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`.
96 */
97 function charToCodepoint(s) {
98 if (s.length > 1) {
99 throw new Error("Error: the length of input string for " + s + "is " + s.length + `,
100 however, it should be 1.`);
101 }
102 else {
103 return s.charCodeAt(0);
104 }
105 }
106 exports.charToCodepoint = charToCodepoint;
107 /**
108 * @description thendo(input, f, ...) like
109 * a ==> f
110 * @param input: the wrapped input.
111 * @param f: the function to be applied.
112 *
113 * @returns:the applied wrapped result `MatcheePair`.
114 */
115 function thenDo(input, f) {
116 if (input._tag == "None") {
117 return input;
118 }
119 else {
120 let inner = input.value;
121 return f(inner);
122 }
123 }
124 exports.thenDo = thenDo;
125 /**
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
133 */
134 function orDo(f1, f2) {
135 return (x) => {
136 let f1x = (f1(x));
137 {
138 if (f1x._tag == "None") {
139 return f2(x);
140 }
141 else {
142 return f1x;
143 }
144 }
145 };
146 }
147 exports.orDo = orDo;
148 /**
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
153 */
154 function zeroOrMoreDo(f) {
155 return (x) => {
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);
161 }
162 ;
163 return wrapped_old_x;
164 };
165 }
166 exports.zeroOrMoreDo = zeroOrMoreDo;
167 /**
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)
171 * returns `None`.
172 * @param f: the function forbidden to be matched.
173 * @returns: combined function `F`.
174 */
175 function notDo(f) {
176 return (x) => {
177 let wrapped_x = {
178 _tag: "Some",
179 value: x
180 };
181 let f_x = thenDo(wrapped_x, f);
182 if (f_x._tag != "None") {
183 return { _tag: "None" };
184 }
185 else {
186 return thenDo(wrapped_x, matchAny);
187 }
188 };
189 }
190 exports.notDo = notDo;
191 /**
192 * if `x` is matched by `f` once, returns `f(x)`. Otherwise,
193 * returns x
194 * similar to `?` in regex `f?`.
195 * @param f : the function to be matched
196 * @returns return wrapped f(x)
197 */
198 function zeroOrOnceDo(f) {
199 return (x) => {
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;
204 }
205 else {
206 return wrapped_old_x;
207 }
208 };
209 }
210 exports.zeroOrOnceDo = zeroOrOnceDo;
211 function tokenize(input) {
212 var input_matchee_pair = toSome({ matched: "",
213 remained: input });
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));
220 };
221 console.log(input + ", result: ");
222 console.log(thenDo(input_matchee_pair, integer));
223 // TODO: id, string, space, basic operator, 3 marks: @, {, }.
224 }
225 exports.tokenize = tokenize;
226 tokenize("+123");
227 tokenize("123");
228 tokenize("-123");
229 tokenize(" 123");
230 tokenize("c123");