@fraczak/k 1.0.1 → 1.1.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # k-language
2
2
 
3
- Another JSON-to-JSON transformation notation. A `k`-expression
3
+ Another JSON transformation notation. A `k`-expression
4
4
  (script) defines a __partial function__, i.e., a function which, in
5
5
  general, is not defined for every input. `k`-expressions can be
6
6
  combined to build other `k`-expressions in three ways:
@@ -11,14 +11,15 @@ combined to build other `k`-expressions in three ways:
11
11
 
12
12
  Apart from empty composition, `()`, which defines _identity_, the paranthesis can be omitted.
13
13
 
14
- 2. product, e.g., vector:
14
+ 2. product, e.g., vector or structure:
15
15
 
16
16
  [ E1, E2, E3, ... ]
17
-
18
- or structure:
19
-
20
17
  { E1 "e1", E2 "e2", E3 "e3", ... }
21
18
 
19
+ Now, structure can also be written similarly to JSON, ie.,
20
+
21
+ { e1: E1, e2: E2, e3: E3, ... }
22
+
22
23
  3. union (merge), e.g.:
23
24
 
24
25
  < E1, E2, E3, ... >
@@ -42,11 +43,10 @@ Elementary partial functions are:
42
43
  'another "String"'
43
44
  123
44
45
  false
45
-
46
- Those functions are always defined, i.e., they ignore their argument.
46
+ null
47
47
 
48
48
  3. There is a number of built-in functions: `GT`, `EQ`, `PLUS`,
49
- `TIMES`, `MINUS`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`. For example
49
+ `TIMES`, `MINUS`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`, `CONS`, `SNOC`. For example
50
50
 
51
51
  [1, 2, 3] PLUS --> integer constant 6
52
52
  [4, 4] TIMES toJSON --> string constant "16"
@@ -61,6 +61,43 @@ Elementary partial functions are:
61
61
 
62
62
  [3,8] < [.0, .1] GT, [.1, .0] GT > .0 --> 8
63
63
 
64
+ ## User defined functions
65
+
66
+ `k`-expression can be prefixed by function definitions. E.g.:
67
+
68
+ dec = [(),1] MINUS;
69
+ factorial = <
70
+ [1,()] GT 1,
71
+ [dec factorial, ()] TIMES
72
+ >;
73
+ { x: (), "x!": factorial }
74
+
75
+ ## Value encodings (also called _types_ or _codes_)
76
+
77
+ There are three predefined value encodings: `int`, `string`, and `bool`. The language
78
+ supports `code`-expressions:
79
+
80
+ * product, e.g., `{x: int, y: int, flag: bool}`
81
+ * disjoint union, e.g., `<x: string, y: bool>`
82
+ * vector, e.g., `[ int ]` (all elements of the vector use the same encoding)
83
+
84
+ One can define recursive codes. E.g.,
85
+
86
+ $ tree = <leaf: string, tree: {left: tree, right: tree}>;
87
+
88
+ Each _code_ definition starts with a `$`.
89
+ The above example defines new code called _tree_.
90
+
91
+ The code can be then used in a `k`-expression as a filter. A `code`-expression
92
+ within `k`-expression is again prefixed by `$`.
93
+
94
+ $tree = <leaf: string, tree: {left: tree, right: tree}>;
95
+ inc = [(),1] PLUS;
96
+ height = $ tree <
97
+ .leaf 0,
98
+ .tree [.left height, .right height] <GT .0, .1> inc
99
+ > $ int;
100
+ height
64
101
 
65
102
 
66
103
  ## Command line script
@@ -113,7 +150,7 @@ run the language from command line.
113
150
 
114
151
  If we want to read `json` objects from a file, e.g., `my-objects.json`, we do
115
152
 
116
- $ ./k.coffee -k test.k -j my-objects.json
153
+ $ ./k.coffee -k test.k my-objects.json
117
154
  {"x&y":"x=432 & y=123"}
118
155
  {"x&y":"onlyx=987"}
119
156
  {"x&y":"no x nor y"}
@@ -178,4 +215,3 @@ run the language from command line.
178
215
 
179
216
  k_fn({"age":2,"name":"Mark"})
180
217
  // RETURNS: {"nom":"Mark","age":"enfant"}
