@lokascript/framework 2.3.0 → 2.4.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/dist/api/index.js +29 -516
- package/dist/api/index.js.map +1 -1
- package/dist/core/index.js +20 -128
- package/dist/core/index.js.map +1 -1
- package/dist/core/pattern-matching/index.js +19 -12
- package/dist/core/pattern-matching/index.js.map +1 -1
- package/dist/core/tokenization/index.js.map +1 -1
- package/dist/core/types.d.ts +7 -354
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +21 -129
- package/dist/core/types.js.map +1 -1
- package/dist/generation/diagnostics.d.ts +5 -115
- package/dist/generation/diagnostics.d.ts.map +1 -1
- package/dist/generation/index.js +20 -77
- package/dist/generation/index.js.map +1 -1
- package/dist/index.cjs +189 -1458
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +108 -1347
- package/dist/index.js.map +1 -1
- package/dist/interfaces/value-extractor.d.ts +20 -0
- package/dist/interfaces/value-extractor.d.ts.map +1 -1
- package/dist/ir/explicit-parser.d.ts +2 -83
- package/dist/ir/explicit-parser.d.ts.map +1 -1
- package/dist/ir/explicit-renderer.d.ts +2 -31
- package/dist/ir/explicit-renderer.d.ts.map +1 -1
- package/dist/ir/index.js +89 -1260
- package/dist/ir/index.js.map +1 -1
- package/dist/ir/protocol-json.d.ts +2 -70
- package/dist/ir/protocol-json.d.ts.map +1 -1
- package/dist/ir/references.d.ts +2 -16
- package/dist/ir/references.d.ts.map +1 -1
- package/dist/ir/types.d.ts +2 -148
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/parsing/index.js +19 -12
- package/dist/parsing/index.js.map +1 -1
- package/dist/schema/command-schema.d.ts +3 -92
- package/dist/schema/command-schema.d.ts.map +1 -1
- package/dist/schema/index.js +3 -20
- package/dist/schema/index.js.map +1 -1
- package/dist/testing/index.js +1133 -755
- package/dist/testing/index.js.map +1 -1
- package/package.json +6 -2
- package/src/core/types.ts +71 -600
- package/src/generation/diagnostics.ts +12 -233
- package/src/interfaces/value-extractor.ts +32 -0
- package/src/ir/explicit-parser.ts +12 -792
- package/src/ir/explicit-renderer.ts +2 -195
- package/src/ir/from-interchange.test.ts +91 -4
- package/src/ir/from-interchange.ts +59 -0
- package/src/ir/protocol-json.test.ts +16 -7
- package/src/ir/protocol-json.ts +9 -748
- package/src/ir/references.ts +2 -30
- package/src/ir/types.ts +18 -190
- package/src/schema/command-schema.ts +3 -134
package/src/core/types.ts
CHANGED
|
@@ -1,272 +1,76 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Core Types — re-exported from @lokascript/intent + framework-specific extensions
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the MEANING of DSL commands independent of surface syntax.
|
|
4
|
+
* The universal semantic types (SemanticNode, SemanticValue, etc.) now live in
|
|
5
|
+
* @lokascript/intent and are re-exported here for backward compatibility.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// =============================================================================
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface SelectorValue {
|
|
77
|
-
readonly type: 'selector';
|
|
78
|
-
readonly value: string; // The selector: #id, .class, [attr], table-name, etc.
|
|
79
|
-
readonly selectorKind?: 'id' | 'class' | 'attribute' | 'element' | 'complex' | 'identifier';
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface ReferenceValue {
|
|
83
|
-
readonly type: 'reference';
|
|
84
|
-
readonly value: string; // Generic reference name (DSL-specific)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface PropertyPathValue {
|
|
88
|
-
readonly type: 'property-path';
|
|
89
|
-
readonly object: SemanticValue;
|
|
90
|
-
readonly property: string;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface ExpressionValue {
|
|
94
|
-
readonly type: 'expression';
|
|
95
|
-
/** Raw expression string for complex expressions that need further parsing */
|
|
96
|
-
readonly raw: string;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* A boolean flag value — present (+flag) or negated (~flag).
|
|
101
|
-
* Used in declarative domains for no-value attributes like primary-key, not-null.
|
|
102
|
-
*/
|
|
103
|
-
export interface FlagValue {
|
|
104
|
-
readonly type: 'flag';
|
|
105
|
-
readonly name: string;
|
|
106
|
-
readonly enabled: boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// =============================================================================
|
|
110
|
-
// Annotations & Diagnostics (v1.2)
|
|
111
|
-
// =============================================================================
|
|
112
|
-
|
|
113
|
-
/** A metadata annotation on a node (v1.2). */
|
|
114
|
-
export interface Annotation {
|
|
115
|
-
readonly name: string;
|
|
116
|
-
readonly value?: string;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* A type constraint diagnostic attached to a node (v1.2).
|
|
121
|
-
*
|
|
122
|
-
* Named `ProtocolDiagnostic` to avoid collision with the framework's own
|
|
123
|
-
* `Diagnostic` type (which has `severity: 'error' | 'warning' | 'info'`
|
|
124
|
-
* and `suggestion?: string`).
|
|
125
|
-
*/
|
|
126
|
-
export interface ProtocolDiagnostic {
|
|
127
|
-
readonly level: 'error' | 'warning';
|
|
128
|
-
readonly role: string;
|
|
129
|
-
readonly message: string;
|
|
130
|
-
readonly code: string;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** Async coordination variant (v1.2). */
|
|
134
|
-
export type AsyncVariant = 'all' | 'race';
|
|
135
|
-
|
|
136
|
-
/** A single arm in a match command (v1.2). */
|
|
137
|
-
export interface MatchArm {
|
|
138
|
-
readonly pattern: SemanticValue;
|
|
139
|
-
readonly body: SemanticNode[];
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// =============================================================================
|
|
143
|
-
// Semantic Nodes
|
|
144
|
-
// =============================================================================
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Base interface for all semantic nodes.
|
|
148
|
-
* Semantic nodes capture the MEANING of DSL constructs.
|
|
149
|
-
*/
|
|
150
|
-
export interface SemanticNode {
|
|
151
|
-
readonly kind: 'command' | 'event-handler' | 'conditional' | 'compound' | 'loop';
|
|
152
|
-
readonly action: ActionType;
|
|
153
|
-
readonly roles: ReadonlyMap<SemanticRole, SemanticValue>;
|
|
154
|
-
readonly metadata?: SemanticMetadata;
|
|
155
|
-
/** Metadata annotations (v1.2). */
|
|
156
|
-
readonly annotations?: readonly Annotation[];
|
|
157
|
-
/** Diagnostics from parsing, validation, and schema checks (v1.2, extended v1.2.1). */
|
|
158
|
-
readonly diagnostics?: readonly Diagnostic[];
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Metadata about the source of a semantic node.
|
|
163
|
-
* Useful for debugging, error messages, and round-trip conversion.
|
|
164
|
-
*/
|
|
165
|
-
export interface SemanticMetadata {
|
|
166
|
-
readonly sourceLanguage?: string;
|
|
167
|
-
readonly sourceText?: string;
|
|
168
|
-
readonly sourcePosition?: SourcePosition;
|
|
169
|
-
readonly patternId?: string;
|
|
170
|
-
/**
|
|
171
|
-
* Confidence score for the parse (0-1).
|
|
172
|
-
* Higher values indicate more certain matches.
|
|
173
|
-
* - 1.0: Exact match with all roles captured
|
|
174
|
-
* - 0.8-0.99: High confidence with minor uncertainty
|
|
175
|
-
* - 0.6-0.8: Medium confidence (normalization, defaults applied)
|
|
176
|
-
* - <0.6: Low confidence (may need fallback)
|
|
177
|
-
*/
|
|
178
|
-
readonly confidence?: number;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export interface SourcePosition {
|
|
182
|
-
readonly start: number;
|
|
183
|
-
readonly end: number;
|
|
184
|
-
readonly line?: number;
|
|
185
|
-
readonly column?: number;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* A command semantic node - represents a single DSL command.
|
|
190
|
-
*
|
|
191
|
-
* v1.2 adds optional fields for try/catch/finally, async coordination (all/race),
|
|
192
|
-
* and pattern matching (match/arms). These are encoded as fields on command nodes
|
|
193
|
-
* (matching the protocol wire format) rather than new node kinds.
|
|
194
|
-
*/
|
|
195
|
-
export interface CommandSemanticNode extends SemanticNode {
|
|
196
|
-
readonly kind: 'command';
|
|
197
|
-
/** try body — commands to execute in the try block (v1.2). */
|
|
198
|
-
readonly body?: readonly SemanticNode[];
|
|
199
|
-
/** catch branch — commands to execute on error (v1.2). */
|
|
200
|
-
readonly catchBranch?: readonly SemanticNode[];
|
|
201
|
-
/** finally branch — cleanup commands that always execute (v1.2). */
|
|
202
|
-
readonly finallyBranch?: readonly SemanticNode[];
|
|
203
|
-
/** Async coordination variant: all (wait for all) or race (first wins) (v1.2). */
|
|
204
|
-
readonly asyncVariant?: AsyncVariant;
|
|
205
|
-
/** Async body — concurrent commands for all/race (v1.2). */
|
|
206
|
-
readonly asyncBody?: readonly SemanticNode[];
|
|
207
|
-
/** Match arms — pattern/body pairs for match command (v1.2). */
|
|
208
|
-
readonly arms?: readonly MatchArm[];
|
|
209
|
-
/** Default arm — executed when no match arm matches (v1.2). */
|
|
210
|
-
readonly defaultArm?: readonly SemanticNode[];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* An event handler semantic node - represents trigger-based commands.
|
|
215
|
-
* E.g., "on click [commands]" in hyperscript, or "when condition [commands]" in other DSLs.
|
|
216
|
-
*/
|
|
217
|
-
export interface EventHandlerSemanticNode extends SemanticNode {
|
|
218
|
-
readonly kind: 'event-handler';
|
|
219
|
-
readonly body: SemanticNode[];
|
|
220
|
-
readonly eventModifiers?: EventModifiers;
|
|
221
|
-
readonly additionalEvents?: readonly SemanticValue[];
|
|
222
|
-
readonly parameterNames?: readonly string[];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export interface EventModifiers {
|
|
226
|
-
readonly once?: boolean;
|
|
227
|
-
readonly debounce?: number;
|
|
228
|
-
readonly throttle?: number;
|
|
229
|
-
readonly queue?: 'first' | 'last' | 'all' | 'none';
|
|
230
|
-
readonly from?: SemanticValue;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* A conditional semantic node - represents "if [condition] then [body] else [body]".
|
|
235
|
-
*/
|
|
236
|
-
export interface ConditionalSemanticNode extends SemanticNode {
|
|
237
|
-
readonly kind: 'conditional';
|
|
238
|
-
readonly thenBranch: SemanticNode[];
|
|
239
|
-
readonly elseBranch?: SemanticNode[];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* A compound semantic node - represents multiple chained statements.
|
|
244
|
-
*/
|
|
245
|
-
export interface CompoundSemanticNode extends SemanticNode {
|
|
246
|
-
readonly kind: 'compound';
|
|
247
|
-
readonly statements: SemanticNode[];
|
|
248
|
-
readonly chainType: 'then' | 'and' | 'async' | 'sequential' | 'pipe';
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Loop variant discriminant for different loop types.
|
|
253
|
-
*/
|
|
254
|
-
export type LoopVariant = 'forever' | 'times' | 'for' | 'while' | 'until';
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* A loop semantic node - represents repeat/for/while loops.
|
|
258
|
-
*/
|
|
259
|
-
export interface LoopSemanticNode extends SemanticNode {
|
|
260
|
-
readonly kind: 'loop';
|
|
261
|
-
readonly loopVariant: LoopVariant;
|
|
262
|
-
readonly body: SemanticNode[];
|
|
263
|
-
readonly loopVariable?: string;
|
|
264
|
-
readonly indexVariable?: string;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// =============================================================================
|
|
268
|
-
// Tokenization Types
|
|
269
|
-
// =============================================================================
|
|
7
|
+
* Framework-specific types (tokenization, pattern matching) are defined below.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Re-export everything from @lokascript/intent
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
ActionType,
|
|
16
|
+
SemanticRole,
|
|
17
|
+
SemanticValue,
|
|
18
|
+
ExpectedType,
|
|
19
|
+
LiteralValue,
|
|
20
|
+
SelectorValue,
|
|
21
|
+
ReferenceValue,
|
|
22
|
+
PropertyPathValue,
|
|
23
|
+
ExpressionValue,
|
|
24
|
+
FlagValue,
|
|
25
|
+
Annotation,
|
|
26
|
+
ProtocolDiagnostic,
|
|
27
|
+
AsyncVariant,
|
|
28
|
+
MatchArm,
|
|
29
|
+
SemanticNode,
|
|
30
|
+
SemanticMetadata,
|
|
31
|
+
SourcePosition,
|
|
32
|
+
CommandSemanticNode,
|
|
33
|
+
EventHandlerSemanticNode,
|
|
34
|
+
EventModifiers,
|
|
35
|
+
ConditionalSemanticNode,
|
|
36
|
+
CompoundSemanticNode,
|
|
37
|
+
LoopVariant,
|
|
38
|
+
LoopSemanticNode,
|
|
39
|
+
LSEEnvelope,
|
|
40
|
+
} from '@lokascript/intent';
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
createLiteral,
|
|
44
|
+
createSelector,
|
|
45
|
+
createReference,
|
|
46
|
+
createPropertyPath,
|
|
47
|
+
createExpression,
|
|
48
|
+
createFlag,
|
|
49
|
+
createCommandNode,
|
|
50
|
+
createEventHandlerNode,
|
|
51
|
+
createConditionalNode,
|
|
52
|
+
createCompoundNode,
|
|
53
|
+
createLoopNode,
|
|
54
|
+
createTryNode,
|
|
55
|
+
createAsyncNode,
|
|
56
|
+
createMatchNode,
|
|
57
|
+
extractValue,
|
|
58
|
+
extractRoleValue,
|
|
59
|
+
getRoleValue,
|
|
60
|
+
} from '@lokascript/intent';
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// Framework-specific types (multilingual DSL infrastructure)
|
|
64
|
+
// =============================================================================
|
|
65
|
+
|
|
66
|
+
import type {
|
|
67
|
+
ActionType,
|
|
68
|
+
SemanticRole,
|
|
69
|
+
SemanticValue,
|
|
70
|
+
SelectorValue,
|
|
71
|
+
ExpectedType,
|
|
72
|
+
SourcePosition,
|
|
73
|
+
} from '@lokascript/intent';
|
|
270
74
|
|
|
271
75
|
/**
|
|
272
76
|
* Token kind - categorizes what type of token this is.
|
|
@@ -290,13 +94,9 @@ export interface LanguageToken {
|
|
|
290
94
|
readonly value: string;
|
|
291
95
|
readonly kind: TokenKind;
|
|
292
96
|
readonly position: SourcePosition;
|
|
293
|
-
/** Normalized form from explicit keyword map */
|
|
294
97
|
readonly normalized?: string;
|
|
295
|
-
/** Morphologically normalized stem */
|
|
296
98
|
readonly stem?: string;
|
|
297
|
-
/** Confidence in the morphological stem (0.0-1.0) */
|
|
298
99
|
readonly stemConfidence?: number;
|
|
299
|
-
/** Additional metadata for specific token types */
|
|
300
100
|
readonly metadata?: Record<string, unknown>;
|
|
301
101
|
}
|
|
302
102
|
|
|
@@ -306,29 +106,14 @@ export interface LanguageToken {
|
|
|
306
106
|
export interface TokenStream {
|
|
307
107
|
readonly tokens: readonly LanguageToken[];
|
|
308
108
|
readonly language: string;
|
|
309
|
-
|
|
310
|
-
/** Look at token at current position + offset without consuming */
|
|
311
109
|
peek(offset?: number): LanguageToken | null;
|
|
312
|
-
|
|
313
|
-
/** Consume and return current token, advance position */
|
|
314
110
|
advance(): LanguageToken;
|
|
315
|
-
|
|
316
|
-
/** Check if we've consumed all tokens */
|
|
317
111
|
isAtEnd(): boolean;
|
|
318
|
-
|
|
319
|
-
/** Save current position for backtracking */
|
|
320
112
|
mark(): StreamMark;
|
|
321
|
-
|
|
322
|
-
/** Restore to a saved position */
|
|
323
113
|
reset(mark: StreamMark): void;
|
|
324
|
-
|
|
325
|
-
/** Get current position */
|
|
326
114
|
position(): number;
|
|
327
115
|
}
|
|
328
116
|
|
|
329
|
-
/**
|
|
330
|
-
* Stream mark for backtracking during parsing.
|
|
331
|
-
*/
|
|
332
117
|
export interface StreamMark {
|
|
333
118
|
readonly position: number;
|
|
334
119
|
}
|
|
@@ -339,11 +124,7 @@ export interface StreamMark {
|
|
|
339
124
|
export interface LanguageTokenizer {
|
|
340
125
|
readonly language: string;
|
|
341
126
|
readonly direction: 'ltr' | 'rtl';
|
|
342
|
-
|
|
343
|
-
/** Convert input string to token stream */
|
|
344
127
|
tokenize(input: string): TokenStream;
|
|
345
|
-
|
|
346
|
-
/** Classify a single token */
|
|
347
128
|
classifyToken(token: string): TokenKind;
|
|
348
129
|
}
|
|
349
130
|
|
|
@@ -351,45 +132,26 @@ export interface LanguageTokenizer {
|
|
|
351
132
|
// Pattern Matching Types
|
|
352
133
|
// =============================================================================
|
|
353
134
|
|
|
354
|
-
/**
|
|
355
|
-
* A language pattern defines how a semantic structure appears in a specific language.
|
|
356
|
-
*/
|
|
357
135
|
export interface LanguagePattern {
|
|
358
|
-
/** Unique identifier for this pattern */
|
|
359
136
|
readonly id: string;
|
|
360
|
-
/** ISO 639-1 language code */
|
|
361
137
|
readonly language: string;
|
|
362
|
-
/** Which command this pattern matches */
|
|
363
138
|
readonly command: ActionType;
|
|
364
|
-
/** Priority for disambiguation (higher = checked first) */
|
|
365
139
|
readonly priority: number;
|
|
366
|
-
/** The pattern template with role placeholders */
|
|
367
140
|
readonly template: PatternTemplate;
|
|
368
|
-
/** Rules for extracting semantic roles from matched tokens */
|
|
369
141
|
readonly extraction: ExtractionRules;
|
|
370
|
-
/** Optional constraints on when this pattern applies */
|
|
371
142
|
readonly constraints?: PatternConstraints;
|
|
372
143
|
}
|
|
373
144
|
|
|
374
|
-
/**
|
|
375
|
-
* Pattern template - defines expected token sequence.
|
|
376
|
-
*/
|
|
377
145
|
export interface PatternTemplate {
|
|
378
|
-
/** Human-readable template string */
|
|
379
146
|
readonly format: string;
|
|
380
|
-
/** Parsed token sequence for matching */
|
|
381
147
|
readonly tokens: PatternToken[];
|
|
382
148
|
}
|
|
383
149
|
|
|
384
|
-
/**
|
|
385
|
-
* Pattern token - literal, role placeholder, or group.
|
|
386
|
-
*/
|
|
387
150
|
export type PatternToken = LiteralPatternToken | RolePatternToken | GroupPatternToken;
|
|
388
151
|
|
|
389
152
|
export interface LiteralPatternToken {
|
|
390
153
|
readonly type: 'literal';
|
|
391
154
|
readonly value: string;
|
|
392
|
-
/** Alternative spellings/forms that also match */
|
|
393
155
|
readonly alternatives?: string[];
|
|
394
156
|
}
|
|
395
157
|
|
|
@@ -397,9 +159,7 @@ export interface RolePatternToken {
|
|
|
397
159
|
readonly type: 'role';
|
|
398
160
|
readonly role: SemanticRole;
|
|
399
161
|
readonly optional?: boolean;
|
|
400
|
-
/** Expected value types (for validation) */
|
|
401
162
|
readonly expectedTypes?: Array<ExpectedType>;
|
|
402
|
-
/** When true, captures all remaining tokens until next marker or end */
|
|
403
163
|
readonly greedy?: boolean;
|
|
404
164
|
}
|
|
405
165
|
|
|
@@ -409,326 +169,37 @@ export interface GroupPatternToken {
|
|
|
409
169
|
readonly optional?: boolean;
|
|
410
170
|
}
|
|
411
171
|
|
|
412
|
-
/**
|
|
413
|
-
* Rules for extracting semantic values from matched tokens.
|
|
414
|
-
*/
|
|
415
172
|
export interface ExtractionRules {
|
|
416
173
|
readonly [role: string]: ExtractionRule;
|
|
417
174
|
}
|
|
418
175
|
|
|
419
176
|
export interface ExtractionRule {
|
|
420
|
-
/** Position-based extraction (0-indexed from pattern start) */
|
|
421
177
|
readonly position?: number;
|
|
422
|
-
/** Marker-based extraction (find value after this marker) */
|
|
423
178
|
readonly marker?: string;
|
|
424
|
-
/** Alternative markers that also work */
|
|
425
179
|
readonly markerAlternatives?: string[];
|
|
426
|
-
/** Transform the extracted value */
|
|
427
180
|
readonly transform?: (raw: string) => SemanticValue;
|
|
428
|
-
/** Default value if not found (for optional roles) */
|
|
429
181
|
readonly default?: SemanticValue;
|
|
430
|
-
/** Static value extraction */
|
|
431
182
|
readonly value?: string;
|
|
432
|
-
/** Extract value from a pattern role by name */
|
|
433
183
|
readonly fromRole?: string;
|
|
434
184
|
}
|
|
435
185
|
|
|
436
|
-
/**
|
|
437
|
-
* Additional constraints on pattern applicability.
|
|
438
|
-
*/
|
|
439
186
|
export interface PatternConstraints {
|
|
440
|
-
/** Required roles that must be present */
|
|
441
187
|
readonly requiredRoles?: SemanticRole[];
|
|
442
|
-
/** Roles that must NOT be present */
|
|
443
188
|
readonly forbiddenRoles?: SemanticRole[];
|
|
444
|
-
/** Valid selector types for the patient role */
|
|
445
189
|
readonly validPatientTypes?: Array<SelectorValue['selectorKind']>;
|
|
446
|
-
/** Pattern IDs this conflicts with */
|
|
447
190
|
readonly conflictsWith?: string[];
|
|
448
191
|
}
|
|
449
192
|
|
|
450
|
-
/**
|
|
451
|
-
* Result of matching a pattern against tokens.
|
|
452
|
-
*/
|
|
453
193
|
export interface PatternMatchResult {
|
|
454
194
|
readonly pattern: LanguagePattern;
|
|
455
195
|
readonly captured: ReadonlyMap<SemanticRole, SemanticValue>;
|
|
456
196
|
readonly consumedTokens: number;
|
|
457
|
-
readonly confidence: number;
|
|
197
|
+
readonly confidence: number;
|
|
458
198
|
}
|
|
459
199
|
|
|
460
|
-
/**
|
|
461
|
-
* Error when pattern matching fails.
|
|
462
|
-
*/
|
|
463
200
|
export interface PatternMatchError {
|
|
464
201
|
readonly message: string;
|
|
465
202
|
readonly position: SourcePosition;
|
|
466
203
|
readonly expectedPatterns?: string[];
|
|
467
204
|
readonly partialMatch?: Partial<PatternMatchResult>;
|
|
468
205
|
}
|
|
469
|
-
|
|
470
|
-
// =============================================================================
|
|
471
|
-
// Helper Functions
|
|
472
|
-
// =============================================================================
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Create a literal value
|
|
476
|
-
*/
|
|
477
|
-
export function createLiteral(
|
|
478
|
-
value: string | number | boolean,
|
|
479
|
-
dataType?: 'string' | 'number' | 'boolean' | 'duration'
|
|
480
|
-
): LiteralValue {
|
|
481
|
-
return dataType ? { type: 'literal', value, dataType } : { type: 'literal', value };
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* Create a selector value
|
|
486
|
-
*/
|
|
487
|
-
export function createSelector(
|
|
488
|
-
value: string,
|
|
489
|
-
selectorKind?: SelectorValue['selectorKind']
|
|
490
|
-
): SelectorValue {
|
|
491
|
-
return selectorKind ? { type: 'selector', value, selectorKind } : { type: 'selector', value };
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Create a reference value
|
|
496
|
-
*/
|
|
497
|
-
export function createReference(value: string): ReferenceValue {
|
|
498
|
-
return { type: 'reference', value };
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Create a property path value
|
|
503
|
-
*/
|
|
504
|
-
export function createPropertyPath(object: SemanticValue, property: string): PropertyPathValue {
|
|
505
|
-
return { type: 'property-path', object, property };
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Create an expression value
|
|
510
|
-
*/
|
|
511
|
-
export function createExpression(raw: string): ExpressionValue {
|
|
512
|
-
return { type: 'expression', raw };
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* Create a boolean flag value (+flag or ~flag)
|
|
517
|
-
*/
|
|
518
|
-
export function createFlag(name: string, enabled: boolean = true): FlagValue {
|
|
519
|
-
return { type: 'flag', name, enabled };
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* Create a command semantic node
|
|
524
|
-
*/
|
|
525
|
-
export function createCommandNode(
|
|
526
|
-
action: ActionType,
|
|
527
|
-
roles: Record<SemanticRole, SemanticValue> | Map<SemanticRole, SemanticValue>,
|
|
528
|
-
metadata?: SemanticMetadata
|
|
529
|
-
): CommandSemanticNode {
|
|
530
|
-
const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
|
|
531
|
-
const node: CommandSemanticNode = {
|
|
532
|
-
kind: 'command',
|
|
533
|
-
action,
|
|
534
|
-
roles: rolesMap,
|
|
535
|
-
};
|
|
536
|
-
if (metadata) {
|
|
537
|
-
return { ...node, metadata };
|
|
538
|
-
}
|
|
539
|
-
return node;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Create an event handler semantic node
|
|
544
|
-
*/
|
|
545
|
-
export function createEventHandlerNode(
|
|
546
|
-
action: ActionType,
|
|
547
|
-
roles: Record<SemanticRole, SemanticValue> | Map<SemanticRole, SemanticValue>,
|
|
548
|
-
body: SemanticNode[],
|
|
549
|
-
metadata?: SemanticMetadata,
|
|
550
|
-
eventModifiers?: EventModifiers
|
|
551
|
-
): EventHandlerSemanticNode {
|
|
552
|
-
const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
|
|
553
|
-
const base = {
|
|
554
|
-
kind: 'event-handler' as const,
|
|
555
|
-
action,
|
|
556
|
-
roles: rolesMap,
|
|
557
|
-
body,
|
|
558
|
-
};
|
|
559
|
-
return {
|
|
560
|
-
...base,
|
|
561
|
-
...(eventModifiers && { eventModifiers }),
|
|
562
|
-
...(metadata && { metadata }),
|
|
563
|
-
};
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* Create a conditional semantic node
|
|
568
|
-
*/
|
|
569
|
-
export function createConditionalNode(
|
|
570
|
-
action: ActionType,
|
|
571
|
-
roles: Record<SemanticRole, SemanticValue> | Map<SemanticRole, SemanticValue>,
|
|
572
|
-
thenBranch: SemanticNode[],
|
|
573
|
-
elseBranch?: SemanticNode[],
|
|
574
|
-
metadata?: SemanticMetadata
|
|
575
|
-
): ConditionalSemanticNode {
|
|
576
|
-
const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
|
|
577
|
-
const base = {
|
|
578
|
-
kind: 'conditional' as const,
|
|
579
|
-
action,
|
|
580
|
-
roles: rolesMap,
|
|
581
|
-
thenBranch,
|
|
582
|
-
};
|
|
583
|
-
return {
|
|
584
|
-
...base,
|
|
585
|
-
...(elseBranch && { elseBranch }),
|
|
586
|
-
...(metadata && { metadata }),
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* Create a compound semantic node
|
|
592
|
-
*/
|
|
593
|
-
export function createCompoundNode(
|
|
594
|
-
statements: SemanticNode[],
|
|
595
|
-
chainType: CompoundSemanticNode['chainType'] = 'sequential',
|
|
596
|
-
metadata?: SemanticMetadata
|
|
597
|
-
): CompoundSemanticNode {
|
|
598
|
-
const base = {
|
|
599
|
-
kind: 'compound' as const,
|
|
600
|
-
action: 'compound' as const,
|
|
601
|
-
roles: new Map(),
|
|
602
|
-
statements,
|
|
603
|
-
chainType,
|
|
604
|
-
};
|
|
605
|
-
return metadata ? { ...base, metadata } : base;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
/**
|
|
609
|
-
* Extract a string value from a SemanticValue.
|
|
610
|
-
*
|
|
611
|
-
* Handles all value types in the SemanticValue union:
|
|
612
|
-
* - ExpressionValue: returns `raw`
|
|
613
|
-
* - LiteralValue/SelectorValue/ReferenceValue: returns `value` as string
|
|
614
|
-
* - PropertyPathValue: returns `object.property` path
|
|
615
|
-
*
|
|
616
|
-
* This is the standard way to get a display string from any semantic value,
|
|
617
|
-
* eliminating the need for `as any` casts in domain code generators.
|
|
618
|
-
*/
|
|
619
|
-
export function extractValue(value: SemanticValue): string {
|
|
620
|
-
if (value.type === 'flag') return value.name;
|
|
621
|
-
if ('raw' in value && value.raw !== undefined) return String(value.raw);
|
|
622
|
-
if ('value' in value && value.value !== undefined) return String(value.value);
|
|
623
|
-
if (value.type === 'property-path') return `${extractValue(value.object)}.${value.property}`;
|
|
624
|
-
return '';
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
/**
|
|
628
|
-
* Extract a string value from a named role on a SemanticNode.
|
|
629
|
-
*
|
|
630
|
-
* Convenience wrapper: looks up the role, returns empty string if missing.
|
|
631
|
-
* Eliminates the common `const x = node.roles.get('role'); const val = x ? extractValue(x as any) : '';` pattern.
|
|
632
|
-
*/
|
|
633
|
-
export function extractRoleValue(node: SemanticNode, role: string): string {
|
|
634
|
-
const value = node.roles.get(role);
|
|
635
|
-
if (!value) return '';
|
|
636
|
-
return extractValue(value);
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
/**
|
|
640
|
-
* Create a loop semantic node
|
|
641
|
-
*/
|
|
642
|
-
export function createLoopNode(
|
|
643
|
-
action: ActionType,
|
|
644
|
-
roles: Record<SemanticRole, SemanticValue> | Map<SemanticRole, SemanticValue>,
|
|
645
|
-
loopVariant: LoopVariant,
|
|
646
|
-
body: SemanticNode[],
|
|
647
|
-
loopVariable?: string,
|
|
648
|
-
indexVariable?: string,
|
|
649
|
-
metadata?: SemanticMetadata
|
|
650
|
-
): LoopSemanticNode {
|
|
651
|
-
const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
|
|
652
|
-
const base = {
|
|
653
|
-
kind: 'loop' as const,
|
|
654
|
-
action,
|
|
655
|
-
roles: rolesMap,
|
|
656
|
-
loopVariant,
|
|
657
|
-
body,
|
|
658
|
-
};
|
|
659
|
-
return {
|
|
660
|
-
...base,
|
|
661
|
-
...(loopVariable && { loopVariable }),
|
|
662
|
-
...(indexVariable && { indexVariable }),
|
|
663
|
-
...(metadata && { metadata }),
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// =============================================================================
|
|
668
|
-
// v1.2 Factory Helpers
|
|
669
|
-
// =============================================================================
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
* Create a try/catch/finally command node (v1.2).
|
|
673
|
-
*/
|
|
674
|
-
export function createTryNode(
|
|
675
|
-
body: SemanticNode[],
|
|
676
|
-
catchBranch?: SemanticNode[],
|
|
677
|
-
finallyBranch?: SemanticNode[],
|
|
678
|
-
metadata?: SemanticMetadata
|
|
679
|
-
): CommandSemanticNode {
|
|
680
|
-
return {
|
|
681
|
-
kind: 'command',
|
|
682
|
-
action: 'try',
|
|
683
|
-
roles: new Map(),
|
|
684
|
-
body,
|
|
685
|
-
...(catchBranch && catchBranch.length > 0 ? { catchBranch } : {}),
|
|
686
|
-
...(finallyBranch && finallyBranch.length > 0 ? { finallyBranch } : {}),
|
|
687
|
-
...(metadata ? { metadata } : {}),
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
/**
|
|
692
|
-
* Create an async coordination (all/race) command node (v1.2).
|
|
693
|
-
*/
|
|
694
|
-
export function createAsyncNode(
|
|
695
|
-
variant: AsyncVariant,
|
|
696
|
-
asyncBody: SemanticNode[],
|
|
697
|
-
metadata?: SemanticMetadata
|
|
698
|
-
): CommandSemanticNode {
|
|
699
|
-
return {
|
|
700
|
-
kind: 'command',
|
|
701
|
-
action: variant,
|
|
702
|
-
roles: new Map(),
|
|
703
|
-
asyncVariant: variant,
|
|
704
|
-
asyncBody,
|
|
705
|
-
...(metadata ? { metadata } : {}),
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
/**
|
|
710
|
-
* Create a match command node with pattern arms (v1.2).
|
|
711
|
-
*/
|
|
712
|
-
export function createMatchNode(
|
|
713
|
-
roles: Record<SemanticRole, SemanticValue> | Map<SemanticRole, SemanticValue>,
|
|
714
|
-
arms: MatchArm[],
|
|
715
|
-
defaultArm?: SemanticNode[],
|
|
716
|
-
metadata?: SemanticMetadata
|
|
717
|
-
): CommandSemanticNode {
|
|
718
|
-
const rolesMap = roles instanceof Map ? roles : new Map(Object.entries(roles));
|
|
719
|
-
return {
|
|
720
|
-
kind: 'command',
|
|
721
|
-
action: 'match',
|
|
722
|
-
roles: rolesMap,
|
|
723
|
-
arms,
|
|
724
|
-
...(defaultArm && defaultArm.length > 0 ? { defaultArm } : {}),
|
|
725
|
-
...(metadata ? { metadata } : {}),
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
/** Wire format envelope with version metadata (v1.2). */
|
|
730
|
-
export interface LSEEnvelope {
|
|
731
|
-
readonly lseVersion: string;
|
|
732
|
-
readonly features?: readonly string[];
|
|
733
|
-
readonly nodes: readonly SemanticNode[];
|
|
734
|
-
}
|