]> git.kianting.info Git - clo/blob - src/index.ts
modify somethinig
[clo] / src / index.ts
1 var fs = require('fs');
2 import jsTokens from "js-tokens";
3 import * as util from 'util';
4 import * as p from 'typescript-parsec';
5 import { Token } from 'typescript-parsec';
6 import { TokenType } from "./tokenize";
7 /**
8 *
9 * # REPRESENTATION
10 */
11 /**
12 * convert a `tkTree` AST to S-expr string
13 * @param t the `tkTree`
14 * @returns S-expr String
15 */
16 export function tkTreeToSExp(t: tkTree): string{
17 var str = "";
18
19 if (Array.isArray(t)){
20 let strArray = t.map((x)=>tkTreeToSExp(x));
21 str = "(" + strArray.join(" ") + ")";
22 }else{
23 if (t=== undefined){
24 str = "%undefined"
25 }else{
26 str = t;
27 }
28 }
29
30 return str;
31 }
32
33 /**inspect the inner of the representation. */
34 let repr = (x : any)=>{return util.inspect(x, {depth: null})};
35 /**
36 *
37 * # TYPES
38 */
39
40
41 type tkTree = string | tkTree[];
42
43 enum TokenKind {
44 Seperator, // ---
45 Semicolon, // ;
46 Number,
47 Op,
48 ExprMark, // @
49 ExcapeAt, // \@
50 Paren,
51 SpaceNL, // \s\t\n\r
52 Id,
53 Str,
54 Comment, // /* ooo */
55 }
56
57 /**
58 * Parsing
59 */
60 const lexer = p.buildLexer([
61 [true, /^\d+(\.\d+)?/g, TokenKind.Number],
62 [true, /^\\\@/g, TokenKind.ExcapeAt],
63 [true, /^\/\*([^/]|\/[^*])*\*\//g, TokenKind.Comment],
64 [true, /^\;/g, TokenKind.Semicolon],
65 [true, /^[-][-][-]/g, TokenKind.Seperator],
66 [true, /^[\+\-\*\/\&\|\!\^\<\>\~\=\?]+/g, TokenKind.Op],
67 [true, /^\@/g, TokenKind.ExprMark],
68 [true, /^[()\[\]{}]/g, TokenKind.Paren],
69 [true, /^["]([\"]|[\\].)*["]/g, TokenKind.Str],
70 [true, /^[']([\']|[\\].)*[']/g, TokenKind.Str],
71 [true, /^[()\[\]{}]/g, TokenKind.Paren],
72 [true, /^[^\/\\\@\s\n\t\r;]+/g, TokenKind.Id],
73 [true, /^(\s|\n|\r|\t)+/g, TokenKind.SpaceNL],
74
75 ]);
76
77 /**
78 *
79 * # TEST
80 */
81 const inputTxt=
82 `import a as b; /*bacourt*/
83 /* ba choir
84 ipsum lorem*/
85
86 import you as john;
87 ---
88
89 臺中市\\\@
90
91 公園
92 @1+2==3;
93
94 console.log("122");@
95
96 山頂
97 `;
98
99
100 const PROG = p.rule<TokenKind, tkTree>();
101 const SEGMENT = p.rule<TokenKind, tkTree>();
102 const IMPORT = p.rule<TokenKind, tkTree>();
103 const IMPORTS = p.rule<TokenKind, tkTree>();
104 const SEMICOLON = p.rule<TokenKind, tkTree>();
105 const EXCAPE_AT = p.rule<TokenKind, tkTree>();
106 const NOT_AT_TEXT = p.rule<TokenKind, tkTree>();
107 const CONTENT = p.rule<TokenKind, tkTree>();
108
109 let doubleMinus = { type: 'Punctuator', value: '--' };
110 let doubleMinus2 = p.str('--');
111 const TERM = p.rule<TokenKind, tkTree>();
112
113 function applySegment(input: [Token<TokenKind>, Token<TokenKind>[],
114 Token<TokenKind>]): tkTree[]{
115 let unpackedInnerExprs = input[1].map((x)=>{return x.text});
116 return ["%exprs", unpackedInnerExprs];
117 }
118
119 function applySemiColon(value: Token<TokenKind.Semicolon>): tkTree{
120 return value.text;
121 }
122
123 function applyParts(first: tkTree,
124 second: [Token<TokenKind>, tkTree]):tkTree {
125 return ["%clo", first , second[1]];
126 }
127
128
129 function applyComment(value: Token<TokenKind.Comment>): tkTree[]{
130 return [value.text];
131 }
132
133
134 function applyImport(input: [Token<TokenKind>,Token<TokenKind>[], tkTree]) : tkTree{
135 let importTail = input[1].map(x=>x.text);
136 return ["import"].concat(importTail);
137 };
138
139
140 /*
141 function applyImportComment(input: [Token<TokenKind>,Token<TokenKind>[],
142 tkTree, Token<TokenKind.Comment>]) : tkTree{
143 let importTail = input[1].map(x=>x.text);
144 let comment = [input[3].text];
145 return ["import"].concat(importTail).concat(comment);
146 };*/
147
148 function applyImports(input : [tkTree, tkTree[]]): tkTree{
149 let resultBody = [input[0]].concat(input[1]);
150 let resultWrapper = ["%import", resultBody];
151 return resultWrapper;
152 };
153
154
155
156
157 function applyNotAtText(value : Token<TokenKind>): tkTree{
158 if (value.text == "\\\@"){
159 return '@';
160 }
161 else{return value.text;}
162 };
163
164 function applyText (input : tkTree): tkTree[]{
165 return ["%text", input];
166 };
167
168 function applyContent(input : tkTree[]): tkTree[]{
169 return ["%content", input];
170 };
171
172 function applySpaceNL(value : Token<TokenKind.SpaceNL>): tkTree{
173 return value.text;
174 }
175
176 /**
177 * IMPORTEE: Number, Op, Paren, Id, Str, Comment,
178 */
179 let IMPORTEE = p.alt(p.tok(TokenKind.Number),
180 p.tok(TokenKind.Op),
181 p.tok(TokenKind.Paren),
182 p.tok(TokenKind.Id),
183 p.tok(TokenKind.Str),
184 p.tok(TokenKind.SpaceNL),
185 p.tok(TokenKind.Comment));
186
187 let NOT_AT = p.alt(p.tok(TokenKind.Seperator),
188 p.tok(TokenKind.Semicolon),
189 p.tok(TokenKind.Number),
190 p.tok(TokenKind.ExcapeAt),
191 p.tok(TokenKind.Op),
192 p.tok(TokenKind.Paren),
193 p.tok(TokenKind.SpaceNL),
194 p.tok(TokenKind.Id),
195 p.tok(TokenKind.Str),
196 p.tok(TokenKind.Comment),
197 );
198
199 /**
200 * PROG : IMPORTS '---' CONTENT;
201 */
202 PROG.setPattern(
203 p.lrec_sc(IMPORTS, p.seq(p.str('---'), CONTENT), applyParts)
204
205 )
206
207 /**
208 * NOT_AT_TEXT : NOT_AT
209 */
210 NOT_AT_TEXT.setPattern(
211 p.apply(NOT_AT, applyNotAtText)
212 );
213
214 IMPORTS.setPattern(
215 p.apply( p.seq(IMPORT, p.rep(IMPORT)), applyImports)
216 );
217
218 /**
219 * IMPORT :
220 * 'import' IMPORTEE* SEMICOLON |
221 * COMMENT |
222 */
223 IMPORT.setPattern(
224 p.alt(
225 p.apply(p.seq(p.str('import'), p.rep_sc(IMPORTEE), SEMICOLON),
226 applyImport),
227 p.apply(p.tok(TokenKind.Comment), applyComment),
228 p.apply(p.tok(TokenKind.SpaceNL), applySpaceNL)
229
230 )
231 );
232
233 /**
234 * SEMICOLON : ';';
235 */
236 SEMICOLON.setPattern(
237 p.apply(p.tok(TokenKind.Semicolon), applySemiColon)
238 );
239
240
241
242 /**
243 * SEGMENT : '@' NOT_AT* '@' |
244 * (NOT_AT_TEXT | EXCAPE_AT)*
245 */
246 SEGMENT.setPattern(
247 p.alt(
248 p.apply(p.rep_sc(NOT_AT_TEXT), applyText),
249 p.apply(p.seq(p.str('@'), p.rep(NOT_AT), p.str('@')), applySegment),
250 )
251 );
252
253 /**
254 * CONTENT : SEGMENT*
255 */
256 CONTENT.setPattern(
257 p.apply(p.rep(SEGMENT), applyContent)
258 );
259
260
261 let tree = p.expectSingleResult(p.expectEOF(PROG.parse(lexer.parse(inputTxt))));
262
263
264
265 console.log("RESULT="+tkTreeToSExp(tree));