181
-
package/bnat.k ADDED
@@ -0,0 +1,121 @@
1
+ -- Standard binary encoding of natural
2
+ -- numbers with addition (+).
3
+
4
+ _ = {{} _};
5
+ _1 = {() "1"};
6
+ _0 = {() "0"};
7
+
8
+ n0 = _ ;
9
+ n1 = _ _1;
10
+
11
+ from_digit = <
12
+ [0, ()] EQ _, -- {_: {}}
13
+ [1, ()] EQ n1, -- {"1": {_: {}}}
14
+ [2, ()] EQ _ _0 _1, -- {"1": {"0": {_: {}}}}
15
+ [3, ()] EQ _ _1 _1, -- {"1": {"1": {_: {}}}}
16
+ [4, ()] EQ _ _0 _0 _1, -- {"1": {"0": {"0": {_: {}}}}}
17
+ [5, ()] EQ _ _1 _0 _1,
18
+ [6, ()] EQ _ _0 _1 _1,
19
+ [7, ()] EQ _ _1 _1 _1,
20
+ [8, ()] EQ _ _0 _0 _0 _1,
21
+ [9, ()] EQ _ _1 _0 _0 _1,
22
+ [10, ()] EQ _ _0 _1 _0 _1
23
+ >;
24
+
25
+ to_digit = <
26
+ ._ 0,
27
+ ."1"._ 1,
28
+ ."1"."0"._ 2,
29
+ ."1"."1"._ 3,
30
+ ."1"."0"."0"._ 4,
31
+ ."1"."0"."1"._ 5,
32
+ ."1"."1"."0"._ 6,
33
+ ."1"."1"."1"._ 7,
34
+ ."1"."0"."0"."0"._ 8,
35
+ ."1"."0"."0"."1"._ 9,
36
+ ."1"."0"."1"."0"._ 10,
37
+ ."1"."0"."1"."1"._ 11,
38
+ ."1"."1"."0"."0"._ 12,
39
+ ."1"."1"."0"."1"._ 13,
40
+ ."1"."1"."1"."0"._ 14,
41
+ ."1"."1"."1"."1"._ 15
42
+ > ;
43
+
44
+ remove_leading_zeros =
45
+ < ."0" remove_leading_zeros, () >;
46
+
47
+ _append_zero =
48
+ < ._ _ _0, -- ( _ -> 0 _)
49
+ ."1" _append_zero _1, -- ('1 ... -> '1 [$.1 | _append_zero]),
50
+ ."0" _append_zero _0 -- ('0 ... -> '0 [$.0 | _append_zero]),
51
+ >
52
+ ;
53
+
54
+ _append_one =
55
+ <
56
+ ._ _ _1,
57
+ ."1" _append_one _1,
58
+ ."0" _append_one _0
59
+ >
60
+ ;
61
+
62
+ reverse_bnat = {() x, _ y} _reverse_bnat;
63
+
64
+ _reverse_bnat =
65
+ <
66
+ {.x._ x, .y y} .y,
67
+ {.x."0" x, .y _0 y} _reverse_bnat,
68
+ {.x."1" x, .y _1 y} _reverse_bnat
69
+ >;
70
+
71
+ _add2wc =
72
+ -- least significant bit first addition with carry
73
+ --- :{ :bnat x, :bnat y, :[0,1] c}
74
+ -- _log_
75
+ <
76
+ {.x."0" x, .y."0" y, .c."0" c} {.x x, .y y, _ _0 c} _add2wc _0,
77
+ {.x."0" x, .y."0" y, .c."1" c} {.x x, .y y, _ _0 c} _add2wc _1,
78
+
79
+ {.x."0" x, .y."1" y, .c."0" c} {.x x, .y y, _ _0 c} _add2wc _1,
80
+ {.x."0" x, .y."1" y, .c."1" c} {.x x, .y y, _ _1 c} _add2wc _0,
81
+
82
+ {.x."1" x, .y."0" y, .c."0" c} {.x x, .y y, _ _0 c} _add2wc _1,
83
+ {.x."1" x, .y."0" y, .c."1" c} {.x x, .y y, _ _1 c} _add2wc _0,
84
+
85
+ {.x."1" x, .y."1" y, .c."0" c} {.x x, .y y, _ _1 c} _add2wc _0,
86
+ {.x."1" x, .y."1" y, .c."1" c} {.x x, .y y, _ _1 c} _add2wc _1,
87
+ {.x._ x, .c."0" c, .y y} .y,
88
+ {.y._ y, .c."0" c, .x x} .x,
89
+ {.x._ x, .c."1" c, .y._ y} n1,
90
+ {.x._ x, .y."0" y, .c."1" c} .y _1,
91
+ {.x."0" x, .y._ y, .c."1" c} .x _1,
92
+ {.x._ x, .y."1" y, .c."1" c} {_ x, .y y, {} _1 c} _add2wc _0,
93
+ {.x."1" x, .y._ y, .c."1" c} {.x x, _ y, {} _1 c} _add2wc _0
94
+ >;
95
+
96
+ plus = <
97
+ SNOC {
98
+ x: .0 from_digit remove_leading_zeros reverse_bnat,
99
+ y: .1 plus remove_leading_zeros reverse_bnat,
100
+ c: {} _0 } _add2wc reverse_bnat,
101
+ .0 from_digit
102
+ >;
103
+
104
+ to_string = <
105
+ ._ "0",
106
+ toString
107
+ >;
108
+
109
+ toString = <
110
+ ._ "",
111
+ ["0", ."0" toString] CONCAT,
112
+ ["1", ."1" toString] CONCAT
113
+ >;
114
+
115
+ [(), plus]
116
+ {
117
+ input: .0,
118
+ sum: {raw: .1, digits: .1 <to_digit,"...too big...">, binary: .1 to_string}
119
+ }
120
+
121
+ -- example: > echo '[9,9,9,8]' | ./k.sh -k ./bnat.k
package/code.k ADDED
@@ -0,0 +1,18 @@
1
+ inc = [(),1] PLUS;
2
+ $tree = <leaf: string, tree: {left: tree, right: tree}>;
3
+ height = $tree <
4
+ .leaf 0,
5
+ .tree [.left height, .right height] <GT .0, .1> inc
6
+ > $int;
7
+
8
+ <$tree,
9
+ {tree:
10
+ { left: { leaf: "a"},
11
+ right: { tree:
12
+ { left: {leaf: "b"},
13
+ right: {leaf: "c"}
14
+ }
15
+ }
16
+ }
17
+ }
18
+ > _log_ height
package/factorial.k ADDED
@@ -0,0 +1,11 @@
1
+ -- factorial.k
2
+ -- E.g.:
3
+ -- > echo "5" | ./k.sh -k factorial.k
4
+ -- {"x":5,"x!":120}
5
+
6
+ dec = [(),1] MINUS;
7
+ factorial = <
8
+ [1,()] GT 1,
9
+ [dec factorial, ()] TIMES
10
+ >;
11
+ { x: (), "x!": factorial }
package/fib.k ADDED
@@ -0,0 +1,15 @@
1
+ fib_aux =
2
+ <
3
+ { [.n, 1] GT [.0,-1] PLUS n,
4
+ ."[fib(n),fib(n-1)" [[.0,.1] PLUS, .0] "[fib(n),fib(n-1)"
5
+ } fib_aux,
6
+ ."[fib(n),fib(n-1)"
7
+ >
8
+ ;
9
+
10
+ fib = {() n, [1,1] "[fib(n),fib(n-1)"}
11
+ fib_aux .0;
12
+
13
+ ----------------------
14
+
15
+ fib
package/index.coffee CHANGED
@@ -3,7 +3,8 @@ fs = require "fs"
3
3
  run = require "./run"
4
4
 
5
5
  compile = (script) ->
6
- do (exp = parse script) ->
6
+ do ({defs,exp} = parse script) ->
7
+ run.defs = defs
7
8
  (data) -> run exp, data
8
9
  compile.doc = "Transforms k-script (string) into a function"
9
10
 
package/index.js CHANGED
@@ -9,7 +9,8 @@
9
9
  run = require("./run");
10
10
 
