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,364 @@
|
|
|
1
|
+
import { T as Token } from './Token-0jpvUdPY.js';
|
|
2
|
+
import { T as TokenFusion, N as NormalizerRule, a as NormalizerMatch } from './NormalizerRule-CEjf1FyD.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TokenNormalizer, post-lexer token normalization pass.
|
|
6
|
+
*
|
|
7
|
+
* ## Purpose
|
|
8
|
+
* Applies domain-specific {@link NormalizerRule | NormalizerRules} to the raw
|
|
9
|
+
* token stream produced by the {@link ExpressionLexer}. This keeps the lexer
|
|
10
|
+
* slim and focused on single-token production, while multi-token pattern
|
|
11
|
+
* matching (phrases, implicit operators, domain merges) lives here.
|
|
12
|
+
*
|
|
13
|
+
* ## What rules can do
|
|
14
|
+
* - **Phrase fusion**: Merge consecutive words into compound tokens
|
|
15
|
+
* (e.g., `IDENT + ... + IDENT` → `CARET`)
|
|
16
|
+
* - **Implicit operator insertion**: Insert missing operators between tokens
|
|
17
|
+
* (e.g., `NUMBER IDENT` → `NUMBER STAR IDENT`)
|
|
18
|
+
* - **Domain-specific transformations**: Coalesce item names, currency pairs,
|
|
19
|
+
* percentage syntax, etc.
|
|
20
|
+
*
|
|
21
|
+
* ## Architecture
|
|
22
|
+
* Providers register NormalizerRules alongside Parselets and OpCode handlers
|
|
23
|
+
* via {@link IEnginePackage.normalizerRules}. The normalizer applies them
|
|
24
|
+
* greedily left-to-right in multiple passes with safety limits.
|
|
25
|
+
*
|
|
26
|
+
* @module TokenNormalizer
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Configuration options for the normalization pass.
|
|
31
|
+
*
|
|
32
|
+
* These control safety limits and diagnostic callbacks. The defaults
|
|
33
|
+
* are chosen to be generous enough for any realistic expression while
|
|
34
|
+
* preventing runaway token expansion from recursive rules.
|
|
35
|
+
*/
|
|
36
|
+
interface NormalizerOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Maximum number of full passes over the token stream before bailing out.
|
|
39
|
+
* Prevents infinite loops from recursive rule chains.
|
|
40
|
+
* @default 100
|
|
41
|
+
*/
|
|
42
|
+
maxPasses?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Maximum number of tokens allowed after normalization.
|
|
45
|
+
* If exceeded, an Error is thrown rather than passing a bloated stream
|
|
46
|
+
* to the parser.
|
|
47
|
+
* @default 10000
|
|
48
|
+
*/
|
|
49
|
+
maxTokens?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Callback invoked for each fusion event during normalization.
|
|
52
|
+
* Used by diagnostic mode to populate {@link NormalizerOutput.fusions}.
|
|
53
|
+
* When `undefined`, fusions are still tracked internally but no callbacks fire.
|
|
54
|
+
*/
|
|
55
|
+
onFusion?: (fusion: TokenFusion) => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new normalized token from fused source tokens.
|
|
59
|
+
*
|
|
60
|
+
* The fused token inherits position information (offset, line, column)
|
|
61
|
+
* from the first source token, which preserves source-map accuracy
|
|
62
|
+
* for error messages and diagnostic highlighting.
|
|
63
|
+
*
|
|
64
|
+
* @param type - The new token type (e.g., "CARET", "TIMES_BY")
|
|
65
|
+
* @param text - The combined text representation (e.g., "to the power of")
|
|
66
|
+
* @param sourceTokens - The original tokens being fused (at least 2)
|
|
67
|
+
* @returns A new {@link LexerToken} with the fused type and combined text
|
|
68
|
+
*/
|
|
69
|
+
declare function createFusedToken(type: string, text: string, sourceTokens: Token[]): Token;
|
|
70
|
+
/**
|
|
71
|
+
* Token normalizer: applies {@link NormalizerRule | NormalizerRules} to a token stream.
|
|
72
|
+
*
|
|
73
|
+
* ## Lifecycle
|
|
74
|
+
* 1. **Registration**: Rules are added via {@link register} and sorted by priority
|
|
75
|
+
* 2. **Normalization**: {@link normalize} applies rules greedily left-to-right
|
|
76
|
+
* 3. **Cleanup**: {@link clear} or {@link unregister} removes rules
|
|
77
|
+
*
|
|
78
|
+
* ## Normalization algorithm
|
|
79
|
+
* The normalizer uses a greedy left-to-right multi-pass algorithm:
|
|
80
|
+
* - At each token position, rules are tried in priority order (highest first)
|
|
81
|
+
* - When a rule matches, matched tokens are consumed and replaced
|
|
82
|
+
* - Processing continues from the replacement position
|
|
83
|
+
* - Multiple passes handle cascading matches (one rule's output triggers another)
|
|
84
|
+
* - Safety limits ({@link NormalizerOptions.maxPasses}) prevent infinite loops
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const normalizer = new TokenNormalizer();
|
|
89
|
+
* normalizer.register(phraseRule); // "to the power of" → CARET
|
|
90
|
+
* normalizer.register(implicitMultRule); // "2 x" → "2 * x"
|
|
91
|
+
* const normalized = normalizer.normalize(rawTokens);
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare class TokenNormalizer {
|
|
95
|
+
/** Registered rules, unsorted, the source of truth. */
|
|
96
|
+
private rules;
|
|
97
|
+
/**
|
|
98
|
+
* Priority-sorted copy of {@link rules}, rebuilt lazily on the next
|
|
99
|
+
* {@link normalize} call after a mutation. Rules are registered once at
|
|
100
|
+
* engine/package-registration time and essentially never change during a
|
|
101
|
+
* session, but normalize() runs on every keystroke-driven evaluation, an
|
|
102
|
+
* earlier version re-sorted a fresh copy of `rules` on every single call,
|
|
103
|
+
* which meant every keystroke paid for an allocation + sort of a list that
|
|
104
|
+
* had usually not changed since the last one. `null` means "stale, rebuild
|
|
105
|
+
* on next use"; {@link register}/{@link unregister}/{@link clear} all
|
|
106
|
+
* invalidate it.
|
|
107
|
+
*/
|
|
108
|
+
private sortedRulesCache;
|
|
109
|
+
/**
|
|
110
|
+
* Phrase trie for single-pass multi-word phrase fusion.
|
|
111
|
+
* Tried at each token position BEFORE other rules, the trie walk
|
|
112
|
+
* is O(depth) vs O(R × W) for separate rule matching.
|
|
113
|
+
*/
|
|
114
|
+
private phraseTrie;
|
|
115
|
+
/** Merged options with defaults applied. */
|
|
116
|
+
private options;
|
|
117
|
+
/**
|
|
118
|
+
* @param options - Configuration overrides for safety limits and diagnostic callbacks
|
|
119
|
+
*/
|
|
120
|
+
constructor(options?: NormalizerOptions);
|
|
121
|
+
/**
|
|
122
|
+
* Register a normalization rule.
|
|
123
|
+
*
|
|
124
|
+
* Rules are sorted by priority (descending) on each {@link normalize} call.
|
|
125
|
+
* Multiple rules can share the same priority, they are tried in registration
|
|
126
|
+
* order when priorities are equal.
|
|
127
|
+
*
|
|
128
|
+
* @param rule - The rule to register
|
|
129
|
+
*/
|
|
130
|
+
register(rule: NormalizerRule): void;
|
|
131
|
+
/**
|
|
132
|
+
* Unregister a normalization rule by its {@link NormalizerRule.name | name}.
|
|
133
|
+
*
|
|
134
|
+
* If multiple rules share the same name, all are removed. This is safe to
|
|
135
|
+
* call with a name that doesn't match any rule, it simply has no effect.
|
|
136
|
+
*
|
|
137
|
+
* @param ruleName - The name of the rule to remove
|
|
138
|
+
*/
|
|
139
|
+
unregister(ruleName: string): void;
|
|
140
|
+
/**
|
|
141
|
+
* Remove all registered rules, resetting the normalizer to its initial state.
|
|
142
|
+
* Also clears the phrase trie.
|
|
143
|
+
*/
|
|
144
|
+
clear(): void;
|
|
145
|
+
/**
|
|
146
|
+
* Priority-sorted view of {@link rules} (descending priority; registration
|
|
147
|
+
* order preserved for ties, since {@link Array.prototype.sort} is stable).
|
|
148
|
+
* Cached until the next mutation. See {@link sortedRulesCache}.
|
|
149
|
+
*/
|
|
150
|
+
private getSortedRules;
|
|
151
|
+
/**
|
|
152
|
+
* Get the number of currently registered rules (excludes phrase trie entries).
|
|
153
|
+
*/
|
|
154
|
+
get ruleCount(): number;
|
|
155
|
+
/**
|
|
156
|
+
* Register a multi-word phrase for fusion into a single compound token.
|
|
157
|
+
*
|
|
158
|
+
* This is the preferred way to add phrase patterns. It inserts into the
|
|
159
|
+
* internal {@link PhraseTrie}, which collapses all phrase rules into a
|
|
160
|
+
* single O(depth) trie walk per position, no separate rule scanning.
|
|
161
|
+
*
|
|
162
|
+
* @param phrase - Multi-word phrase (e.g., "to the power of", "abyssal whip")
|
|
163
|
+
* @param tokenType - Target token type after fusion (e.g., "CARET", "ITEM")
|
|
164
|
+
*/
|
|
165
|
+
addPhrase(phrase: string, tokenType: string): void;
|
|
166
|
+
/**
|
|
167
|
+
* Check whether a word can start any registered phrase.
|
|
168
|
+
*
|
|
169
|
+
* Used by {@link implicitMultiplyRule} to suppress `*` insertion
|
|
170
|
+
* before phrase-starting identifiers (e.g., "2 power of 3" → `2 ^ 3`,
|
|
171
|
+
* not `2 * power of 3`). Delegates to {@link PhraseTrie.canStart}.
|
|
172
|
+
*/
|
|
173
|
+
/**
|
|
174
|
+
* Get all registered phrases and their target token types.
|
|
175
|
+
*
|
|
176
|
+
* Exposes the full phrase trie structure for diagnostic rendering
|
|
177
|
+
* in the playground's NormalizerTab. Returns ALL registered phrases,
|
|
178
|
+
* not just the ones that matched in the last evaluation.
|
|
179
|
+
*/
|
|
180
|
+
getPhrases(): Record<string, string>;
|
|
181
|
+
canStartPhrase(word: string): boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Normalize a token stream by applying all registered rules.
|
|
184
|
+
*
|
|
185
|
+
* ## Algorithm
|
|
186
|
+
* Applies rules greedily left-to-right in multiple passes:
|
|
187
|
+
* 1. Sort rules by priority (descending)
|
|
188
|
+
* 2. Walk the token stream left to right
|
|
189
|
+
* 3. At each position, try rules in priority order
|
|
190
|
+
* 4. On match: consume matched tokens, insert replacements, restart from insert point
|
|
191
|
+
* 5. On no match: pass token through unchanged
|
|
192
|
+
* 6. Repeat until a full pass produces no changes, or maxPasses is reached
|
|
193
|
+
*
|
|
194
|
+
* ## Fusion tracking
|
|
195
|
+
* When a rule consumes more tokens than it produces, the normalizer calls
|
|
196
|
+
* `onFusion` with a {@link TokenFusion} record for diagnostic collection.
|
|
197
|
+
* This populates {@link NormalizerOutput.fusions} in the playground pipeline view.
|
|
198
|
+
*
|
|
199
|
+
* ## Safety
|
|
200
|
+
* If the normalized token count exceeds {@link NormalizerOptions.maxTokens},
|
|
201
|
+
* an Error is thrown to prevent memory exhaustion from runaway rule expansion.
|
|
202
|
+
*
|
|
203
|
+
* @param tokens - Raw tokens from the lexer
|
|
204
|
+
* @param onFusion - Optional fusion callback (overrides {@link NormalizerOptions.onFusion})
|
|
205
|
+
* @returns Normalized tokens ready for parsing
|
|
206
|
+
* @throws {Error} If the normalized token count exceeds maxTokens
|
|
207
|
+
*/
|
|
208
|
+
normalize(tokens: Token[], onFusion?: (fusion: TokenFusion) => void): Token[];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* PhraseTrie, optimized word-level trie for multi-word phrase fusion.
|
|
213
|
+
*
|
|
214
|
+
* ## Problem
|
|
215
|
+
* The normalizer previously applied N separate `phraseFusionRule` instances,
|
|
216
|
+
* each scanning forward from the current token position. For R phrase rules
|
|
217
|
+
* and W average phrase length, this cost O(N × R × W) per pass.
|
|
218
|
+
*
|
|
219
|
+
* ## Solution
|
|
220
|
+
* A single trie walk per position collapses all phrase rules into O(D)
|
|
221
|
+
* where D ≤ longest phrase depth (typically ≤ 5 words). The trie tracks
|
|
222
|
+
* the deepest terminal node reached, implementing longest-match-wins
|
|
223
|
+
* without priority sorting.
|
|
224
|
+
*
|
|
225
|
+
* ## Optimizations
|
|
226
|
+
* 1. **Set<string> quick-reject**, the `startWords` set contains the first
|
|
227
|
+
* word of every registered phrase. At each position, if the token's
|
|
228
|
+
* lowercase value isn't in the set, we bail in O(1) without touching
|
|
229
|
+
* the trie. ~80% of tokens (numbers, operators) hit this fast path.
|
|
230
|
+
* 2. **Longest-match-wins**, the `matchAt()` walk continues past terminal
|
|
231
|
+
* nodes, tracking the deepest one. Shorter overlapping phrases (e.g.,
|
|
232
|
+
* "power of") don't need lower priority, the trie naturally prefers
|
|
233
|
+
* the longer match.
|
|
234
|
+
* 3. **Map-based children**, `Map<string, TrieNode>` gives O(1) amortized
|
|
235
|
+
* child lookup per word, faster than array scanning for sparse branches.
|
|
236
|
+
*
|
|
237
|
+
* ## Package integration
|
|
238
|
+
* Packages add phrases via {@link TokenNormalizer.addPhrase} (public API)
|
|
239
|
+
* or the {@link IEnginePackage.phrases} declarative field. Each call to
|
|
240
|
+
* `addPhrase()` inserts the phrase into this trie and updates `startWords`.
|
|
241
|
+
*
|
|
242
|
+
* @module PhraseTrie
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Word-level trie for single-pass multi-word phrase matching.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```ts
|
|
250
|
+
* const trie = new PhraseTrie();
|
|
251
|
+
* trie.addPhrase("to the power of", "CARET");
|
|
252
|
+
* trie.addPhrase("power of", "CARET");
|
|
253
|
+
* trie.addPhrase("abyssal whip", "ITEM");
|
|
254
|
+
*
|
|
255
|
+
* // At position 0 with tokens ["to","the","power","of","3"]
|
|
256
|
+
* const match = trie.matchAt(tokens, 0);
|
|
257
|
+
* // → { consumed: 4, replacement: [CARET("to the power of")] }
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
declare class PhraseTrie {
|
|
261
|
+
/**
|
|
262
|
+
* First words that can start any registered phrase (all lowercase).
|
|
263
|
+
* O(1) quick-reject: if `tokens[pos].value.toLowerCase()` isn't here,
|
|
264
|
+
* no phrase can match at this position.
|
|
265
|
+
*/
|
|
266
|
+
private startWords;
|
|
267
|
+
/**
|
|
268
|
+
* Root maps first word → child node.
|
|
269
|
+
* Two-level root avoids an unnecessary intermediate TrieNode.
|
|
270
|
+
*/
|
|
271
|
+
private root;
|
|
272
|
+
/**
|
|
273
|
+
* Register a phrase for fusion into a single compound token.
|
|
274
|
+
*
|
|
275
|
+
* @param phrase - Multi-word phrase (e.g., "to the power of")
|
|
276
|
+
* @param tokenType - Target token type after fusion (e.g., "CARET")
|
|
277
|
+
*/
|
|
278
|
+
addPhrase(phrase: string, tokenType: string): void;
|
|
279
|
+
/**
|
|
280
|
+
* Attempt to match a phrase starting at `pos` in the token stream.
|
|
281
|
+
*
|
|
282
|
+
* Walks the trie one token at a time, tracking the deepest terminal
|
|
283
|
+
* node reached. Returns the longest match found, or `null` if no
|
|
284
|
+
* phrase starts at this position.
|
|
285
|
+
*
|
|
286
|
+
* @param tokens - The current token stream
|
|
287
|
+
* @param pos - Position to attempt matching from
|
|
288
|
+
* @returns The longest {@link NormalizerMatch}, or `null` on no match
|
|
289
|
+
*/
|
|
290
|
+
matchAt(tokens: Token[], pos: number): NormalizerMatch | null;
|
|
291
|
+
/** Number of unique first words (not total phrases). */
|
|
292
|
+
get size(): number;
|
|
293
|
+
/**
|
|
294
|
+
* Return all registered phrases and their target token types.
|
|
295
|
+
*
|
|
296
|
+
* Used by diagnostic mode to expose the complete trie structure to the
|
|
297
|
+
* playground's NormalizerTab for rendering ALL registered phrases
|
|
298
|
+
* (not just the ones that matched in this evaluation).
|
|
299
|
+
*/
|
|
300
|
+
getAllPhrases(): Record<string, string>;
|
|
301
|
+
/** Check if any phrase starts with this word (case-insensitive). */
|
|
302
|
+
canStart(word: string): boolean;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Built-in normalization rules for the {@link TokenNormalizer}.
|
|
307
|
+
*
|
|
308
|
+
* These rules handle common expression patterns that span multiple tokens.
|
|
309
|
+
* Phrase fusion (e.g., "to the power of" → CARET) is handled by the
|
|
310
|
+
* internal {@link PhraseTrie}. See {@link TokenNormalizer.addPhrase}.
|
|
311
|
+
* This module only exports non-phrase rules like {@link implicitMultiplyRule}.
|
|
312
|
+
*
|
|
313
|
+
* @module BuiltinNormalizerRules
|
|
314
|
+
*/
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Creates a normalization rule that inserts an implicit multiplication operator
|
|
318
|
+
* between adjacent tokens where multiplication is implied.
|
|
319
|
+
*
|
|
320
|
+
* ## When it fires
|
|
321
|
+
* Inserts a STAR token between:
|
|
322
|
+
* - `NUMBER IDENT` (e.g., "2 x" → "2 * x")
|
|
323
|
+
* - `RPAREN IDENT` (e.g., "(x+1)y" → "(x+1) * y")
|
|
324
|
+
* - `NUMBER LPAREN` (e.g., "2(x+1)" → "2 * (x+1)")
|
|
325
|
+
* - `NUMBER PI` / `NUMBER E` (e.g., "2π" → "2 * π")
|
|
326
|
+
*
|
|
327
|
+
* ## When it doesn't fire
|
|
328
|
+
* - When the following identifier starts a multi-word phrase
|
|
329
|
+
* (checked against {@link PHRASE_START_WORDS})
|
|
330
|
+
* - When the following token is not an identifier or parenthesized expression
|
|
331
|
+
*
|
|
332
|
+
* ## Priority
|
|
333
|
+
* Default priority is 50, below phrase fusion so phrases match first.
|
|
334
|
+
*
|
|
335
|
+
* @param priority - Rule priority (default 50)
|
|
336
|
+
* @returns A {@link NormalizerRule} that inserts implicit multiply operators
|
|
337
|
+
*/
|
|
338
|
+
declare function implicitMultiplyRule(priority?: number, canStart?: (word: string) => boolean): NormalizerRule;
|
|
339
|
+
/**
|
|
340
|
+
* Creates built-in non-phrase normalization rules.
|
|
341
|
+
*
|
|
342
|
+
* Returns implicit multiply insertion (priority 50).
|
|
343
|
+
*
|
|
344
|
+
* **Prefer** calling {@link implicitMultiplyRule} directly with a
|
|
345
|
+
* `canStart` predicate wired to the normalizer's phrase trie:
|
|
346
|
+
* ```ts
|
|
347
|
+
* normalizer.register(implicitMultiplyRule(50, (w) => normalizer.canStartPhrase(w)));
|
|
348
|
+
* ```
|
|
349
|
+
* Without the predicate, this function falls back to a hardcoded
|
|
350
|
+
* {@link PHRASE_START_WORDS} set that won't reflect package-registered phrases.
|
|
351
|
+
*
|
|
352
|
+
* @returns An array of {@link NormalizerRule} instances ready for registration
|
|
353
|
+
*/
|
|
354
|
+
declare function createBuiltinNormalizerRules(): NormalizerRule[];
|
|
355
|
+
/**
|
|
356
|
+
* Built-in phrase → tokenType mappings.
|
|
357
|
+
*
|
|
358
|
+
* These are registered into the engine's {@link PhraseTrie} during
|
|
359
|
+
* construction. Tests that create a standalone {@link TokenNormalizer}
|
|
360
|
+
* should register these via {@link TokenNormalizer.addPhrase}.
|
|
361
|
+
*/
|
|
362
|
+
declare const BUILTIN_PHRASES: Record<string, string>;
|
|
363
|
+
|
|
364
|
+
export { BUILTIN_PHRASES, NormalizerMatch, type NormalizerOptions, NormalizerRule, PhraseTrie, TokenFusion, TokenNormalizer, createBuiltinNormalizerRules, createFusedToken, implicitMultiplyRule };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import './chunk-2RWAXT6O.js';
|
|
2
|
+
export { BUILTIN_PHRASES, PhraseTrie, TokenNormalizer, createBuiltinNormalizerRules, createFusedToken, implicitMultiplyRule } from './chunk-64W6GLLZ.js';
|
|
3
|
+
import './chunk-XVWCOTR6.js';
|
|
4
|
+
import './chunk-RIN643A3.js';
|
|
5
|
+
import './chunk-GOLDJNMZ.js';
|
|
6
|
+
import './chunk-LIPPNDBE.js';
|
|
7
|
+
import './chunk-4MG4XKO2.js';
|
|
8
|
+
import './chunk-6RDSQURE.js';
|
|
9
|
+
import './chunk-YLJ4XMA6.js';
|
|
10
|
+
//# sourceMappingURL=normalizer.js.map
|
|
11
|
+
//# sourceMappingURL=normalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"normalizer.js"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkRZCWSXTA_cjs = require('./chunk-RZCWSXTA.cjs');
|
|
4
|
+
require('./chunk-C4XZV6E7.cjs');
|
|
5
|
+
require('./chunk-EBSPLUW4.cjs');
|
|
6
|
+
require('./chunk-N5YFR4UP.cjs');
|
|
7
|
+
require('./chunk-WQTTOGXC.cjs');
|
|
8
|
+
require('./chunk-Z2XP767T.cjs');
|
|
9
|
+
require('./chunk-J73SJHR3.cjs');
|
|
10
|
+
require('./chunk-FEAIOR7N.cjs');
|
|
11
|
+
require('./chunk-XJCMXB2E.cjs');
|
|
12
|
+
require('./chunk-MZOVP3WI.cjs');
|
|
13
|
+
require('./chunk-VEKIWQ3F.cjs');
|
|
14
|
+
require('./chunk-OT6OJY7C.cjs');
|
|
15
|
+
require('./chunk-HTXVVJRA.cjs');
|
|
16
|
+
require('./chunk-OC6LTXYS.cjs');
|
|
17
|
+
require('./chunk-QNJ4ACRT.cjs');
|
|
18
|
+
require('./chunk-NMD5VRN4.cjs');
|
|
19
|
+
require('./chunk-GW32KPCU.cjs');
|
|
20
|
+
require('./chunk-3YNVWKR2.cjs');
|
|
21
|
+
require('./chunk-EHAHVROS.cjs');
|
|
22
|
+
require('./chunk-53B6KDDJ.cjs');
|
|
23
|
+
require('./chunk-M4N5GA5Z.cjs');
|
|
24
|
+
require('./chunk-B7LXJ6LC.cjs');
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Object.defineProperty(exports, "ARITHMETIC_PACKAGE", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return chunkRZCWSXTA_cjs.ARITHMETIC_PACKAGE; }
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports, "BIGINT_PACKAGE", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return chunkRZCWSXTA_cjs.BIGINT_PACKAGE; }
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "BUILTIN_PACKAGES", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return chunkRZCWSXTA_cjs.BUILTIN_PACKAGES; }
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "CONDITIONALS_PACKAGE", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () { return chunkRZCWSXTA_cjs.CONDITIONALS_PACKAGE; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "CONVERTERS_PACKAGE", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return chunkRZCWSXTA_cjs.CONVERTERS_PACKAGE; }
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "CURRENCY_PACKAGE", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return chunkRZCWSXTA_cjs.CURRENCY_PACKAGE; }
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "DATETIME_PACKAGE", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return chunkRZCWSXTA_cjs.DATETIME_PACKAGE; }
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(exports, "DICE_PACKAGE", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () { return chunkRZCWSXTA_cjs.DICE_PACKAGE; }
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "FINANCE_PACKAGE", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () { return chunkRZCWSXTA_cjs.FINANCE_PACKAGE; }
|
|
63
|
+
});
|
|
64
|
+
Object.defineProperty(exports, "FUNCTION_PACKAGE", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
get: function () { return chunkRZCWSXTA_cjs.FUNCTION_PACKAGE; }
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(exports, "LINES_PACKAGE", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function () { return chunkRZCWSXTA_cjs.LINES_PACKAGE; }
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "MAPREDUCE_PACKAGE", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () { return chunkRZCWSXTA_cjs.MAPREDUCE_PACKAGE; }
|
|
75
|
+
});
|
|
76
|
+
Object.defineProperty(exports, "MATHPHRASES_PACKAGE", {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
get: function () { return chunkRZCWSXTA_cjs.MATHPHRASES_PACKAGE; }
|
|
79
|
+
});
|
|
80
|
+
Object.defineProperty(exports, "MATRIX_PACKAGE", {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get: function () { return chunkRZCWSXTA_cjs.MATRIX_PACKAGE; }
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, "PERCENTAGE_PACKAGE", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () { return chunkRZCWSXTA_cjs.PERCENTAGE_PACKAGE; }
|
|
87
|
+
});
|
|
88
|
+
Object.defineProperty(exports, "SYMBOLIC_PACKAGE", {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
get: function () { return chunkRZCWSXTA_cjs.SYMBOLIC_PACKAGE; }
|
|
91
|
+
});
|
|
92
|
+
Object.defineProperty(exports, "TIME_PACKAGE", {
|
|
93
|
+
enumerable: true,
|
|
94
|
+
get: function () { return chunkRZCWSXTA_cjs.TIME_PACKAGE; }
|
|
95
|
+
});
|
|
96
|
+
Object.defineProperty(exports, "UOM_PACKAGE", {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
get: function () { return chunkRZCWSXTA_cjs.UOM_PACKAGE; }
|
|
99
|
+
});
|
|
100
|
+
Object.defineProperty(exports, "VARIABLES_PACKAGE", {
|
|
101
|
+
enumerable: true,
|
|
102
|
+
get: function () { return chunkRZCWSXTA_cjs.VARIABLES_PACKAGE; }
|
|
103
|
+
});
|
|
104
|
+
Object.defineProperty(exports, "VECTOR_PACKAGE", {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
get: function () { return chunkRZCWSXTA_cjs.VECTOR_PACKAGE; }
|
|
107
|
+
});
|
|
108
|
+
Object.defineProperty(exports, "WEATHER_PACKAGE", {
|
|
109
|
+
enumerable: true,
|
|
110
|
+
get: function () { return chunkRZCWSXTA_cjs.WEATHER_PACKAGE; }
|
|
111
|
+
});
|
|
112
|
+
Object.defineProperty(exports, "createKnowledgePackage", {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
get: function () { return chunkRZCWSXTA_cjs.createKnowledgePackage; }
|
|
115
|
+
});
|
|
116
|
+
Object.defineProperty(exports, "createStocksPackage", {
|
|
117
|
+
enumerable: true,
|
|
118
|
+
get: function () { return chunkRZCWSXTA_cjs.createStocksPackage; }
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=packages.cjs.map
|
|
121
|
+
//# sourceMappingURL=packages.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"packages.cjs"}
|