@lokascript/semantic 1.0.0 → 1.1.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.
Files changed (162) hide show
  1. package/dist/browser-ar.ar.global.js +2 -2
  2. package/dist/browser-core.core.global.js +2 -2
  3. package/dist/browser-de.de.global.js +2 -2
  4. package/dist/browser-east-asian.east-asian.global.js +2 -2
  5. package/dist/browser-en-tr.en-tr.global.js +2 -2
  6. package/dist/browser-en.en.global.js +2 -2
  7. package/dist/browser-es-en.es-en.global.js +2 -2
  8. package/dist/browser-es.es.global.js +2 -2
  9. package/dist/browser-fr.fr.global.js +2 -2
  10. package/dist/browser-id.id.global.js +2 -2
  11. package/dist/browser-ja.ja.global.js +2 -2
  12. package/dist/browser-ko.ko.global.js +2 -2
  13. package/dist/browser-lazy.lazy.global.js +2 -2
  14. package/dist/browser-priority.priority.global.js +2 -2
  15. package/dist/browser-pt.pt.global.js +2 -2
  16. package/dist/browser-qu.qu.global.js +2 -2
  17. package/dist/browser-sw.sw.global.js +2 -2
  18. package/dist/browser-tr.tr.global.js +2 -2
  19. package/dist/browser-western.western.global.js +2 -2
  20. package/dist/browser-zh.zh.global.js +2 -2
  21. package/dist/browser.global.js +2 -2
  22. package/dist/browser.global.js.map +1 -1
  23. package/dist/index.cjs +13042 -17462
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +49 -5
  26. package/dist/index.d.ts +49 -5
  27. package/dist/index.js +14044 -18464
  28. package/dist/index.js.map +1 -1
  29. package/dist/languages/ar.d.ts +1 -1
  30. package/dist/languages/ar.js +31 -44
  31. package/dist/languages/ar.js.map +1 -1
  32. package/dist/languages/de.d.ts +1 -1
  33. package/dist/languages/de.js +14 -2
  34. package/dist/languages/de.js.map +1 -1
  35. package/dist/languages/en.d.ts +1 -1
  36. package/dist/languages/en.js +558 -12
  37. package/dist/languages/en.js.map +1 -1
  38. package/dist/languages/es.d.ts +1 -1
  39. package/dist/languages/es.js +16 -0
  40. package/dist/languages/es.js.map +1 -1
  41. package/dist/languages/fr.d.ts +1 -1
  42. package/dist/languages/fr.js +14 -2
  43. package/dist/languages/fr.js.map +1 -1
  44. package/dist/languages/id.d.ts +1 -1
  45. package/dist/languages/id.js +14 -2
  46. package/dist/languages/id.js.map +1 -1
  47. package/dist/languages/ja.d.ts +1 -1
  48. package/dist/languages/ja.js +18 -3
  49. package/dist/languages/ja.js.map +1 -1
  50. package/dist/languages/ko.d.ts +8 -1
  51. package/dist/languages/ko.js +75 -43
  52. package/dist/languages/ko.js.map +1 -1
  53. package/dist/languages/pt.d.ts +1 -1
  54. package/dist/languages/pt.js +17 -0
  55. package/dist/languages/pt.js.map +1 -1
  56. package/dist/languages/qu.d.ts +12 -1
  57. package/dist/languages/qu.js +77 -2
  58. package/dist/languages/qu.js.map +1 -1
  59. package/dist/languages/sw.d.ts +1 -1
  60. package/dist/languages/sw.js.map +1 -1
  61. package/dist/languages/tr.d.ts +9 -1
  62. package/dist/languages/tr.js +96 -72
  63. package/dist/languages/tr.js.map +1 -1
  64. package/dist/languages/zh.d.ts +1 -1
  65. package/dist/languages/zh.js +16 -0
  66. package/dist/languages/zh.js.map +1 -1
  67. package/dist/{types-C4dcj53L.d.ts → types-BY3Id07j.d.ts} +20 -5
  68. package/package.json +20 -29
  69. package/src/generators/command-schemas.ts +21 -10
  70. package/src/generators/event-handler-generator.ts +50 -44
  71. package/src/generators/language-profiles.ts +6 -0
  72. package/src/generators/pattern-generator.ts +883 -1
  73. package/src/generators/profiles/arabic.ts +19 -3
  74. package/src/generators/profiles/bengali.ts +12 -1
  75. package/src/generators/profiles/chinese.ts +15 -0
  76. package/src/generators/profiles/french.ts +12 -1
  77. package/src/generators/profiles/german.ts +12 -1
  78. package/src/generators/profiles/hebrew.ts +148 -0
  79. package/src/generators/profiles/hindi.ts +12 -1
  80. package/src/generators/profiles/index.ts +2 -0
  81. package/src/generators/profiles/indonesian.ts +12 -1
  82. package/src/generators/profiles/italian.ts +16 -0
  83. package/src/generators/profiles/japanese.ts +11 -2
  84. package/src/generators/profiles/korean.ts +15 -1
  85. package/src/generators/profiles/polish.ts +12 -0
  86. package/src/generators/profiles/portuguese.ts +16 -0
  87. package/src/generators/profiles/russian.ts +11 -0
  88. package/src/generators/profiles/spanish.ts +15 -0
  89. package/src/generators/profiles/spanishMexico.ts +176 -0
  90. package/src/generators/profiles/thai.ts +11 -0
  91. package/src/generators/profiles/turkish.ts +49 -7
  92. package/src/generators/profiles/types.ts +21 -5
  93. package/src/generators/profiles/ukrainian.ts +11 -0
  94. package/src/generators/profiles/vietnamese.ts +11 -0
  95. package/src/language-building-schema.ts +111 -0
  96. package/src/languages/_all.ts +5 -1
  97. package/src/languages/es-MX.ts +32 -0
  98. package/src/languages/he.ts +15 -0
  99. package/src/parser/pattern-matcher.ts +10 -1
  100. package/src/parser/semantic-parser.ts +3 -0
  101. package/src/patterns/add/ar.ts +3 -59
  102. package/src/patterns/add/index.ts +5 -1
  103. package/src/patterns/add/ja.ts +3 -81
  104. package/src/patterns/add/ko.ts +3 -62
  105. package/src/patterns/add/qu.ts +69 -0
  106. package/src/patterns/add/tr.ts +3 -59
  107. package/src/patterns/builders.ts +1 -0
  108. package/src/patterns/decrement/tr.ts +3 -36
  109. package/src/patterns/event-handler/ar.ts +3 -139
  110. package/src/patterns/event-handler/he.ts +15 -0
  111. package/src/patterns/event-handler/index.ts +5 -1
  112. package/src/patterns/event-handler/ja.ts +3 -106
  113. package/src/patterns/event-handler/ko.ts +3 -121
  114. package/src/patterns/event-handler/ms.ts +45 -20
  115. package/src/patterns/event-handler/tr.ts +3 -158
  116. package/src/patterns/get/ar.ts +3 -37
  117. package/src/patterns/get/ja.ts +3 -41
  118. package/src/patterns/get/ko.ts +3 -41
  119. package/src/patterns/grammar-transformed/ja.ts +3 -1701
  120. package/src/patterns/grammar-transformed/ko.ts +3 -1299
  121. package/src/patterns/grammar-transformed/tr.ts +3 -1055
  122. package/src/patterns/hide/ar.ts +3 -55
  123. package/src/patterns/hide/ja.ts +3 -57
  124. package/src/patterns/hide/ko.ts +3 -57
  125. package/src/patterns/hide/tr.ts +3 -53
  126. package/src/patterns/increment/tr.ts +3 -40
  127. package/src/patterns/put/ar.ts +3 -62
  128. package/src/patterns/put/ja.ts +3 -63
  129. package/src/patterns/put/ko.ts +3 -55
  130. package/src/patterns/put/tr.ts +3 -55
  131. package/src/patterns/remove/ar.ts +3 -59
  132. package/src/patterns/remove/index.ts +5 -1
  133. package/src/patterns/remove/ja.ts +3 -62
  134. package/src/patterns/remove/ko.ts +3 -66
  135. package/src/patterns/remove/qu.ts +69 -0
  136. package/src/patterns/remove/tr.ts +3 -66
  137. package/src/patterns/set/ar.ts +3 -72
  138. package/src/patterns/set/ja.ts +3 -74
  139. package/src/patterns/set/ko.ts +3 -73
  140. package/src/patterns/set/tr.ts +3 -95
  141. package/src/patterns/show/ar.ts +3 -55
  142. package/src/patterns/show/ja.ts +3 -57
  143. package/src/patterns/show/ko.ts +3 -61
  144. package/src/patterns/show/tr.ts +3 -53
  145. package/src/patterns/take/ar.ts +3 -39
  146. package/src/patterns/toggle/ar.ts +3 -49
  147. package/src/patterns/toggle/index.ts +5 -1
  148. package/src/patterns/toggle/ja.ts +3 -144
  149. package/src/patterns/toggle/ko.ts +3 -101
  150. package/src/patterns/toggle/qu.ts +90 -0
  151. package/src/patterns/toggle/tr.ts +3 -76
  152. package/src/registry.ts +179 -15
  153. package/src/tokenizers/arabic.ts +13 -46
  154. package/src/tokenizers/bengali.ts +2 -16
  155. package/src/tokenizers/he.ts +542 -0
  156. package/src/tokenizers/index.ts +1 -0
  157. package/src/tokenizers/japanese.ts +3 -1
  158. package/src/tokenizers/korean.ts +104 -48
  159. package/src/tokenizers/ms.ts +3 -0
  160. package/src/tokenizers/quechua.ts +101 -2
  161. package/src/tokenizers/turkish.ts +64 -69
  162. package/src/types.ts +13 -0