11
11
  compile = function(script) {
12
- return (function(exp) {
12
+ return (function({defs, exp}) {
13
+ run.defs = defs;
13
14
  return function(data) {
14
15
  return run(exp, data);
15
16
  };
package/k.coffee CHANGED
@@ -4,7 +4,8 @@ k = require "./"
4
4
 
5
5
  prog = process.argv[1]
6
6
 
7
- {kScript,jsonStream} = do (args = process.argv.slice(2)) ->
7
+ {kScript,jsonStream,oneJson} =
8
+ do (oneJson = false, args = process.argv.slice(2)) ->
8
9
  try
9
10
  kScript = do (arg = args.shift()) ->
10
11
  throw new Error() unless arg?
@@ -16,30 +17,43 @@ prog = process.argv[1]
16
17
  kScript = k.compile kScript
17
18
 
18
19
  jsonStream = do (arg = args.shift()) ->
20
+ if arg is "-1"
21
+ oneJson = true
22
+ arg = args.shift()
19
23
  return process.stdin unless arg?
20
24
  fs.createReadStream arg
21
25
 
22
- {kScript, jsonStream}
26
+ {kScript, jsonStream, oneJson}
23
27
  catch e
24
28
  console.error e
25
- console.error "Usage: #{prog} ( k-expr | -k k-file ) [ json-file ]"
29
+ console.error "Usage: #{prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]"
26
30
  console.error " E.g., echo '{\"a\": 12}' | #{prog} '[(),()]'"
27
31
  process.exit -1
28
32
 
29
- do (buffer = [], line = 0) ->
30
- jsonStream.on 'data', (data) ->
31
- [first, rest...] = data.toString("utf8").split "\n"
32
- buffer.push first
33
- if rest.length > 0
34
- todo = buffer.join ""
35
- [rest..., last] = rest
36
- buffer = [last]
37
- todo = [todo, rest...]
38
- for json in todo
39
- if not json.match /^[ \n\t]*(?:#.*)?$/
40
- try
41
- console.log JSON.stringify kScript JSON.parse json
42
- catch e
43
- console.error "Problem [line #{line}]: '#{json}'"
44
- console.error e
45
- line = line + 1
33
+ if oneJson
34
+ do (buffer = []) ->
35
+ jsonStream.on 'data', (data) ->
36
+ buffer.push data
37
+ jsonStream.on 'end', ->
38
+ try
39
+ console.log JSON.stringify kScript JSON.parse buffer.join('')
40
+ catch e
41
+ console.error e
42
+ else
43
+ do (buffer = [], line = 0) ->
44
+ jsonStream.on 'data', (data) ->
45
+ [first, rest...] = data.toString("utf8").split "\n"
46
+ buffer.push first
47
+ if rest.length > 0
48
+ todo = buffer.join ""
49
+ [rest..., last] = rest
50
+ buffer = [last]
51
+ todo = [todo, rest...]
52
+ for json in todo
53
+ if not json.match /^[ \n\t]*(?:#.*)?$/
54
+ try
55
+ console.log JSON.stringify kScript JSON.parse json
56
+ catch e
57
+ console.error "Problem [line #{line}]: '#{json}'"
58
+ console.error e
59
+ line = line + 1
package/k.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
2
  (function() {
3
3
  //!/usr/bin/env coffee
4
- var fs, jsonStream, k, kScript, prog,
4
+ var fs, jsonStream, k, kScript, oneJson, prog,
5
5
  splice = [].splice;
6
6
 
7
7
  fs = require("fs");
@@ -10,7 +10,7 @@
10
10
 
11
11
  prog = process.argv[1];
12
12
 
13
- ({kScript, jsonStream} = (function(args) {
13
+ ({kScript, jsonStream, oneJson} = (function(oneJson, args) {
14
14
  var e;
15
15
  try {
16
16
  kScript = (function(arg) {
@@ -25,48 +25,69 @@
25
25
  })(args.shift());
26
26
  kScript = k.compile(kScript);
27
27
  jsonStream = (function(arg) {
28
+ if (arg === "-1") {
29
+ oneJson = true;
30
+ arg = args.shift();
31
+ }
28
32
  if (arg == null) {
29
33
  return process.stdin;
30
34
  }
31
35
  return fs.createReadStream(arg);
32
36
  })(args.shift());
33
- return {kScript, jsonStream};
37
+ return {kScript, jsonStream, oneJson};
34
38
  } catch (error) {
35
39
  e = error;
36
40
  console.error(e);
37
- console.error(`Usage: ${prog} ( k-expr | -k k-file ) [ json-file ]`);
41
+ console.error(`Usage: ${prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]`);
38
42
  console.error(` E.g., echo '{\"a\": 12}' | ${prog} '[(),()]'`);
39
43
  return process.exit(-1);
40
44
  }
41
- })(process.argv.slice(2)));
45
+ })(false, process.argv.slice(2)));
42
46
 
43
- (function(buffer, line) {
44
- return jsonStream.on('data', function(data) {
45
- var e, first, i, json, last, len, ref, rest, results, todo;
46
- [first, ...rest] = data.toString("utf8").split("\n");
47
- buffer.push(first);
48
- if (rest.length > 0) {
49
- todo = buffer.join("");
50
- ref = rest, [...rest] = ref, [last] = splice.call(rest, -1);
51
- buffer = [last];
52
- todo = [todo, ...rest];
53
- results = [];
54
- for (i = 0, len = todo.length; i < len; i++) {
55
- json = todo[i];
56
- if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
57
- try {
58
- console.log(JSON.stringify(kScript(JSON.parse(json))));
59
- } catch (error) {
60
- e = error;
61
- console.error(`Problem [line ${line}]: '${json}'`);
62
- console.error(e);
47
+ if (oneJson) {
48
+ (function(buffer) {
49
+ jsonStream.on('data', function(data) {
50
+ return buffer.push(data);
51
+ });
52
+ return jsonStream.on('end', function() {
53
+ var e;
54
+ try {
55
+ return console.log(JSON.stringify(kScript(JSON.parse(buffer.join('')))));
56
+ } catch (error) {
57
+ e = error;
58
+ return console.error(e);
59
+ }
60
+ });
61
+ })([]);
62
+ } else {
63
+ (function(buffer, line) {
64
+ return jsonStream.on('data', function(data) {
65
+ var e, first, i, json, last, len, ref, rest, results, todo;
66
+ [first, ...rest] = data.toString("utf8").split("\n");
67
+ buffer.push(first);
68
+ if (rest.length > 0) {
69
+ todo = buffer.join("");
70
+ ref = rest, [...rest] = ref, [last] = splice.call(rest, -1);
71
+ buffer = [last];
72
+ todo = [todo, ...rest];
73
+ results = [];
74
+ for (i = 0, len = todo.length; i < len; i++) {
75
+ json = todo[i];
76
+ if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
77
+ try {
78
+ console.log(JSON.stringify(kScript(JSON.parse(json))));
79
+ } catch (error) {
80
+ e = error;
81
+ console.error(`Problem [line ${line}]: '${json}'`);
82
+ console.error(e);
83
+ }
63
84
  }
85
+ results.push(line = line + 1);
64
86
  }
65
- results.push(line = line + 1);
87
+ return results;
66
88
  }
67
- return results;
68
- }
69
- });
70
- })([], 0);
89
+ });
90
+ })([], 0);
91
+ }
71
92
 
72
93
  }).call(this);
package/k.sh CHANGED
@@ -2,7 +2,7 @@
2
2
  // Generated by CoffeeScript 2.7.0
3
3
  (function() {
4
4
  //!/usr/bin/env coffee
5
- var fs, jsonStream, k, kScript, prog,
5
+ var fs, jsonStream, k, kScript, oneJson, prog,
6
6
  splice = [].splice;
7
7
 
8
8
  fs = require("fs");
@@ -11,7 +11,7 @@
11
11
 
12
12
  prog = process.argv[1];
13
13
 
14
- ({kScript, jsonStream} = (function(args) {
14
+ ({kScript, jsonStream, oneJson} = (function(oneJson, args) {
15
15
  var e;
16
16
  try {
17
17
  kScript = (function(arg) {
@@ -26,48 +26,69 @@
26
26
  })(args.shift());
27
27
  kScript = k.compile(kScript);
28
28
  jsonStream = (function(arg) {
29
+ if (arg === "-1") {
30
+ oneJson = true;
31
+ arg = args.shift();
32
+ }
29
33
  if (arg == null) {
30
34
  return process.stdin;
31
35
  }
32
36
  return fs.createReadStream(arg);
33
37
  })(args.shift());
34
- return {kScript, jsonStream};
38
+ return {kScript, jsonStream, oneJson};
35
39
  } catch (error) {
36
40
  e = error;
37
41
  console.error(e);
38
- console.error(`Usage: ${prog} ( k-expr | -k k-file ) [ json-file ]`);
42
+ console.error(`Usage: ${prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]`);
39
43
  console.error(` E.g., echo '{\"a\": 12}' | ${prog} '[(),()]'`);
40
44
  return process.exit(-1);
41
45
  }
42
- })(process.argv.slice(2)));
46
+ })(false, process.argv.slice(2)));
43
47
 
44
- (function(buffer, line) {
45
- return jsonStream.on('data', function(data) {
46
- var e, first, i, json, last, len, ref, rest, results, todo;
47
- [first, ...rest] = data.toString("utf8").split("\n");
48
- buffer.push(first);
49
- if (rest.length > 0) {
50
- todo = buffer.join("");
51
- ref = rest, [...rest] = ref, [last] = splice.call(rest, -1);
52
- buffer = [last];
53
- todo = [todo, ...rest];
54
- results = [];
55
- for (i = 0, len = todo.length; i < len; i++) {
56
- json = todo[i];
57
- if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
58
- try {
59
- console.log(JSON.stringify(kScript(JSON.parse(json))));
60
- } catch (error) {
61
- e = error;
62
- console.error(`Problem [line ${line}]: '${json}'`);
63
- console.error(e);
48
+ if (oneJson) {
49
+ (function(buffer) {
50
+ jsonStream.on('data', function(data) {
51
+ return buffer.push(data);
52
+ });
53
+ return jsonStream.on('end', function() {
54
+ var e;
55
+ try {
56
+ return console.log(JSON.stringify(kScript(JSON.parse(buffer.join('')))));
57
+ } catch (error) {
58
+ e = error;
59
+ return console.error(e);
60
+ }
61
+ });
62
+ })([]);
63
+ } else {
64
+ (function(buffer, line) {
65
+ return jsonStream.on('data', function(data) {
66
+ var e, first, i, json, last, len, ref, rest, results, todo;
67
+ [first, ...rest] = data.toString("utf8").split("\n");
68
+ buffer.push(first);
69
+ if (rest.length > 0) {
70
+ todo = buffer.join("");
71
+ ref = rest, [...rest] = ref, [last] = splice.call(rest, -1);
72
+ buffer = [last];
73
+ todo = [todo, ...rest];
74
+ results = [];
75
+ for (i = 0, len = todo.length; i < len; i++) {
76
+ json = todo[i];
77
+ if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
78
+ try {
79
+ console.log(JSON.stringify(kScript(JSON.parse(json))));
80
+ } catch (error) {
81
+ e = error;
82
+ console.error(`Problem [line ${line}]: '${json}'`);
83
+ console.error(e);
84
+ }
64
85
  }
86
+ results.push(line = line + 1);
65
87
  }
66
- results.push(line = line + 1);
88
+ return results;
67
89
  }
68
- return results;
69
- }
70
- });
71
- })([], 0);
90
+ });
91
+ })([], 0);
92
+ }
72
93
 
73
94
  }).call(this);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "1.0.1",
4
- "description": "k-language for untyped JSON like data transformation",
3
+ "version": "1.1.0",
4
+ "description": "k-language for JSON-like data transformation",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "prepare": "coffee -c symbol-table.coffee; jison parser.jison",
8
8
  "prepublishOnly": "coffee -c *.coffee; echo '#!/usr/bin/env node' | cat - k.js > k.sh",
9
- "test": "coffee -c symbol-table.coffee; jison parser.jison; coffee test.coffee;"
9
+ "test": "coffee -c symbol-table.coffee; jison parser.jison; coffee test.coffee"
10
10
  },
11
11
  "author": "Wojciech Fraczak",
12
12
  "license": "ISC",
package/parser.jison CHANGED
@@ -18,17 +18,21 @@ var s = require("./symbol-table");
18
18
  "}" return 'RC';
19
19
  "]" return 'RB';
20
20
  ")" return 'RP';
21
+ "=" return 'EQ';
21
22
  "." return 'DOT';
22
23
  "," return 'COMMA';
24
+ ";" return 'SC';
25
+ ":" return 'COL';
26
+ "$" return 'DOLLAR';
23
27
  \"[^\"\n]*\"|\'[^\'\n]*\' return 'STRING'
24
- [a-zA-Z_][a-zA-Z0-9_]* return 'NAME';
28
+ [a-zA-Z_][a-zA-Z0-9_?!]* return 'NAME';
25
29
  0|[-]?[1-9][0-9]* return 'INT';
26
30
  <<EOF>> return 'EOF';
27
31
 
28
32
  /lex
29
33
 
30
34
  %token NAME STRING INT
31
- %token LA LC LB LP RA RP RB RC COMMA
35
+ %token LA LC LB LP RA RP RB RC EQ DOT COMMA SC COL DOLLAR
32
36
  %token EOF
33
37
 
34
38
  %start input_with_eof
@@ -39,14 +43,53 @@ name: NAME { $$ = String(yytext); };
39
43
  str: STRING { $$ = String(yytext).slice(1,-1); };
40
44
  int: INT { $$ = parseInt(String(yytext)); };
41
45
 
42
- input_with_eof: comp EOF {
43
- // console.log(JSON.stringify($1, "", 2));
44
- return $1;
46
+ input_with_eof: defs comp EOF {
47
+ result = {defs: $1, exp: $2};
48
+ // console.log(JSON.stringify(result, "", 2));
49
+ return result;
45
50
  };
46
51
 
52
+ defs: { $$ = {codes: {}, rels: {}}; }
53
+ | defs name EQ comp SC { $1.rels[$2] = $4; $$ = $1; }
54
+ | defs DOLLAR name EQ code SC { $1.codes[$3] = $5; $$ = $1; }
55
+ ;
56
+
57
+ code
58
+ : name { $$ = {code: "ref", ref: $1}; }
59
+ | LC labelled_codes RC { $$ = {code: "product",
60
+ product: $2.reduce((r, lc) => {
61
+ r[lc.label] = lc.code;
62
+ return r }
63
+ , {})}; }
64
+ | LB code RB { $$ = {code: "vector", vector: $2}; }
65
+ | LA labelled_codes RA { $$ = {code: "union",
66
+ union: $2.reduce((r, lc) => {
67
+ r[lc.label] = lc.code;
68
+ return r }
69
+ , {})}; }
70
+ ;
71
+
72
+ labelled_codes
73
+ : { $$ = [] }
74
+ | non_empty_labelled_codes { $$ = $1; }
75
+ ;
76
+
77
+ non_empty_labelled_codes
78
+ : code_label { $$ = [$1]; }
79
+ | non_empty_labelled_codes COMMA code_label
80
+ { $$ = [].concat($1,$3); }
81
+ ;
82
+
83
+ code_label
84
+ : code name { $$ = {label: $2, code: $1}; }
85
+ | code str { $$ = {label: $2, code: $1}; }
86
+ | name COL code { $$ = {label: $1, code: $3}; }
87
+ | str COL code { $$ = {label: $1, code: $3}; }
88
+ ;
89
+
47
90
  comp
48
- : exp { $$ = $1; }
49
- | comp exp { $$ = s.comp($1, $2); }
91
+ : exp { $$ = $1; }
92
+ | comp exp { $$ = s.comp($1, $2); }
50
93
  ;
51
94
 
52
95
  exp
@@ -61,6 +104,7 @@ exp
61
104
  | DOT int { $$ = {op: "dot", dot: $2}; }
62
105
  | DOT str { $$ = {op: "dot", dot: $2}; }
63
106
  | DOT name { $$ = {op: "dot", dot: $2}; }
107
+ | DOLLAR code { $$ = {op: "code", code: $2}; }
64
108
  ;
65
109
 
66
110
  labelled
@@ -78,6 +122,8 @@ non_empty_labelled
78
122
  comp_label
79
123
  : comp name { $$ = {label: $2, exp: $1}; }
80
124
  | comp str { $$ = {label: $2, exp: $1}; }
125
+ | name COL comp { $$ = {label: $1, exp: $3}; }
126
+ | str COL comp { $$ = {label: $1, exp: $3}; }
81
127
  ;
82
128
 
83
129
  list
package/parser.js CHANGED
@@ -72,12 +72,12 @@
72
72
  }
73
73
  */
74
74
  var parser = (function(){
75
- var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,12],$V1=[1,13],$V2=[1,14],$V3=[1,4],$V4=[1,5],$V5=[1,6],$V6=[1,8],$V7=[1,11],$V8=[4,6,8,11,13,16,18,19,20,21,22,23,26],$V9=[2,24],$Va=[2,10],$Vb=[2,13],$Vc=[4,6,8,11,13,15,16,18,19,20,21,22,23,26],$Vd=[15,26],$Ve=[18,20,26],$Vf=[4,6,8,13,16,19,21,23],$Vg=[2,22],$Vh=[2,23];
75
+ var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[4,6,8,15,17,20,22,31,33],$V1=[1,7],$V2=[1,15],$V3=[1,16],$V4=[1,8],$V5=[1,9],$V6=[1,10],$V7=[1,11],$V8=[1,14],$V9=[1,20],$Va=[4,6,8,12,15,17,20,22,31,33],$Vb=[2,25],$Vc=[1,24],$Vd=[1,25],$Ve=[1,26],$Vf=[4,6,8,12,14,15,17,19,20,21,22,23,26,31,32,33],$Vg=[2,42],$Vh=[2,28],$Vi=[2,8],$Vj=[2,12],$Vk=[19,26],$Vl=[21,23,26],$Vm=[19,23,26],$Vn=[2,38],$Vo=[2,39];
76
76
  var parser = {trace: function trace () { },
77
77
  yy: {},
78
- symbols_: {"error":2,"name":3,"NAME":4,"str":5,"STRING":6,"int":7,"INT":8,"input_with_eof":9,"comp":10,"EOF":11,"exp":12,"LC":13,"labelled":14,"RC":15,"LB":16,"list":17,"RB":18,"LA":19,"RA":20,"LP":21,"RP":22,"DOT":23,"non_empty_labelled":24,"comp_label":25,"COMMA":26,"non_empty_list":27,"$accept":0,"$end":1},
79
- terminals_: {2:"error",4:"NAME",6:"STRING",8:"INT",11:"EOF",13:"LC",15:"RC",16:"LB",18:"RB",19:"LA",20:"RA",21:"LP",22:"RP",23:"DOT",26:"COMMA"},
80
- productions_: [0,[3,1],[5,1],[7,1],[9,2],[10,1],[10,2],[12,3],[12,3],[12,3],[12,1],[12,2],[12,3],[12,1],[12,1],[12,2],[12,2],[12,2],[14,0],[14,1],[24,1],[24,3],[25,2],[25,2],[17,0],[17,1],[27,1],[27,3]],
78
+ symbols_: {"error":2,"name":3,"NAME":4,"str":5,"STRING":6,"int":7,"INT":8,"input_with_eof":9,"defs":10,"comp":11,"EOF":12,"EQ":13,"SC":14,"DOLLAR":15,"code":16,"LC":17,"labelled_codes":18,"RC":19,"LB":20,"RB":21,"LA":22,"RA":23,"non_empty_labelled_codes":24,"code_label":25,"COMMA":26,"COL":27,"exp":28,"labelled":29,"list":30,"LP":31,"RP":32,"DOT":33,"non_empty_labelled":34,"comp_label":35,"non_empty_list":36,"$accept":0,"$end":1},
79
+ terminals_: {2:"error",4:"NAME",6:"STRING",8:"INT",12:"EOF",13:"EQ",14:"SC",15:"DOLLAR",17:"LC",19:"RC",20:"LB",21:"RB",22:"LA",23:"RA",26:"COMMA",27:"COL",31:"LP",32:"RP",33:"DOT"},
80
+ productions_: [0,[3,1],[5,1],[7,1],[9,3],[10,0],[10,5],[10,6],[16,1],[16,3],[16,3],[16,3],[18,0],[18,1],[24,1],[24,3],[25,2],[25,2],[25,3],[25,3],[11,1],[11,2],[28,3],[28,3],[28,3],[28,1],[28,2],[28,3],[28,1],[28,1],[28,2],[28,2],[28,2],[28,2],[29,0],[29,1],[34,1],[34,3],[35,2],[35,2],[35,3],[35,3],[30,0],[30,1],[36,1],[36,3]],
81
81
  performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
82
82
  /* this == yyval */
83
83
 
@@ -94,68 +94,113 @@ case 3:
94
94
  break;
95
95
  case 4:
96
96
 
97
- // console.log(JSON.stringify($$[$0-1], "", 2));
98
- return $$[$0-1];
97
+ result = {defs: $$[$0-2], exp: $$[$0-1]};
98
+ // console.log(JSON.stringify(result, "", 2));
99
+ return result;
99
100
 
100
101
  break;
101
- case 5: case 19: case 25:
102
- this.$ = $$[$0];
102
+ case 5:
103
+ this.$ = {codes: {}, rels: {}};
103
104
  break;
104
105
  case 6:
105
- this.$ = s.comp($$[$0-1], $$[$0]);
106
+ $$[$0-4].rels[$$[$0-3]] = $$[$0-1]; this.$ = $$[$0-4];
106
107
  break;
107
108
  case 7:
108
- this.$ = $$[$0-1];
109
+ $$[$0-5].codes[$$[$0-3]] = $$[$0-1]; this.$ = $$[$0-5];
109
110
  break;
110
111
  case 8:
111
- this.$ = {op: "vector", vector: $$[$0-1]};
112
+ this.$ = {code: "ref", ref: $$[$0]};
112
113
  break;
113
114
  case 9:
114
- this.$ = {op: "union", union: $$[$0-1]};
115
+ this.$ = {code: "product",
116
+ product: $$[$0-1].reduce((r, lc) => {
117
+ r[lc.label] = lc.code;
118
+ return r }
119
+ , {})};
115
120
  break;
116
121
  case 10:
117
- this.$ = {op: "ref", ref: $$[$0]};
122
+ this.$ = {code: "vector", vector: $$[$0-1]};
118
123
  break;
119
124
  case 11:
120
- this.$ = s.identity;
125
+ this.$ = {code: "union",
126
+ union: $$[$0-1].reduce((r, lc) => {
127
+ r[lc.label] = lc.code;
128
+ return r }
129
+ , {})};
121
130
  break;
122
131
  case 12:
132
+ this.$ = []
133
+ break;
134
+ case 13: case 20: case 35: case 43:
135
+ this.$ = $$[$0];
136
+ break;
137
+ case 14: case 44:
138
+ this.$ = [$$[$0]];
139
+ break;
140
+ case 15: case 45:
141
+ this.$ = [].concat($$[$0-2],$$[$0]);
142
+ break;
143
+ case 16: case 17:
144
+ this.$ = {label: $$[$0], code: $$[$0-1]};
145
+ break;
146
+ case 18: case 19:
147
+ this.$ = {label: $$[$0-2], code: $$[$0]};
148
+ break;
149
+ case 21:
150
+ this.$ = s.comp($$[$0-1], $$[$0]);
151
+ break;
152
+ case 22:
153
+ this.$ = $$[$0-1];
154
+ break;
155
+ case 23:
156
+ this.$ = {op: "vector", vector: $$[$0-1]};
157
+ break;
158
+ case 24:
159
+ this.$ = {op: "union", union: $$[$0-1]};
160
+ break;
161
+ case 25:
162
+ this.$ = {op: "ref", ref: $$[$0]};
163
+ break;
164
+ case 26:
165
+ this.$ = s.identity;
166
+ break;
167
+ case 27:
123
168
  this.$ = $$[$0-1];
124
169
  break;
125
- case 13:
170
+ case 28:
126
171
  this.$ = {op: "str", str: $$[$0]};
127
172
  break;
128
- case 14:
173
+ case 29:
129
174
  this.$ = {op: "int", int: $$[$0]};
130
175
  break;
131
- case 15: case 16: case 17:
176
+ case 30: case 31: case 32:
132
177
  this.$ = {op: "dot", dot: $$[$0]};
133
178
  break;
134
- case 18:
179
+ case 33:
180
+ this.$ = {op: "code", code: $$[$0]};
181
+ break;
182
+ case 34:
135
183
  this.$ = {op: "product", product: []};
136
184
  break;
137
- case 20:
185
+ case 36:
138
186
  this.$ = {op: "product", product: [$$[$0]]};
139
187
  break;
140
- case 21:
188
+ case 37:
141
189
  $$[$0-2].product = [].concat($$[$0-2].product,$$[$0]); this.$ = $$[$0-2];
142
190
  break;
143
- case 22: case 23:
191
+ case 38: case 39:
144
192
  this.$ = {label: $$[$0], exp: $$[$0-1]};
145
193
  break;
146
- case 24:
147
- this.$ = [];
148
- break;
149
- case 26:
150
- this.$ = [$$[$0]];
194
+ case 40: case 41:
195
+ this.$ = {label: $$[$0-2], exp: $$[$0]};
151
196
  break;
152
- case 27:
153
- this.$ = [].concat($$[$0-2],$$[$0]);
197
+ case 42:
198
+ this.$ = [];
154
199
  break;
155
200
  }
156
201
  },
157
- table: [{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,9:1,10:2,12:3,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7},{1:[3]},{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,11:[1,15],12:16,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7},o($V8,[2,5]),{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,10:20,12:3,13:$V3,14:17,15:[2,18],16:$V4,19:$V5,21:$V6,23:$V7,24:18,25:19},{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,10:23,12:3,13:$V3,16:$V4,17:21,18:$V9,19:$V5,21:$V6,23:$V7,27:22},{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,10:23,12:3,13:$V3,16:$V4,17:24,19:$V5,20:$V9,21:$V6,23:$V7,27:22},o($V8,$Va),{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,10:26,12:3,13:$V3,16:$V4,19:$V5,21:$V6,22:[1,25],23:$V7},o($V8,$Vb),o($V8,[2,14]),{3:29,4:$V0,5:28,6:$V1,7:27,8:$V2},o($Vc,[2,1]),o($Vc,[2,2]),o($V8,[2,3]),{1:[2,4]},o($V8,[2,6]),{15:[1,30]},{15:[2,19],26:[1,31]},o($Vd,[2,20]),{3:32,4:$V0,5:33,6:$V1,7:10,8:$V2,12:16,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7},{18:[1,34]},o([18,20],[2,25],{26:[1,35]}),o($Ve,[2,26],{3:7,5:9,7:10,12:16,4:$V0,6:$V1,8:$V2,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7}),{20:[1,36]},o($V8,[2,11]),{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,12:16,13:$V3,16:$V4,19:$V5,21:$V6,22:[1,37],23:$V7},o($V8,[2,15]),o($V8,[2,16]),o($V8,[2,17]),o($V8,[2,7]),{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,10:20,12:3,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7,25:38},o($Vf,$Va,{15:$Vg,26:$Vg}),o($Vf,$Vb,{15:$Vh,26:$Vh}),o($V8,[2,8]),{3:7,4:$V0,5:9,6:$V1,7:10,8:$V2,10:39,12:3,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7},o($V8,[2,9]),o($V8,[2,12]),o($Vd,[2,21]),o($Ve,[2,27],{3:7,5:9,7:10,12:16,4:$V0,6:$V1,8:$V2,13:$V3,16:$V4,19:$V5,21:$V6,23:$V7})],
158
- defaultActions: {15:[2,4]},
202
+ table: [o($V0,[2,5],{9:1,10:2}),{1:[3]},{3:4,4:$V1,5:12,6:$V2,7:13,8:$V3,11:3,15:[1,5],17:$V4,20:$V5,22:$V6,28:6,31:$V7,33:$V8},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,12:[1,17],15:$V9,17:$V4,20:$V5,22:$V6,28:18,31:$V7,33:$V8},o($Va,$Vb,{13:[1,21]}),{3:22,4:$V1,16:23,17:$Vc,20:$Vd,22:$Ve},o($Vf,[2,20]),o([4,6,8,12,13,14,15,17,19,20,21,22,23,26,27,31,32,33],[2,1]),{3:31,4:$V1,5:32,6:$V2,7:13,8:$V3,11:30,15:$V9,17:$V4,19:[2,34],20:$V5,22:$V6,28:6,29:27,31:$V7,33:$V8,34:28,35:29},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:35,15:$V9,17:$V4,20:$V5,21:$Vg,22:$V6,28:6,30:33,31:$V7,33:$V8,36:34},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:35,15:$V9,17:$V4,20:$V5,22:$V6,23:$Vg,28:6,30:36,31:$V7,33:$V8,36:34},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:38,15:$V9,17:$V4,20:$V5,22:$V6,28:6,31:$V7,32:[1,37],33:$V8},o($Vf,$Vh),o($Vf,[2,29]),{3:41,4:$V1,5:40,6:$V2,7:39,8:$V3},o([4,6,8,12,14,15,17,19,20,21,22,23,26,27,31,32,33],[2,2]),o($Vf,[2,3]),{1:[2,4]},o($Vf,[2,21]),o($Vf,$Vb),{3:42,4:$V1,16:23,17:$Vc,20:$Vd,22:$Ve},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:43,15:$V9,17:$V4,20:$V5,22:$V6,28:6,31:$V7,33:$V8},o($Va,$Vi,{13:[1,44]}),o($Vf,[2,33]),{3:49,4:$V1,5:50,6:$V2,16:48,17:$Vc,18:45,19:$Vj,20:$Vd,22:$Ve,24:46,25:47},{3:42,4:$V1,16:51,17:$Vc,20:$Vd,22:$Ve},{3:49,4:$V1,5:50,6:$V2,16:48,17:$Vc,18:52,20:$Vd,22:$Ve,23:$Vj,24:46,25:47},{19:[1,53]},{19:[2,35],26:[1,54]},o($Vk,[2,36]),{3:55,4:$V1,5:56,6:$V2,7:13,8:$V3,15:$V9,17:$V4,20:$V5,22:$V6,28:18,31:$V7,33:$V8},o($V0,$Vb,{27:[1,57]}),o($V0,$Vh,{27:[1,58]}),{21:[1,59]},o([21,23],[2,43],{26:[1,60]}),o($Vl,[2,44],{5:12,7:13,28:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,17:$V4,20:$V5,22:$V6,31:$V7,33:$V8}),{23:[1,61]},o($Vf,[2,26]),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,15:$V9,17:$V4,20:$V5,22:$V6,28:18,31:$V7,32:[1,62],33:$V8},o($Vf,[2,30]),o($Vf,[2,31]),o($Vf,[2,32]),o($Vf,$Vi),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,14:[1,63],15:$V9,17:$V4,20:$V5,22:$V6,28:18,31:$V7,33:$V8},{3:42,4:$V1,16:64,17:$Vc,20:$Vd,22:$Ve},{19:[1,65]},o([19,23],[2,13],{26:[1,66]}),o($Vm,[2,14]),{3:67,4:$V1,5:68,6:$V2},o([4,6],$Vi,{27:[1,69]}),{27:[1,70]},{21:[1,71]},{23:[1,72]},o($Vf,[2,22]),{3:31,4:$V1,5:32,6:$V2,7:13,8:$V3,11:30,15:$V9,17:$V4,20:$V5,22:$V6,28:6,31:$V7,33:$V8,35:73},o($V0,$Vb,{19:$Vn,26:$Vn}),o($V0,$Vh,{19:$Vo,26:$Vo}),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:74,15:$V9,17:$V4,20:$V5,22:$V6,28:6,31:$V7,33:$V8},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:75,15:$V9,17:$V4,20:$V5,22:$V6,28:6,31:$V7,33:$V8},o($Vf,[2,23]),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:76,15:$V9,17:$V4,20:$V5,22:$V6,28:6,31:$V7,33:$V8},o($Vf,[2,24]),o($Vf,[2,27]),o($V0,[2,6]),{14:[1,77]},o($Vf,[2,9]),{3:49,4:$V1,5:50,6:$V2,16:48,17:$Vc,20:$Vd,22:$Ve,25:78},o($Vm,[2,16]),o($Vm,[2,17]),{3:42,4:$V1,16:79,17:$Vc,20:$Vd,22:$Ve},{3:42,4:$V1,16:80,17:$Vc,20:$Vd,22:$Ve},o($Vf,[2,10]),o($Vf,[2,11]),o($Vk,[2,37]),o($Vk,[2,40],{5:12,7:13,28:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,17:$V4,20:$V5,22:$V6,31:$V7,33:$V8}),o($Vk,[2,41],{5:12,7:13,28:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,17:$V4,20:$V5,22:$V6,31:$V7,33:$V8}),o($Vl,[2,45],{5:12,7:13,28:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,17:$V4,20:$V5,22:$V6,31:$V7,33:$V8}),o($V0,[2,7]),o($Vm,[2,15]),o($Vm,[2,18]),o($Vm,[2,19])],
203
+ defaultActions: {17:[2,4]},
159
204
  parseError: function parseError (str, hash) {
160
205
  if (hash.recoverable) {
161
206
  this.trace(str);
@@ -641,38 +686,46 @@ case 1:/* one line comment */
641
686
  break;
642
687
  case 2:/* blanks */
643
688
  break;
644
- case 3:return 19;
689
+ case 3:return 22;
690
+ break;
691
+ case 4:return 17;
692
+ break;
693
+ case 5:return 20;
694
+ break;
695
+ case 6:return 31;
696
+ break;
697
+ case 7:return 23;
645
698
  break;
646
- case 4:return 13;
699
+ case 8:return 19;
647
700
  break;
648
- case 5:return 16;
701
+ case 9:return 21;
649
702
  break;
650
- case 6:return 21;
703
+ case 10:return 32;
651
704
  break;
652
- case 7:return 20;
705
+ case 11:return 13;
653
706
  break;
654
- case 8:return 15;
707
+ case 12:return 33;
655
708
  break;
656
- case 9:return 18;
709
+ case 13:return 26;
657
710
  break;
658
- case 10:return 22;
711
+ case 14:return 14;
659
712
  break;
660
- case 11:return 23;
713
+ case 15:return 27;
661
714
  break;
662
- case 12:return 26;
715
+ case 16:return 15;
663
716
  break;
664
- case 13:return 6
717
+ case 17:return 6
665
718
  break;
666
- case 14:return 4;
719
+ case 18:return 4;
667
720
  break;
668
- case 15:return 8;
721
+ case 19:return 8;
669
722
  break;
670
- case 16:return 11;
723
+ case 20:return 12;
671
724
  break;
672
725
  }
673
726
  },
