@cirru/parser.ts 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yaml +21 -0
- package/.github/workflows/upload.yaml +49 -0
- package/README.md +27 -0
- package/jest.config.js +13 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +297 -0
- package/lib/index.js.map +1 -0
- package/lib/tree.d.ts +10 -0
- package/lib/tree.js +106 -0
- package/lib/tree.js.map +1 -0
- package/lib/types.d.ts +14 -0
- package/lib/types.js +17 -0
- package/lib/types.js.map +1 -0
- package/package.json +62 -0
- package/src/index.ts +292 -0
- package/src/parser.test.ts +77 -0
- package/src/tree.ts +99 -0
- package/src/types.ts +17 -0
- package/tsconfig-compile.json +23 -0
- package/tsconfig-node.json +21 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: npm publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish-npm:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v2
|
|
12
|
+
- uses: actions/setup-node@v1
|
|
13
|
+
with:
|
|
14
|
+
node-version: 12
|
|
15
|
+
registry-url: https://registry.npmjs.org/
|
|
16
|
+
|
|
17
|
+
- run: yarn && yarn compile
|
|
18
|
+
|
|
19
|
+
- run: npm publish
|
|
20
|
+
env:
|
|
21
|
+
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Upload Assets
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request: {}
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- master
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
upload-assets:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v2
|
|
14
|
+
|
|
15
|
+
- name: Use Node.js
|
|
16
|
+
uses: actions/setup-node@v1
|
|
17
|
+
|
|
18
|
+
- name: Get yarn cache
|
|
19
|
+
id: yarn-cache
|
|
20
|
+
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
21
|
+
|
|
22
|
+
- uses: actions/cache@v1
|
|
23
|
+
with:
|
|
24
|
+
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
25
|
+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
26
|
+
restore-keys: |
|
|
27
|
+
${{ runner.os }}-yarn-
|
|
28
|
+
|
|
29
|
+
- run: yarn
|
|
30
|
+
- run: yarn test
|
|
31
|
+
- run: yarn tsc -d --project tsconfig-compile.json --outDir lib/
|
|
32
|
+
|
|
33
|
+
- run: yarn release
|
|
34
|
+
name: Build web assets
|
|
35
|
+
|
|
36
|
+
- name: Deploy to server
|
|
37
|
+
id: deploy
|
|
38
|
+
uses: Pendect/action-rsyncer@v1.1.0
|
|
39
|
+
env:
|
|
40
|
+
DEPLOY_KEY: ${{secrets.rsync_private_key}}
|
|
41
|
+
with:
|
|
42
|
+
flags: "-avzr --progress"
|
|
43
|
+
options: ""
|
|
44
|
+
ssh_options: ""
|
|
45
|
+
src: "dist/*"
|
|
46
|
+
dest: "rsync-user@cirru.org:/web-assets/repo/${{ github.repository }}"
|
|
47
|
+
|
|
48
|
+
- name: Display status from deploy
|
|
49
|
+
run: echo "${{ steps.deploy.outputs.status }}"
|
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## Cirru Parser in TypeScript
|
|
2
|
+
|
|
3
|
+
> based on latest parser of ClojureScript version.
|
|
4
|
+
|
|
5
|
+
Demo http://repo.cirru.org/parser.ts/
|
|
6
|
+
|
|
7
|
+
### Usage
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
yarn add @cirru/parser.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { parse } from "@cirru/parser.ts";
|
|
17
|
+
|
|
18
|
+
parse("a (demo)");
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Workflow
|
|
22
|
+
|
|
23
|
+
https://github.com/jimengio/ts-workflow
|
|
24
|
+
|
|
25
|
+
### License
|
|
26
|
+
|
|
27
|
+
MIT
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
preset: "ts-jest",
|
|
3
|
+
testEnvironment: "node",
|
|
4
|
+
roots: ["<rootDir>/src"],
|
|
5
|
+
transform: {
|
|
6
|
+
"^.+\\.tsx?$": "ts-jest",
|
|
7
|
+
},
|
|
8
|
+
moduleNameMapper: {
|
|
9
|
+
"^lodash-es$": "lodash",
|
|
10
|
+
},
|
|
11
|
+
silent: false,
|
|
12
|
+
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
|
|
13
|
+
};
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parse = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const tree_1 = require("./tree");
|
|
6
|
+
let graspeExprs = (pullToken) => {
|
|
7
|
+
let acc = [];
|
|
8
|
+
let pointer = acc;
|
|
9
|
+
let pointerStack = [];
|
|
10
|
+
while (true) {
|
|
11
|
+
let cursor = pullToken();
|
|
12
|
+
// console.log(pointerStack, pointer, cursor);
|
|
13
|
+
switch (cursor) {
|
|
14
|
+
case types_1.ELexControl.close:
|
|
15
|
+
if (pointerStack.length === 0) {
|
|
16
|
+
return pointer;
|
|
17
|
+
}
|
|
18
|
+
let collected = pointer;
|
|
19
|
+
pointer = pointerStack.pop();
|
|
20
|
+
pointer.push(collected);
|
|
21
|
+
break;
|
|
22
|
+
case types_1.ELexControl.open:
|
|
23
|
+
pointerStack.push(pointer);
|
|
24
|
+
pointer = [];
|
|
25
|
+
break;
|
|
26
|
+
case types_1.ELexControl.close:
|
|
27
|
+
throw new Error("Unexpected close token");
|
|
28
|
+
default:
|
|
29
|
+
if (tree_1.isString(cursor)) {
|
|
30
|
+
pointer.push(cursor);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(JSON.stringify(cursor));
|
|
35
|
+
throw new Error("Unknown cursor");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
let buildExprs = (pullToken) => {
|
|
41
|
+
let acc = [];
|
|
42
|
+
while (true) {
|
|
43
|
+
let chunk = pullToken();
|
|
44
|
+
if (chunk === types_1.ELexControl.open) {
|
|
45
|
+
let expr = graspeExprs(pullToken);
|
|
46
|
+
acc.push(expr);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
else if (chunk == null) {
|
|
50
|
+
return acc;
|
|
51
|
+
}
|
|
52
|
+
else if (chunk === types_1.ELexControl.close) {
|
|
53
|
+
throw new Error(`Unexpected ")"`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw new Error(`Unexpected chunk ${JSON.stringify(chunk)}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
let parseIndentation = (buffer) => {
|
|
61
|
+
let size = buffer.length;
|
|
62
|
+
if (tree_1.isOdd(size)) {
|
|
63
|
+
throw new Error(`Invalid indentation size ${size}`);
|
|
64
|
+
}
|
|
65
|
+
return size / 2;
|
|
66
|
+
};
|
|
67
|
+
let lex = (initialCode) => {
|
|
68
|
+
let acc = [];
|
|
69
|
+
let state = types_1.ELexState.indent;
|
|
70
|
+
let buffer = "";
|
|
71
|
+
let code = initialCode;
|
|
72
|
+
// let count = 0;
|
|
73
|
+
let pointer = 0;
|
|
74
|
+
while (true) {
|
|
75
|
+
// count += 1;
|
|
76
|
+
// if (count > 1000) {
|
|
77
|
+
// break;
|
|
78
|
+
// }
|
|
79
|
+
if (pointer >= code.length) {
|
|
80
|
+
switch (state) {
|
|
81
|
+
case types_1.ELexState.space:
|
|
82
|
+
return acc;
|
|
83
|
+
case types_1.ELexState.token:
|
|
84
|
+
acc.push(buffer);
|
|
85
|
+
return acc;
|
|
86
|
+
break;
|
|
87
|
+
case types_1.ELexState.escape:
|
|
88
|
+
throw new Error("Should not be escape");
|
|
89
|
+
case types_1.ELexState.indent:
|
|
90
|
+
return acc;
|
|
91
|
+
case types_1.ELexState.string:
|
|
92
|
+
throw new Error("Should not be string");
|
|
93
|
+
default:
|
|
94
|
+
console.log(state);
|
|
95
|
+
throw new Error("Unkown state");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
let c = code[pointer];
|
|
100
|
+
pointer += 1;
|
|
101
|
+
switch (state) {
|
|
102
|
+
case types_1.ELexState.space:
|
|
103
|
+
switch (c) {
|
|
104
|
+
case " ":
|
|
105
|
+
[acc, state, buffer] = [acc, types_1.ELexState.space, ""];
|
|
106
|
+
break;
|
|
107
|
+
case "\n":
|
|
108
|
+
[acc, state, buffer] = [acc, types_1.ELexState.indent, ""];
|
|
109
|
+
break;
|
|
110
|
+
case "(":
|
|
111
|
+
acc.push(types_1.ELexControl.open);
|
|
112
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
113
|
+
break;
|
|
114
|
+
case ")":
|
|
115
|
+
acc.push(types_1.ELexControl.close);
|
|
116
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
117
|
+
break;
|
|
118
|
+
case '"':
|
|
119
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, ""];
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
[acc, state, buffer] = [acc, types_1.ELexState.token, c];
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
case types_1.ELexState.token:
|
|
127
|
+
switch (c) {
|
|
128
|
+
case " ":
|
|
129
|
+
acc.push(buffer);
|
|
130
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
131
|
+
break;
|
|
132
|
+
case '"':
|
|
133
|
+
acc.push(buffer);
|
|
134
|
+
[state, buffer] = [types_1.ELexState.string, ""];
|
|
135
|
+
break;
|
|
136
|
+
case "\n":
|
|
137
|
+
acc.push(buffer);
|
|
138
|
+
[state, buffer] = [types_1.ELexState.indent, ""];
|
|
139
|
+
break;
|
|
140
|
+
case "(":
|
|
141
|
+
acc.push(buffer, types_1.ELexControl.open);
|
|
142
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
143
|
+
break;
|
|
144
|
+
case ")":
|
|
145
|
+
acc.push(buffer, types_1.ELexControl.close);
|
|
146
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
[acc, state, buffer] = [acc, types_1.ELexState.token, `${buffer}${c}`];
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
case types_1.ELexState.string:
|
|
154
|
+
switch (c) {
|
|
155
|
+
case '"':
|
|
156
|
+
acc.push(buffer);
|
|
157
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
158
|
+
break;
|
|
159
|
+
case "\\":
|
|
160
|
+
[acc, state, buffer] = [acc, types_1.ELexState.escape, buffer];
|
|
161
|
+
break;
|
|
162
|
+
case "\n":
|
|
163
|
+
throw new Error("Expected newline in string");
|
|
164
|
+
default:
|
|
165
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, `${buffer}${c}`];
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
case types_1.ELexState.escape:
|
|
170
|
+
switch (c) {
|
|
171
|
+
case '"':
|
|
172
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, `${buffer}"`];
|
|
173
|
+
break;
|
|
174
|
+
case "'":
|
|
175
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, `${buffer}'`];
|
|
176
|
+
break;
|
|
177
|
+
case "t":
|
|
178
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, `${buffer}\t`];
|
|
179
|
+
break;
|
|
180
|
+
case "n":
|
|
181
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, `${buffer}\n`];
|
|
182
|
+
break;
|
|
183
|
+
case "\\":
|
|
184
|
+
[acc, state, buffer] = [acc, types_1.ELexState.string, `${buffer}\\`];
|
|
185
|
+
break;
|
|
186
|
+
default:
|
|
187
|
+
throw new Error(`Unknown ${c} in escape`);
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
case types_1.ELexState.indent:
|
|
191
|
+
switch (c) {
|
|
192
|
+
case " ":
|
|
193
|
+
[acc, state, buffer] = [acc, types_1.ELexState.indent, `${buffer}${c}`];
|
|
194
|
+
break;
|
|
195
|
+
case "\n":
|
|
196
|
+
[acc, state, buffer] = [acc, types_1.ELexState.indent, ""];
|
|
197
|
+
break;
|
|
198
|
+
case '"':
|
|
199
|
+
acc.push(parseIndentation(buffer));
|
|
200
|
+
[state, buffer] = [types_1.ELexState.string, ""];
|
|
201
|
+
break;
|
|
202
|
+
case "(":
|
|
203
|
+
acc.push(parseIndentation(buffer), types_1.ELexControl.open);
|
|
204
|
+
[state, buffer] = [types_1.ELexState.space, ""];
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
acc.push(parseIndentation(buffer));
|
|
208
|
+
[state, buffer] = [types_1.ELexState.token, c];
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
default:
|
|
213
|
+
console.log("Unknown state:", c);
|
|
214
|
+
return acc;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return acc;
|
|
219
|
+
};
|
|
220
|
+
let repeat = (times, x) => {
|
|
221
|
+
let xs = [];
|
|
222
|
+
for (let i = 1; i <= times; i++) {
|
|
223
|
+
xs.push(x);
|
|
224
|
+
}
|
|
225
|
+
return xs;
|
|
226
|
+
};
|
|
227
|
+
let resolveIndentations = (initialTokens) => {
|
|
228
|
+
let acc = [];
|
|
229
|
+
let level = 0;
|
|
230
|
+
let tokens = initialTokens;
|
|
231
|
+
let pointer = 0;
|
|
232
|
+
while (true) {
|
|
233
|
+
if (pointer >= tokens.length) {
|
|
234
|
+
if (tree_1.isEmpty(acc)) {
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
acc.unshift(types_1.ELexControl.open);
|
|
239
|
+
tree_1.pushToList(acc, repeat(level, types_1.ELexControl.close), [types_1.ELexControl.close]);
|
|
240
|
+
return acc;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
let cursor = tokens[pointer];
|
|
245
|
+
if (typeof cursor === "string") {
|
|
246
|
+
acc.push(cursor);
|
|
247
|
+
pointer += 1;
|
|
248
|
+
[level] = [level];
|
|
249
|
+
}
|
|
250
|
+
else if (cursor === types_1.ELexControl.open || cursor === types_1.ELexControl.close) {
|
|
251
|
+
acc.push(cursor);
|
|
252
|
+
pointer += 1;
|
|
253
|
+
[level] = [level];
|
|
254
|
+
}
|
|
255
|
+
else if (typeof cursor === "number") {
|
|
256
|
+
if (cursor > level) {
|
|
257
|
+
let delta = cursor - level;
|
|
258
|
+
tree_1.pushToList(acc, repeat(delta, types_1.ELexControl.open));
|
|
259
|
+
pointer += 1;
|
|
260
|
+
[level] = [cursor];
|
|
261
|
+
}
|
|
262
|
+
else if (cursor < level) {
|
|
263
|
+
let delta = level - cursor;
|
|
264
|
+
tree_1.pushToList(acc, repeat(delta, types_1.ELexControl.close), [types_1.ELexControl.close, types_1.ELexControl.open]);
|
|
265
|
+
pointer += 1;
|
|
266
|
+
[level] = [cursor];
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
if (tree_1.isEmpty(acc)) {
|
|
270
|
+
acc = [];
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
acc.push(types_1.ELexControl.close, types_1.ELexControl.open);
|
|
274
|
+
}
|
|
275
|
+
pointer += 1;
|
|
276
|
+
[level] = [level];
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
console.log(cursor);
|
|
281
|
+
throw new Error("Unknown token");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
let parse = (code) => {
|
|
287
|
+
let tokens = resolveIndentations(lex(code));
|
|
288
|
+
let pointer = 0;
|
|
289
|
+
let pullToken = () => {
|
|
290
|
+
let c = tokens[pointer];
|
|
291
|
+
pointer += 1;
|
|
292
|
+
return c;
|
|
293
|
+
};
|
|
294
|
+
return tree_1.resolveComma(tree_1.resolveDollar(buildExprs(pullToken)));
|
|
295
|
+
};
|
|
296
|
+
exports.parse = parse;
|
|
297
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/tree.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ICirruNode } from "./types";
|
|
2
|
+
export declare let pushToList: <T>(acc: T[], xs: T[], ys?: T[], zs?: T[]) => T[];
|
|
3
|
+
export declare let isArray: (arg: any) => arg is any[];
|
|
4
|
+
export declare let isEmpty: (xs: any[] | string) => boolean;
|
|
5
|
+
export declare let notEmpty: (xs: any[]) => boolean;
|
|
6
|
+
export declare let isString: (x: any) => boolean;
|
|
7
|
+
export declare let isNumber: (x: any) => boolean;
|
|
8
|
+
export declare let isOdd: (x: number) => boolean;
|
|
9
|
+
export declare let resolveComma: (xs: ICirruNode[]) => ICirruNode[];
|
|
10
|
+
export declare let resolveDollar: (xs: ICirruNode[]) => ICirruNode[];
|
package/lib/tree.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveDollar = exports.resolveComma = exports.isOdd = exports.isNumber = exports.isString = exports.notEmpty = exports.isEmpty = exports.isArray = exports.pushToList = void 0;
|
|
4
|
+
let pushToList = (acc, xs, ys, zs) => {
|
|
5
|
+
let result = acc;
|
|
6
|
+
xs.forEach((x) => {
|
|
7
|
+
result.push(x);
|
|
8
|
+
});
|
|
9
|
+
if (ys != null) {
|
|
10
|
+
ys.forEach((y) => {
|
|
11
|
+
result.push(y);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (zs != null) {
|
|
15
|
+
zs.forEach((y) => {
|
|
16
|
+
result.push(y);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
exports.pushToList = pushToList;
|
|
22
|
+
exports.isArray = Array.isArray;
|
|
23
|
+
let isEmpty = (xs) => xs.length === 0;
|
|
24
|
+
exports.isEmpty = isEmpty;
|
|
25
|
+
let notEmpty = (xs) => xs.length > 0;
|
|
26
|
+
exports.notEmpty = notEmpty;
|
|
27
|
+
let isString = (x) => typeof x === "string";
|
|
28
|
+
exports.isString = isString;
|
|
29
|
+
let isNumber = (x) => typeof x === "number";
|
|
30
|
+
exports.isNumber = isNumber;
|
|
31
|
+
let isOdd = (x) => x % 2 === 1;
|
|
32
|
+
exports.isOdd = isOdd;
|
|
33
|
+
let resolveComma = (xs) => {
|
|
34
|
+
if (exports.isEmpty(xs)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return commaHelper(xs);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
exports.resolveComma = resolveComma;
|
|
42
|
+
let commaHelper = (intialAfter) => {
|
|
43
|
+
let before = [];
|
|
44
|
+
let after = intialAfter;
|
|
45
|
+
let pointer = 0;
|
|
46
|
+
while (true) {
|
|
47
|
+
if (pointer >= after.length) {
|
|
48
|
+
return before;
|
|
49
|
+
}
|
|
50
|
+
let cursor = after[pointer];
|
|
51
|
+
if (exports.isArray(cursor) && exports.notEmpty(cursor)) {
|
|
52
|
+
let head = cursor[0];
|
|
53
|
+
if (exports.isArray(head)) {
|
|
54
|
+
before.push(exports.resolveComma(cursor));
|
|
55
|
+
pointer += 1;
|
|
56
|
+
}
|
|
57
|
+
else if (head === ",") {
|
|
58
|
+
exports.pushToList(before, exports.resolveComma(cursor.slice(1)));
|
|
59
|
+
pointer += 1;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
before.push(exports.resolveComma(cursor));
|
|
63
|
+
pointer += 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
before.push(cursor);
|
|
68
|
+
pointer += 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
let resolveDollar = (xs) => {
|
|
73
|
+
if (exports.isEmpty(xs)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return dollarHelper(xs);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
exports.resolveDollar = resolveDollar;
|
|
81
|
+
let dollarHelper = (initialAfter) => {
|
|
82
|
+
let before = [];
|
|
83
|
+
let after = initialAfter;
|
|
84
|
+
let pointer = 0;
|
|
85
|
+
while (true) {
|
|
86
|
+
if (pointer >= after.length) {
|
|
87
|
+
return before;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
let cursor = after[pointer];
|
|
91
|
+
if (exports.isArray(cursor)) {
|
|
92
|
+
before.push(exports.resolveDollar(cursor));
|
|
93
|
+
pointer += 1;
|
|
94
|
+
}
|
|
95
|
+
else if (cursor === "$") {
|
|
96
|
+
before.push(exports.resolveDollar(after.slice(pointer + 1))); // pick items after pointer for $
|
|
97
|
+
pointer = after.length; // trying to exit
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
before.push(cursor);
|
|
101
|
+
pointer += 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=tree.js.map
|
package/lib/tree.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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"}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare type ICirruNode = string | ICirruNode[];
|
|
2
|
+
export declare enum ELexState {
|
|
3
|
+
space = 0,
|
|
4
|
+
token = 1,
|
|
5
|
+
escape = 2,
|
|
6
|
+
indent = 3,
|
|
7
|
+
string = 4
|
|
8
|
+
}
|
|
9
|
+
export declare enum ELexControl {
|
|
10
|
+
open = -1000,
|
|
11
|
+
close = -2000
|
|
12
|
+
}
|
|
13
|
+
export declare type LexList = (string | ELexControl | number)[];
|
|
14
|
+
export declare type LexListItem = string | ELexControl | number;
|
package/lib/types.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ELexControl = exports.ELexState = void 0;
|
|
4
|
+
var ELexState;
|
|
5
|
+
(function (ELexState) {
|
|
6
|
+
ELexState[ELexState["space"] = 0] = "space";
|
|
7
|
+
ELexState[ELexState["token"] = 1] = "token";
|
|
8
|
+
ELexState[ELexState["escape"] = 2] = "escape";
|
|
9
|
+
ELexState[ELexState["indent"] = 3] = "indent";
|
|
10
|
+
ELexState[ELexState["string"] = 4] = "string";
|
|
11
|
+
})(ELexState = exports.ELexState || (exports.ELexState = {}));
|
|
12
|
+
var ELexControl;
|
|
13
|
+
(function (ELexControl) {
|
|
14
|
+
ELexControl[ELexControl["open"] = -1000] = "open";
|
|
15
|
+
ELexControl[ELexControl["close"] = -2000] = "close";
|
|
16
|
+
})(ELexControl = exports.ELexControl || (exports.ELexControl = {}));
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
package/lib/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAEA,IAAY,SAMX;AAND,WAAY,SAAS;IACnB,2CAAK,CAAA;IACL,2CAAK,CAAA;IACL,6CAAM,CAAA;IACN,6CAAM,CAAA;IACN,6CAAM,CAAA;AACR,CAAC,EANW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAMpB;AAED,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,iDAAY,CAAA;IACZ,mDAAa,CAAA;AACf,CAAC,EAHW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAGtB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cirru/parser.ts",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "Cirru Parser in TypeScript",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "webpack serve --hot --config webpack/dev.js",
|
|
8
|
+
"watch": "webpack serve --hot --config webpack/dev.js",
|
|
9
|
+
"release": "rm -rfv dist/* && time webpack --config webpack/release.js",
|
|
10
|
+
"build": "yarn release",
|
|
11
|
+
"serve": "http-server dist/ -s",
|
|
12
|
+
"test": "yarn jest",
|
|
13
|
+
"compile": "rm -rfv lib/* && tsc -d --project tsconfig-compile.json --outDir lib/",
|
|
14
|
+
"prepare": "yarn test && yarn compile",
|
|
15
|
+
"upload": "rsync -avr --progress dist/ cirru.org:~/repo/Cirru/parser.ts",
|
|
16
|
+
"gen-router": "ts-node -P tsconfig-node.json -r tsconfig-paths/register example/gen-router.ts",
|
|
17
|
+
"postinstall": "rm -rfv node_modules/@types/*/node_modules/@types/react"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@emotion/css": "^11.1.3",
|
|
24
|
+
"@jimengio/ci-progress-webpack-plugin": "^0.1.0",
|
|
25
|
+
"@types/jest": "^26.0.20",
|
|
26
|
+
"@types/node": "^14.14.25",
|
|
27
|
+
"@types/prettier": "^2.1.6",
|
|
28
|
+
"@types/react": "^17.0.1",
|
|
29
|
+
"@types/react-dom": "^17.0.0",
|
|
30
|
+
"cache-loader": "^4.1.0",
|
|
31
|
+
"css-loader": "^5.0.1",
|
|
32
|
+
"dayjs": "^1.10.4",
|
|
33
|
+
"duplicate-package-checker-webpack-plugin": "^3.0.0",
|
|
34
|
+
"file-loader": "^6.2.0",
|
|
35
|
+
"font-awesome": "^4.7.0",
|
|
36
|
+
"fork-ts-checker-webpack-plugin": "^6.1.0",
|
|
37
|
+
"html-webpack-plugin": "^5.0.0",
|
|
38
|
+
"html-webpack-tags-plugin": "^3.0.0",
|
|
39
|
+
"immer": "^8.0.1",
|
|
40
|
+
"jest": "^26.6.3",
|
|
41
|
+
"mini-css-extract-plugin": "^1.3.5",
|
|
42
|
+
"prettier": "^2.2.1",
|
|
43
|
+
"query-string": "^6.13.8",
|
|
44
|
+
"react": "^17.0.1",
|
|
45
|
+
"react-dom": "^17.0.1",
|
|
46
|
+
"style-loader": "^2.0.0",
|
|
47
|
+
"thread-loader": "^3.0.1",
|
|
48
|
+
"ts-jest": "^26.5.0",
|
|
49
|
+
"ts-loader": "^8.0.14",
|
|
50
|
+
"tsconfig-paths": "^3.9.0",
|
|
51
|
+
"tsconfig-paths-webpack-plugin": "^3.3.0",
|
|
52
|
+
"typescript": "^4.1.3",
|
|
53
|
+
"typescript-styled-plugin": "^0.15.0",
|
|
54
|
+
"url-loader": "^4.1.1",
|
|
55
|
+
"webpack": "^5.20.1",
|
|
56
|
+
"webpack-bundle-analyzer": "^4.4.0",
|
|
57
|
+
"webpack-cli": "^4.5.0",
|
|
58
|
+
"webpack-dev-server": "^3.11.2",
|
|
59
|
+
"webpack-hud": "^0.1.2"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {}
|
|
62
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { ICirruNode, ELexState, ELexControl, LexList, LexListItem } from "./types";
|
|
2
|
+
import { pushToList, resolveComma, resolveDollar, isEmpty, isString, isNumber, isOdd, isArray } from "./tree";
|
|
3
|
+
|
|
4
|
+
export { ICirruNode } from "./types";
|
|
5
|
+
|
|
6
|
+
type FuncTokenGet = () => string | ELexControl;
|
|
7
|
+
|
|
8
|
+
let graspeExprs = (pullToken: FuncTokenGet) => {
|
|
9
|
+
let acc: ICirruNode[] = [];
|
|
10
|
+
let pointer = acc;
|
|
11
|
+
let pointerStack = [];
|
|
12
|
+
while (true) {
|
|
13
|
+
let cursor = pullToken();
|
|
14
|
+
// console.log(pointerStack, pointer, cursor);
|
|
15
|
+
switch (cursor) {
|
|
16
|
+
case ELexControl.close:
|
|
17
|
+
if (pointerStack.length === 0) {
|
|
18
|
+
return pointer;
|
|
19
|
+
}
|
|
20
|
+
let collected = pointer;
|
|
21
|
+
pointer = pointerStack.pop();
|
|
22
|
+
pointer.push(collected);
|
|
23
|
+
break;
|
|
24
|
+
case ELexControl.open:
|
|
25
|
+
pointerStack.push(pointer);
|
|
26
|
+
pointer = [];
|
|
27
|
+
break;
|
|
28
|
+
case ELexControl.close:
|
|
29
|
+
throw new Error("Unexpected close token");
|
|
30
|
+
default:
|
|
31
|
+
if (isString(cursor)) {
|
|
32
|
+
pointer.push(cursor);
|
|
33
|
+
break;
|
|
34
|
+
} else {
|
|
35
|
+
console.log(JSON.stringify(cursor));
|
|
36
|
+
throw new Error("Unknown cursor");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
let buildExprs = (pullToken: FuncTokenGet) => {
|
|
43
|
+
let acc = [];
|
|
44
|
+
while (true) {
|
|
45
|
+
let chunk = pullToken();
|
|
46
|
+
if (chunk === ELexControl.open) {
|
|
47
|
+
let expr = graspeExprs(pullToken);
|
|
48
|
+
acc.push(expr);
|
|
49
|
+
continue;
|
|
50
|
+
} else if (chunk == null) {
|
|
51
|
+
return acc;
|
|
52
|
+
} else if (chunk === ELexControl.close) {
|
|
53
|
+
throw new Error(`Unexpected ")"`);
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error(`Unexpected chunk ${JSON.stringify(chunk)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
let parseIndentation = (buffer: string) => {
|
|
61
|
+
let size = buffer.length;
|
|
62
|
+
if (isOdd(size)) {
|
|
63
|
+
throw new Error(`Invalid indentation size ${size}`);
|
|
64
|
+
}
|
|
65
|
+
return size / 2;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
let lex = (initialCode: string) => {
|
|
69
|
+
let acc: LexList = [];
|
|
70
|
+
let state = ELexState.indent as ELexState;
|
|
71
|
+
let buffer = "";
|
|
72
|
+
let code = initialCode;
|
|
73
|
+
// let count = 0;
|
|
74
|
+
|
|
75
|
+
let pointer = 0;
|
|
76
|
+
|
|
77
|
+
while (true) {
|
|
78
|
+
// count += 1;
|
|
79
|
+
// if (count > 1000) {
|
|
80
|
+
// break;
|
|
81
|
+
// }
|
|
82
|
+
if (pointer >= code.length) {
|
|
83
|
+
switch (state) {
|
|
84
|
+
case ELexState.space:
|
|
85
|
+
return acc;
|
|
86
|
+
case ELexState.token:
|
|
87
|
+
acc.push(buffer);
|
|
88
|
+
return acc;
|
|
89
|
+
break;
|
|
90
|
+
case ELexState.escape:
|
|
91
|
+
throw new Error("Should not be escape");
|
|
92
|
+
case ELexState.indent:
|
|
93
|
+
return acc;
|
|
94
|
+
case ELexState.string:
|
|
95
|
+
throw new Error("Should not be string");
|
|
96
|
+
default:
|
|
97
|
+
console.log(state);
|
|
98
|
+
throw new Error("Unkown state");
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
let c = code[pointer];
|
|
102
|
+
pointer += 1;
|
|
103
|
+
switch (state) {
|
|
104
|
+
case ELexState.space:
|
|
105
|
+
switch (c) {
|
|
106
|
+
case " ":
|
|
107
|
+
[acc, state, buffer] = [acc, ELexState.space, ""];
|
|
108
|
+
break;
|
|
109
|
+
case "\n":
|
|
110
|
+
[acc, state, buffer] = [acc, ELexState.indent, ""];
|
|
111
|
+
break;
|
|
112
|
+
case "(":
|
|
113
|
+
acc.push(ELexControl.open);
|
|
114
|
+
[state, buffer] = [ELexState.space, ""];
|
|
115
|
+
break;
|
|
116
|
+
case ")":
|
|
117
|
+
acc.push(ELexControl.close);
|
|
118
|
+
[state, buffer] = [ELexState.space, ""];
|
|
119
|
+
break;
|
|
120
|
+
case '"':
|
|
121
|
+
[acc, state, buffer] = [acc, ELexState.string, ""];
|
|
122
|
+
break;
|
|
123
|
+
default:
|
|
124
|
+
[acc, state, buffer] = [acc, ELexState.token, c];
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case ELexState.token:
|
|
129
|
+
switch (c) {
|
|
130
|
+
case " ":
|
|
131
|
+
acc.push(buffer);
|
|
132
|
+
[state, buffer] = [ELexState.space, ""];
|
|
133
|
+
break;
|
|
134
|
+
case '"':
|
|
135
|
+
acc.push(buffer);
|
|
136
|
+
[state, buffer] = [ELexState.string, ""];
|
|
137
|
+
break;
|
|
138
|
+
case "\n":
|
|
139
|
+
acc.push(buffer);
|
|
140
|
+
[state, buffer] = [ELexState.indent, ""];
|
|
141
|
+
break;
|
|
142
|
+
case "(":
|
|
143
|
+
acc.push(buffer, ELexControl.open);
|
|
144
|
+
[state, buffer] = [ELexState.space, ""];
|
|
145
|
+
break;
|
|
146
|
+
case ")":
|
|
147
|
+
acc.push(buffer, ELexControl.close);
|
|
148
|
+
[state, buffer] = [ELexState.space, ""];
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
[acc, state, buffer] = [acc, ELexState.token, `${buffer}${c}`];
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
case ELexState.string:
|
|
156
|
+
switch (c) {
|
|
157
|
+
case '"':
|
|
158
|
+
acc.push(buffer);
|
|
159
|
+
[state, buffer] = [ELexState.space, ""];
|
|
160
|
+
break;
|
|
161
|
+
case "\\":
|
|
162
|
+
[acc, state, buffer] = [acc, ELexState.escape, buffer];
|
|
163
|
+
break;
|
|
164
|
+
case "\n":
|
|
165
|
+
throw new Error("Expected newline in string");
|
|
166
|
+
default:
|
|
167
|
+
[acc, state, buffer] = [acc, ELexState.string, `${buffer}${c}`];
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
case ELexState.escape:
|
|
172
|
+
switch (c) {
|
|
173
|
+
case '"':
|
|
174
|
+
[acc, state, buffer] = [acc, ELexState.string, `${buffer}"`];
|
|
175
|
+
break;
|
|
176
|
+
case "'":
|
|
177
|
+
[acc, state, buffer] = [acc, ELexState.string, `${buffer}'`];
|
|
178
|
+
break;
|
|
179
|
+
case "t":
|
|
180
|
+
[acc, state, buffer] = [acc, ELexState.string, `${buffer}\t`];
|
|
181
|
+
break;
|
|
182
|
+
case "n":
|
|
183
|
+
[acc, state, buffer] = [acc, ELexState.string, `${buffer}\n`];
|
|
184
|
+
break;
|
|
185
|
+
case "\\":
|
|
186
|
+
[acc, state, buffer] = [acc, ELexState.string, `${buffer}\\`];
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
throw new Error(`Unknown ${c} in escape`);
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
case ELexState.indent:
|
|
193
|
+
switch (c) {
|
|
194
|
+
case " ":
|
|
195
|
+
[acc, state, buffer] = [acc, ELexState.indent, `${buffer}${c}`];
|
|
196
|
+
break;
|
|
197
|
+
case "\n":
|
|
198
|
+
[acc, state, buffer] = [acc, ELexState.indent, ""];
|
|
199
|
+
break;
|
|
200
|
+
case '"':
|
|
201
|
+
acc.push(parseIndentation(buffer));
|
|
202
|
+
[state, buffer] = [ELexState.string, ""];
|
|
203
|
+
break;
|
|
204
|
+
case "(":
|
|
205
|
+
acc.push(parseIndentation(buffer), ELexControl.open);
|
|
206
|
+
[state, buffer] = [ELexState.space, ""];
|
|
207
|
+
break;
|
|
208
|
+
default:
|
|
209
|
+
acc.push(parseIndentation(buffer));
|
|
210
|
+
[state, buffer] = [ELexState.token, c];
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
default:
|
|
215
|
+
console.log("Unknown state:", c);
|
|
216
|
+
return acc;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return acc;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
let repeat = <T>(times: number, x: T) => {
|
|
224
|
+
let xs: T[] = [];
|
|
225
|
+
for (let i = 1; i <= times; i++) {
|
|
226
|
+
xs.push(x);
|
|
227
|
+
}
|
|
228
|
+
return xs;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
let resolveIndentations = (initialTokens: LexList) => {
|
|
232
|
+
let acc: LexList = [];
|
|
233
|
+
let level = 0;
|
|
234
|
+
let tokens: LexList = initialTokens;
|
|
235
|
+
let pointer = 0;
|
|
236
|
+
while (true) {
|
|
237
|
+
if (pointer >= tokens.length) {
|
|
238
|
+
if (isEmpty(acc)) {
|
|
239
|
+
return [];
|
|
240
|
+
} else {
|
|
241
|
+
acc.unshift(ELexControl.open);
|
|
242
|
+
pushToList(acc, repeat(level, ELexControl.close), [ELexControl.close]);
|
|
243
|
+
return acc;
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
let cursor = tokens[pointer];
|
|
247
|
+
if (typeof cursor === "string") {
|
|
248
|
+
acc.push(cursor);
|
|
249
|
+
pointer += 1;
|
|
250
|
+
[level] = [level];
|
|
251
|
+
} else if (cursor === ELexControl.open || cursor === ELexControl.close) {
|
|
252
|
+
acc.push(cursor);
|
|
253
|
+
pointer += 1;
|
|
254
|
+
[level] = [level];
|
|
255
|
+
} else if (typeof cursor === "number") {
|
|
256
|
+
if (cursor > level) {
|
|
257
|
+
let delta = cursor - level;
|
|
258
|
+
pushToList(acc, repeat(delta, ELexControl.open));
|
|
259
|
+
pointer += 1;
|
|
260
|
+
[level] = [cursor];
|
|
261
|
+
} else if (cursor < level) {
|
|
262
|
+
let delta = level - cursor;
|
|
263
|
+
pushToList(acc, repeat(delta, ELexControl.close), [ELexControl.close, ELexControl.open]);
|
|
264
|
+
pointer += 1;
|
|
265
|
+
[level] = [cursor];
|
|
266
|
+
} else {
|
|
267
|
+
if (isEmpty(acc)) {
|
|
268
|
+
acc = [];
|
|
269
|
+
} else {
|
|
270
|
+
acc.push(ELexControl.close, ELexControl.open);
|
|
271
|
+
}
|
|
272
|
+
pointer += 1;
|
|
273
|
+
[level] = [level];
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
console.log(cursor);
|
|
277
|
+
throw new Error("Unknown token");
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
export let parse = (code: string) => {
|
|
284
|
+
let tokens = resolveIndentations(lex(code));
|
|
285
|
+
let pointer = 0;
|
|
286
|
+
let pullToken = () => {
|
|
287
|
+
let c = tokens[pointer];
|
|
288
|
+
pointer += 1;
|
|
289
|
+
return c;
|
|
290
|
+
};
|
|
291
|
+
return resolveComma(resolveDollar(buildExprs(pullToken)));
|
|
292
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
let fs = require("fs");
|
|
2
|
+
let path = require("path");
|
|
3
|
+
let { parse } = require("./index");
|
|
4
|
+
|
|
5
|
+
test("single quote", () => expect(parse('a "\\\'"')).toEqual([["a", "'"]]));
|
|
6
|
+
|
|
7
|
+
test("demo", () => {
|
|
8
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/demo.cirru"), "utf8");
|
|
9
|
+
let data = require(path.join(__dirname, "../test/ast/demo.json"));
|
|
10
|
+
expect(parse(code)).toEqual(data);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("comma", () => {
|
|
14
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/comma.cirru"), "utf8");
|
|
15
|
+
let data = require(path.join(__dirname, "../test/ast/comma.json"));
|
|
16
|
+
expect(parse(code)).toEqual(data);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("empty", () => {
|
|
20
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/empty.cirru"), "utf8");
|
|
21
|
+
let data = require(path.join(__dirname, "../test/ast/empty.json"));
|
|
22
|
+
expect(parse(code)).toEqual(data);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("folded-beginning", () => {
|
|
26
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/folded-beginning.cirru"), "utf8");
|
|
27
|
+
let data = require(path.join(__dirname, "../test/ast/folded-beginning.json"));
|
|
28
|
+
expect(parse(code)).toEqual(data);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("folding", () => {
|
|
32
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/folding.cirru"), "utf8");
|
|
33
|
+
let data = require(path.join(__dirname, "../test/ast/folding.json"));
|
|
34
|
+
expect(parse(code)).toEqual(data);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("html", () => {
|
|
38
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/html.cirru"), "utf8");
|
|
39
|
+
let data = require(path.join(__dirname, "../test/ast/html.json"));
|
|
40
|
+
expect(parse(code)).toEqual(data);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("indent", () => {
|
|
44
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/indent.cirru"), "utf8");
|
|
45
|
+
let data = require(path.join(__dirname, "../test/ast/indent.json"));
|
|
46
|
+
expect(parse(code)).toEqual(data);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("line", () => {
|
|
50
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/line.cirru"), "utf8");
|
|
51
|
+
let data = require(path.join(__dirname, "../test/ast/line.json"));
|
|
52
|
+
expect(parse(code)).toEqual(data);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("parentheses", () => {
|
|
56
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/parentheses.cirru"), "utf8");
|
|
57
|
+
let data = require(path.join(__dirname, "../test/ast/parentheses.json"));
|
|
58
|
+
expect(parse(code)).toEqual(data);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("quote", () => {
|
|
62
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/quote.cirru"), "utf8");
|
|
63
|
+
let data = require(path.join(__dirname, "../test/ast/quote.json"));
|
|
64
|
+
expect(parse(code)).toEqual(data);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("spaces", () => {
|
|
68
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/spaces.cirru"), "utf8");
|
|
69
|
+
let data = require(path.join(__dirname, "../test/ast/spaces.json"));
|
|
70
|
+
expect(parse(code)).toEqual(data);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("unfolding", () => {
|
|
74
|
+
let code = fs.readFileSync(path.join(__dirname, "../test/cirru/unfolding.cirru"), "utf8");
|
|
75
|
+
let data = require(path.join(__dirname, "../test/ast/unfolding.json"));
|
|
76
|
+
expect(parse(code)).toEqual(data);
|
|
77
|
+
});
|
package/src/tree.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ICirruNode } from "./types";
|
|
2
|
+
|
|
3
|
+
export let pushToList = <T>(acc: T[], xs: T[], ys?: T[], zs?: T[]) => {
|
|
4
|
+
let result = acc;
|
|
5
|
+
xs.forEach((x) => {
|
|
6
|
+
result.push(x);
|
|
7
|
+
});
|
|
8
|
+
if (ys != null) {
|
|
9
|
+
ys.forEach((y) => {
|
|
10
|
+
result.push(y);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
if (zs != null) {
|
|
14
|
+
zs.forEach((y) => {
|
|
15
|
+
result.push(y);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export let isArray = Array.isArray;
|
|
22
|
+
export let isEmpty = (xs: any[] | string) => xs.length === 0;
|
|
23
|
+
export let notEmpty = (xs: any[]) => xs.length > 0;
|
|
24
|
+
export let isString = (x: any) => typeof x === "string";
|
|
25
|
+
export let isNumber = (x: any) => typeof x === "number";
|
|
26
|
+
export let isOdd = (x: number) => x % 2 === 1;
|
|
27
|
+
|
|
28
|
+
export let resolveComma = (xs: ICirruNode[]) => {
|
|
29
|
+
if (isEmpty(xs)) {
|
|
30
|
+
return [];
|
|
31
|
+
} else {
|
|
32
|
+
return commaHelper(xs);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
let commaHelper = (intialAfter: ICirruNode[]) => {
|
|
37
|
+
let before: ICirruNode[] = [];
|
|
38
|
+
let after: ICirruNode[] = intialAfter;
|
|
39
|
+
|
|
40
|
+
let pointer = 0;
|
|
41
|
+
|
|
42
|
+
while (true) {
|
|
43
|
+
if (pointer >= after.length) {
|
|
44
|
+
return before;
|
|
45
|
+
}
|
|
46
|
+
let cursor = after[pointer];
|
|
47
|
+
|
|
48
|
+
if (isArray(cursor) && notEmpty(cursor)) {
|
|
49
|
+
let head = cursor[0];
|
|
50
|
+
if (isArray(head)) {
|
|
51
|
+
before.push(resolveComma(cursor));
|
|
52
|
+
pointer += 1;
|
|
53
|
+
} else if (head === ",") {
|
|
54
|
+
pushToList(before, resolveComma(cursor.slice(1)));
|
|
55
|
+
pointer += 1;
|
|
56
|
+
} else {
|
|
57
|
+
before.push(resolveComma(cursor));
|
|
58
|
+
pointer += 1;
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
before.push(cursor);
|
|
62
|
+
pointer += 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export let resolveDollar = (xs: ICirruNode[]) => {
|
|
68
|
+
if (isEmpty(xs)) {
|
|
69
|
+
return [];
|
|
70
|
+
} else {
|
|
71
|
+
return dollarHelper(xs);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
let dollarHelper = (initialAfter: ICirruNode[]) => {
|
|
76
|
+
let before: ICirruNode[] = [];
|
|
77
|
+
let after: ICirruNode[] = initialAfter;
|
|
78
|
+
|
|
79
|
+
let pointer = 0;
|
|
80
|
+
|
|
81
|
+
while (true) {
|
|
82
|
+
if (pointer >= after.length) {
|
|
83
|
+
return before;
|
|
84
|
+
} else {
|
|
85
|
+
let cursor = after[pointer];
|
|
86
|
+
|
|
87
|
+
if (isArray(cursor)) {
|
|
88
|
+
before.push(resolveDollar(cursor));
|
|
89
|
+
pointer += 1;
|
|
90
|
+
} else if (cursor === "$") {
|
|
91
|
+
before.push(resolveDollar(after.slice(pointer + 1))); // pick items after pointer for $
|
|
92
|
+
pointer = after.length; // trying to exit
|
|
93
|
+
} else {
|
|
94
|
+
before.push(cursor);
|
|
95
|
+
pointer += 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ICirruNode = string | ICirruNode[];
|
|
2
|
+
|
|
3
|
+
export enum ELexState {
|
|
4
|
+
space,
|
|
5
|
+
token,
|
|
6
|
+
escape,
|
|
7
|
+
indent,
|
|
8
|
+
string,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export enum ELexControl {
|
|
12
|
+
open = -1000,
|
|
13
|
+
close = -2000,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type LexList = (string | ELexControl | number)[];
|
|
17
|
+
export type LexListItem = string | ELexControl | number;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowSyntheticDefaultImports": true,
|
|
4
|
+
"experimentalDecorators": true,
|
|
5
|
+
"sourceMap": true,
|
|
6
|
+
"noImplicitAny": false,
|
|
7
|
+
"noImplicitThis": true,
|
|
8
|
+
"strictNullChecks": false,
|
|
9
|
+
"moduleResolution": "node",
|
|
10
|
+
"module": "commonjs",
|
|
11
|
+
"target": "es2015",
|
|
12
|
+
"jsx": "react",
|
|
13
|
+
"lib": ["es2016", "dom"],
|
|
14
|
+
"types": [],
|
|
15
|
+
"plugins": [
|
|
16
|
+
{
|
|
17
|
+
"name": "typescript-styled-plugin"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"include": ["src/*.ts", "src/*/*.ts"],
|
|
22
|
+
"exclude": ["src/*.test.ts"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowSyntheticDefaultImports": true,
|
|
4
|
+
"experimentalDecorators": true,
|
|
5
|
+
"sourceMap": true,
|
|
6
|
+
"noImplicitAny": false,
|
|
7
|
+
"noImplicitThis": true,
|
|
8
|
+
"strictNullChecks": false,
|
|
9
|
+
"moduleResolution": "node",
|
|
10
|
+
"module": "commonjs",
|
|
11
|
+
"target": "es2016",
|
|
12
|
+
"jsx": "react",
|
|
13
|
+
"lib": ["es2016"],
|
|
14
|
+
"types": ["node"],
|
|
15
|
+
"baseUrl": "./example/",
|
|
16
|
+
"paths": {
|
|
17
|
+
"models": ["./example/models"]
|
|
18
|
+
},
|
|
19
|
+
"plugins": []
|
|
20
|
+
}
|
|
21
|
+
}
|