@@ -1644,7 +1644,8 @@ var putSchema = {
1644
1644
  required: true,
1645
1645
  expectedTypes: ["literal", "selector", "reference", "expression"],
1646
1646
  svoPosition: 1,
1647
- sovPosition: 2
1647
+ sovPosition: 1
1648
+ // SOV: patient comes first (を marker)
1648
1649
  },
1649
1650
  {
1650
1651
  role: "destination",
@@ -1652,7 +1653,8 @@ var putSchema = {
1652
1653
  required: true,
1653
1654
  expectedTypes: ["selector", "reference"],
1654
1655
  svoPosition: 2,
1655
- sovPosition: 1
1656
+ sovPosition: 2
1657
+ // SOV: destination comes second (に/에/a marker)
1656
1658
  }
1657
1659
  ],
1658
1660
  // Runtime error documentation
@@ -1700,14 +1702,23 @@ var setSchema = {
1700
1702
  role: "destination",
1701
1703
  description: "The property or variable to set",
1702
1704
  required: true,
1703
- expectedTypes: ["selector", "reference"],
1705
+ expectedTypes: ["selector", "reference", "expression"],
1704
1706
  svoPosition: 1,
1705
1707
  sovPosition: 1,
1706
1708
  // Override destination marker for English (remove 'on', use no marker)
1707
- // Other languages keep their default destination markers
1709
+ // SOV languages swap markers: variable gets patient marker (を/를/i)
1710
+ // Arabic (VSO): no marker before variable
1708
1711
  markerOverride: {
1709
- en: ""
1712
+ en: "",
1710
1713
  // No marker before destination in English: "set :x to 5"
1714
+ ja: "\u3092",
1715
+ // "x を 10 に 設定" - variable gets object marker
1716
+ ko: "\uB97C",
1717
+ // "x 를 10 으로 설정" - variable gets object marker
1718
+ tr: "i",
1719
+ // "x i 10 e ayarla" - variable gets accusative marker
1720
+ ar: ""
1721
+ // "عيّن x إلى 10" - no marker before variable
1711
1722
  }
1712
1723
  },