674
- rules: [/^(?:[/][*]([*][^/]|[^*])*[*][/])/,/^(?:(\/\/|#|%|--)[^\n]*)/,/^(?:\s+)/,/^(?:<)/,/^(?:\{)/,/^(?:\[)/,/^(?:\()/,/^(?:>)/,/^(?:\})/,/^(?:\])/,/^(?:\))/,/^(?:\.)/,/^(?:,)/,/^(?:"[^\"\n]*"|'[^\'\n]*')/,/^(?:[a-zA-Z_][a-zA-Z0-9_]*)/,/^(?:0|[-]?[1-9][0-9]*)/,/^(?:$)/],
675
- conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"inclusive":true}}
727
+ rules: [/^(?:[/][*]([*][^/]|[^*])*[*][/])/,/^(?:(\/\/|#|%|--)[^\n]*)/,/^(?:\s+)/,/^(?:<)/,/^(?:\{)/,/^(?:\[)/,/^(?:\()/,/^(?:>)/,/^(?:\})/,/^(?:\])/,/^(?:\))/,/^(?:=)/,/^(?:\.)/,/^(?:,)/,/^(?:;)/,/^(?::)/,/^(?:\$)/,/^(?:"[^\"\n]*"|'[^\'\n]*')/,/^(?:[a-zA-Z_][a-zA-Z0-9_?!]*)/,/^(?:0|[-]?[1-9][0-9]*)/,/^(?:$)/],
728
+ conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],"inclusive":true}}
676
729
  });
