@fraczak/k 1.0.0
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/README.md +181 -0
- package/index.coffee +18 -0
- package/index.js +40 -0
- package/k.coffee +45 -0
- package/k.js +72 -0
- package/k.sh +73 -0
- package/my-objects.json +6 -0
- package/package.json +22 -0
- package/parser.jison +93 -0
- package/parser.js +703 -0
- package/run.coffee +76 -0
- package/run.js +157 -0
- package/symbol-table.coffee +14 -0
- package/symbol-table.js +42 -0
- package/test.coffee +34 -0
- package/test.js +76 -0
- package/test.t +13 -0
package/run.coffee
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
valid = (x) ->
|
|
2
|
+
return undefined if isNaN x
|
|
3
|
+
return x if x?
|
|
4
|
+
|
|
5
|
+
builtin =
|
|
6
|
+
"GT": (args) ->
|
|
7
|
+
[ok,_] = do ([last,args...] = args) ->
|
|
8
|
+
args.reduce ([ok,last], x) ->
|
|
9
|
+
[ok and (last > x), x ]
|
|
10
|
+
, [true,last]
|
|
11
|
+
return args if ok
|
|
12
|
+
"EQ": (args) ->
|
|
13
|
+
[ok,_] = do ([last,args...] = args) ->
|
|
14
|
+
args.reduce ([ok,last], x) ->
|
|
15
|
+
[ok and (last is x), x ]
|
|
16
|
+
, [true,last]
|
|
17
|
+
return args if ok
|
|
18
|
+
"PLUS": (args) -> valid args.reduce ((res, x) -> res + x), 0
|
|
19
|
+
"TIMES": (args) -> valid args.reduce ((res, x) -> res * x), 1
|
|
20
|
+
"MINUS": (args) ->
|
|
21
|
+
return valid(- args) if 'number' is typeof args
|
|
22
|
+
do ([res,args...] = args) ->
|
|
23
|
+
return valid (- res) if args.length is 0
|
|
24
|
+
valid args.reduce ((res, x) -> res - x), res
|
|
25
|
+
"DIV": ([x,y]) ->
|
|
26
|
+
div = x // y
|
|
27
|
+
rem = x %% y
|
|
28
|
+
return {div,rem} if x is div * y + rem
|
|
29
|
+
"CONCAT": (strs) -> strs.join('')
|
|
30
|
+
"true": -> true
|
|
31
|
+
"false": -> false
|
|
32
|
+
"null": -> null
|
|
33
|
+
"toJSON": (x) -> JSON.stringify x
|
|
34
|
+
"fromJSON": (x) -> JSON.parse x
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
run = (exp, value) ->
|
|
38
|
+
return undefined unless value?
|
|
39
|
+
try
|
|
40
|
+
switch exp.op
|
|
41
|
+
when "identity"
|
|
42
|
+
return value
|
|
43
|
+
when "str", "int"
|
|
44
|
+
return exp[exp.op]
|
|
45
|
+
when "ref"
|
|
46
|
+
return do (value = builtin[exp.ref] value) ->
|
|
47
|
+
throw new Error "Undefined" if value is undefined
|
|
48
|
+
value
|
|
49
|
+
when "dot"
|
|
50
|
+
return value[exp.dot]
|
|
51
|
+
when "comp"
|
|
52
|
+
return exp.comp.reduce (value, exp) ->
|
|
53
|
+
value = run exp, value
|
|
54
|
+
throw new Error "Undefined" unless value?
|
|
55
|
+
value
|
|
56
|
+
, value
|
|
57
|
+
when "vector"
|
|
58
|
+
return exp.vector.map (exp) ->
|
|
59
|
+
result = run exp, value
|
|
60
|
+
throw new Error "Undefined" unless result?
|
|
61
|
+
result
|
|
62
|
+
when "union"
|
|
63
|
+
for e in exp.union
|
|
64
|
+
result = try run e, value
|
|
65
|
+
return result if result?
|
|
66
|
+
return undefined
|
|
67
|
+
when "product"
|
|
68
|
+
return exp.product.reduce (result, {label, exp}) ->
|
|
69
|
+
do (value = run exp, value) ->
|
|
70
|
+
throw new Error "Undefined" unless value?
|
|
71
|
+
result[label] = value
|
|
72
|
+
result
|
|
73
|
+
, {}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
module.exports = run
|
package/run.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
(function() {
|
|
3
|
+
var builtin, run, valid,
|
|
4
|
+
modulo = function(a, b) { return (+a % (b = +b) + b) % b; };
|
|
5
|
+
|
|
6
|
+
valid = function(x) {
|
|
7
|
+
if (isNaN(x)) {
|
|
8
|
+
return void 0;
|
|
9
|
+
}
|
|
10
|
+
if (x != null) {
|
|
11
|
+
return x;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
builtin = {
|
|
16
|
+
"GT": function(args) {
|
|
17
|
+
var _, ok;
|
|
18
|
+
[ok, _] = (function([last, ...args]) {
|
|
19
|
+
return args.reduce(function([ok, last], x) {
|
|
20
|
+
return [ok && (last > x), x];
|
|
21
|
+
}, [true, last]);
|
|
22
|
+
})(args);
|
|
23
|
+
if (ok) {
|
|
24
|
+
return args;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"EQ": function(args) {
|
|
28
|
+
var _, ok;
|
|
29
|
+
[ok, _] = (function([last, ...args]) {
|
|
30
|
+
return args.reduce(function([ok, last], x) {
|
|
31
|
+
return [ok && (last === x), x];
|
|
32
|
+
}, [true, last]);
|
|
33
|
+
})(args);
|
|
34
|
+
if (ok) {
|
|
35
|
+
return args;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"PLUS": function(args) {
|
|
39
|
+
return valid(args.reduce((function(res, x) {
|
|
40
|
+
return res + x;
|
|
41
|
+
}), 0));
|
|
42
|
+
},
|
|
43
|
+
"TIMES": function(args) {
|
|
44
|
+
return valid(args.reduce((function(res, x) {
|
|
45
|
+
return res * x;
|
|
46
|
+
}), 1));
|
|
47
|
+
},
|
|
48
|
+
"MINUS": function(args) {
|
|
49
|
+
if ('number' === typeof args) {
|
|
50
|
+
return valid(-args);
|
|
51
|
+
}
|
|
52
|
+
return (function([res, ...args]) {
|
|
53
|
+
if (args.length === 0) {
|
|
54
|
+
return valid(-res);
|
|
55
|
+
}
|
|
56
|
+
return valid(args.reduce((function(res, x) {
|
|
57
|
+
return res - x;
|
|
58
|
+
}), res));
|
|
59
|
+
})(args);
|
|
60
|
+
},
|
|
61
|
+
"DIV": function([x, y]) {
|
|
62
|
+
var div, rem;
|
|
63
|
+
div = Math.floor(x / y);
|
|
64
|
+
rem = modulo(x, y);
|
|
65
|
+
if (x === div * y + rem) {
|
|
66
|
+
return {div, rem};
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"CONCAT": function(strs) {
|
|
70
|
+
return strs.join('');
|
|
71
|
+
},
|
|
72
|
+
"true": function() {
|
|
73
|
+
return true;
|
|
74
|
+
},
|
|
75
|
+
"false": function() {
|
|
76
|
+
return false;
|
|
77
|
+
},
|
|
78
|
+
"null": function() {
|
|
79
|
+
return null;
|
|
80
|
+
},
|
|
81
|
+
"toJSON": function(x) {
|
|
82
|
+
return JSON.stringify(x);
|
|
83
|
+
},
|
|
84
|
+
"fromJSON": function(x) {
|
|
85
|
+
return JSON.parse(x);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
run = function(exp, value) {
|
|
90
|
+
var e, i, len, ref, result;
|
|
91
|
+
if (value == null) {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
switch (exp.op) {
|
|
96
|
+
case "identity":
|
|
97
|
+
return value;
|
|
98
|
+
case "str":
|
|
99
|
+
case "int":
|
|
100
|
+
return exp[exp.op];
|
|
101
|
+
case "ref":
|
|
102
|
+
return (function(value) {
|
|
103
|
+
if (value === void 0) {
|
|
104
|
+
throw new Error("Undefined");
|
|
105
|
+
}
|
|
106
|
+
return value;
|
|
107
|
+
})(builtin[exp.ref](value));
|
|
108
|
+
case "dot":
|
|
109
|
+
return value[exp.dot];
|
|
110
|
+
case "comp":
|
|
111
|
+
return exp.comp.reduce(function(value, exp) {
|
|
112
|
+
value = run(exp, value);
|
|
113
|
+
if (value == null) {
|
|
114
|
+
throw new Error("Undefined");
|
|
115
|
+
}
|
|
116
|
+
return value;
|
|
117
|
+
}, value);
|
|
118
|
+
case "vector":
|
|
119
|
+
return exp.vector.map(function(exp) {
|
|
120
|
+
var result;
|
|
121
|
+
result = run(exp, value);
|
|
122
|
+
if (result == null) {
|
|
123
|
+
throw new Error("Undefined");
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
});
|
|
127
|
+
case "union":
|
|
128
|
+
ref = exp.union;
|
|
129
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
|
130
|
+
e = ref[i];
|
|
131
|
+
result = (function() {
|
|
132
|
+
try {
|
|
133
|
+
return run(e, value);
|
|
134
|
+
} catch (error) {}
|
|
135
|
+
})();
|
|
136
|
+
if (result != null) {
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return void 0;
|
|
141
|
+
case "product":
|
|
142
|
+
return exp.product.reduce(function(result, {label, exp}) {
|
|
143
|
+
return (function(value) {
|
|
144
|
+
if (value == null) {
|
|
145
|
+
throw new Error("Undefined");
|
|
146
|
+
}
|
|
147
|
+
result[label] = value;
|
|
148
|
+
return result;
|
|
149
|
+
})(run(exp, value));
|
|
150
|
+
}, {});
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
module.exports = run;
|
|
156
|
+
|
|
157
|
+
}).call(this);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
identity = op: "identity"
|
|
2
|
+
|
|
3
|
+
comp = (e1, e2) ->
|
|
4
|
+
return e2 if e1.op is "identity"
|
|
5
|
+
return e1 if e2.op is "identity"
|
|
6
|
+
if e1.op is "comp" and e2.op is "comp"
|
|
7
|
+
return {op: "comp", comp: [].concat(e1.comp,e2.comp)}
|
|
8
|
+
if e1.op is "comp"
|
|
9
|
+
return {op: "comp", comp: [].concat(e1.comp,[e2])}
|
|
10
|
+
if e2.op is "comp"
|
|
11
|
+
return {op: "comp", comp: [].concat([e1],e2.comp)}
|
|
12
|
+
{op: "comp", comp: [e1,e2]}
|
|
13
|
+
|
|
14
|
+
module.exports = {identity, comp};
|
package/symbol-table.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
(function() {
|
|
3
|
+
var comp, identity;
|
|
4
|
+
|
|
5
|
+
identity = {
|
|
6
|
+
op: "identity"
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
comp = function(e1, e2) {
|
|
10
|
+
if (e1.op === "identity") {
|
|
11
|
+
return e2;
|
|
12
|
+
}
|
|
13
|
+
if (e2.op === "identity") {
|
|
14
|
+
return e1;
|
|
15
|
+
}
|
|
16
|
+
if (e1.op === "comp" && e2.op === "comp") {
|
|
17
|
+
return {
|
|
18
|
+
op: "comp",
|
|
19
|
+
comp: [].concat(e1.comp, e2.comp)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (e1.op === "comp") {
|
|
23
|
+
return {
|
|
24
|
+
op: "comp",
|
|
25
|
+
comp: [].concat(e1.comp, [e2])
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (e2.op === "comp") {
|
|
29
|
+
return {
|
|
30
|
+
op: "comp",
|
|
31
|
+
comp: [].concat([e1], e2.comp)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
op: "comp",
|
|
36
|
+
comp: [e1, e2]
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = {identity, comp};
|
|
41
|
+
|
|
42
|
+
}).call(this);
|
package/test.coffee
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
k = require "./index.coffee"
|
|
3
|
+
|
|
4
|
+
console.log 'var k = require("k");'
|
|
5
|
+
console.log ""
|
|
6
|
+
[
|
|
7
|
+
["ANYTHING...", '()']
|
|
8
|
+
["ANYTHING...", '{"ala" name, 23 age}']
|
|
9
|
+
[{year: 2002, age: 19}, '[.year, .age]' ]
|
|
10
|
+
["duplicate me", '[(), ()]']
|
|
11
|
+
["nesting", '[[[()]]]']
|
|
12
|
+
["nesting and accessing", '[[()]] {() nested, .0.0 val}']
|
|
13
|
+
[{test: "parse integer"}, '0000']
|
|
14
|
+
[{x: 3, y: 4}, '[.y,.x] PLUS']
|
|
15
|
+
].map ([data,script]) ->
|
|
16
|
+
console.log "k_expression = '#{script}';"
|
|
17
|
+
console.log "k.run(k_expression,#{JSON.stringify(data)});"
|
|
18
|
+
console.log "// RETURNS: #{JSON.stringify k.run script, data}"
|
|
19
|
+
console.log ""
|
|
20
|
+
|
|
21
|
+
k_expression = '{.name nom, <[.age, 18] GT .0, [.age, 12] GT "ado", "enfant"> age}'
|
|
22
|
+
k_fn = k.compile k_expression
|
|
23
|
+
|
|
24
|
+
console.log "var k_fn = k.compile('#{k_expression}');"
|
|
25
|
+
console.log ""
|
|
26
|
+
|
|
27
|
+
[
|
|
28
|
+
{age: 23, name: "Emily"}
|
|
29
|
+
{age: 16, name: "Katrina"}
|
|
30
|
+
{age: 2, name: "Mark"}
|
|
31
|
+
].map (data) ->
|
|
32
|
+
console.log "k_fn(#{JSON.stringify(data)});"
|
|
33
|
+
console.log "// RETURNS: #{JSON.stringify k_fn data}"
|
|
34
|
+
console.log ""
|
package/test.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
(function() {
|
|
3
|
+
var k, k_expression, k_fn;
|
|
4
|
+
|
|
5
|
+
k = require("./index.coffee");
|
|
6
|
+
|
|
7
|
+
console.log('var k = require("k");');
|
|
8
|
+
|
|
9
|
+
console.log("");
|
|
10
|
+
|
|
11
|
+
[
|
|
12
|
+
["ANYTHING...",
|
|
13
|
+
'()'],
|
|
14
|
+
["ANYTHING...",
|
|
15
|
+
'{"ala" name, 23 age}'],
|
|
16
|
+
[
|
|
17
|
+
{
|
|
18
|
+
year: 2002,
|
|
19
|
+
age: 19
|
|
20
|
+
},
|
|
21
|
+
'[.year, .age]'
|
|
22
|
+
],
|
|
23
|
+
["duplicate me",
|
|
24
|
+
'[(), ()]'],
|
|
25
|
+
["nesting",
|
|
26
|
+
'[[[()]]]'],
|
|
27
|
+
["nesting and accessing",
|
|
28
|
+
'[[()]] {() nested, .0.0 val}'],
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
test: "parse integer"
|
|
32
|
+
},
|
|
33
|
+
'0000'
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
{
|
|
37
|
+
x: 3,
|
|
38
|
+
y: 4
|
|
39
|
+
},
|
|
40
|
+
'[.y,.x] PLUS'
|
|
41
|
+
]
|
|
42
|
+
].map(function([data, script]) {
|
|
43
|
+
console.log(`k_expression = '${script}';`);
|
|
44
|
+
console.log(`k.run(k_expression,${JSON.stringify(data)});`);
|
|
45
|
+
console.log(`// RETURNS: ${JSON.stringify(k.run(script, data))}`);
|
|
46
|
+
return console.log("");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
k_expression = '{.name nom, <[.age, 18] GT .0, [.age, 12] GT "ado", "enfant"> age}';
|
|
50
|
+
|
|
51
|
+
k_fn = k.compile(k_expression);
|
|
52
|
+
|
|
53
|
+
console.log(`var k_fn = k.compile('${k_expression}');`);
|
|
54
|
+
|
|
55
|
+
console.log("");
|
|
56
|
+
|
|
57
|
+
[
|
|
58
|
+
{
|
|
59
|
+
age: 23,
|
|
60
|
+
name: "Emily"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
age: 16,
|
|
64
|
+
name: "Katrina"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
age: 2,
|
|
68
|
+
name: "Mark"
|
|
69
|
+
}
|
|
70
|
+
].map(function(data) {
|
|
71
|
+
console.log(`k_fn(${JSON.stringify(data)});`);
|
|
72
|
+
console.log(`// RETURNS: ${JSON.stringify(k_fn(data))}`);
|
|
73
|
+
return console.log("");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
}).call(this);
|
package/test.t
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
--------- comments start by #, --, or // ----------------------------------
|
|
2
|
+
< -- merge of 4 partial functions...
|
|
3
|
+
["x=", .x, " & y=", .y], -- produces a vector of 4 values, if fields 'x' and 'y' are present
|
|
4
|
+
["only x=", .x], -- produces a pair '["only x=", "value-of-x"]', for input like {"x":"value-of-x"}
|
|
5
|
+
-- it is defined only if field 'x' is present
|
|
6
|
+
["only y=", .y],
|
|
7
|
+
["no x nor y"] -- defined for all input, returns always the same one element vector
|
|
8
|
+
>
|
|
9
|
+
-- one of the string vectors is passed to the following partial function,
|
|
10
|
+
-- which produces a record (map) with one field "x&y", whose value is the
|
|
11
|
+
-- result of concatenating elements of the passed in vector
|
|
12
|
+
{ CONCAT "x&y" }
|
|
13
|
+
------------------------------------------------------------------------------
|