1713
1724
  {
@@ -1718,7 +1729,8 @@ var setSchema = {
1718
1729
  svoPosition: 2,
1719
1730
  sovPosition: 2,
1720
1731
  // Override patient marker for SVO languages with their native prepositions
1721
- // SOV languages (Korean, Japanese, Turkish) use their default object markers
1732
+ // SOV languages swap markers: value gets destination marker (に/으로/e)
1733
+ // Arabic (VSO): إلى preposition before value
1722
1734
  markerOverride: {
1723
1735
  en: "to",
1724
1736
  // "set :x to 5"
@@ -1730,8 +1742,16 @@ var setSchema = {
1730
1742
  // "définir x à 10"
1731
1743
  de: "auf",
1732
1744
  // "setze x auf 10"
1733
- id: "ke"
1745
+ id: "ke",
1734
1746
  // "atur x ke 10"
1747
+ ja: "\u306B",
1748
+ // "x を 10 に 設定" - value gets destination marker
1749
+ ko: "\uC73C\uB85C",
1750
+ // "x 를 10 으로 설정" - value gets manner/instrument marker
1751
+ tr: "e",
1752
+ // "x i 10 e ayarla" - value gets dative marker
1753
+ ar: "\u0625\u0644\u0649"
1754
+ // "عيّن x إلى 10" - value gets preposition "to"
1735
1755
  }
1736
1756
  }
1737
1757
  ],
@@ -2049,18 +2069,23 @@ var getCommandSchema = {
2049
2069
  expectedTypes: ["selector", "reference", "expression"],
2050
2070
  svoPosition: 1,
2051
2071
  sovPosition: 2,
2052
- // No marker before source for simple GET pattern: "get #element" not "get from #element"
2072
+ // Marker overrides for GET pattern
2073
+ // SOV languages use object markers, SVO languages have no marker
2053
2074
  markerOverride: {
2054
2075
  en: "",
2055
2076
  es: "",
2056
2077
  pt: "",
2057
2078
  fr: "",
2058
2079
  de: "",
2059
- ja: "",
2080
+ ja: "\u3092",
2081
+ // Japanese object marker: #element を 取得
2060
2082
  zh: "",
2061
- ko: "",
2062
- ar: "",
2063
- tr: "",
2083
+ ko: "\uB97C",
2084
+ // Korean object marker: #element 를 가져오기
2085
+ ar: "\u0639\u0644\u0649",
2086
+ // Arabic preposition: احصل على #element
2087
+ tr: "i",
2088
+ // Turkish accusative: #element i al
2064
2089
  id: ""
2065
2090
  }
2066
2091
  },
@@ -2881,9 +2906,530 @@ function generatePatternsForLanguage(profile, config = defaultConfig) {
2881
2906
  }
2882
2907
  const variants = generatePatternVariants(schema, profile, config);
2883
2908
  patterns.push(...variants);
2909
+ if (profile.eventHandler?.eventMarker) {
2910
+ const eventHandlerPatterns = generateEventHandlerPatterns(schema, profile, config);
2911
+ patterns.push(...eventHandlerPatterns);
2912
+ }
2913
+ }
2914
+ return patterns;
2915
+ }
2916
+ function generateEventHandlerPatterns(commandSchema, profile, config = defaultConfig) {
2917
+ if (!profile.eventHandler || !profile.eventHandler.eventMarker) {
2918
+ return [];
2919
+ }
2920
+ const patterns = [];
2921
+ const eventMarker = profile.eventHandler.eventMarker;
2922
+ const keyword = profile.keywords[commandSchema.action];
2923
+ if (!keyword) {
2924
+ return [];
2925
+ }
2926
+ const requiredRoles = commandSchema.roles.filter((r) => r.required);
2927
+ const hasTwoRequiredRoles = requiredRoles.length === 2;
2928
+ if (profile.wordOrder === "SOV") {
2929
+ if (hasTwoRequiredRoles) {
2930
+ patterns.push(
2931
+ generateSOVTwoRoleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2932
+ );
2933
+ } else {
2934
+ patterns.push(
2935
+ generateSOVEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2936
+ );
2937
+ const markerWords = eventMarker.primary.split(/\s+/);
2938
+ const hasNoSpaceAlternative = eventMarker.alternatives?.some(
2939
+ (alt) => !alt.includes(" ") && alt.length > 1
2940
+ );
2941
+ if (markerWords.length > 1 && hasNoSpaceAlternative) {
2942
+ patterns.push(
2943
+ generateSOVCompactEventHandlerPattern(
2944
+ commandSchema,
2945
+ profile,
2946
+ keyword,
2947
+ eventMarker,
2948
+ config
2949
+ )
2950
+ );
2951
+ }
2952
+ patterns.push(
2953
+ generateSOVSimpleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2954
+ );
2955
+ const temporalPattern = generateSOVTemporalEventHandlerPattern(
2956
+ commandSchema,
2957
+ profile,
2958
+ keyword,
2959
+ config
2960
+ );
2961
+ if (temporalPattern) {
2962
+ patterns.push(temporalPattern);
2963
+ }
2964
+ }
2965
+ } else if (profile.wordOrder === "VSO") {
2966
+ if (hasTwoRequiredRoles) {
2967
+ patterns.push(
2968
+ generateVSOTwoRoleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2969
+ );
2970
+ } else {
2971
+ patterns.push(
2972
+ generateVSOEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2973
+ );
2974
+ if (profile.eventHandler?.negationMarker) {
2975
+ patterns.push(
2976
+ generateVSONegatedEventHandlerPattern(
2977
+ commandSchema,
2978
+ profile,
2979
+ keyword,
2980
+ eventMarker,
2981
+ config
2982
+ )
2983
+ );
2984
+ }
2985
+ if (profile.tokenization?.prefixes) {
2986
+ patterns.push(
2987
+ generateVSOProcliticEventHandlerPattern(commandSchema, profile, keyword, config)
2988
+ );
2989
+ }
2990
+ }
2991
+ } else {
2992
+ if (hasTwoRequiredRoles) {
2993
+ patterns.push(
2994
+ generateVSOTwoRoleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2995
+ );
2996
+ } else {
2997
+ patterns.push(
2998
+ generateVSOEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config)
2999
+ );
3000
+ }
2884
3001
  }