677
730
  return lexer;
678
731
  })();
package/pow.k ADDED
@@ -0,0 +1,7 @@
1
+
2
+ pow =
3
+ < [(), 0] EQ 1,
4
+ [[(), -1] PLUS pow, ()] TIMES
5
+ >;
6
+
7
+ pow
package/run.coffee CHANGED
@@ -2,7 +2,10 @@ valid = (x) ->
2
2
  return undefined if isNaN x
3
3
  return x if x?
4
4
 
5
- builtin =
5
+ builtin =
6
+ "_log_": (arg) ->
7
+ console.log "_log_: #{JSON.stringify arg}"
8
+ arg
6
9
  "GT": (args) ->
7
10
  [ok,_] = do ([last,args...] = args) ->
8
11
  args.reduce ([ok,last], x) ->
@@ -32,20 +35,55 @@ builtin =
32
35
  "null": -> null
33
36
  "toJSON": (x) -> JSON.stringify x
34
37
  "fromJSON": (x) -> JSON.parse x
38
+ "CONS": ([x,y]) -> [x,y...]
39
+ "SNOC": (x) ->
40
+ return [x[0],x.slice 1] if x.length > 1
35
41
 
42
+ codes =
43
+ "int": (x) ->
44
+ Number.isInteger x
45
+ "string": (x) ->
46
+ (x instanceof String) or ('string' is typeof x)
47
+ "bool": (x) ->
48
+ x is true or x is false
49
+
50
+ verify = (code, value) ->
51
+ switch code.code
52
+ when "ref"
53
+ do (c = run.defs.codes[code.ref]) ->
54
+ return verify c, value if c?
55
+ codes[code.ref] value
56
+ when "vector"
57
+ value.every (x) ->
58
+ verify code.vector, x
59
+ when "product"
60
+ do (fields = Object.keys(value)) ->
61
+ return false unless fields.length is Object.keys(code.product).length
62
+ fields.every (label) ->
63
+ verify code.product[label], value[label]
64
+ when "union"
65
+ do (fields = Object.keys(value)) ->
66
+ return false unless fields.length is 1
67
+ verify code.union[fields[0]], value[fields[0]]
36
68
 
