]> git.kianting.info Git - clo/blob - src/index.ts
rebuild parser
[clo] / src / index.ts
1 var fs = require('fs');
2 import { argv, resourceUsage } from 'node:process';
3 import * as tk from './tokenize.js';
4 import * as util from 'util';
5 import { drawEllipsePath, reduceRotation } from 'pdf-lib';
6 import { isTypedArray } from 'node:util/types';
7 import { error } from 'node:console';
8
9 /**
10 * debug reprensenting
11 */
12 let repr = (x : any)=>{return util.inspect(x, {depth: null})};
13
14 /**
15 * token tree type.
16 */
17 type tkTree = tkTree[] | tk.Token
18
19 /**
20 * concated 2 `tkTree`s
21 * @param x the array to be concated
22 * @param y the item or array to ve concated
23 * @returns concated tkTree array, or thrown error if can't be concated.
24 */
25 function concat(x: tkTree, y:tkTree): tkTree[] {
26 if (Array.isArray(x)){
27 return x.concat(y);
28 }else{
29 throw new Error("the tkTree can't be concated, because it's not an array.");
30
31 }
32 }
33
34 function slice(x: tkTree, index?:number, end?:number): tkTree[] {
35 if (Array.isArray(x)){
36 return x.slice(index,end);
37 }else{
38 throw new Error("the tkTree can't be concated, because it's not an array.");
39
40 }
41 }
42
43 /**
44 * TokenMatcheePair for tokens' parser combinator
45 * matched: the matched (now and before) tokens
46 * remained: tokens to be matched
47 * ast: abstract syntax tree
48 */
49 export interface TokenMatcheePair {
50 matched: tk.Token[]
51 remained: tk.Token[]
52 ast : tkTree[]
53 }
54
55 /**
56 * @description
57 * match one token type.
58 *
59 * it returns a function which test if the type of first token of the `remained` part of
60 * the argument of the function is `typ` , if it's true, update the `TokenMatcheePair` wrapped
61 * in `Some`. Otherwise, it returns `None`.
62 * * @param typ : the type to be test.
63 * @returns the updated `TokenMatcheePair` wrapped in `Some(x)` or `None`.
64 */
65 export function m1TType(typ: tk.TokenType):
66 (m: TokenMatcheePair) => tk.Maybe<TokenMatcheePair> {
67 return (m: TokenMatcheePair) => {
68 if (m.remained.length == 0) {
69 return { _tag: "None" };
70 }
71 /**
72 * token to be matched
73 * */
74 const ttbm = m.remained[0];
75
76 if (ttbm.type == typ) {
77 let new_matched = m.matched.concat(ttbm);
78 let result : tk.Some<TokenMatcheePair> = {
79 _tag: "Some", value: {
80 matched: new_matched,
81 remained: m.remained.slice(1),
82 ast: ([ttbm]),
83 }
84 };
85 return result;
86 }
87 else {
88 return { _tag: "None" };
89 }
90 }
91 };
92
93 /**
94 * type int
95 */
96 let tInt = m1TType(tk.TokenType.INT);
97 let tAdd = m1TType(tk.TokenType.I_ADD);
98 let tMul = m1TType(tk.TokenType.I_MUL);
99
100
101 argv.forEach((val, index) => {
102 console.log(`${index}=${val}`);
103 });
104
105
106 /**
107 * like `m ==> f` in ocaml
108 * @param m matchee wrapped
109 * @param f matching function
110 * @returns wrapped result
111 */
112 function thenDo(m : tk.Maybe<TokenMatcheePair>, f : Function){
113 if (m._tag == "None"){
114 return m;
115 }else{
116 var a : tk.Maybe<TokenMatcheePair> = f(m.value);
117 if (a._tag == "Some"){
118 a.value.ast = concat(m.value.ast, a.value.ast);
119 }
120
121 return a;
122 }
123 }
124
125 /**
126 * like `f1 | f2` in regex
127 * @param f1 the first tried function
128 * @param f2 the second tried function
129 * @returns wrapped result
130 */
131 function orDo(f1 : Function, f2 : Function){
132 return (x : TokenMatcheePair) =>{
133 let res1 : tk.Maybe<TokenMatcheePair> = f1(x);
134 if (res1._tag == "Some"){
135 return res1;
136 }else{
137 let res2 : tk.Maybe<TokenMatcheePair> = f2(x);
138 return res2;
139 }
140 }
141
142 }
143
144 let midfix = (f : Function, signal? : string) => (x : TokenMatcheePair)=>{
145 var a = f(x);
146 if (a._tag == "Some"){
147 let ast_head : tkTree[] = slice(a.value.ast,0,a.value.ast.length-3);
148 let ast_tail : tkTree[] = slice(a.value.ast,a.value.ast.length-3);
149 let new_ast = [ast_tail];
150 a.value.ast = new_ast;
151
152 console.log("+"+signal+"+"+repr(a));
153
154
155 }
156 return a;
157 }
158
159 /**
160 *
161 * fac1 = int MUL int
162 */
163 //let fac1 = midfix((x : TokenMatcheePair)=>
164 // thenDo(thenDo(thenDo(tk.toSome(x), tInt), tMul), tInt));
165
166 let fac1 = (x : TokenMatcheePair) => {
167 let a = midfix((x : TokenMatcheePair)=>
168 thenDo(thenDo(thenDo(tk.toSome(x), tInt), tMul), tInt), "fac1")(x);
169
170 return a;
171 }
172
173
174 /**
175 *
176 * fac2 = int MUL int
177 */
178 let fac2 = tInt;
179
180 /**
181 * fac = fac1 | fac2
182 */
183 let fac = orDo(fac1, fac2);
184
185
186 /**
187 *
188 * expr1 = fac ADD fac
189 */
190 let expr1 = midfix((x : TokenMatcheePair)=>
191 thenDo(thenDo(thenDo(tk.toSome(x), fac), tAdd), fac), "expr1");
192 /**
193 * expr2 = fac
194 */
195 let expr2 = fac;
196
197 /**
198 * expr = expr1 | expr2
199 */
200 let expr = orDo(expr1, expr2);
201
202
203
204
205 let tokens = tk.tokenize("2+3*4");//tk.tokenize(argv[2]);
206 let tokensFiltered = tokens.filter(
207 (x)=>{return (x.type != tk.TokenType.NL
208 && x.type != tk.TokenType.SP)});
209
210 let wrappedTokens : tk.Maybe<TokenMatcheePair> =
211 tk.toSome({
212 matched : [] ,
213 remained : tokensFiltered,
214 ast : []});
215
216 let beta = expr({
217 matched : [] ,
218 remained : tokensFiltered,
219 ast : []});
220
221 console.log(repr(wrappedTokens));
222
223 console.log(repr(beta));
224