@lokascript/semantic 1.0.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/LICENSE +21 -0
- package/README.md +686 -0
- package/dist/browser-ar.ar.global.js +2 -0
- package/dist/browser-core.core.global.js +2 -0
- package/dist/browser-de.de.global.js +2 -0
- package/dist/browser-east-asian.east-asian.global.js +2 -0
- package/dist/browser-en-tr.en-tr.global.js +2 -0
- package/dist/browser-en.en.global.js +2 -0
- package/dist/browser-es-en.es-en.global.js +2 -0
- package/dist/browser-es.es.global.js +2 -0
- package/dist/browser-fr.fr.global.js +2 -0
- package/dist/browser-id.id.global.js +2 -0
- package/dist/browser-ja.ja.global.js +2 -0
- package/dist/browser-ko.ko.global.js +2 -0
- package/dist/browser-lazy.lazy.global.js +2 -0
- package/dist/browser-priority.priority.global.js +2 -0
- package/dist/browser-pt.pt.global.js +2 -0
- package/dist/browser-qu.qu.global.js +2 -0
- package/dist/browser-sw.sw.global.js +2 -0
- package/dist/browser-tr.tr.global.js +2 -0
- package/dist/browser-western.western.global.js +2 -0
- package/dist/browser-zh.zh.global.js +2 -0
- package/dist/browser.global.js +3 -0
- package/dist/browser.global.js.map +1 -0
- package/dist/index.cjs +35051 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3426 -0
- package/dist/index.d.ts +3426 -0
- package/dist/index.js +34890 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/ar.d.ts +78 -0
- package/dist/languages/ar.js +1622 -0
- package/dist/languages/ar.js.map +1 -0
- package/dist/languages/de.d.ts +38 -0
- package/dist/languages/de.js +1168 -0
- package/dist/languages/de.js.map +1 -0
- package/dist/languages/en.d.ts +44 -0
- package/dist/languages/en.js +3491 -0
- package/dist/languages/en.js.map +1 -0
- package/dist/languages/es.d.ts +52 -0
- package/dist/languages/es.js +1493 -0
- package/dist/languages/es.js.map +1 -0
- package/dist/languages/fr.d.ts +37 -0
- package/dist/languages/fr.js +1159 -0
- package/dist/languages/fr.js.map +1 -0
- package/dist/languages/id.d.ts +35 -0
- package/dist/languages/id.js +1152 -0
- package/dist/languages/id.js.map +1 -0
- package/dist/languages/ja.d.ts +53 -0
- package/dist/languages/ja.js +1430 -0
- package/dist/languages/ja.js.map +1 -0
- package/dist/languages/ko.d.ts +51 -0
- package/dist/languages/ko.js +1729 -0
- package/dist/languages/ko.js.map +1 -0
- package/dist/languages/pt.d.ts +37 -0
- package/dist/languages/pt.js +1127 -0
- package/dist/languages/pt.js.map +1 -0
- package/dist/languages/qu.d.ts +36 -0
- package/dist/languages/qu.js +1143 -0
- package/dist/languages/qu.js.map +1 -0
- package/dist/languages/sw.d.ts +35 -0
- package/dist/languages/sw.js +1147 -0
- package/dist/languages/sw.js.map +1 -0
- package/dist/languages/tr.d.ts +45 -0
- package/dist/languages/tr.js +1529 -0
- package/dist/languages/tr.js.map +1 -0
- package/dist/languages/zh.d.ts +58 -0
- package/dist/languages/zh.js +1257 -0
- package/dist/languages/zh.js.map +1 -0
- package/dist/types-C4dcj53L.d.ts +600 -0
- package/package.json +202 -0
- package/src/__test-utils__/index.ts +7 -0
- package/src/__test-utils__/test-helpers.ts +8 -0
- package/src/__types__/test-helpers.ts +122 -0
- package/src/analysis/index.ts +479 -0
- package/src/ast-builder/command-mappers.ts +1133 -0
- package/src/ast-builder/expression-parser/index.ts +41 -0
- package/src/ast-builder/expression-parser/parser.ts +563 -0
- package/src/ast-builder/expression-parser/tokenizer.ts +394 -0
- package/src/ast-builder/expression-parser/types.ts +208 -0
- package/src/ast-builder/index.ts +536 -0
- package/src/ast-builder/value-converters.ts +172 -0
- package/src/bridge.ts +275 -0
- package/src/browser-ar.ts +162 -0
- package/src/browser-core.ts +231 -0
- package/src/browser-de.ts +162 -0
- package/src/browser-east-asian.ts +173 -0
- package/src/browser-en-tr.ts +165 -0
- package/src/browser-en.ts +157 -0
- package/src/browser-es-en.ts +200 -0
- package/src/browser-es.ts +170 -0
- package/src/browser-fr.ts +162 -0
- package/src/browser-id.ts +162 -0
- package/src/browser-ja.ts +162 -0
- package/src/browser-ko.ts +162 -0
- package/src/browser-lazy.ts +189 -0
- package/src/browser-priority.ts +214 -0
- package/src/browser-pt.ts +162 -0
- package/src/browser-qu.ts +162 -0
- package/src/browser-sw.ts +162 -0
- package/src/browser-tr.ts +162 -0
- package/src/browser-western.ts +181 -0
- package/src/browser-zh.ts +162 -0
- package/src/browser.ts +268 -0
- package/src/cache/index.ts +14 -0
- package/src/cache/semantic-cache.ts +344 -0
- package/src/core-bridge.ts +372 -0
- package/src/explicit/converter.ts +258 -0
- package/src/explicit/index.ts +18 -0
- package/src/explicit/parser.ts +236 -0
- package/src/explicit/renderer.ts +424 -0
- package/src/generators/command-schemas.ts +1636 -0
- package/src/generators/event-handler-generator.ts +109 -0
- package/src/generators/index.ts +117 -0
- package/src/generators/language-profiles.ts +139 -0
- package/src/generators/pattern-generator.ts +537 -0
- package/src/generators/profiles/arabic.ts +131 -0
- package/src/generators/profiles/bengali.ts +132 -0
- package/src/generators/profiles/chinese.ts +124 -0
- package/src/generators/profiles/english.ts +113 -0
- package/src/generators/profiles/french.ts +125 -0
- package/src/generators/profiles/german.ts +126 -0
- package/src/generators/profiles/hindi.ts +146 -0
- package/src/generators/profiles/index.ts +46 -0
- package/src/generators/profiles/indonesian.ts +125 -0
- package/src/generators/profiles/italian.ts +139 -0
- package/src/generators/profiles/japanese.ts +149 -0
- package/src/generators/profiles/korean.ts +127 -0
- package/src/generators/profiles/marker-templates.ts +288 -0
- package/src/generators/profiles/ms.ts +130 -0
- package/src/generators/profiles/polish.ts +249 -0
- package/src/generators/profiles/portuguese.ts +115 -0
- package/src/generators/profiles/quechua.ts +113 -0
- package/src/generators/profiles/russian.ts +260 -0
- package/src/generators/profiles/spanish.ts +130 -0
- package/src/generators/profiles/swahili.ts +129 -0
- package/src/generators/profiles/thai.ts +132 -0
- package/src/generators/profiles/tl.ts +128 -0
- package/src/generators/profiles/turkish.ts +124 -0
- package/src/generators/profiles/types.ts +165 -0
- package/src/generators/profiles/ukrainian.ts +270 -0
- package/src/generators/profiles/vietnamese.ts +133 -0
- package/src/generators/schema-error-codes.ts +160 -0
- package/src/generators/schema-validator.ts +391 -0
- package/src/index.ts +429 -0
- package/src/language-building-schema.ts +3170 -0
- package/src/language-loader.ts +394 -0
- package/src/languages/_all.ts +65 -0
- package/src/languages/ar.ts +15 -0
- package/src/languages/bn.ts +16 -0
- package/src/languages/de.ts +15 -0
- package/src/languages/en.ts +29 -0
- package/src/languages/es.ts +15 -0
- package/src/languages/fr.ts +15 -0
- package/src/languages/hi.ts +26 -0
- package/src/languages/id.ts +15 -0
- package/src/languages/index.ts +18 -0
- package/src/languages/it.ts +15 -0
- package/src/languages/ja.ts +15 -0
- package/src/languages/ko.ts +15 -0
- package/src/languages/ms.ts +16 -0
- package/src/languages/pl.ts +18 -0
- package/src/languages/pt.ts +15 -0
- package/src/languages/qu.ts +15 -0
- package/src/languages/ru.ts +26 -0
- package/src/languages/sw.ts +15 -0
- package/src/languages/th.ts +16 -0
- package/src/languages/tl.ts +16 -0
- package/src/languages/tr.ts +15 -0
- package/src/languages/uk.ts +26 -0
- package/src/languages/vi.ts +16 -0
- package/src/languages/zh.ts +15 -0
- package/src/parser/index.ts +15 -0
- package/src/parser/pattern-matcher.ts +1181 -0
- package/src/parser/semantic-parser.ts +573 -0
- package/src/parser/utils/index.ts +35 -0
- package/src/parser/utils/marker-resolution.ts +111 -0
- package/src/parser/utils/possessive-keywords.ts +43 -0
- package/src/parser/utils/role-positioning.ts +70 -0
- package/src/parser/utils/type-validation.ts +134 -0
- package/src/patterns/add/ar.ts +71 -0
- package/src/patterns/add/bn.ts +70 -0
- package/src/patterns/add/hi.ts +69 -0
- package/src/patterns/add/index.ts +87 -0
- package/src/patterns/add/it.ts +61 -0
- package/src/patterns/add/ja.ts +93 -0
- package/src/patterns/add/ko.ts +74 -0
- package/src/patterns/add/ms.ts +30 -0
- package/src/patterns/add/pl.ts +62 -0
- package/src/patterns/add/ru.ts +62 -0
- package/src/patterns/add/th.ts +49 -0
- package/src/patterns/add/tl.ts +30 -0
- package/src/patterns/add/tr.ts +71 -0
- package/src/patterns/add/uk.ts +62 -0
- package/src/patterns/add/vi.ts +61 -0
- package/src/patterns/add/zh.ts +71 -0
- package/src/patterns/builders.ts +207 -0
- package/src/patterns/decrement/bn.ts +70 -0
- package/src/patterns/decrement/de.ts +42 -0
- package/src/patterns/decrement/hi.ts +68 -0
- package/src/patterns/decrement/index.ts +79 -0
- package/src/patterns/decrement/it.ts +69 -0
- package/src/patterns/decrement/ms.ts +30 -0
- package/src/patterns/decrement/pl.ts +58 -0
- package/src/patterns/decrement/ru.ts +58 -0
- package/src/patterns/decrement/th.ts +49 -0
- package/src/patterns/decrement/tl.ts +30 -0
- package/src/patterns/decrement/tr.ts +48 -0
- package/src/patterns/decrement/uk.ts +58 -0
- package/src/patterns/decrement/vi.ts +61 -0
- package/src/patterns/decrement/zh.ts +32 -0
- package/src/patterns/en.ts +302 -0
- package/src/patterns/event-handler/ar.ts +151 -0
- package/src/patterns/event-handler/bn.ts +72 -0
- package/src/patterns/event-handler/de.ts +117 -0
- package/src/patterns/event-handler/en.ts +117 -0
- package/src/patterns/event-handler/es.ts +136 -0
- package/src/patterns/event-handler/fr.ts +117 -0
- package/src/patterns/event-handler/hi.ts +64 -0
- package/src/patterns/event-handler/id.ts +117 -0
- package/src/patterns/event-handler/index.ts +119 -0
- package/src/patterns/event-handler/it.ts +54 -0
- package/src/patterns/event-handler/ja.ts +118 -0
- package/src/patterns/event-handler/ko.ts +133 -0
- package/src/patterns/event-handler/ms.ts +30 -0
- package/src/patterns/event-handler/pl.ts +62 -0
- package/src/patterns/event-handler/pt.ts +117 -0
- package/src/patterns/event-handler/qu.ts +66 -0
- package/src/patterns/event-handler/ru.ts +62 -0
- package/src/patterns/event-handler/shared.ts +270 -0
- package/src/patterns/event-handler/sw.ts +117 -0
- package/src/patterns/event-handler/th.ts +53 -0
- package/src/patterns/event-handler/tl.ts +30 -0
- package/src/patterns/event-handler/tr.ts +170 -0
- package/src/patterns/event-handler/uk.ts +62 -0
- package/src/patterns/event-handler/vi.ts +61 -0
- package/src/patterns/event-handler/zh.ts +150 -0
- package/src/patterns/get/ar.ts +49 -0
- package/src/patterns/get/bn.ts +47 -0
- package/src/patterns/get/de.ts +32 -0
- package/src/patterns/get/hi.ts +52 -0
- package/src/patterns/get/index.ts +83 -0
- package/src/patterns/get/it.ts +56 -0
- package/src/patterns/get/ja.ts +53 -0
- package/src/patterns/get/ko.ts +53 -0
- package/src/patterns/get/ms.ts +30 -0
- package/src/patterns/get/pl.ts +57 -0
- package/src/patterns/get/ru.ts +57 -0
- package/src/patterns/get/th.ts +29 -0
- package/src/patterns/get/tl.ts +30 -0
- package/src/patterns/get/uk.ts +57 -0
- package/src/patterns/get/vi.ts +48 -0
- package/src/patterns/grammar-transformed/index.ts +39 -0
- package/src/patterns/grammar-transformed/ja.ts +1713 -0
- package/src/patterns/grammar-transformed/ko.ts +1311 -0
- package/src/patterns/grammar-transformed/tr.ts +1067 -0
- package/src/patterns/hide/ar.ts +67 -0
- package/src/patterns/hide/bn.ts +47 -0
- package/src/patterns/hide/de.ts +36 -0
- package/src/patterns/hide/hi.ts +61 -0
- package/src/patterns/hide/index.ts +91 -0
- package/src/patterns/hide/it.ts +56 -0
- package/src/patterns/hide/ja.ts +69 -0
- package/src/patterns/hide/ko.ts +69 -0
- package/src/patterns/hide/ms.ts +30 -0
- package/src/patterns/hide/pl.ts +57 -0
- package/src/patterns/hide/ru.ts +57 -0
- package/src/patterns/hide/th.ts +29 -0
- package/src/patterns/hide/tl.ts +30 -0
- package/src/patterns/hide/tr.ts +65 -0
- package/src/patterns/hide/uk.ts +57 -0
- package/src/patterns/hide/vi.ts +56 -0
- package/src/patterns/hide/zh.ts +68 -0
- package/src/patterns/increment/bn.ts +70 -0
- package/src/patterns/increment/de.ts +36 -0
- package/src/patterns/increment/hi.ts +68 -0
- package/src/patterns/increment/index.ts +79 -0
- package/src/patterns/increment/it.ts +69 -0
- package/src/patterns/increment/ms.ts +30 -0
- package/src/patterns/increment/pl.ts +58 -0
- package/src/patterns/increment/ru.ts +58 -0
- package/src/patterns/increment/th.ts +49 -0
- package/src/patterns/increment/tl.ts +30 -0
- package/src/patterns/increment/tr.ts +52 -0
- package/src/patterns/increment/uk.ts +58 -0
- package/src/patterns/increment/vi.ts +61 -0
- package/src/patterns/increment/zh.ts +32 -0
- package/src/patterns/index.ts +84 -0
- package/src/patterns/languages/en/control-flow.ts +93 -0
- package/src/patterns/languages/en/fetch.ts +62 -0
- package/src/patterns/languages/en/index.ts +42 -0
- package/src/patterns/languages/en/repeat.ts +67 -0
- package/src/patterns/languages/en/set.ts +48 -0
- package/src/patterns/languages/en/swap.ts +38 -0
- package/src/patterns/languages/en/temporal.ts +57 -0
- package/src/patterns/put/ar.ts +74 -0
- package/src/patterns/put/bn.ts +53 -0
- package/src/patterns/put/en.ts +74 -0
- package/src/patterns/put/es.ts +74 -0
- package/src/patterns/put/hi.ts +69 -0
- package/src/patterns/put/id.ts +96 -0
- package/src/patterns/put/index.ts +99 -0
- package/src/patterns/put/it.ts +56 -0
- package/src/patterns/put/ja.ts +75 -0
- package/src/patterns/put/ko.ts +67 -0
- package/src/patterns/put/ms.ts +30 -0
- package/src/patterns/put/pl.ts +81 -0
- package/src/patterns/put/ru.ts +85 -0
- package/src/patterns/put/th.ts +32 -0
- package/src/patterns/put/tl.ts +30 -0
- package/src/patterns/put/tr.ts +67 -0
- package/src/patterns/put/uk.ts +85 -0
- package/src/patterns/put/vi.ts +72 -0
- package/src/patterns/put/zh.ts +62 -0
- package/src/patterns/registry.ts +163 -0
- package/src/patterns/remove/ar.ts +71 -0
- package/src/patterns/remove/bn.ts +68 -0
- package/src/patterns/remove/hi.ts +69 -0
- package/src/patterns/remove/index.ts +87 -0
- package/src/patterns/remove/it.ts +69 -0
- package/src/patterns/remove/ja.ts +74 -0
- package/src/patterns/remove/ko.ts +78 -0
- package/src/patterns/remove/ms.ts +30 -0
- package/src/patterns/remove/pl.ts +62 -0
- package/src/patterns/remove/ru.ts +62 -0
- package/src/patterns/remove/th.ts +49 -0
- package/src/patterns/remove/tl.ts +30 -0
- package/src/patterns/remove/tr.ts +78 -0
- package/src/patterns/remove/uk.ts +62 -0
- package/src/patterns/remove/vi.ts +61 -0
- package/src/patterns/remove/zh.ts +72 -0
- package/src/patterns/set/ar.ts +84 -0
- package/src/patterns/set/bn.ts +53 -0
- package/src/patterns/set/de.ts +84 -0
- package/src/patterns/set/es.ts +92 -0
- package/src/patterns/set/fr.ts +88 -0
- package/src/patterns/set/hi.ts +56 -0
- package/src/patterns/set/id.ts +84 -0
- package/src/patterns/set/index.ts +107 -0
- package/src/patterns/set/it.ts +56 -0
- package/src/patterns/set/ja.ts +86 -0
- package/src/patterns/set/ko.ts +85 -0
- package/src/patterns/set/ms.ts +30 -0
- package/src/patterns/set/pl.ts +57 -0
- package/src/patterns/set/pt.ts +84 -0
- package/src/patterns/set/ru.ts +57 -0
- package/src/patterns/set/th.ts +31 -0
- package/src/patterns/set/tl.ts +30 -0
- package/src/patterns/set/tr.ts +107 -0
- package/src/patterns/set/uk.ts +57 -0
- package/src/patterns/set/vi.ts +53 -0
- package/src/patterns/set/zh.ts +84 -0
- package/src/patterns/show/ar.ts +67 -0
- package/src/patterns/show/bn.ts +47 -0
- package/src/patterns/show/de.ts +32 -0
- package/src/patterns/show/fr.ts +32 -0
- package/src/patterns/show/hi.ts +61 -0
- package/src/patterns/show/index.ts +95 -0
- package/src/patterns/show/it.ts +56 -0
- package/src/patterns/show/ja.ts +69 -0
- package/src/patterns/show/ko.ts +73 -0
- package/src/patterns/show/ms.ts +30 -0
- package/src/patterns/show/pl.ts +57 -0
- package/src/patterns/show/ru.ts +57 -0
- package/src/patterns/show/th.ts +29 -0
- package/src/patterns/show/tl.ts +30 -0
- package/src/patterns/show/tr.ts +65 -0
- package/src/patterns/show/uk.ts +57 -0
- package/src/patterns/show/vi.ts +56 -0
- package/src/patterns/show/zh.ts +68 -0
- package/src/patterns/take/ar.ts +51 -0
- package/src/patterns/take/index.ts +31 -0
- package/src/patterns/toggle/ar.ts +61 -0
- package/src/patterns/toggle/bn.ts +70 -0
- package/src/patterns/toggle/en.ts +61 -0
- package/src/patterns/toggle/es.ts +61 -0
- package/src/patterns/toggle/hi.ts +80 -0
- package/src/patterns/toggle/index.ts +95 -0
- package/src/patterns/toggle/it.ts +69 -0
- package/src/patterns/toggle/ja.ts +156 -0
- package/src/patterns/toggle/ko.ts +113 -0
- package/src/patterns/toggle/ms.ts +30 -0
- package/src/patterns/toggle/pl.ts +62 -0
- package/src/patterns/toggle/ru.ts +62 -0
- package/src/patterns/toggle/th.ts +50 -0
- package/src/patterns/toggle/tl.ts +30 -0
- package/src/patterns/toggle/tr.ts +88 -0
- package/src/patterns/toggle/uk.ts +62 -0
- package/src/patterns/toggle/vi.ts +61 -0
- package/src/patterns/toggle/zh.ts +99 -0
- package/src/public-api.ts +286 -0
- package/src/registry.ts +441 -0
- package/src/tokenizers/arabic.ts +723 -0
- package/src/tokenizers/base.ts +1300 -0
- package/src/tokenizers/bengali.ts +289 -0
- package/src/tokenizers/chinese.ts +481 -0
- package/src/tokenizers/english.ts +416 -0
- package/src/tokenizers/french.ts +326 -0
- package/src/tokenizers/german.ts +324 -0
- package/src/tokenizers/hindi.ts +319 -0
- package/src/tokenizers/index.ts +127 -0
- package/src/tokenizers/indonesian.ts +306 -0
- package/src/tokenizers/italian.ts +458 -0
- package/src/tokenizers/japanese.ts +447 -0
- package/src/tokenizers/korean.ts +642 -0
- package/src/tokenizers/morphology/arabic-normalizer.ts +242 -0
- package/src/tokenizers/morphology/french-normalizer.ts +268 -0
- package/src/tokenizers/morphology/german-normalizer.ts +256 -0
- package/src/tokenizers/morphology/index.ts +46 -0
- package/src/tokenizers/morphology/italian-normalizer.ts +329 -0
- package/src/tokenizers/morphology/japanese-normalizer.ts +288 -0
- package/src/tokenizers/morphology/korean-normalizer.ts +428 -0
- package/src/tokenizers/morphology/polish-normalizer.ts +264 -0
- package/src/tokenizers/morphology/portuguese-normalizer.ts +310 -0
- package/src/tokenizers/morphology/spanish-normalizer.ts +327 -0
- package/src/tokenizers/morphology/turkish-normalizer.ts +412 -0
- package/src/tokenizers/morphology/types.ts +211 -0
- package/src/tokenizers/ms.ts +198 -0
- package/src/tokenizers/polish.ts +354 -0
- package/src/tokenizers/portuguese.ts +304 -0
- package/src/tokenizers/quechua.ts +339 -0
- package/src/tokenizers/russian.ts +375 -0
- package/src/tokenizers/spanish.ts +403 -0
- package/src/tokenizers/swahili.ts +303 -0
- package/src/tokenizers/thai.ts +236 -0
- package/src/tokenizers/tl.ts +198 -0
- package/src/tokenizers/turkish.ts +411 -0
- package/src/tokenizers/ukrainian.ts +369 -0
- package/src/tokenizers/vietnamese.ts +410 -0
- package/src/types/grammar-types.ts +617 -0
- package/src/types/unified-profile.ts +267 -0
- package/src/types.ts +709 -0
- package/src/utils/confidence-calculator.ts +147 -0
- package/src/validators/command-validator.ts +380 -0
- package/src/validators/index.ts +15 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Parser Bridge
|
|
3
|
+
*
|
|
4
|
+
* Provides the SemanticAnalyzer interface that integrates semantic parsing
|
|
5
|
+
* into the core hyperscript parser. This bridge enables confidence-driven
|
|
6
|
+
* fallback between semantic and traditional parsing.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
SemanticNode,
|
|
11
|
+
SemanticValue,
|
|
12
|
+
ActionType,
|
|
13
|
+
PatternMatchResult,
|
|
14
|
+
SemanticRole,
|
|
15
|
+
} from './types';
|
|
16
|
+
import { PatternMatcher } from './parser/pattern-matcher';
|
|
17
|
+
import { getTokenizer } from './tokenizers';
|
|
18
|
+
// Import from registry for tree-shaking (registry uses directly-registered patterns first)
|
|
19
|
+
import { getPatternsForLanguage, getRegisteredLanguages } from './registry';
|
|
20
|
+
import { SemanticCache, semanticCache, type SemanticCacheConfig, type CacheStats } from './cache';
|
|
21
|
+
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// SemanticAnalyzer Interface
|
|
24
|
+
// =============================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Result of semantic analysis.
|
|
28
|
+
*/
|
|
29
|
+
export interface SemanticAnalysisResult {
|
|
30
|
+
/** Confidence score (0-1) for this analysis */
|
|
31
|
+
readonly confidence: number;
|
|
32
|
+
/** The parsed command info (if successful) */
|
|
33
|
+
readonly command?: {
|
|
34
|
+
readonly name: ActionType;
|
|
35
|
+
readonly roles: ReadonlyMap<SemanticRole, SemanticValue>;
|
|
36
|
+
};
|
|
37
|
+
/** The full semantic node (if successful) */
|
|
38
|
+
readonly node?: SemanticNode;
|
|
39
|
+
/** Any errors encountered */
|
|
40
|
+
readonly errors?: string[];
|
|
41
|
+
/** Number of tokens consumed */
|
|
42
|
+
readonly tokensConsumed?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Interface for semantic analysis that can be integrated into the core parser.
|
|
47
|
+
* This allows the core parser to optionally use semantic parsing with
|
|
48
|
+
* confidence-based fallback to traditional parsing.
|
|
49
|
+
*/
|
|
50
|
+
export interface SemanticAnalyzer {
|
|
51
|
+
/**
|
|
52
|
+
* Analyze input in the specified language.
|
|
53
|
+
*
|
|
54
|
+
* @param input The input string to analyze
|
|
55
|
+
* @param language ISO 639-1 language code
|
|
56
|
+
* @returns Analysis result with confidence score
|
|
57
|
+
*/
|
|
58
|
+
analyze(input: string, language: string): SemanticAnalysisResult;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if semantic parsing is available for a language.
|
|
62
|
+
*/
|
|
63
|
+
supportsLanguage(language: string): boolean;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get the list of supported languages.
|
|
67
|
+
*/
|
|
68
|
+
supportedLanguages(): string[];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get cache statistics.
|
|
72
|
+
*/
|
|
73
|
+
getCacheStats(): CacheStats;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clear the result cache.
|
|
77
|
+
*/
|
|
78
|
+
clearCache(): void;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Configure the cache.
|
|
82
|
+
*/
|
|
83
|
+
configureCache(config: Partial<SemanticCacheConfig>): void;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// SemanticAnalyzer Implementation
|
|
88
|
+
// =============================================================================
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Options for creating a SemanticAnalyzer.
|
|
92
|
+
*/
|
|
93
|
+
export interface SemanticAnalyzerOptions {
|
|
94
|
+
/** Cache configuration. Pass false to disable caching. */
|
|
95
|
+
cache?: SemanticCacheConfig | false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Implementation of SemanticAnalyzer that wraps the semantic parser.
|
|
100
|
+
* Includes LRU caching for performance optimization on repeated inputs.
|
|
101
|
+
*/
|
|
102
|
+
export class SemanticAnalyzerImpl implements SemanticAnalyzer {
|
|
103
|
+
private readonly patternMatcher: PatternMatcher;
|
|
104
|
+
private readonly languages: Set<string>;
|
|
105
|
+
private readonly cache: SemanticCache;
|
|
106
|
+
|
|
107
|
+
constructor(options: SemanticAnalyzerOptions = {}) {
|
|
108
|
+
this.patternMatcher = new PatternMatcher();
|
|
109
|
+
// Get all registered languages from the registry (dynamically updated as languages are loaded)
|
|
110
|
+
this.languages = new Set(getRegisteredLanguages());
|
|
111
|
+
|
|
112
|
+
// Initialize cache
|
|
113
|
+
if (options.cache === false) {
|
|
114
|
+
this.cache = new SemanticCache({ enabled: false });
|
|
115
|
+
} else {
|
|
116
|
+
this.cache = options.cache ? new SemanticCache(options.cache) : semanticCache;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
analyze(input: string, language: string): SemanticAnalysisResult {
|
|
121
|
+
// Check language support
|
|
122
|
+
if (!this.supportsLanguage(language)) {
|
|
123
|
+
return {
|
|
124
|
+
confidence: 0,
|
|
125
|
+
errors: [`Language '${language}' is not supported for semantic parsing`],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Check cache first
|
|
130
|
+
const cached = this.cache.get(input, language);
|
|
131
|
+
if (cached) {
|
|
132
|
+
return cached;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Perform analysis
|
|
136
|
+
const result = this.analyzeUncached(input, language);
|
|
137
|
+
|
|
138
|
+
// Cache successful results
|
|
139
|
+
this.cache.set(input, language, result);
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Perform analysis without cache lookup.
|
|
146
|
+
*/
|
|
147
|
+
private analyzeUncached(input: string, language: string): SemanticAnalysisResult {
|
|
148
|
+
try {
|
|
149
|
+
// Tokenize
|
|
150
|
+
const tokenizer = getTokenizer(language);
|
|
151
|
+
if (!tokenizer) {
|
|
152
|
+
return {
|
|
153
|
+
confidence: 0,
|
|
154
|
+
errors: [`No tokenizer available for language '${language}'`],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const tokenStream = tokenizer.tokenize(input);
|
|
159
|
+
|
|
160
|
+
// Get patterns for this language
|
|
161
|
+
const patterns = getPatternsForLanguage(language);
|
|
162
|
+
if (patterns.length === 0) {
|
|
163
|
+
return {
|
|
164
|
+
confidence: 0,
|
|
165
|
+
errors: [`No patterns available for language '${language}'`],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Try to match patterns
|
|
170
|
+
const match = this.patternMatcher.matchBest(tokenStream, patterns);
|
|
171
|
+
|
|
172
|
+
if (!match) {
|
|
173
|
+
return {
|
|
174
|
+
confidence: 0,
|
|
175
|
+
errors: ['No pattern matched the input'],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Build semantic node from match
|
|
180
|
+
const node = this.buildSemanticNode(match);
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
confidence: match.confidence,
|
|
184
|
+
command: {
|
|
185
|
+
name: match.pattern.command,
|
|
186
|
+
roles: match.captured,
|
|
187
|
+
},
|
|
188
|
+
node,
|
|
189
|
+
tokensConsumed: match.consumedTokens,
|
|
190
|
+
};
|
|
191
|
+
} catch (error) {
|
|
192
|
+
return {
|
|
193
|
+
confidence: 0,
|
|
194
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
supportsLanguage(language: string): boolean {
|
|
200
|
+
return this.languages.has(language);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
supportedLanguages(): string[] {
|
|
204
|
+
return Array.from(this.languages);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
getCacheStats(): CacheStats {
|
|
208
|
+
return this.cache.getStats();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
clearCache(): void {
|
|
212
|
+
this.cache.clear();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
configureCache(config: Partial<SemanticCacheConfig>): void {
|
|
216
|
+
this.cache.configure(config);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private buildSemanticNode(match: PatternMatchResult): SemanticNode {
|
|
220
|
+
return {
|
|
221
|
+
kind: 'command',
|
|
222
|
+
action: match.pattern.command,
|
|
223
|
+
roles: match.captured,
|
|
224
|
+
metadata: {
|
|
225
|
+
patternId: match.pattern.id,
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// =============================================================================
|
|
232
|
+
// Factory Function
|
|
233
|
+
// =============================================================================
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Create a SemanticAnalyzer instance.
|
|
237
|
+
*
|
|
238
|
+
* @param options - Configuration options including cache settings
|
|
239
|
+
* @returns A new SemanticAnalyzer
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* // Default: uses shared global cache
|
|
243
|
+
* const analyzer = createSemanticAnalyzer();
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* // Custom cache size
|
|
247
|
+
* const analyzer = createSemanticAnalyzer({ cache: { maxSize: 500 } });
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* // Disable caching
|
|
251
|
+
* const analyzer = createSemanticAnalyzer({ cache: false });
|
|
252
|
+
*/
|
|
253
|
+
export function createSemanticAnalyzer(options?: SemanticAnalyzerOptions): SemanticAnalyzer {
|
|
254
|
+
return new SemanticAnalyzerImpl(options);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Re-export cache types for convenience
|
|
258
|
+
export type { SemanticCacheConfig, CacheStats } from './cache';
|
|
259
|
+
|
|
260
|
+
// =============================================================================
|
|
261
|
+
// Confidence Thresholds
|
|
262
|
+
// =============================================================================
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Default confidence threshold for preferring semantic parsing.
|
|
266
|
+
* If confidence is above this, use semantic result; otherwise fallback.
|
|
267
|
+
*/
|
|
268
|
+
export const DEFAULT_CONFIDENCE_THRESHOLD = 0.5;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* High confidence threshold for very certain matches.
|
|
272
|
+
*/
|
|
273
|
+
export const HIGH_CONFIDENCE_THRESHOLD = 0.8;
|
|
274
|
+
|
|
275
|
+
// =============================================================================
|
|
276
|
+
// Integration Helpers
|
|
277
|
+
// =============================================================================
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Determine if semantic analysis should be used based on confidence.
|
|
281
|
+
*/
|
|
282
|
+
export function shouldUseSemanticResult(
|
|
283
|
+
result: SemanticAnalysisResult,
|
|
284
|
+
threshold: number = DEFAULT_CONFIDENCE_THRESHOLD
|
|
285
|
+
): boolean {
|
|
286
|
+
return result.confidence >= threshold && result.command !== undefined;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Convert semantic roles to the format expected by core parser commands.
|
|
291
|
+
* This maps semantic roles to the positional/modifier structure used by
|
|
292
|
+
* the core command implementations.
|
|
293
|
+
*
|
|
294
|
+
* Role to preposition mapping:
|
|
295
|
+
* - patient → first positional arg
|
|
296
|
+
* - event → first positional arg
|
|
297
|
+
* - destination → 'into' (put) or 'on' (others)
|
|
298
|
+
* - source → 'from'
|
|
299
|
+
* - quantity → 'by'
|
|
300
|
+
* - duration → 'over' or 'for'
|
|
301
|
+
* - method → 'as'
|
|
302
|
+
* - style → 'with'
|
|
303
|
+
* - condition → 'if'
|
|
304
|
+
*/
|
|
305
|
+
export function rolesToCommandArgs(
|
|
306
|
+
roles: ReadonlyMap<SemanticRole, SemanticValue>,
|
|
307
|
+
command: ActionType
|
|
308
|
+
): {
|
|
309
|
+
args: SemanticValue[];
|
|
310
|
+
modifiers: Record<string, SemanticValue>;
|
|
311
|
+
} {
|
|
312
|
+
const args: SemanticValue[] = [];
|
|
313
|
+
const modifiers: Record<string, SemanticValue> = {};
|
|
314
|
+
|
|
315
|
+
for (const [role, value] of roles) {
|
|
316
|
+
switch (role) {
|
|
317
|
+
// Primary arguments (positional)
|
|
318
|
+
case 'patient':
|
|
319
|
+
case 'event':
|
|
320
|
+
args.push(value);
|
|
321
|
+
break;
|
|
322
|
+
|
|
323
|
+
// Destination: context-dependent preposition
|
|
324
|
+
case 'destination':
|
|
325
|
+
if (command === 'put') {
|
|
326
|
+
modifiers['into'] = value;
|
|
327
|
+
} else {
|
|
328
|
+
modifiers['on'] = value;
|
|
329
|
+
}
|
|
330
|
+
break;
|
|
331
|
+
|
|
332
|
+
// Source: always 'from'
|
|
333
|
+
case 'source':
|
|
334
|
+
modifiers['from'] = value;
|
|
335
|
+
break;
|
|
336
|
+
|
|
337
|
+
// Quantitative roles
|
|
338
|
+
case 'quantity':
|
|
339
|
+
modifiers['by'] = value;
|
|
340
|
+
break;
|
|
341
|
+
|
|
342
|
+
case 'duration':
|
|
343
|
+
modifiers['over'] = value;
|
|
344
|
+
break;
|
|
345
|
+
|
|
346
|
+
// Adverbial roles
|
|
347
|
+
case 'method':
|
|
348
|
+
modifiers['as'] = value;
|
|
349
|
+
break;
|
|
350
|
+
|
|
351
|
+
case 'style':
|
|
352
|
+
modifiers['with'] = value;
|
|
353
|
+
break;
|
|
354
|
+
|
|
355
|
+
// Conditional
|
|
356
|
+
case 'condition':
|
|
357
|
+
modifiers['if'] = value;
|
|
358
|
+
break;
|
|
359
|
+
|
|
360
|
+
// Agent (for future multi-actor systems)
|
|
361
|
+
case 'agent':
|
|
362
|
+
modifiers['agent'] = value;
|
|
363
|
+
break;
|
|
364
|
+
|
|
365
|
+
default:
|
|
366
|
+
// Unknown roles become modifiers using role name as key
|
|
367
|
+
modifiers[role] = value;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return { args, modifiers };
|
|
372
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bidirectional Converter
|
|
3
|
+
*
|
|
4
|
+
* Converts between natural language syntax and explicit syntax,
|
|
5
|
+
* and between different natural languages.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { SemanticNode } from '../types';
|
|
9
|
+
import { parse } from '../parser';
|
|
10
|
+
import { render, renderExplicit } from './renderer';
|
|
11
|
+
import { parseExplicit, isExplicitSyntax } from './parser';
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Bidirectional Conversion
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Convert natural language hyperscript to explicit syntax.
|
|
19
|
+
*
|
|
20
|
+
* @param input Natural language hyperscript
|
|
21
|
+
* @param sourceLanguage Source language code
|
|
22
|
+
* @returns Explicit syntax string
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* toExplicit('toggle .active on #button', 'en')
|
|
26
|
+
* // → '[toggle patient:.active destination:#button]'
|
|
27
|
+
*
|
|
28
|
+
* toExplicit('#button の .active を 切り替え', 'ja')
|
|
29
|
+
* // → '[toggle patient:.active destination:#button]'
|
|
30
|
+
*/
|
|
31
|
+
export function toExplicit(input: string, sourceLanguage: string): string {
|
|
32
|
+
// If already explicit, return as-is
|
|
33
|
+
if (isExplicitSyntax(input)) {
|
|
34
|
+
return input;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const node = parse(input, sourceLanguage);
|
|
38
|
+
return renderExplicit(node);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Convert explicit syntax to natural language.
|
|
43
|
+
*
|
|
44
|
+
* @param explicit Explicit syntax string
|
|
45
|
+
* @param targetLanguage Target language code
|
|
46
|
+
* @returns Natural language hyperscript
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* fromExplicit('[toggle patient:.active destination:#button]', 'en')
|
|
50
|
+
* // → 'toggle .active on #button'
|
|
51
|
+
*
|
|
52
|
+
* fromExplicit('[toggle patient:.active destination:#button]', 'ja')
|
|
53
|
+
* // → '#button の .active を 切り替え'
|
|
54
|
+
*/
|
|
55
|
+
export function fromExplicit(explicit: string, targetLanguage: string): string {
|
|
56
|
+
const node = parseExplicit(explicit);
|
|
57
|
+
return render(node, targetLanguage);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Translate hyperscript from one language to another.
|
|
62
|
+
*
|
|
63
|
+
* @param input Natural language hyperscript
|
|
64
|
+
* @param sourceLanguage Source language code
|
|
65
|
+
* @param targetLanguage Target language code
|
|
66
|
+
* @returns Translated hyperscript
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* translate('toggle .active on #button', 'en', 'ja')
|
|
70
|
+
* // → '#button の .active を 切り替え'
|
|
71
|
+
*
|
|
72
|
+
* translate('#button の .active を 切り替え', 'ja', 'ar')
|
|
73
|
+
* // → 'بدّل .active على #button'
|
|
74
|
+
*/
|
|
75
|
+
export function translate(input: string, sourceLanguage: string, targetLanguage: string): string {
|
|
76
|
+
// Handle explicit syntax
|
|
77
|
+
if (isExplicitSyntax(input)) {
|
|
78
|
+
return fromExplicit(input, targetLanguage);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Parse source language
|
|
82
|
+
const node = parse(input, sourceLanguage);
|
|
83
|
+
|
|
84
|
+
// Render in target language
|
|
85
|
+
return render(node, targetLanguage);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Parse input (either explicit or natural language) to semantic node.
|
|
90
|
+
*
|
|
91
|
+
* @param input Hyperscript input (explicit or natural)
|
|
92
|
+
* @param language Language code (required for natural, ignored for explicit)
|
|
93
|
+
* @returns Semantic node
|
|
94
|
+
*/
|
|
95
|
+
export function parseAny(input: string, language: string): SemanticNode {
|
|
96
|
+
if (isExplicitSyntax(input)) {
|
|
97
|
+
return parseExplicit(input);
|
|
98
|
+
}
|
|
99
|
+
return parse(input, language);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Round-trip validation: parse and re-render to verify consistency.
|
|
104
|
+
*
|
|
105
|
+
* When called with 2 arguments, returns an object with validation info.
|
|
106
|
+
* When called with 3 arguments, returns the rendered string directly.
|
|
107
|
+
*
|
|
108
|
+
* @param input Original input
|
|
109
|
+
* @param sourceLanguage Source language code
|
|
110
|
+
* @param targetLanguage Target language code (optional, if provided returns string only)
|
|
111
|
+
* @returns Object with original, semantic, re-rendered, and match status (or just string if targetLanguage provided)
|
|
112
|
+
*/
|
|
113
|
+
export function roundTrip(
|
|
114
|
+
input: string,
|
|
115
|
+
sourceLanguage: string,
|
|
116
|
+
targetLanguage?: string
|
|
117
|
+
):
|
|
118
|
+
| string
|
|
119
|
+
| {
|
|
120
|
+
original: string;
|
|
121
|
+
semantic: SemanticNode;
|
|
122
|
+
rendered: string;
|
|
123
|
+
matches: boolean;
|
|
124
|
+
} {
|
|
125
|
+
const semantic = parseAny(input, sourceLanguage);
|
|
126
|
+
const outputLanguage = targetLanguage ?? sourceLanguage;
|
|
127
|
+
const rendered = isExplicitSyntax(input)
|
|
128
|
+
? renderExplicit(semantic)
|
|
129
|
+
: render(semantic, outputLanguage);
|
|
130
|
+
|
|
131
|
+
// If target language is explicitly provided, return just the rendered string
|
|
132
|
+
if (targetLanguage !== undefined) {
|
|
133
|
+
return rendered;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Normalize for comparison (trim whitespace, lowercase)
|
|
137
|
+
const normalizedOriginal = input.trim().toLowerCase();
|
|
138
|
+
const normalizedRendered = rendered.trim().toLowerCase();
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
original: input,
|
|
142
|
+
semantic,
|
|
143
|
+
rendered,
|
|
144
|
+
matches: normalizedOriginal === normalizedRendered,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// =============================================================================
|
|
149
|
+
// Utility Functions
|
|
150
|
+
// =============================================================================
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get all translations of a hyperscript statement.
|
|
154
|
+
*
|
|
155
|
+
* @param input Hyperscript input
|
|
156
|
+
* @param sourceLanguage Source language (or 'explicit')
|
|
157
|
+
* @param targetLanguages List of target language codes (defaults to all 13 supported languages)
|
|
158
|
+
* @returns Object mapping language codes to translations
|
|
159
|
+
*/
|
|
160
|
+
export function getAllTranslations(
|
|
161
|
+
input: string,
|
|
162
|
+
sourceLanguage: string,
|
|
163
|
+
targetLanguages: string[] = [
|
|
164
|
+
'en',
|
|
165
|
+
'ja',
|
|
166
|
+
'ar',
|
|
167
|
+
'es',
|
|
168
|
+
'ko',
|
|
169
|
+
'zh',
|
|
170
|
+
'tr',
|
|
171
|
+
'pt',
|
|
172
|
+
'fr',
|
|
173
|
+
'de',
|
|
174
|
+
'id',
|
|
175
|
+
'qu',
|
|
176
|
+
'sw',
|
|
177
|
+
]
|
|
178
|
+
): Record<string, string> {
|
|
179
|
+
const result: Record<string, string> = {};
|
|
180
|
+
|
|
181
|
+
// Parse once
|
|
182
|
+
const node = parseAny(input, sourceLanguage);
|
|
183
|
+
|
|
184
|
+
// Render for each target language
|
|
185
|
+
for (const lang of targetLanguages) {
|
|
186
|
+
result[lang] = render(node, lang);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Also include explicit
|
|
190
|
+
result['explicit'] = renderExplicit(node);
|
|
191
|
+
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Validate that a translation is semantically equivalent.
|
|
197
|
+
*
|
|
198
|
+
* @param original Original hyperscript
|
|
199
|
+
* @param translated Translated hyperscript
|
|
200
|
+
* @param originalLang Original language
|
|
201
|
+
* @param translatedLang Translated language
|
|
202
|
+
* @returns true if semantically equivalent
|
|
203
|
+
*/
|
|
204
|
+
export function validateTranslation(
|
|
205
|
+
original: string,
|
|
206
|
+
translated: string,
|
|
207
|
+
originalLang: string,
|
|
208
|
+
translatedLang: string
|
|
209
|
+
): boolean {
|
|
210
|
+
try {
|
|
211
|
+
const originalNode = parseAny(original, originalLang);
|
|
212
|
+
const translatedNode = parseAny(translated, translatedLang);
|
|
213
|
+
|
|
214
|
+
// Compare semantic content
|
|
215
|
+
if (originalNode.action !== translatedNode.action) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Compare roles
|
|
220
|
+
for (const [role, value] of originalNode.roles) {
|
|
221
|
+
const translatedValue = translatedNode.roles.get(role);
|
|
222
|
+
if (!translatedValue) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Deep compare values
|
|
227
|
+
if (!semanticValuesEqual(value, translatedValue)) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return true;
|
|
233
|
+
} catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Check if two semantic values are equal.
|
|
240
|
+
*/
|
|
241
|
+
function semanticValuesEqual(a: any, b: any): boolean {
|
|
242
|
+
if (a.type !== b.type) return false;
|
|
243
|
+
|
|
244
|
+
switch (a.type) {
|
|
245
|
+
case 'literal':
|
|
246
|
+
return a.value === b.value;
|
|
247
|
+
case 'selector':
|
|
248
|
+
return a.value === b.value;
|
|
249
|
+
case 'reference':
|
|
250
|
+
return a.value === b.value;
|
|
251
|
+
case 'property-path':
|
|
252
|
+
return semanticValuesEqual(a.object, b.object) && a.property === b.property;
|
|
253
|
+
case 'expression':
|
|
254
|
+
return a.raw === b.raw;
|
|
255
|
+
default:
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explicit Mode Module
|
|
3
|
+
*
|
|
4
|
+
* Provides the explicit [command role:value] syntax for learning,
|
|
5
|
+
* debugging, and language-neutral representation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { parseExplicit, isExplicitSyntax } from './parser';
|
|
9
|
+
export { SemanticRendererImpl, semanticRenderer, render, renderExplicit } from './renderer';
|
|
10
|
+
export {
|
|
11
|
+
toExplicit,
|
|
12
|
+
fromExplicit,
|
|
13
|
+
translate,
|
|
14
|
+
parseAny,
|
|
15
|
+
roundTrip,
|
|
16
|
+
getAllTranslations,
|
|
17
|
+
validateTranslation,
|
|
18
|
+
} from './converter';
|