@cavelang/parser 0.31.1 → 0.32.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 +14 -4
- package/dist/src/ast.d.ts +14 -1
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/document.d.ts +8 -3
- package/dist/src/document.d.ts.map +1 -1
- package/dist/src/document.js +95 -28
- package/dist/src/document.js.map +1 -1
- package/package.json +2 -2
- package/src/ast.ts +7 -4
- package/src/document.ts +110 -29
package/README.md
CHANGED
|
@@ -32,13 +32,15 @@ parse('a USES b') // strict variant: throws on any diagnostic
|
|
|
32
32
|
(`Token.splitComment`).
|
|
33
33
|
3. **Tokenize** into words / `"text"` literals / `` `code` `` literals
|
|
34
34
|
(`token.ts`, `@prelude/parser` combinators).
|
|
35
|
-
4. **
|
|
35
|
+
4. **Expand incomplete prefixes** (§8.5): prepend every incomplete ancestor's
|
|
36
|
+
tokens recursively; blank and comment lines are transparent.
|
|
37
|
+
5. **Classify** the completed logical line per §8's three-kind table: qualifier (starts with
|
|
36
38
|
`WHEN`/`UNLESS`/`VIA`/`BECAUSE`), continuation (starts with a bare
|
|
37
39
|
relational verb), or full claim.
|
|
38
|
-
|
|
40
|
+
6. **Parse the token stream** (`line.ts`): subject, verb, `NOT`, payload,
|
|
39
41
|
then metadata items.
|
|
40
|
-
|
|
41
|
-
less-indented
|
|
42
|
+
7. **Resolve parents**: each completed line links to the nearest
|
|
43
|
+
less-indented materialized claim above; prefix headers do not become claims.
|
|
42
44
|
|
|
43
45
|
## Payload classification
|
|
44
46
|
|
|
@@ -100,6 +102,14 @@ examples and are tried in order:
|
|
|
100
102
|
with last-wins retention (§3.2 allows repetition only for contexts and
|
|
101
103
|
tags); a glued attribute colon (`expiry:3600s`) splits into the attribute
|
|
102
104
|
form with a diagnostic, since payload `:` is reserved (§4.3).
|
|
105
|
+
- **Prefix compatibility boundary.** A physical line becomes a §8.5 prefix
|
|
106
|
+
only when its accumulated tokens are incomplete and it has indented
|
|
107
|
+
content. Complete lines retain the established qualifier, continuation,
|
|
108
|
+
and grouped-claim semantics. Prefixes compose recursively; blank and
|
|
109
|
+
full-line comments are transparent. A prefix's trailing comment is
|
|
110
|
+
documentary and not inherited, while a leaf comment remains persisted.
|
|
111
|
+
`raw` preserves the physical leaf and `expanded` carries the self-contained
|
|
112
|
+
logical line used as stored `raw_line`.
|
|
103
113
|
|
|
104
114
|
## Tests
|
|
105
115
|
|
package/dist/src/ast.d.ts
CHANGED
|
@@ -68,7 +68,9 @@ export type QualifierPayload = {
|
|
|
68
68
|
/**
|
|
69
69
|
* A parsed line. `depth` is the indentation width in characters; `parent` is
|
|
70
70
|
* the index (into the document's `lines`) of the nearest less-indented
|
|
71
|
-
*
|
|
71
|
+
* materialized claim above (spec §8). `raw` is the physical line exactly as
|
|
72
|
+
* written. A shorthand leaf also carries `expanded`, the self-contained
|
|
73
|
+
* logical line assembled from its incomplete prefix ancestors (§8.5).
|
|
72
74
|
*/
|
|
73
75
|
export type Line = {
|
|
74
76
|
readonly kind: 'blank';
|
|
@@ -79,10 +81,19 @@ export type Line = {
|
|
|
79
81
|
readonly line: number;
|
|
80
82
|
readonly raw: string;
|
|
81
83
|
readonly text: string;
|
|
84
|
+
} | {
|
|
85
|
+
readonly kind: 'prefix';
|
|
86
|
+
readonly line: number;
|
|
87
|
+
readonly raw: string;
|
|
88
|
+
readonly depth: number;
|
|
89
|
+
readonly parent?: number;
|
|
90
|
+
readonly expanded: string;
|
|
91
|
+
readonly comment?: string;
|
|
82
92
|
} | {
|
|
83
93
|
readonly kind: 'claim';
|
|
84
94
|
readonly line: number;
|
|
85
95
|
readonly raw: string;
|
|
96
|
+
readonly expanded?: string;
|
|
86
97
|
readonly depth: number;
|
|
87
98
|
readonly parent?: number;
|
|
88
99
|
readonly claim: Full;
|
|
@@ -90,6 +101,7 @@ export type Line = {
|
|
|
90
101
|
readonly kind: 'continuation';
|
|
91
102
|
readonly line: number;
|
|
92
103
|
readonly raw: string;
|
|
104
|
+
readonly expanded?: string;
|
|
93
105
|
readonly depth: number;
|
|
94
106
|
readonly parent?: number;
|
|
95
107
|
readonly body: Body;
|
|
@@ -97,6 +109,7 @@ export type Line = {
|
|
|
97
109
|
readonly kind: 'qualifier';
|
|
98
110
|
readonly line: number;
|
|
99
111
|
readonly raw: string;
|
|
112
|
+
readonly expanded?: string;
|
|
100
113
|
readonly depth: number;
|
|
101
114
|
readonly parent?: number;
|
|
102
115
|
readonly qualifier: Verb.Qualifier;
|
package/dist/src/ast.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAEtE,sDAAsD;AACtD,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC,EAAE,CAAA;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC,EAAE,CAAA;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IACxB,mCAAmC;IACnC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,sBAAsB;AACtB,eAAO,MAAM,SAAS,EAAE,IACuB,CAAA;AAE/C,mFAAmF;AACnF,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CACpB,CAAA;AAED,kCAAkC;AAClC,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG;IACxB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAA;CAC7B,CAAA;AAED,uFAAuF;AACvF,MAAM,MAAM,YAAY,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,CAAA;AAE/D,eAAO,MAAM,aAAa,EAAE,SAAS,YAAY,EACd,CAAA;AAEnC;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GACtG;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAA;AAElK
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"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"}
|
package/dist/src/document.d.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Document parser (spec §8, §16).
|
|
3
3
|
*
|
|
4
4
|
* Splits input into physical lines, measures indentation, classifies each
|
|
5
|
-
* line (blank / comment / claim / continuation / qualifier), and
|
|
6
|
-
* each
|
|
7
|
-
* above (spec §8).
|
|
5
|
+
* line (blank / comment / prefix / claim / continuation / qualifier), and
|
|
6
|
+
* resolves each materialized line's parent — the nearest less-indented
|
|
7
|
+
* materialized claim above (spec §8).
|
|
8
8
|
*
|
|
9
9
|
* Classification of an indented line follows spec §8's table, decided by
|
|
10
10
|
* what the line starts with:
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* - bare relational verb → continuation
|
|
14
14
|
* - full triple → grouped claim
|
|
15
15
|
*
|
|
16
|
+
* An incomplete line with indented content is a shorthand prefix (§8.5).
|
|
17
|
+
* Its tokens are prepended to every child; nested incomplete prefixes
|
|
18
|
+
* compose recursively. Complete lines never become prefixes, preserving the
|
|
19
|
+
* three existing indentation meanings above.
|
|
20
|
+
*
|
|
16
21
|
* One ambiguity needs a tiebreak: `API NEEDS auth` starts with a token that
|
|
17
22
|
* is lexically verb-shaped. A two-token `VERB VERB` line is a continuation:
|
|
18
23
|
* it has a verb and object but no third token for a full claim's payload.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/document.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,KAAK,GAAG,MAAM,UAAU,CAAA;AA2EpC;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,GAAG,CAAC,QAmJjD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,SAAS,GAAG,CAAC,IAAI,EAStD,CAAA"}
|
package/dist/src/document.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Document parser (spec §8, §16).
|
|
3
3
|
*
|
|
4
4
|
* Splits input into physical lines, measures indentation, classifies each
|
|
5
|
-
* line (blank / comment / claim / continuation / qualifier), and
|
|
6
|
-
* each
|
|
7
|
-
* above (spec §8).
|
|
5
|
+
* line (blank / comment / prefix / claim / continuation / qualifier), and
|
|
6
|
+
* resolves each materialized line's parent — the nearest less-indented
|
|
7
|
+
* materialized claim above (spec §8).
|
|
8
8
|
*
|
|
9
9
|
* Classification of an indented line follows spec §8's table, decided by
|
|
10
10
|
* what the line starts with:
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* - bare relational verb → continuation
|
|
14
14
|
* - full triple → grouped claim
|
|
15
15
|
*
|
|
16
|
+
* An incomplete line with indented content is a shorthand prefix (§8.5).
|
|
17
|
+
* Its tokens are prepended to every child; nested incomplete prefixes
|
|
18
|
+
* compose recursively. Complete lines never become prefixes, preserving the
|
|
19
|
+
* three existing indentation meanings above.
|
|
20
|
+
*
|
|
16
21
|
* One ambiguity needs a tiebreak: `API NEEDS auth` starts with a token that
|
|
17
22
|
* is lexically verb-shaped. A two-token `VERB VERB` line is a continuation:
|
|
18
23
|
* it has a verb and object but no third token for a full claim's payload.
|
|
@@ -65,6 +70,17 @@ const classify = (tokens, depth) => {
|
|
|
65
70
|
}
|
|
66
71
|
return 'claim';
|
|
67
72
|
};
|
|
73
|
+
const hasIndentedContent = (rawLines, at, depth) => {
|
|
74
|
+
for (let next = at + 1; next < rawLines.length; next += 1) {
|
|
75
|
+
const info = indentOf(rawLines[next]);
|
|
76
|
+
if (info.rest === '' || info.rest.startsWith(';')) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
return info.depth > depth;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
};
|
|
83
|
+
const logicalRaw = (head, comment) => comment === undefined ? head : `${head} ; ${comment}`;
|
|
68
84
|
/**
|
|
69
85
|
* Parses a CAVE document. Never throws; problems surface as diagnostics and
|
|
70
86
|
* `invalid` lines.
|
|
@@ -91,26 +107,55 @@ export const parseDocument = (input) => {
|
|
|
91
107
|
lines.push({ kind: 'comment', line: lineNo, raw, text: rest.slice(1).trim() });
|
|
92
108
|
return;
|
|
93
109
|
}
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
const kind = classify(tokens, depth);
|
|
101
|
-
if (typeof kind === 'object') {
|
|
102
|
-
problem(lineNo, raw, kind.error);
|
|
103
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: kind.error });
|
|
110
|
+
const split = Token.splitComment(rest);
|
|
111
|
+
const ownHead = split.head.trim();
|
|
112
|
+
const ownTokens = Token.tokenize(ownHead);
|
|
113
|
+
if (ownTokens.length === 0) {
|
|
114
|
+
lines.push({ kind: 'comment', line: lineNo, raw, text: split.comment ?? '' });
|
|
104
115
|
return;
|
|
105
116
|
}
|
|
106
117
|
while (stack.length > 0 && stack[stack.length - 1].depth >= depth) {
|
|
107
118
|
stack.pop();
|
|
108
119
|
}
|
|
109
|
-
const
|
|
120
|
+
const frame = stack[stack.length - 1];
|
|
121
|
+
const inherited = frame?.prefix;
|
|
122
|
+
const tokens = inherited === undefined ?
|
|
123
|
+
ownTokens :
|
|
124
|
+
[...inherited.tokens, ...ownTokens];
|
|
125
|
+
const head = inherited === undefined ?
|
|
126
|
+
ownHead :
|
|
127
|
+
`${inherited.head} ${ownHead}`;
|
|
128
|
+
const semanticDepth = inherited?.semanticDepth ?? depth;
|
|
129
|
+
const parent = inherited === undefined ? frame?.index : inherited.parent;
|
|
130
|
+
const expanded = inherited === undefined ? undefined : logicalRaw(head, split.comment);
|
|
131
|
+
const asPrefix = (message) => {
|
|
132
|
+
if (!hasIndentedContent(rawLines, at, depth)) {
|
|
133
|
+
problem(lineNo, raw, message);
|
|
134
|
+
lines.push({ kind: 'invalid', line: lineNo, raw, message });
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const index = lines.length;
|
|
138
|
+
const prefix = { tokens, head, semanticDepth, ...parent === undefined ? {} : { parent } };
|
|
139
|
+
lines.push({
|
|
140
|
+
kind: 'prefix',
|
|
141
|
+
line: lineNo,
|
|
142
|
+
raw,
|
|
143
|
+
depth,
|
|
144
|
+
expanded: head,
|
|
145
|
+
...parent === undefined ? {} : { parent },
|
|
146
|
+
...split.comment === undefined ? {} : { comment: split.comment }
|
|
147
|
+
});
|
|
148
|
+
stack.push({ index, depth, prefix });
|
|
149
|
+
return true;
|
|
150
|
+
};
|
|
151
|
+
const kind = classify(tokens, semanticDepth);
|
|
152
|
+
if (typeof kind === 'object') {
|
|
153
|
+
asPrefix(kind.error);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
110
156
|
if (parent === undefined && kind !== 'claim') {
|
|
111
157
|
const message = `${kind} line has no parent claim above (spec §8)`;
|
|
112
|
-
|
|
113
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message });
|
|
158
|
+
asPrefix(message);
|
|
114
159
|
return;
|
|
115
160
|
}
|
|
116
161
|
const index = lines.length;
|
|
@@ -123,34 +168,56 @@ export const parseDocument = (input) => {
|
|
|
123
168
|
};
|
|
124
169
|
switch (kind) {
|
|
125
170
|
case 'claim': {
|
|
126
|
-
const result = Line.parseClaim(tokens, comment);
|
|
171
|
+
const result = Line.parseClaim(tokens, split.comment);
|
|
127
172
|
if (!result.ok) {
|
|
128
|
-
|
|
129
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: result.message });
|
|
173
|
+
asPrefix(result.message);
|
|
130
174
|
return;
|
|
131
175
|
}
|
|
132
|
-
push({
|
|
176
|
+
push({
|
|
177
|
+
kind: 'claim',
|
|
178
|
+
line: lineNo,
|
|
179
|
+
raw,
|
|
180
|
+
depth,
|
|
181
|
+
...expanded === undefined ? {} : { expanded },
|
|
182
|
+
...parent !== undefined ? { parent } : {},
|
|
183
|
+
claim: result.value
|
|
184
|
+
}, result.problems);
|
|
133
185
|
return;
|
|
134
186
|
}
|
|
135
187
|
case 'continuation': {
|
|
136
|
-
const result = Line.parseBody(tokens, comment);
|
|
188
|
+
const result = Line.parseBody(tokens, split.comment);
|
|
137
189
|
if (!result.ok) {
|
|
138
|
-
|
|
139
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: result.message });
|
|
190
|
+
asPrefix(result.message);
|
|
140
191
|
return;
|
|
141
192
|
}
|
|
142
|
-
push({
|
|
193
|
+
push({
|
|
194
|
+
kind: 'continuation',
|
|
195
|
+
line: lineNo,
|
|
196
|
+
raw,
|
|
197
|
+
depth,
|
|
198
|
+
parent: parent,
|
|
199
|
+
...expanded === undefined ? {} : { expanded },
|
|
200
|
+
body: result.value
|
|
201
|
+
}, result.problems);
|
|
143
202
|
return;
|
|
144
203
|
}
|
|
145
204
|
case 'qualifier': {
|
|
146
205
|
const qualifier = tokens[0].text;
|
|
147
|
-
const result = Line.parseQualifierPayload(tokens.slice(1), comment);
|
|
206
|
+
const result = Line.parseQualifierPayload(tokens.slice(1), split.comment);
|
|
148
207
|
if (!result.ok) {
|
|
149
|
-
|
|
150
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: result.message });
|
|
208
|
+
asPrefix(result.message);
|
|
151
209
|
return;
|
|
152
210
|
}
|
|
153
|
-
push({
|
|
211
|
+
push({
|
|
212
|
+
kind: 'qualifier',
|
|
213
|
+
line: lineNo,
|
|
214
|
+
raw,
|
|
215
|
+
depth,
|
|
216
|
+
parent: parent,
|
|
217
|
+
...expanded === undefined ? {} : { expanded },
|
|
218
|
+
qualifier,
|
|
219
|
+
payload: result.value
|
|
220
|
+
}, result.problems);
|
|
154
221
|
return;
|
|
155
222
|
}
|
|
156
223
|
}
|
package/dist/src/document.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/document.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/document.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cavelang/parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CAVE text to AST parser built on @prelude/parser combinators.",
|
|
6
6
|
"keywords": [
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@prelude/parser": "^7.1.0",
|
|
47
|
-
"@cavelang/core": "0.
|
|
47
|
+
"@cavelang/core": "0.32.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsc -b",
|
package/src/ast.ts
CHANGED
|
@@ -66,14 +66,17 @@ export type QualifierPayload =
|
|
|
66
66
|
/**
|
|
67
67
|
* A parsed line. `depth` is the indentation width in characters; `parent` is
|
|
68
68
|
* the index (into the document's `lines`) of the nearest less-indented
|
|
69
|
-
*
|
|
69
|
+
* materialized claim above (spec §8). `raw` is the physical line exactly as
|
|
70
|
+
* written. A shorthand leaf also carries `expanded`, the self-contained
|
|
71
|
+
* logical line assembled from its incomplete prefix ancestors (§8.5).
|
|
70
72
|
*/
|
|
71
73
|
export type Line =
|
|
72
74
|
| { readonly kind: 'blank', readonly line: number, readonly raw: string }
|
|
73
75
|
| { readonly kind: 'comment', readonly line: number, readonly raw: string, readonly text: string }
|
|
74
|
-
| { readonly kind: '
|
|
75
|
-
| { readonly kind: '
|
|
76
|
-
| { readonly kind: '
|
|
76
|
+
| { readonly kind: 'prefix', readonly line: number, readonly raw: string, readonly depth: number, readonly parent?: number, readonly expanded: string, readonly comment?: string }
|
|
77
|
+
| { readonly kind: 'claim', readonly line: number, readonly raw: string, readonly expanded?: string, readonly depth: number, readonly parent?: number, readonly claim: Full }
|
|
78
|
+
| { readonly kind: 'continuation', readonly line: number, readonly raw: string, readonly expanded?: string, readonly depth: number, readonly parent?: number, readonly body: Body }
|
|
79
|
+
| { readonly kind: 'qualifier', readonly line: number, readonly raw: string, readonly expanded?: string, readonly depth: number, readonly parent?: number, readonly qualifier: Verb.Qualifier, readonly payload: QualifierPayload }
|
|
77
80
|
| { readonly kind: 'invalid', readonly line: number, readonly raw: string, readonly message: string }
|
|
78
81
|
|
|
79
82
|
export type t = Line
|
package/src/document.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Document parser (spec §8, §16).
|
|
3
3
|
*
|
|
4
4
|
* Splits input into physical lines, measures indentation, classifies each
|
|
5
|
-
* line (blank / comment / claim / continuation / qualifier), and
|
|
6
|
-
* each
|
|
7
|
-
* above (spec §8).
|
|
5
|
+
* line (blank / comment / prefix / claim / continuation / qualifier), and
|
|
6
|
+
* resolves each materialized line's parent — the nearest less-indented
|
|
7
|
+
* materialized claim above (spec §8).
|
|
8
8
|
*
|
|
9
9
|
* Classification of an indented line follows spec §8's table, decided by
|
|
10
10
|
* what the line starts with:
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* - bare relational verb → continuation
|
|
14
14
|
* - full triple → grouped claim
|
|
15
15
|
*
|
|
16
|
+
* An incomplete line with indented content is a shorthand prefix (§8.5).
|
|
17
|
+
* Its tokens are prepended to every child; nested incomplete prefixes
|
|
18
|
+
* compose recursively. Complete lines never become prefixes, preserving the
|
|
19
|
+
* three existing indentation meanings above.
|
|
20
|
+
*
|
|
16
21
|
* One ambiguity needs a tiebreak: `API NEEDS auth` starts with a token that
|
|
17
22
|
* is lexically verb-shaped. A two-token `VERB VERB` line is a continuation:
|
|
18
23
|
* it has a verb and object but no third token for a full claim's payload.
|
|
@@ -72,7 +77,32 @@ const classify = (tokens: readonly Token.t[], depth: number): Classified | { err
|
|
|
72
77
|
return 'claim'
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
type
|
|
80
|
+
type Prefix = {
|
|
81
|
+
readonly tokens: readonly Token.t[]
|
|
82
|
+
readonly head: string
|
|
83
|
+
readonly semanticDepth: number
|
|
84
|
+
readonly parent?: number
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type Frame = {
|
|
88
|
+
readonly index: number
|
|
89
|
+
readonly depth: number
|
|
90
|
+
readonly prefix?: Prefix
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const hasIndentedContent = (rawLines: readonly string[], at: number, depth: number): boolean => {
|
|
94
|
+
for (let next = at + 1; next < rawLines.length; next += 1) {
|
|
95
|
+
const info = indentOf(rawLines[next]!)
|
|
96
|
+
if (info.rest === '' || info.rest.startsWith(';')) {
|
|
97
|
+
continue
|
|
98
|
+
}
|
|
99
|
+
return info.depth > depth
|
|
100
|
+
}
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const logicalRaw = (head: string, comment?: string): string =>
|
|
105
|
+
comment === undefined ? head : `${head} ; ${comment}`
|
|
76
106
|
|
|
77
107
|
/**
|
|
78
108
|
* Parses a CAVE document. Never throws; problems surface as diagnostics and
|
|
@@ -100,26 +130,55 @@ export const parseDocument = (input: string): Ast.Document => {
|
|
|
100
130
|
lines.push({ kind: 'comment', line: lineNo, raw, text: rest.slice(1).trim() })
|
|
101
131
|
return
|
|
102
132
|
}
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
const kind = classify(tokens, depth)
|
|
110
|
-
if (typeof kind === 'object') {
|
|
111
|
-
problem(lineNo, raw, kind.error)
|
|
112
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: kind.error })
|
|
133
|
+
const split = Token.splitComment(rest)
|
|
134
|
+
const ownHead = split.head.trim()
|
|
135
|
+
const ownTokens = Token.tokenize(ownHead)
|
|
136
|
+
if (ownTokens.length === 0) {
|
|
137
|
+
lines.push({ kind: 'comment', line: lineNo, raw, text: split.comment ?? '' })
|
|
113
138
|
return
|
|
114
139
|
}
|
|
115
140
|
while (stack.length > 0 && stack[stack.length - 1]!.depth >= depth) {
|
|
116
141
|
stack.pop()
|
|
117
142
|
}
|
|
118
|
-
const
|
|
143
|
+
const frame = stack[stack.length - 1]
|
|
144
|
+
const inherited = frame?.prefix
|
|
145
|
+
const tokens = inherited === undefined ?
|
|
146
|
+
ownTokens :
|
|
147
|
+
[...inherited.tokens, ...ownTokens]
|
|
148
|
+
const head = inherited === undefined ?
|
|
149
|
+
ownHead :
|
|
150
|
+
`${inherited.head} ${ownHead}`
|
|
151
|
+
const semanticDepth = inherited?.semanticDepth ?? depth
|
|
152
|
+
const parent = inherited === undefined ? frame?.index : inherited.parent
|
|
153
|
+
const expanded = inherited === undefined ? undefined : logicalRaw(head, split.comment)
|
|
154
|
+
const asPrefix = (message: string): boolean => {
|
|
155
|
+
if (!hasIndentedContent(rawLines, at, depth)) {
|
|
156
|
+
problem(lineNo, raw, message)
|
|
157
|
+
lines.push({ kind: 'invalid', line: lineNo, raw, message })
|
|
158
|
+
return false
|
|
159
|
+
}
|
|
160
|
+
const index = lines.length
|
|
161
|
+
const prefix: Prefix = { tokens, head, semanticDepth, ...parent === undefined ? {} : { parent } }
|
|
162
|
+
lines.push({
|
|
163
|
+
kind: 'prefix',
|
|
164
|
+
line: lineNo,
|
|
165
|
+
raw,
|
|
166
|
+
depth,
|
|
167
|
+
expanded: head,
|
|
168
|
+
...parent === undefined ? {} : { parent },
|
|
169
|
+
...split.comment === undefined ? {} : { comment: split.comment }
|
|
170
|
+
})
|
|
171
|
+
stack.push({ index, depth, prefix })
|
|
172
|
+
return true
|
|
173
|
+
}
|
|
174
|
+
const kind = classify(tokens, semanticDepth)
|
|
175
|
+
if (typeof kind === 'object') {
|
|
176
|
+
asPrefix(kind.error)
|
|
177
|
+
return
|
|
178
|
+
}
|
|
119
179
|
if (parent === undefined && kind !== 'claim') {
|
|
120
180
|
const message = `${kind} line has no parent claim above (spec §8)`
|
|
121
|
-
|
|
122
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message })
|
|
181
|
+
asPrefix(message)
|
|
123
182
|
return
|
|
124
183
|
}
|
|
125
184
|
const index = lines.length
|
|
@@ -132,41 +191,63 @@ export const parseDocument = (input: string): Ast.Document => {
|
|
|
132
191
|
}
|
|
133
192
|
switch (kind) {
|
|
134
193
|
case 'claim': {
|
|
135
|
-
const result = Line.parseClaim(tokens, comment)
|
|
194
|
+
const result = Line.parseClaim(tokens, split.comment)
|
|
136
195
|
if (!result.ok) {
|
|
137
|
-
|
|
138
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: result.message })
|
|
196
|
+
asPrefix(result.message)
|
|
139
197
|
return
|
|
140
198
|
}
|
|
141
199
|
push(
|
|
142
|
-
{
|
|
200
|
+
{
|
|
201
|
+
kind: 'claim',
|
|
202
|
+
line: lineNo,
|
|
203
|
+
raw,
|
|
204
|
+
depth,
|
|
205
|
+
...expanded === undefined ? {} : { expanded },
|
|
206
|
+
...parent !== undefined ? { parent } : {},
|
|
207
|
+
claim: result.value
|
|
208
|
+
},
|
|
143
209
|
result.problems
|
|
144
210
|
)
|
|
145
211
|
return
|
|
146
212
|
}
|
|
147
213
|
case 'continuation': {
|
|
148
|
-
const result = Line.parseBody(tokens, comment)
|
|
214
|
+
const result = Line.parseBody(tokens, split.comment)
|
|
149
215
|
if (!result.ok) {
|
|
150
|
-
|
|
151
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: result.message })
|
|
216
|
+
asPrefix(result.message)
|
|
152
217
|
return
|
|
153
218
|
}
|
|
154
219
|
push(
|
|
155
|
-
{
|
|
220
|
+
{
|
|
221
|
+
kind: 'continuation',
|
|
222
|
+
line: lineNo,
|
|
223
|
+
raw,
|
|
224
|
+
depth,
|
|
225
|
+
parent: parent!,
|
|
226
|
+
...expanded === undefined ? {} : { expanded },
|
|
227
|
+
body: result.value
|
|
228
|
+
},
|
|
156
229
|
result.problems
|
|
157
230
|
)
|
|
158
231
|
return
|
|
159
232
|
}
|
|
160
233
|
case 'qualifier': {
|
|
161
234
|
const qualifier = (tokens[0] as { text: string }).text as Verb.Qualifier
|
|
162
|
-
const result = Line.parseQualifierPayload(tokens.slice(1), comment)
|
|
235
|
+
const result = Line.parseQualifierPayload(tokens.slice(1), split.comment)
|
|
163
236
|
if (!result.ok) {
|
|
164
|
-
|
|
165
|
-
lines.push({ kind: 'invalid', line: lineNo, raw, message: result.message })
|
|
237
|
+
asPrefix(result.message)
|
|
166
238
|
return
|
|
167
239
|
}
|
|
168
240
|
push(
|
|
169
|
-
{
|
|
241
|
+
{
|
|
242
|
+
kind: 'qualifier',
|
|
243
|
+
line: lineNo,
|
|
244
|
+
raw,
|
|
245
|
+
depth,
|
|
246
|
+
parent: parent!,
|
|
247
|
+
...expanded === undefined ? {} : { expanded },
|
|
248
|
+
qualifier,
|
|
249
|
+
payload: result.value
|
|
250
|
+
},
|
|
170
251
|
result.problems
|
|
171
252
|
)
|
|
172
253
|
return
|