2885
3002
  return patterns;
2886
3003
  }
3004
+ function generateSOVEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3005
+ const tokens = [];
3006
+ tokens.push({ type: "role", role: "event", optional: false });
3007
+ if (eventMarker.position === "after") {
3008
+ const markerWords = eventMarker.primary.split(/\s+/);
3009
+ if (markerWords.length > 1) {
3010
+ for (const word of markerWords) {
3011
+ tokens.push({ type: "literal", value: word });
3012
+ }
3013
+ } else {
3014
+ const markerToken = eventMarker.alternatives ? { type: "literal", value: eventMarker.primary, alternatives: eventMarker.alternatives } : { type: "literal", value: eventMarker.primary };
3015
+ tokens.push(markerToken);
3016
+ }
3017
+ }
3018
+ const destMarker = profile.roleMarkers.destination;
3019
+ if (destMarker) {
3020
+ tokens.push({
3021
+ type: "group",
3022
+ optional: true,
3023
+ tokens: [
3024
+ { type: "role", role: "destination", optional: true },
3025
+ destMarker.alternatives ? { type: "literal", value: destMarker.primary, alternatives: destMarker.alternatives } : { type: "literal", value: destMarker.primary }
3026
+ ]
3027
+ });
3028
+ }
3029
+ tokens.push({ type: "role", role: "patient", optional: false });
3030
+ const patientMarker = profile.roleMarkers.patient;
3031
+ if (patientMarker) {
3032
+ const patMarkerToken = patientMarker.alternatives ? { type: "literal", value: patientMarker.primary, alternatives: patientMarker.alternatives } : { type: "literal", value: patientMarker.primary };
3033
+ tokens.push(patMarkerToken);
3034
+ }
3035
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3036
+ tokens.push(verbToken);
3037
+ return {
3038
+ id: `${commandSchema.action}-event-${profile.code}-sov`,
3039
+ language: profile.code,
3040
+ command: "on",
3041
+ // This is an event handler pattern
3042
+ priority: (config.basePriority ?? 100) + 50,
3043
+ // Higher priority than simple commands
3044
+ template: {
3045
+ format: `{event} ${eventMarker.primary} {destination?} {patient} ${patientMarker?.primary || ""} ${keyword.primary}`,
3046
+ tokens
3047
+ },
3048
+ extraction: {
3049
+ action: { value: commandSchema.action },
3050
+ // Extract the wrapped command
3051
+ event: { fromRole: "event" },
3052
+ patient: { fromRole: "patient" },
3053
+ destination: { fromRole: "destination", default: { type: "reference", value: "me" } }
3054
+ }
3055
+ };
3056
+ }
3057
+ function generateSOVCompactEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3058
+ const tokens = [];
3059
+ tokens.push({ type: "role", role: "event", optional: false });
3060
+ const noSpaceAlternatives = eventMarker.alternatives?.filter((alt) => !alt.includes(" ") && alt.length > 1) || [];
3061
+ if (noSpaceAlternatives.length > 0) {
3062
+ tokens.push({
3063
+ type: "literal",
3064
+ value: noSpaceAlternatives[0],
3065
+ alternatives: noSpaceAlternatives.slice(1)
3066
+ });
3067
+ }
3068
+ const destMarker = profile.roleMarkers.destination;
3069
+ if (destMarker) {
3070
+ tokens.push({
3071
+ type: "group",
3072
+ optional: true,
3073
+ tokens: [
3074
+ { type: "role", role: "destination", optional: true },
3075
+ destMarker.alternatives ? { type: "literal", value: destMarker.primary, alternatives: destMarker.alternatives } : { type: "literal", value: destMarker.primary }
3076
+ ]
3077
+ });
3078
+ }
3079
+ tokens.push({ type: "role", role: "patient", optional: false });
3080
+ const patientMarker = profile.roleMarkers.patient;
3081
+ if (patientMarker) {
3082
+ const patMarkerToken = patientMarker.alternatives ? { type: "literal", value: patientMarker.primary, alternatives: patientMarker.alternatives } : { type: "literal", value: patientMarker.primary };
3083
+ tokens.push(patMarkerToken);
3084
+ }
3085
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3086
+ tokens.push(verbToken);
3087
+ return {
3088
+ id: `${commandSchema.action}-event-${profile.code}-sov-compact`,
3089
+ language: profile.code,
3090
+ command: "on",
3091
+ // This is an event handler pattern
3092
+ priority: (config.basePriority ?? 100) + 52,
3093
+ // Slightly higher priority for compact forms
3094
+ template: {
3095
+ format: `{event}${noSpaceAlternatives[0] || ""} {patient} ${keyword.primary}`,
3096
+ tokens
3097
+ },
3098
+ extraction: {
3099
+ action: { value: commandSchema.action },
3100
+ // Extract the wrapped command
3101
+ event: { fromRole: "event" },
3102
+ patient: { fromRole: "patient" },
3103
+ destination: { fromRole: "destination", default: { type: "reference", value: "me" } }
3104
+ }
3105
+ };
3106
+ }
3107
+ function generateSOVSimpleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3108
+ const tokens = [];
3109
+ tokens.push({ type: "role", role: "event", optional: false });
3110
+ if (eventMarker.position === "after") {
3111
+ const markerWords = eventMarker.primary.split(/\s+/);
3112
+ if (markerWords.length > 1) {
3113
+ for (const word of markerWords) {
3114
+ tokens.push({ type: "literal", value: word });
3115
+ }
3116
+ } else {
3117
+ const markerToken = eventMarker.alternatives ? { type: "literal", value: eventMarker.primary, alternatives: eventMarker.alternatives } : { type: "literal", value: eventMarker.primary };
3118
+ tokens.push(markerToken);
3119
+ }
3120
+ }
3121
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3122
+ tokens.push(verbToken);
3123
+ return {
3124
+ id: `${commandSchema.action}-event-${profile.code}-sov-simple`,
3125
+ language: profile.code,
3126
+ command: "on",
3127
+ priority: (config.basePriority ?? 100) + 48,
3128
+ // Lower than full pattern (50) but higher than base
3129
+ template: {
3130
+ format: `{event} ${eventMarker.primary} ${keyword.primary}`,
3131
+ tokens
3132
+ },
3133
+ extraction: {
3134
+ action: { value: commandSchema.action },
3135
+ event: { fromRole: "event" },
3136
+ patient: { default: { type: "reference", value: "me" } }
3137
+ // Default to 'me'
3138
+ }
3139
+ };
3140
+ }
3141
+ function generateSOVTemporalEventHandlerPattern(commandSchema, profile, keyword, config) {
3142
+ const temporalMarkers = profile.eventHandler?.temporalMarkers;
3143
+ if (!temporalMarkers || temporalMarkers.length === 0) return null;
3144
+ const tokens = [];
3145
+ tokens.push({ type: "role", role: "event", optional: false });
3146
+ if (profile.possessive?.marker) {
3147
+ tokens.push({
3148
+ type: "group",
3149
+ optional: true,
3150
+ tokens: [{ type: "literal", value: profile.possessive.marker }]
3151
+ });
3152
+ }
3153
+ tokens.push({
3154
+ type: "literal",
3155
+ value: temporalMarkers[0],
3156
+ alternatives: temporalMarkers.slice(1)
3157
+ });
3158
+ tokens.push({ type: "role", role: "patient", optional: false });
3159
+ const patientMarker = profile.roleMarkers.patient;
3160
+ if (patientMarker?.primary) {
3161
+ const patMarkerToken = patientMarker.alternatives ? { type: "literal", value: patientMarker.primary, alternatives: patientMarker.alternatives } : { type: "literal", value: patientMarker.primary };
3162
+ tokens.push(patMarkerToken);
3163
+ }
3164
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3165
+ tokens.push(verbToken);
3166
+ return {
3167
+ id: `${commandSchema.action}-event-${profile.code}-sov-temporal`,
3168
+ language: profile.code,
3169
+ command: "on",
3170
+ priority: (config.basePriority ?? 100) + 49,
3171
+ // Between simple and full pattern
3172
+ template: {
3173
+ format: `{event} ${temporalMarkers[0]} {patient} ${keyword.primary}`,
3174
+ tokens
3175
+ },
3176
+ extraction: {
3177
+ action: { value: commandSchema.action },
3178
+ event: { fromRole: "event" },
3179
+ patient: { fromRole: "patient" }
3180
+ }
3181
+ };
3182
+ }
3183
+ function generateVSOEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3184
+ const tokens = [];
3185
+ if (eventMarker.position === "before") {
3186
+ const markerToken = eventMarker.alternatives ? { type: "literal", value: eventMarker.primary, alternatives: eventMarker.alternatives } : { type: "literal", value: eventMarker.primary };
3187
+ tokens.push(markerToken);
3188
+ }
3189
+ tokens.push({ type: "role", role: "event", optional: false });
3190
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3191
+ tokens.push(verbToken);
3192
+ tokens.push({ type: "role", role: "patient", optional: false });
3193
+ const destMarker = profile.roleMarkers.destination;
3194
+ if (destMarker) {
3195
+ tokens.push({
3196
+ type: "group",
3197
+ optional: true,
3198
+ tokens: [
3199
+ destMarker.alternatives ? { type: "literal", value: destMarker.primary, alternatives: destMarker.alternatives } : { type: "literal", value: destMarker.primary },
3200
+ { type: "role", role: "destination", optional: true }
3201
+ ]
3202
+ });
3203
+ }
3204
+ return {
3205
+ id: `${commandSchema.action}-event-${profile.code}-vso`,
3206
+ language: profile.code,
3207
+ command: "on",
3208
+ // This is an event handler pattern
3209
+ priority: (config.basePriority ?? 100) + 50,
3210
+ // Higher priority than simple commands
3211
+ template: {
3212
+ format: `${eventMarker.primary} {event} ${keyword.primary} {patient} ${destMarker?.primary || ""} {destination?}`,
3213
+ tokens
3214
+ },
3215
+ extraction: {
3216
+ action: { value: commandSchema.action },
3217
+ // Extract the wrapped command
3218
+ event: { fromRole: "event" },
3219
+ patient: { fromRole: "patient" },
3220
+ destination: { fromRole: "destination", default: { type: "reference", value: "me" } }
3221
+ }
3222
+ };
3223
+ }
3224
+ function generateSOVTwoRoleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3225
+ const tokens = [];
3226
+ tokens.push({ type: "role", role: "event", optional: false });
3227
+ if (eventMarker.position === "after") {
3228
+ const markerWords = eventMarker.primary.split(/\s+/);
3229
+ if (markerWords.length > 1) {
3230
+ for (const word of markerWords) {
3231
+ tokens.push({ type: "literal", value: word });
3232
+ }
3233
+ } else {
3234
+ const markerToken = eventMarker.alternatives ? { type: "literal", value: eventMarker.primary, alternatives: eventMarker.alternatives } : { type: "literal", value: eventMarker.primary };
3235
+ tokens.push(markerToken);
3236
+ }
3237
+ }
3238
+ const requiredRoles = commandSchema.roles.filter((r) => r.required);
3239
+ const sortedRoles = [...requiredRoles].sort((a, b) => {
3240
+ const aPos = a.sovPosition ?? 999;
3241
+ const bPos = b.sovPosition ?? 999;
3242
+ return aPos - bPos;
3243
+ });
3244
+ for (const roleSpec of sortedRoles) {
3245
+ tokens.push({ type: "role", role: roleSpec.role, optional: false });
3246
+ let marker;
3247
+ let markerAlternatives;
3248
+ if (roleSpec.markerOverride && roleSpec.markerOverride[profile.code]) {
3249
+ marker = roleSpec.markerOverride[profile.code];
3250
+ } else {
3251
+ const roleMarker = profile.roleMarkers[roleSpec.role];
3252
+ if (roleMarker) {
3253
+ marker = roleMarker.primary;
3254
+ markerAlternatives = roleMarker.alternatives;
3255
+ }
3256
+ }
3257
+ if (marker) {
3258
+ const markerToken = markerAlternatives ? { type: "literal", value: marker, alternatives: markerAlternatives } : { type: "literal", value: marker };
3259
+ tokens.push(markerToken);
3260
+ }
3261
+ }
3262
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3263
+ tokens.push(verbToken);
3264
+ const roleNames = sortedRoles.map((r) => `{${r.role}}`).join(" ");
3265
+ return {
3266
+ id: `${commandSchema.action}-event-${profile.code}-sov-2role`,
3267
+ language: profile.code,
3268
+ command: "on",
3269
+ // This is an event handler pattern
3270
+ priority: (config.basePriority ?? 100) + 55,
3271
+ // Higher priority than single-role patterns
3272
+ template: {
3273
+ format: `{event} ${eventMarker.primary} ${roleNames} ${keyword.primary}`,
3274
+ tokens
3275
+ },
3276
+ extraction: {
3277
+ action: { value: commandSchema.action },
3278
+ // Extract the wrapped command
3279
+ event: { fromRole: "event" },
3280
+ patient: { fromRole: "patient" },
3281
+ destination: { fromRole: "destination" }
3282
+ }
3283
+ };
3284
+ }
3285
+ function generateVSOTwoRoleEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3286
+ const tokens = [];
3287
+ if (eventMarker.position === "before") {
3288
+ const markerToken = eventMarker.alternatives ? { type: "literal", value: eventMarker.primary, alternatives: eventMarker.alternatives } : { type: "literal", value: eventMarker.primary };
3289
+ tokens.push(markerToken);
3290
+ }
3291
+ tokens.push({ type: "role", role: "event", optional: false });
3292
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3293
+ tokens.push(verbToken);
3294
+ const requiredRoles = commandSchema.roles.filter((r) => r.required);
3295
+ const sortedRoles = [...requiredRoles].sort((a, b) => {
3296
+ const aPos = a.svoPosition ?? 999;
3297
+ const bPos = b.svoPosition ?? 999;
3298
+ return aPos - bPos;
3299
+ });
3300
+ for (const roleSpec of sortedRoles) {
3301
+ let marker;
3302
+ let markerAlternatives;
3303
+ if (roleSpec.markerOverride && roleSpec.markerOverride[profile.code]) {
3304
+ marker = roleSpec.markerOverride[profile.code];
3305
+ } else {
3306
+ const roleMarker = profile.roleMarkers[roleSpec.role];
3307
+ if (roleMarker) {
3308
+ marker = roleMarker.primary;
3309
+ markerAlternatives = roleMarker.alternatives;
3310
+ }
3311
+ }
3312
+ if (marker) {
3313
+ const markerToken = markerAlternatives ? { type: "literal", value: marker, alternatives: markerAlternatives } : { type: "literal", value: marker };
3314
+ tokens.push(markerToken);
3315
+ }
3316
+ tokens.push({ type: "role", role: roleSpec.role, optional: false });
3317
+ }
3318
+ const roleNames = sortedRoles.map((r) => `{${r.role}}`).join(" ");
3319
+ return {
3320
+ id: `${commandSchema.action}-event-${profile.code}-vso-2role`,
3321
+ language: profile.code,
3322
+ command: "on",
3323
+ // This is an event handler pattern
3324
+ priority: (config.basePriority ?? 100) + 55,
3325
+ // Higher priority than single-role patterns
3326
+ template: {
3327
+ format: `${eventMarker.primary} {event} ${keyword.primary} ${roleNames}`,
3328
+ tokens
3329
+ },
3330
+ extraction: {
3331
+ action: { value: commandSchema.action },
3332
+ // Extract the wrapped command
3333
+ event: { fromRole: "event" },
3334
+ patient: { fromRole: "patient" },
3335
+ destination: { fromRole: "destination" }
3336
+ }
3337
+ };
3338
+ }
3339
+ function generateVSONegatedEventHandlerPattern(commandSchema, profile, keyword, eventMarker, config) {
3340
+ const tokens = [];
3341
+ const negationMarker = profile.eventHandler?.negationMarker;
3342
+ if (eventMarker.position === "before") {
3343
+ const markerToken = eventMarker.alternatives ? { type: "literal", value: eventMarker.primary, alternatives: eventMarker.alternatives } : { type: "literal", value: eventMarker.primary };
3344
+ tokens.push(markerToken);
3345
+ }
3346
+ if (negationMarker) {
3347
+ const negToken = negationMarker.alternatives ? {
3348
+ type: "literal",
3349
+ value: negationMarker.primary,
3350
+ alternatives: negationMarker.alternatives
3351
+ } : { type: "literal", value: negationMarker.primary };
3352
+ tokens.push(negToken);
3353
+ }
3354
+ tokens.push({ type: "role", role: "event", optional: false });
3355
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3356
+ tokens.push(verbToken);
3357
+ tokens.push({ type: "role", role: "patient", optional: false });
3358
+ const destMarker = profile.roleMarkers.destination;
3359
+ if (destMarker) {
3360
+ tokens.push({
3361
+ type: "group",
3362
+ optional: true,
3363
+ tokens: [
3364
+ destMarker.alternatives ? { type: "literal", value: destMarker.primary, alternatives: destMarker.alternatives } : { type: "literal", value: destMarker.primary },
3365
+ { type: "role", role: "destination", optional: true }
3366
+ ]
3367
+ });
3368
+ }
3369
+ return {
3370
+ id: `${commandSchema.action}-event-${profile.code}-vso-negated`,
3371
+ language: profile.code,
3372
+ command: "on",
3373
+ // This is an event handler pattern
3374
+ priority: (config.basePriority ?? 100) + 48,
3375
+ // Slightly lower priority than standard patterns
3376
+ template: {
3377
+ format: `${eventMarker.primary} ${negationMarker?.primary || ""} {event} ${keyword.primary} {patient} ${destMarker?.primary || ""} {destination?}`,
3378
+ tokens
3379
+ },
3380
+ extraction: {
3381
+ action: { value: commandSchema.action },
3382
+ // Extract the wrapped command
3383
+ event: { fromRole: "event" },
3384
+ patient: { fromRole: "patient" },
3385
+ destination: { fromRole: "destination", default: { type: "reference", value: "me" } }
3386
+ }
3387
+ };
3388
+ }
3389
+ function generateVSOProcliticEventHandlerPattern(commandSchema, profile, keyword, config) {
3390
+ const tokens = [];
3391
+ tokens.push({
3392
+ type: "literal",
3393
+ value: "and",
3394
+ // Matches normalized 'and' (Arabic: و)
3395
+ alternatives: ["then"]
3396
+ // Also matches normalized 'then' (Arabic: ف)
3397
+ });
3398
+ tokens.push({ type: "role", role: "event", optional: false });
3399
+ const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
3400
+ tokens.push(verbToken);
3401
+ tokens.push({ type: "role", role: "patient", optional: false });
3402
+ const destMarker = profile.roleMarkers.destination;
3403
+ if (destMarker) {
3404
+ tokens.push({
3405
+ type: "group",
3406
+ optional: true,
3407
+ tokens: [
3408
+ destMarker.alternatives ? { type: "literal", value: destMarker.primary, alternatives: destMarker.alternatives } : { type: "literal", value: destMarker.primary },
3409
+ { type: "role", role: "destination", optional: true }
3410
+ ]
3411
+ });
3412
+ }
3413
+ return {
3414
+ id: `${commandSchema.action}-event-${profile.code}-vso-proclitic`,
3415
+ language: profile.code,
3416
+ command: "on",
3417
+ // This is an event handler pattern
3418
+ priority: (config.basePriority ?? 100) + 45,
3419
+ // Lower priority than standard patterns
3420
+ template: {
3421
+ format: `[proclitic?] {event} ${keyword.primary} {patient} ${destMarker?.primary || ""} {destination?}`,
3422
+ tokens
3423
+ },
3424
+ extraction: {
3425
+ action: { value: commandSchema.action },
3426
+ // Extract the wrapped command
3427
+ event: { fromRole: "event" },
3428
+ patient: { fromRole: "patient" },
3429
+ destination: { fromRole: "destination", default: { type: "reference", value: "me" } }
3430
+ }
3431
+ };
3432
+ }
2887
3433
  function buildTokens(schema, profile, keyword) {
2888
3434
  const tokens = [];
2889
3435
  const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };