-
Notifications
You must be signed in to change notification settings - Fork 0
/
example.js
98 lines (90 loc) · 2.9 KB
/
example.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
let { oneOf, readToken, lit, combinator, inline, many, many1, sepBy, sepBy1, toGrammar } = require("./index");
let { cata, getSchema } = require("church-cat");
let { llParser, extractValue } = require("./ll-parser");
function json() {
return oneOf(lit("number"), lit("string"), object, array);
}
function object() {
readToken("{");
let [entries] = sepBy(
inline(() => {
let key = readToken("string");
readToken(":");
let val = json();
return [key, val]
}),
lit(","))();
readToken("}");
return Object.fromEntries(entries);
}
function array() {
readToken("[");
let [entries] = sepBy(json, lit(","))();
readToken("]");
return entries;
}
function tokenize(str) {
let tokens = [];
let gen = tokenizer((tok) => tokens.push(tok));
gen.next();
for(let chr of str.split('')) {
gen.next(chr);
}
return tokens;
}
function* tokenizer(out) {
let chr = yield;
while(true) {
if("{}[],:".indexOf(chr) > -1) {
out({type: chr, value: chr});
chr = yield;
} else if(chr === '"') {
let str = [];
while(true) {
let next = yield;
if(next === '"') {
out({type: 'string', value: str.join("")});
break;
}
if(next === '\\') {
next = yield;
}
str.push(next);
}
chr = yield;
} else if("0123456789".indexOf(chr) > -1) {
let ns = [chr];
while(true) {
let next = yield;
if("0123456789".indexOf(next) > -1) {
ns.push(next);
} else {
chr = next;
out({type: 'number', value: parseInt(ns.join(''))});
break;
}
}
} else if(" \t\n".indexOf(chr) > -1) {
chr = yield;
}
}
}
function logADT(adt, showADT = (adt) => ``, showK = (x) => `${x}`) {
let schema = getSchema(adt);
cata(adt, Object.fromEntries(
Object.entries(schema).map(([name,kinds]) => ([name, function(...args) {
let self = this;
return [`${name} - ${showADT(this)}`,
...args.map((arg,ii) => schema[name][ii]({
K: () => [showK(arg)],
I: () => arg
})).flat(1).map(line => `++${line}`)];
}]))))(adt).map(line => console.log(line));
}
let testInput = JSON.stringify([ "foo", {"bar": "baz"}, 123 ]);
let testTokens = tokenize(testInput).reduceRight((xs,x) => [x,xs], []);
let {gmr: jsonGmr, fns: jsonFns} = toGrammar(json);
let parser = llParser(jsonGmr);
let [parsed, remained] = parser( testTokens );
let res = extractValue(jsonGmr, parsed, jsonFns);
console.log(JSON.stringify(res));