37
69
  run = (exp, value) ->
38
70
  return undefined if value is undefined
39
71
  try
40
72
  switch exp.op
73
+ when "code"
74
+ return value if verify exp.code, value
41
75
  when "identity"
42
76
  return value
43
77
  when "str", "int"
44
78
  return exp[exp.op]
45
79
  when "ref"
46
- return do (value = builtin[exp.ref] value) ->
47
- throw new Error "Undefined" if value is undefined
48
- value
80
+ do (defn = run.defs.rels[exp.ref]) ->
81
+ if defn?
82
+ run defn, value
83
+ else
84
+ do ( value = builtin[exp.ref] value ) ->
85
+ throw new Error "Undefined" if value is undefined
86
+ value
49
87
  when "dot"
50
88
  return value[exp.dot]
51
89
  when "comp"
@@ -71,6 +109,8 @@ run = (exp, value) ->
71
109
  result[label] = value
72
110
  result
73
111
  , {}
112
+ else
113
+ console.log exp.op
74
114
 
75
115
 
76
116
  module.exports = run
package/run.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
2
  (function() {
3
- var builtin, run, valid,
3
+ var builtin, codes, run, valid, verify,
4
4
  modulo = function(a, b) { return (+a % (b = +b) + b) % b; };
5
5
 
6
6
  valid = function(x) {
@@ -13,6 +13,10 @@
13
13
  };
14
14
 
15
15
  builtin = {
16
+ "_log_": function(arg) {
17
+ console.log(`_log_: ${JSON.stringify(arg)}`);
18
+ return arg;
19
+ },
16
20
  "GT": function(args) {
17
21
  var _, ok;
18
22
  [ok, _] = (function([last, ...args]) {
@@ -83,6 +87,58 @@
83
87
  },
84
88
  "fromJSON": function(x) {
85
89
  return JSON.parse(x);
90
+ },
91
+ "CONS": function([x, y]) {
92
+ return [x, ...y];
93
+ },
94
+ "SNOC": function(x) {
95
+ if (x.length > 1) {
96
+ return [x[0], x.slice(1)];
97
+ }
98
+ }
99
+ };
100
+
101
+ codes = {
102
+ "int": function(x) {
103
+ return Number.isInteger(x);
104
+ },
105
+ "string": function(x) {
106
+ return (x instanceof String) || ('string' === typeof x);
107
+ },
108
+ "bool": function(x) {
109
+ return x === true || x === false;
110
+ }
111
+ };
112
+
113
+ verify = function(code, value) {
114
+ switch (code.code) {
115
+ case "ref":
116
+ return (function(c) {
117
+ if (c != null) {
118
+ return verify(c, value);
119
+ }
120
+ return codes[code.ref](value);
121
+ })(run.defs.codes[code.ref]);
122
+ case "vector":
123
+ return value.every(function(x) {
124
+ return verify(code.vector, x);
125
+ });
126
+ case "product":
127
+ return (function(fields) {
128
+ if (fields.length !== Object.keys(code.product).length) {
129
+ return false;
130
+ }
131
+ return fields.every(function(label) {
132
+ return verify(code.product[label], value[label]);
133
+ });
134
+ })(Object.keys(value));
135
+ case "union":
136
+ return (function(fields) {
137
+ if (fields.length !== 1) {
138
+ return false;
139
+ }
140
+ return verify(code.union[fields[0]], value[fields[0]]);
141
+ })(Object.keys(value));
86
142
  }
87
143
  };
88
144
 
@@ -93,18 +149,29 @@
93
149
  }
94
150
  try {
95
151
  switch (exp.op) {
152
+ case "code":
153
+ if (verify(exp.code, value)) {
154
+ return value;
155
+ }
156
+ break;
96
157
  case "identity":
97
158
  return value;
98
159
  case "str":
99
160
  case "int":
100
161
  return exp[exp.op];
101
162
  case "ref":
102
- return (function(value) {
103
- if (value === void 0) {
104
- throw new Error("Undefined");
163
+ return (function(defn) {
164
+ if (defn != null) {
165
+ return run(defn, value);
166
+ } else {
167
+ return (function(value) {
168
+ if (value === void 0) {
169
+ throw new Error("Undefined");
170
+ }
171
+ return value;
172
+ })(builtin[exp.ref](value));
105
173
  }
106
- return value;
107
- })(builtin[exp.ref](value));
174
+ })(run.defs.rels[exp.ref]);
108
175
  case "dot":
109
176
  return value[exp.dot];
110
177
  case "comp":
@@ -148,6 +215,8 @@
148
215
  return result;
149
216
  })(run(exp, value));
150
217
  }, {});
218
+ default:
219
+ return console.log(exp.op);
151
220
  }
152
221
  } catch (error) {}
