solve-engine 1.0.0-beta.0 → 1.0.0-beta.2
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/BytecodeBuilder-3egMyuDi.d.cts +274 -0
- package/dist/BytecodeBuilder-3egMyuDi.d.ts +274 -0
- package/dist/Configuration-fVpd-HC-.d.cts +228 -0
- package/dist/Configuration-fVpd-HC-.d.ts +228 -0
- package/dist/EngineError-DvPSnhZi.d.cts +304 -0
- package/dist/EngineError-DvPSnhZi.d.ts +304 -0
- package/dist/Lexer-BJdhlnej.d.cts +531 -0
- package/dist/Lexer-D9l4Yrk2.d.ts +531 -0
- package/dist/NormalizerRule-BrVoVjmP.d.cts +163 -0
- package/dist/NormalizerRule-CEjf1FyD.d.ts +163 -0
- package/dist/PackageRegistry-D-Tv_7ca.d.cts +2572 -0
- package/dist/PackageRegistry-DaH4aIKP.d.ts +2572 -0
- package/dist/Parselet-CK8cQu2a.d.cts +299 -0
- package/dist/Parselet-ConOIdRO.d.ts +299 -0
- package/dist/ScopeManager-B5k0nk05.d.ts +559 -0
- package/dist/ScopeManager-CKfQtl7l.d.cts +559 -0
- package/dist/Token-0jpvUdPY.d.cts +245 -0
- package/dist/Token-0jpvUdPY.d.ts +245 -0
- package/dist/VMCheckpoints-BmDwIXgK.d.ts +171 -0
- package/dist/VMCheckpoints-CqFuLwrT.d.cts +171 -0
- package/dist/Value-KtAQNHur.d.cts +295 -0
- package/dist/Value-KtAQNHur.d.ts +295 -0
- package/dist/chunk-2RWAXT6O.js +3 -0
- package/dist/chunk-2RWAXT6O.js.map +1 -0
- package/dist/chunk-34RRD7PC.js +1492 -0
- package/dist/chunk-34RRD7PC.js.map +1 -0
- package/dist/chunk-3PPFLFH4.js +5097 -0
- package/dist/chunk-3PPFLFH4.js.map +1 -0
- package/dist/chunk-3VGDNEE3.js +84 -0
- package/dist/chunk-3VGDNEE3.js.map +1 -0
- package/dist/chunk-3YNVWKR2.cjs +370 -0
- package/dist/chunk-3YNVWKR2.cjs.map +1 -0
- package/dist/chunk-47LRVGOT.cjs +316 -0
- package/dist/chunk-47LRVGOT.cjs.map +1 -0
- package/dist/chunk-4MG4XKO2.js +1644 -0
- package/dist/chunk-4MG4XKO2.js.map +1 -0
- package/dist/chunk-4QADQTWS.js +2392 -0
- package/dist/chunk-4QADQTWS.js.map +1 -0
- package/dist/chunk-53B6KDDJ.cjs +1651 -0
- package/dist/chunk-53B6KDDJ.cjs.map +1 -0
- package/dist/chunk-5X2PTP6F.cjs +104 -0
- package/dist/chunk-5X2PTP6F.cjs.map +1 -0
- package/dist/chunk-5YEMOYSE.js +264 -0
- package/dist/chunk-5YEMOYSE.js.map +1 -0
- package/dist/chunk-64W6GLLZ.js +481 -0
- package/dist/chunk-64W6GLLZ.js.map +1 -0
- package/dist/chunk-6BKTCEUP.cjs +233 -0
- package/dist/chunk-6BKTCEUP.cjs.map +1 -0
- package/dist/chunk-6NTVRDQV.cjs +1642 -0
- package/dist/chunk-6NTVRDQV.cjs.map +1 -0
- package/dist/chunk-6RDSQURE.js +290 -0
- package/dist/chunk-6RDSQURE.js.map +1 -0
- package/dist/chunk-75JP4BZX.js +93 -0
- package/dist/chunk-75JP4BZX.js.map +1 -0
- package/dist/chunk-B7LXJ6LC.cjs +36 -0
- package/dist/chunk-B7LXJ6LC.cjs.map +1 -0
- package/dist/chunk-BVAR5J2F.js +257 -0
- package/dist/chunk-BVAR5J2F.js.map +1 -0
- package/dist/chunk-C4XZV6E7.cjs +269 -0
- package/dist/chunk-C4XZV6E7.cjs.map +1 -0
- package/dist/chunk-CCJPSHGI.cjs +40 -0
- package/dist/chunk-CCJPSHGI.cjs.map +1 -0
- package/dist/chunk-CLL7RUQV.cjs +316 -0
- package/dist/chunk-CLL7RUQV.cjs.map +1 -0
- package/dist/chunk-DM3LMRBC.js +329 -0
- package/dist/chunk-DM3LMRBC.js.map +1 -0
- package/dist/chunk-DUEZFTK2.js +38 -0
- package/dist/chunk-DUEZFTK2.js.map +1 -0
- package/dist/chunk-EBSPLUW4.cjs +489 -0
- package/dist/chunk-EBSPLUW4.cjs.map +1 -0
- package/dist/chunk-EHAHVROS.cjs +261 -0
- package/dist/chunk-EHAHVROS.cjs.map +1 -0
- package/dist/chunk-EIGTWK5N.js +167 -0
- package/dist/chunk-EIGTWK5N.js.map +1 -0
- package/dist/chunk-EPOXXJBK.js +96 -0
- package/dist/chunk-EPOXXJBK.js.map +1 -0
- package/dist/chunk-FEAIOR7N.cjs +91 -0
- package/dist/chunk-FEAIOR7N.cjs.map +1 -0
- package/dist/chunk-G535KJEG.js +312 -0
- package/dist/chunk-G535KJEG.js.map +1 -0
- package/dist/chunk-GCM5JHMX.js +88 -0
- package/dist/chunk-GCM5JHMX.js.map +1 -0
- package/dist/chunk-GOLDJNMZ.js +368 -0
- package/dist/chunk-GOLDJNMZ.js.map +1 -0
- package/dist/chunk-GW32KPCU.cjs +360 -0
- package/dist/chunk-GW32KPCU.cjs.map +1 -0
- package/dist/chunk-HTXVVJRA.cjs +1549 -0
- package/dist/chunk-HTXVVJRA.cjs.map +1 -0
- package/dist/chunk-HWSZJQCI.js +311 -0
- package/dist/chunk-HWSZJQCI.js.map +1 -0
- package/dist/chunk-IF532O7C.js +101 -0
- package/dist/chunk-IF532O7C.js.map +1 -0
- package/dist/chunk-J73SJHR3.cjs +2415 -0
- package/dist/chunk-J73SJHR3.cjs.map +1 -0
- package/dist/chunk-JBSYC7BB.cjs +7473 -0
- package/dist/chunk-JBSYC7BB.cjs.map +1 -0
- package/dist/chunk-KVILKGMS.js +228 -0
- package/dist/chunk-KVILKGMS.js.map +1 -0
- package/dist/chunk-LIPPNDBE.js +258 -0
- package/dist/chunk-LIPPNDBE.js.map +1 -0
- package/dist/chunk-LR7YASZF.cjs +172 -0
- package/dist/chunk-LR7YASZF.cjs.map +1 -0
- package/dist/chunk-M4N5GA5Z.cjs +309 -0
- package/dist/chunk-M4N5GA5Z.cjs.map +1 -0
- package/dist/chunk-M5LX5AOO.js +7459 -0
- package/dist/chunk-M5LX5AOO.js.map +1 -0
- package/dist/chunk-MZOVP3WI.cjs +96 -0
- package/dist/chunk-MZOVP3WI.cjs.map +1 -0
- package/dist/chunk-N5YFR4UP.cjs +10 -0
- package/dist/chunk-N5YFR4UP.cjs.map +1 -0
- package/dist/chunk-NGBBNL4K.cjs +4 -0
- package/dist/chunk-NGBBNL4K.cjs.map +1 -0
- package/dist/chunk-NH2O2AUR.js +146 -0
- package/dist/chunk-NH2O2AUR.js.map +1 -0
- package/dist/chunk-NLNDMWZC.js +31 -0
- package/dist/chunk-NLNDMWZC.js.map +1 -0
- package/dist/chunk-NMCRQP3Z.cjs +778 -0
- package/dist/chunk-NMCRQP3Z.cjs.map +1 -0
- package/dist/chunk-NMD5VRN4.cjs +1327 -0
- package/dist/chunk-NMD5VRN4.cjs.map +1 -0
- package/dist/chunk-OC6LTXYS.cjs +286 -0
- package/dist/chunk-OC6LTXYS.cjs.map +1 -0
- package/dist/chunk-OT6OJY7C.cjs +114 -0
- package/dist/chunk-OT6OJY7C.cjs.map +1 -0
- package/dist/chunk-PFSDGGYL.js +8 -0
- package/dist/chunk-PFSDGGYL.js.map +1 -0
- package/dist/chunk-QNJ4ACRT.cjs +155 -0
- package/dist/chunk-QNJ4ACRT.cjs.map +1 -0
- package/dist/chunk-QWY3VEZN.js +1637 -0
- package/dist/chunk-QWY3VEZN.js.map +1 -0
- package/dist/chunk-RFYD5TJE.js +111 -0
- package/dist/chunk-RFYD5TJE.js.map +1 -0
- package/dist/chunk-RIN643A3.js +354 -0
- package/dist/chunk-RIN643A3.js.map +1 -0
- package/dist/chunk-RZCWSXTA.cjs +5122 -0
- package/dist/chunk-RZCWSXTA.cjs.map +1 -0
- package/dist/chunk-SDGRK7EP.js +774 -0
- package/dist/chunk-SDGRK7EP.js.map +1 -0
- package/dist/chunk-VEKIWQ3F.cjs +39 -0
- package/dist/chunk-VEKIWQ3F.cjs.map +1 -0
- package/dist/chunk-WQTTOGXC.cjs +99 -0
- package/dist/chunk-WQTTOGXC.cjs.map +1 -0
- package/dist/chunk-X6K3HUOY.cjs +86 -0
- package/dist/chunk-X6K3HUOY.cjs.map +1 -0
- package/dist/chunk-XJCMXB2E.cjs +333 -0
- package/dist/chunk-XJCMXB2E.cjs.map +1 -0
- package/dist/chunk-XVWCOTR6.js +1324 -0
- package/dist/chunk-XVWCOTR6.js.map +1 -0
- package/dist/chunk-YLJ4XMA6.js +33 -0
- package/dist/chunk-YLJ4XMA6.js.map +1 -0
- package/dist/chunk-Z2XP767T.cjs +35 -0
- package/dist/chunk-Z2XP767T.cjs.map +1 -0
- package/dist/chunk-Z4X2RWOF.js +37 -0
- package/dist/chunk-Z4X2RWOF.js.map +1 -0
- package/dist/constants.cjs +22 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +12 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/engine.cjs +79 -0
- package/dist/engine.cjs.map +1 -0
- package/dist/engine.d.cts +587 -0
- package/dist/engine.d.ts +587 -0
- package/dist/engine.js +34 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.cjs +81 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +95 -0
- package/dist/errors.d.ts +95 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/format.cjs +171 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.cts +51 -0
- package/dist/format.d.ts +51 -0
- package/dist/format.js +168 -0
- package/dist/format.js.map +1 -0
- package/dist/index.cjs +97 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +152 -0
- package/dist/index.d.ts +152 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/language.cjs +308 -0
- package/dist/language.cjs.map +1 -0
- package/dist/language.d.cts +110 -0
- package/dist/language.d.ts +110 -0
- package/dist/language.js +287 -0
- package/dist/language.js.map +1 -0
- package/dist/lexer.cjs +64 -0
- package/dist/lexer.cjs.map +1 -0
- package/dist/lexer.d.cts +56 -0
- package/dist/lexer.d.ts +56 -0
- package/dist/lexer.js +11 -0
- package/dist/lexer.js.map +1 -0
- package/dist/normalizer.cjs +40 -0
- package/dist/normalizer.cjs.map +1 -0
- package/dist/normalizer.d.cts +364 -0
- package/dist/normalizer.d.ts +364 -0
- package/dist/normalizer.js +11 -0
- package/dist/normalizer.js.map +1 -0
- package/dist/packages.cjs +121 -0
- package/dist/packages.cjs.map +1 -0
- package/dist/packages.d.cts +691 -0
- package/dist/packages.d.ts +691 -0
- package/dist/packages.js +24 -0
- package/dist/packages.js.map +1 -0
- package/dist/parser.cjs +55 -0
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +46 -0
- package/dist/parser.d.ts +46 -0
- package/dist/parser.js +10 -0
- package/dist/parser.js.map +1 -0
- package/dist/pipeline-CrsRPmsv.d.ts +285 -0
- package/dist/pipeline-DPUQt7yL.d.cts +285 -0
- package/dist/resolvers.cjs +13 -0
- package/dist/resolvers.cjs.map +1 -0
- package/dist/resolvers.d.cts +111 -0
- package/dist/resolvers.d.ts +111 -0
- package/dist/resolvers.js +4 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/services.cjs +21 -0
- package/dist/services.cjs.map +1 -0
- package/dist/services.d.cts +30 -0
- package/dist/services.d.ts +30 -0
- package/dist/services.js +4 -0
- package/dist/services.js.map +1 -0
- package/dist/uom.cjs +56 -0
- package/dist/uom.cjs.map +1 -0
- package/dist/uom.d.cts +224 -0
- package/dist/uom.d.ts +224 -0
- package/dist/uom.js +11 -0
- package/dist/uom.js.map +1 -0
- package/dist/utilities.cjs +32 -0
- package/dist/utilities.cjs.map +1 -0
- package/dist/utilities.d.cts +113 -0
- package/dist/utilities.d.ts +113 -0
- package/dist/utilities.js +7 -0
- package/dist/utilities.js.map +1 -0
- package/dist/variables.cjs +17 -0
- package/dist/variables.cjs.map +1 -0
- package/dist/variables.d.cts +87 -0
- package/dist/variables.d.ts +87 -0
- package/dist/variables.js +4 -0
- package/dist/variables.js.map +1 -0
- package/dist/vm.cjs +284 -0
- package/dist/vm.cjs.map +1 -0
- package/dist/vm.d.cts +68 -0
- package/dist/vm.d.ts +68 -0
- package/dist/vm.js +194 -0
- package/dist/vm.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { T as Token } from './Token-0jpvUdPY.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NormalizerRule, pluggable token normalization rule for the
|
|
5
|
+
* TokenNormalizer post-lexer pass.
|
|
6
|
+
*
|
|
7
|
+
* ## Purpose
|
|
8
|
+
* After the ExpressionLexer produces raw tokens (numbers, identifiers,
|
|
9
|
+
* operators, etc.), the TokenNormalizer applies domain-specific rules
|
|
10
|
+
* to transform the token stream before parsing. This keeps the lexer
|
|
11
|
+
* focused on single-token production and moves multi-token pattern
|
|
12
|
+
* matching into a dedicated normalization layer.
|
|
13
|
+
*
|
|
14
|
+
* ## How rules work
|
|
15
|
+
* Rules are applied in priority order (highest first). At each token
|
|
16
|
+
* position, the normalizer tries every rule in priority order until one
|
|
17
|
+
* matches. Matched tokens are consumed and replaced; unmatched tokens
|
|
18
|
+
* pass through unchanged.
|
|
19
|
+
*
|
|
20
|
+
* ## What rules can do
|
|
21
|
+
* - **Phrase fusion**: Merge consecutive words into compound tokens
|
|
22
|
+
* (e.g., `"to" "the" "power" "of"` → `CARET`)
|
|
23
|
+
* - **Implicit operators**: Insert missing operators between tokens
|
|
24
|
+
* (e.g., `NUMBER IDENT` → `NUMBER STAR IDENT`)
|
|
25
|
+
* - **Domain transformations**: Coalesce item names, currency pairs, etc.
|
|
26
|
+
*
|
|
27
|
+
* ## Why a separate file?
|
|
28
|
+
* This is a duplicate-free copy of the interface defined in
|
|
29
|
+
* TokenNormalizer.ts. Storing it in a separate file avoids circular
|
|
30
|
+
* imports, TokenNormalizer imports NormalizerRule, and rule factories
|
|
31
|
+
* import TokenNormalizer's `createFusedToken`.
|
|
32
|
+
*
|
|
33
|
+
* @module NormalizerRule
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Result of a successful rule match attempt against the token stream.
|
|
38
|
+
*
|
|
39
|
+
* When a {@link NormalizerRule.match} function finds a pattern at the
|
|
40
|
+
* current position, it returns a NormalizerMatch describing how many
|
|
41
|
+
* tokens to consume and what to replace them with.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // The phrase "to the power of" (5 tokens) becomes a single CARET token
|
|
46
|
+
* const match: NormalizerMatch = {
|
|
47
|
+
* consumed: 5,
|
|
48
|
+
* replacement: [caretToken],
|
|
49
|
+
* };
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
interface NormalizerMatch {
|
|
53
|
+
/**
|
|
54
|
+
* Number of tokens consumed from the stream at the match position.
|
|
55
|
+
* Must be ≥ 1, a match always advances the cursor.
|
|
56
|
+
*/
|
|
57
|
+
consumed: number;
|
|
58
|
+
/**
|
|
59
|
+
* Replacement tokens to insert at the match position.
|
|
60
|
+
* May be empty (deletion), a single token (fusion), or multiple
|
|
61
|
+
* tokens (expansion/splitting).
|
|
62
|
+
*/
|
|
63
|
+
replacement: Token[];
|
|
64
|
+
/**
|
|
65
|
+
* Human-readable rule name for diagnostic fusion tracking.
|
|
66
|
+
* When set, the normalizer uses this instead of the rule's `name`
|
|
67
|
+
* in {@link TokenFusion} records. Used by {@link PhraseTrie} to
|
|
68
|
+
* report which specific phrase matched (e.g., "phrase:to the power of").
|
|
69
|
+
*/
|
|
70
|
+
ruleName?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A pluggable normalization rule registered with the TokenNormalizer.
|
|
74
|
+
*
|
|
75
|
+
* Each rule has a {@link name}, {@link priority}, and {@link match} function.
|
|
76
|
+
* The match function receives the current token stream and a position,
|
|
77
|
+
* and returns a {@link NormalizerMatch} on success or `null` on failure.
|
|
78
|
+
*
|
|
79
|
+
* ## Priority ordering
|
|
80
|
+
* Higher priority rules are tried first at each position. This allows
|
|
81
|
+
* long phrases (priority 100, e.g. "to the power of") to match before
|
|
82
|
+
* shorter fragments (priority 80, e.g. "power of").
|
|
83
|
+
*
|
|
84
|
+
* ## Match contract
|
|
85
|
+
* - Must be pure (no side effects, no mutation of input tokens)
|
|
86
|
+
* - Must return `null` for any position that doesn't match
|
|
87
|
+
* - Consumed tokens must be consecutive starting at `pos`
|
|
88
|
+
* - Replacement tokens must be valid for downstream parsing
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* // A phrase fusion rule that converts "to the power of" into CARET
|
|
93
|
+
* const phraseRule: NormalizerRule = {
|
|
94
|
+
* name: 'phrase:to the power of',
|
|
95
|
+
* priority: 100,
|
|
96
|
+
* match: (tokens, pos) => {
|
|
97
|
+
* if (pos + 4 > tokens.length) return null;
|
|
98
|
+
* const phrase = tokens.slice(pos, pos + 5)
|
|
99
|
+
* .map(t => t.value.toLowerCase()).join(' ');
|
|
100
|
+
* if (phrase === 'to the power of') {
|
|
101
|
+
* return {
|
|
102
|
+
* consumed: 5,
|
|
103
|
+
* replacement: [createFusedToken('CARET', 'to the power of', tokens.slice(pos, pos + 5))],
|
|
104
|
+
* };
|
|
105
|
+
* }
|
|
106
|
+
* return null;
|
|
107
|
+
* },
|
|
108
|
+
* };
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
interface NormalizerRule {
|
|
112
|
+
/**
|
|
113
|
+
* Human-readable name for debugging and diagnostic display.
|
|
114
|
+
* Convention: `"category:description"`, e.g. `"phrase:to the power of"`.
|
|
115
|
+
*/
|
|
116
|
+
readonly name: string;
|
|
117
|
+
/**
|
|
118
|
+
* Priority for ordering rules. Higher values are tried first.
|
|
119
|
+
* Recommended ranges:
|
|
120
|
+
* - 100: Long multi-word phrase fusion (e.g., "to the power of")
|
|
121
|
+
* - 80: Short phrase fusion (e.g., "power of", "times by")
|
|
122
|
+
* - 50: Implicit operator insertion (e.g., implicit multiply)
|
|
123
|
+
* - 20: Domain-specific transformations
|
|
124
|
+
*/
|
|
125
|
+
readonly priority: number;
|
|
126
|
+
/**
|
|
127
|
+
* Attempt to match a pattern starting at position `pos` in the token stream.
|
|
128
|
+
*
|
|
129
|
+
* @param tokens - The current token stream (may be partially normalized from prior passes)
|
|
130
|
+
* @param pos - The current position to attempt matching from
|
|
131
|
+
* @returns A {@link NormalizerMatch} if the pattern is found, or `null` if no match
|
|
132
|
+
*/
|
|
133
|
+
match(tokens: Token[], pos: number): NormalizerMatch | null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Record of a token fusion event performed by the normalizer.
|
|
137
|
+
*
|
|
138
|
+
* When a rule merges multiple source tokens into fewer replacement tokens,
|
|
139
|
+
* the normalizer fires a {@link NormalizerOptions.onFusion | fusion callback}
|
|
140
|
+
* with this record. The playground uses these records to render the
|
|
141
|
+
* fusion detail table showing exactly which tokens were merged and by
|
|
142
|
+
* which rule.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* // "to" "the" "power" "of" fused into CARET "^"
|
|
147
|
+
* const fusion: TokenFusion = {
|
|
148
|
+
* rule: "phrase:to the power of",
|
|
149
|
+
* sourceTokens: [toToken, theToken, powerToken, ofToken],
|
|
150
|
+
* fusedToken: caretToken,
|
|
151
|
+
* };
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
interface TokenFusion {
|
|
155
|
+
/** The name of the rule that triggered this fusion (e.g., "phrase:to the power of") */
|
|
156
|
+
rule: string;
|
|
157
|
+
/** The original tokens before fusion, always ≥ 2 tokens */
|
|
158
|
+
sourceTokens: Token[];
|
|
159
|
+
/** The resulting fused token with its new type and combined value */
|
|
160
|
+
fusedToken: Token;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export type { NormalizerRule as N, TokenFusion as T, NormalizerMatch as a };
|