capdag 1.426.27 → 1.439.69
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 +56 -4
- package/cap-fab-renderer.js +216 -74
- package/capdag.js +4239 -1115
- package/formal/index.d.ts +1 -1
- package/formal/index.js +2 -2
- package/formal/program.wasm +0 -0
- package/machine-parser.js +1547 -234
- package/machine.pegjs +112 -17
- package/package.json +4 -4
package/machine.pegjs
CHANGED
|
@@ -1,57 +1,152 @@
|
|
|
1
1
|
// Machine notation grammar for Peggy.
|
|
2
2
|
//
|
|
3
|
-
// This grammar
|
|
4
|
-
//
|
|
3
|
+
// This grammar reads the same language as the reference's pest grammar
|
|
4
|
+
// (capdag-rs/src/machine/machine.pest). Every part of a statement carries
|
|
5
|
+
// where it stands in the text, for editor support.
|
|
5
6
|
//
|
|
6
7
|
// Two equally valid statement forms:
|
|
7
8
|
//
|
|
8
9
|
// Bracketed (one or more statements per line, any layout):
|
|
9
|
-
// [extract cap:in="media:ext=pdf";extract;out="media:txt
|
|
10
|
+
// [extract cap:in="media:document;ext=pdf";extract;out="media:enc=utf-8;ext=txt"]
|
|
10
11
|
// [doc -> extract -> text]
|
|
11
12
|
//
|
|
12
13
|
// Line-based (one statement per line, no brackets):
|
|
13
|
-
// extract cap:in="media:ext=pdf";extract;out="media:txt
|
|
14
|
+
// extract cap:in="media:document;ext=pdf";extract;out="media:enc=utf-8;ext=txt"
|
|
14
15
|
// doc -> extract -> text
|
|
15
16
|
// (thumbnail, model_spec) -> describe -> description
|
|
16
17
|
//
|
|
17
18
|
// Both forms can be freely mixed in the same program.
|
|
19
|
+
//
|
|
20
|
+
// A wiring is one invocation: what it is given, the step, what is taken.
|
|
21
|
+
// (path, benchmark=bench) -> compare -> result a named member
|
|
22
|
+
// (prices, window=20, statistic="mean") -> rolling -> s constants: any JSON value
|
|
23
|
+
// () -> now -> stamp a source given nothing
|
|
24
|
+
// report -> publish -> () a sink
|
|
25
|
+
// obs -> regress -> (fit, residuals=res) several outputs
|
|
26
|
+
// ref -> fetch{retry=3} -> series a step policy
|
|
18
27
|
|
|
19
28
|
program = _ stmts:stmt* _ { return stmts; }
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
// A bracketed statement stands where its brackets do.
|
|
31
|
+
stmt = b:bracketed _ { return b; }
|
|
22
32
|
/ inner:inner _ { return inner; }
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
bracketed = "[" _ inner:inner _ "]" { return { ...inner, location: location() }; }
|
|
35
|
+
|
|
36
|
+
// A wiring is tried first: it is the only form with an arrow, and its first
|
|
37
|
+
// token may be a group. The two headers both start with an alias and are told
|
|
38
|
+
// apart by what follows it.
|
|
39
|
+
inner = wiring / machine_header / header
|
|
25
40
|
|
|
26
41
|
// Header: alias followed by a cap URN starting with "cap:".
|
|
27
42
|
header = a:alias_loc __ c:cap_urn_loc {
|
|
28
43
|
return { type: 'header', alias: a.value, capUrn: c.value, location: location(), aliasLocation: a.location, capUrnLocation: c.location };
|
|
29
44
|
}
|
|
30
45
|
|
|
31
|
-
//
|
|
46
|
+
// Machine header: an alias for another machine, usable in step position. The
|
|
47
|
+
// reference is an opaque string the host resolves; it is kept as written
|
|
48
|
+
// (`referenceText`), and read as the JSON string it is by the syntax layer.
|
|
49
|
+
machine_header = a:alias_loc __ machine_kw _ r:string_loc {
|
|
50
|
+
return { type: 'machine_header', alias: a.value, referenceText: r.value, location: location(), aliasLocation: a.location, referenceLocation: r.location };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
machine_kw = "machine" !alias_continue
|
|
54
|
+
|
|
55
|
+
// Wiring: sources -> step -> targets
|
|
32
56
|
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
wiring = s:
|
|
36
|
-
return {
|
|
57
|
+
// There is no per-item marker and no gather marker: both are derived from
|
|
58
|
+
// cardinality, never authored syntax.
|
|
59
|
+
wiring = s:sources _ a1:arrow_loc _ c:step _ a2:arrow_loc _ t:targets {
|
|
60
|
+
return {
|
|
61
|
+
type: 'wiring',
|
|
62
|
+
sources: s.members,
|
|
63
|
+
sourcesLocation: s.location,
|
|
64
|
+
step: c.alias.value,
|
|
65
|
+
stepLocation: c.alias.location,
|
|
66
|
+
policy: c.policy,
|
|
67
|
+
policyLocation: c.policyLocation,
|
|
68
|
+
arrowLocations: [a1, a2],
|
|
69
|
+
targets: t.targets,
|
|
70
|
+
targetsLocation: t.location,
|
|
71
|
+
location: location(),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
sources = g:source_group { return g; }
|
|
76
|
+
/ a:alias_loc { return { members: [{ name: null, nameLocation: null, node: a.value, location: a.location, valueLocation: a.location }], location: a.location }; }
|
|
77
|
+
|
|
78
|
+
source_group = "(" _ ms:(first:member rest:(_ "," _ m:member { return m; })* { return [first, ...rest]; })? _ ")" {
|
|
79
|
+
return { members: ms || [], location: location() };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// A member names an arg, or does not. Named is tried first: it is the longer
|
|
83
|
+
// form, and an unnamed member is exactly a node alias. A member stands where
|
|
84
|
+
// all of it does; its name and its value each where they do.
|
|
85
|
+
member = named_member
|
|
86
|
+
/ c:constant_loc { return { name: null, nameLocation: null, constantText: c.value, location: c.location, valueLocation: c.location }; }
|
|
87
|
+
/ a:alias_loc { return { name: null, nameLocation: null, node: a.value, location: a.location, valueLocation: a.location }; }
|
|
88
|
+
|
|
89
|
+
named_member = n:alias_loc _ "=" _ v:(c:constant_loc { return { constantText: c.value, valueLocation: c.location }; }
|
|
90
|
+
/ a:alias_loc { return { node: a.value, valueLocation: a.location }; }) {
|
|
91
|
+
return { name: n.value, nameLocation: n.location, ...v, location: location() };
|
|
37
92
|
}
|
|
38
93
|
|
|
39
|
-
|
|
94
|
+
// A step is a header alias or a registered cap alias, with an optional policy.
|
|
95
|
+
step = a:alias_loc _ p:policy_loc? {
|
|
96
|
+
return { alias: a, policy: p ? p.entries : [], policyLocation: p ? p.location : null };
|
|
97
|
+
}
|
|
40
98
|
|
|
41
|
-
|
|
99
|
+
policy_loc = "{" _ es:(first:policy_entry rest:(_ "," _ e:policy_entry { return e; })* { return [first, ...rest]; })? _ "}" {
|
|
100
|
+
return { entries: es || [], location: location() };
|
|
101
|
+
}
|
|
42
102
|
|
|
43
|
-
|
|
44
|
-
return {
|
|
103
|
+
policy_entry = k:alias_loc _ "=" _ v:policy_value {
|
|
104
|
+
return { key: k.value, keyLocation: k.location, value: v.value, isNumber: v.isNumber, valueLocation: v.location };
|
|
45
105
|
}
|
|
46
106
|
|
|
47
|
-
|
|
107
|
+
policy_value = n:$number { return { value: n, isNumber: true, location: location() }; }
|
|
108
|
+
/ a:alias { return { value: a, isNumber: false, location: location() }; }
|
|
109
|
+
|
|
110
|
+
targets = g:target_group { return g; }
|
|
111
|
+
/ a:alias_loc { return { targets: [{ name: null, nameLocation: null, node: a.value, location: a.location, valueLocation: a.location }], location: a.location }; }
|
|
112
|
+
|
|
113
|
+
target_group = "(" _ ts:(first:target rest:(_ "," _ t:target { return t; })* { return [first, ...rest]; })? _ ")" {
|
|
114
|
+
return { targets: ts || [], location: location() };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// A target stands where all of it does; its name and its node each where they do.
|
|
118
|
+
target = n:alias_loc _ "=" _ a:alias_loc { return { name: n.value, nameLocation: n.location, node: a.value, location: location(), valueLocation: a.location }; }
|
|
119
|
+
/ a:alias_loc { return { name: null, nameLocation: null, node: a.value, location: a.location, valueLocation: a.location }; }
|
|
120
|
+
|
|
121
|
+
arrow_loc = "-"+ ">" { return location(); }
|
|
48
122
|
|
|
49
123
|
// Alias with location tracking
|
|
50
124
|
alias_loc = a:alias { return { value: a, location: location() }; }
|
|
51
125
|
|
|
52
126
|
// Alias: starts with alpha or underscore, continues with alphanumeric, underscore, or hyphen.
|
|
53
127
|
// This is atomic — no whitespace skipping inside.
|
|
54
|
-
alias = $( [a-zA-Z_]
|
|
128
|
+
alias = $( [a-zA-Z_] alias_continue* )
|
|
129
|
+
alias_continue = [a-zA-Z0-9_-]
|
|
130
|
+
|
|
131
|
+
// A constant is a JSON value. `true`, `false` and `null` are constants, never
|
|
132
|
+
// node names; a bare word that is none of them is an alias. The text is kept
|
|
133
|
+
// as written; the syntax layer reads it as the value it writes.
|
|
134
|
+
constant_loc = c:$constant { return { value: c, location: location() }; }
|
|
135
|
+
constant = object / array / string / number / boolean / null
|
|
136
|
+
boolean = ("true" / "false") !alias_continue
|
|
137
|
+
null = "null" !alias_continue
|
|
138
|
+
object = "{" _ (pair (_ "," _ pair)*)? _ "}"
|
|
139
|
+
pair = string _ ":" _ constant
|
|
140
|
+
array = "[" _ (constant (_ "," _ constant)*)? _ "]"
|
|
141
|
+
number = "-"? ("0" / [1-9] [0-9]*) ("." [0-9]+)? ([eE] [+-]? [0-9]+)? !alias_continue
|
|
142
|
+
|
|
143
|
+
// A JSON string: any character but an unescaped quote, backslash or control
|
|
144
|
+
// character, with JSON's escapes.
|
|
145
|
+
string_loc = s:$string { return { value: s, location: location() }; }
|
|
146
|
+
string = '"' string_char* '"'
|
|
147
|
+
string_char = [^"\\\u0000-\u001F]
|
|
148
|
+
/ "\\" ["\\/bfnrt]
|
|
149
|
+
/ "\\u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]
|
|
55
150
|
|
|
56
151
|
// Cap URN with location tracking
|
|
57
152
|
cap_urn_loc = c:cap_urn { return { value: c, location: location() }; }
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Bahram Joharshamshiri",
|
|
3
3
|
"dependencies": {
|
|
4
|
-
"lungo-ts": "1.
|
|
4
|
+
"lungo-ts": "1.108.38",
|
|
5
5
|
"peggy": "^5.1.0",
|
|
6
|
-
"tagged-urn": "^1.
|
|
6
|
+
"tagged-urn": "^1.137.33"
|
|
7
7
|
},
|
|
8
8
|
"description": "JavaScript implementation of Cap URN (Capability Uniform Resource Names) with strict validation and matching",
|
|
9
9
|
"engines": {
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"build:parser": "npx peggy --format es -o machine-parser.js machine.pegjs",
|
|
48
48
|
"build:browser": "npm run build:parser && node build-browser.js",
|
|
49
49
|
"pretest": "npm run build:parser",
|
|
50
|
-
"test": "node capdag.test.js"
|
|
50
|
+
"test": "node capdag.test.js && node machine.test.js"
|
|
51
51
|
},
|
|
52
52
|
"type": "module",
|
|
53
|
-
"version": "1.
|
|
53
|
+
"version": "1.439.69"
|
|
54
54
|
}
|