153
222
  };
package/test.coffee CHANGED
@@ -32,3 +32,19 @@ console.log ""
32
32
  console.log "k_fn(#{JSON.stringify(data)});"
33
33
  console.log "// RETURNS: #{JSON.stringify k_fn data}"
34
34
  console.log ""
35
+
36
+ k_expression = "$t = < i: int, t: [ t ] > ; <$t, $int>"
37
+ k_fn = k.compile k_expression
38
+
39
+ console.log "var k_fn = k.compile('#{k_expression}');"
40
+ console.log ""
41
+
42
+ [
43
+ 1
44
+ {i:1}
45
+ [{i:2},{i:3},{t:[]}]
46
+ {"t":[{"i":2},{"i":3},{"t":[]}]}
47
+ ].map (data) ->
48
+ console.log "k_fn(#{JSON.stringify(data)});"
49
+ console.log "// RETURNS: #{JSON.stringify k_fn data}"
50
+ console.log ""
package/test.js CHANGED
@@ -73,4 +73,47 @@
73
73
  return console.log("");
74
74
  });
75
75
 
76
+ k_expression = "$t = < i: int, t: [ t ] > ; <$t, $int>";
77
+
78
+ k_fn = k.compile(k_expression);
79
+
80
+ console.log(`var k_fn = k.compile('${k_expression}');`);
81
+
82
+ console.log("");
83
+
84
+ [
85
+ 1,
86
+ {
87
+ i: 1
88
+ },
89
+ [
90
+ {
91
+ i: 2
92
+ },
93
+ {
94
+ i: 3
95
+ },
96
+ {
97
+ t: []
98
+ }
99
+ ],
100
+ {
101
+ "t": [
102
+ {
103
+ "i": 2
104
+ },
105
+ {
106
+ "i": 3
107
+ },
108
+ {
109
+ "t": []
110
+ }
111
+ ]
112
+ }
113
+ ].map(function(data) {
114
+ console.log(`k_fn(${JSON.stringify(data)});`);
115
+ console.log(`// RETURNS: ${JSON.stringify(k_fn(data))}`);
116
+ return console.log("");
117
+ });
118
+
76
119
  }).call(this);
@@ -2,7 +2,7 @@
2
2
  < -- merge of 4 partial functions...
3
3
  ["x=", .x, " & y=", .y], -- produces a vector of 4 values, if fields 'x' and 'y' are present
4
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
5
+ -- it is defined only if field 'x' is present
6
6
  ["only y=", .y],
7
7
  ["no x nor y"] -- defined for all input, returns always the same one element vector
8
8
  >