@kensio/pinyinjs 1.8.6 → 1.9.1

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 (132) hide show
  1. package/data/core.entries +27 -27
  2. package/data/core.freq +0 -0
  3. package/data/core.keys +1 -1
  4. package/data/full.counts +0 -0
  5. package/data/full.entries +4139 -4139
  6. package/data/full.freq +0 -0
  7. package/data/manifest.json +11 -11
  8. package/data/script.map +3 -2
  9. package/data/standard.entries +385 -385
  10. package/data/standard.freq +0 -0
  11. package/data/standard.keys +1 -1
  12. package/dist/decode/chang-context.d.ts +4 -0
  13. package/dist/decode/chang-context.d.ts.map +1 -1
  14. package/dist/decode/chang-context.js +16 -2
  15. package/dist/decode/chang-context.js.map +1 -1
  16. package/dist/decode/chang-rule.d.ts.map +1 -1
  17. package/dist/decode/chang-rule.js +6 -0
  18. package/dist/decode/chang-rule.js.map +1 -1
  19. package/dist/decode/chang-span.d.ts +37 -0
  20. package/dist/decode/chang-span.d.ts.map +1 -0
  21. package/dist/decode/chang-span.js +100 -0
  22. package/dist/decode/chang-span.js.map +1 -0
  23. package/dist/decode/chong-frames.d.ts +9 -0
  24. package/dist/decode/chong-frames.d.ts.map +1 -0
  25. package/dist/decode/chong-frames.js +58 -0
  26. package/dist/decode/chong-frames.js.map +1 -0
  27. package/dist/decode/ding-frames.d.ts +8 -0
  28. package/dist/decode/ding-frames.d.ts.map +1 -0
  29. package/dist/decode/ding-frames.js +54 -0
  30. package/dist/decode/ding-frames.js.map +1 -0
  31. package/dist/decode/dominant-readings.d.ts +55 -0
  32. package/dist/decode/dominant-readings.d.ts.map +1 -0
  33. package/dist/decode/dominant-readings.js +67 -0
  34. package/dist/decode/dominant-readings.js.map +1 -0
  35. package/dist/decode/dominant-rule.d.ts +24 -0
  36. package/dist/decode/dominant-rule.d.ts.map +1 -0
  37. package/dist/decode/dominant-rule.js +122 -0
  38. package/dist/decode/dominant-rule.js.map +1 -0
  39. package/dist/decode/guo-rule.d.ts.map +1 -1
  40. package/dist/decode/guo-rule.js +12 -0
  41. package/dist/decode/guo-rule.js.map +1 -1
  42. package/dist/decode/hao-rule.d.ts +16 -0
  43. package/dist/decode/hao-rule.d.ts.map +1 -0
  44. package/dist/decode/hao-rule.js +61 -0
  45. package/dist/decode/hao-rule.js.map +1 -0
  46. package/dist/decode/ji-frames.d.ts +9 -0
  47. package/dist/decode/ji-frames.d.ts.map +1 -0
  48. package/dist/decode/ji-frames.js +71 -0
  49. package/dist/decode/ji-frames.js.map +1 -0
  50. package/dist/decode/jiao-rule.d.ts +5 -6
  51. package/dist/decode/jiao-rule.d.ts.map +1 -1
  52. package/dist/decode/jiao-rule.js +39 -3
  53. package/dist/decode/jiao-rule.js.map +1 -1
  54. package/dist/decode/jie-frames.d.ts +6 -0
  55. package/dist/decode/jie-frames.d.ts.map +1 -0
  56. package/dist/decode/jie-frames.js +94 -0
  57. package/dist/decode/jie-frames.js.map +1 -0
  58. package/dist/decode/liang-frames.d.ts +6 -0
  59. package/dist/decode/liang-frames.d.ts.map +1 -0
  60. package/dist/decode/liang-frames.js +112 -0
  61. package/dist/decode/liang-frames.js.map +1 -0
  62. package/dist/decode/polyphone-rules.d.ts +2 -1
  63. package/dist/decode/polyphone-rules.d.ts.map +1 -1
  64. package/dist/decode/polyphone-rules.js +2 -1
  65. package/dist/decode/polyphone-rules.js.map +1 -1
  66. package/dist/decode/reading-rules.d.ts +3 -1
  67. package/dist/decode/reading-rules.d.ts.map +1 -1
  68. package/dist/decode/reading-rules.js +9 -2
  69. package/dist/decode/reading-rules.js.map +1 -1
  70. package/dist/decode/reduplication-readings.d.ts +26 -0
  71. package/dist/decode/reduplication-readings.d.ts.map +1 -0
  72. package/dist/decode/reduplication-readings.js +48 -0
  73. package/dist/decode/reduplication-readings.js.map +1 -0
  74. package/dist/decode/reduplication-rule.d.ts +1 -1
  75. package/dist/decode/reduplication-rule.d.ts.map +1 -1
  76. package/dist/decode/reduplication-rule.js +2 -41
  77. package/dist/decode/reduplication-rule.js.map +1 -1
  78. package/dist/decode/shu-frames.d.ts +6 -0
  79. package/dist/decode/shu-frames.d.ts.map +1 -0
  80. package/dist/decode/shu-frames.js +102 -0
  81. package/dist/decode/shu-frames.js.map +1 -0
  82. package/dist/decode/split-infix.d.ts +25 -0
  83. package/dist/decode/split-infix.d.ts.map +1 -0
  84. package/dist/decode/split-infix.js +134 -0
  85. package/dist/decode/split-infix.js.map +1 -0
  86. package/dist/decode/split-rule.d.ts +11 -0
  87. package/dist/decode/split-rule.d.ts.map +1 -1
  88. package/dist/decode/split-rule.js +17 -4
  89. package/dist/decode/split-rule.js.map +1 -1
  90. package/dist/decode/tiao-frames.d.ts +6 -0
  91. package/dist/decode/tiao-frames.d.ts.map +1 -0
  92. package/dist/decode/tiao-frames.js +60 -0
  93. package/dist/decode/tiao-frames.js.map +1 -0
  94. package/dist/decode/verbal-frame.d.ts +68 -0
  95. package/dist/decode/verbal-frame.d.ts.map +1 -0
  96. package/dist/decode/verbal-frame.js +76 -0
  97. package/dist/decode/verbal-frame.js.map +1 -0
  98. package/dist/decode/verbal-held.d.ts +12 -0
  99. package/dist/decode/verbal-held.d.ts.map +1 -0
  100. package/dist/decode/verbal-held.js +63 -0
  101. package/dist/decode/verbal-held.js.map +1 -0
  102. package/dist/decode/verbal-rule.d.ts +31 -0
  103. package/dist/decode/verbal-rule.d.ts.map +1 -0
  104. package/dist/decode/verbal-rule.js +100 -0
  105. package/dist/decode/verbal-rule.js.map +1 -0
  106. package/dist/decode/xiang-frames.d.ts +6 -0
  107. package/dist/decode/xiang-frames.d.ts.map +1 -0
  108. package/dist/decode/xiang-frames.js +65 -0
  109. package/dist/decode/xiang-frames.js.map +1 -0
  110. package/dist/decode/zhuan-frames.d.ts +6 -0
  111. package/dist/decode/zhuan-frames.d.ts.map +1 -0
  112. package/dist/decode/zhuan-frames.js +97 -0
  113. package/dist/decode/zhuan-frames.js.map +1 -0
  114. package/dist/dictionary/character-defaults.d.ts.map +1 -1
  115. package/dist/dictionary/character-defaults.js +4 -1
  116. package/dist/dictionary/character-defaults.js.map +1 -1
  117. package/dist/dictionary/character-readings.d.ts.map +1 -1
  118. package/dist/dictionary/character-readings.js +9 -0
  119. package/dist/dictionary/character-readings.js.map +1 -1
  120. package/dist/dictionary/free-readings.d.ts +70 -0
  121. package/dist/dictionary/free-readings.d.ts.map +1 -0
  122. package/dist/dictionary/free-readings.js +108 -0
  123. package/dist/dictionary/free-readings.js.map +1 -0
  124. package/dist/dictionary/frequency-table.d.ts +8 -0
  125. package/dist/dictionary/frequency-table.d.ts.map +1 -1
  126. package/dist/dictionary/frequency-table.js +11 -1
  127. package/dist/dictionary/frequency-table.js.map +1 -1
  128. package/dist/index.d.ts +1 -1
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +1 -1
  131. package/dist/index.js.map +1 -1
  132. package/package.json +1 -1
@@ -0,0 +1,134 @@
1
+ /**
2
+ * How a 离合词 is read when more than a 个 stands between its halves.
3
+ *
4
+ * 睡不着觉, 请了假 and 睡了八个小时觉 part the word around an aspect particle,
5
+ * a complement or a count. `SEPARATED_COMPOUND` in `split-rule.ts` asks this
6
+ * module for the tail's reading wherever the 个 shape has nothing to say.
7
+ */
8
+ import { QUANTITY_CHARACTERS } from "../numerals/characters.js";
9
+ import { tagOf } from "./rules.js";
10
+ /**
11
+ * The tag prefix jieba gives a verb.
12
+ *
13
+ * The same prefix `split-rule.ts` reads, so `vn` and `vd` are in.
14
+ */
15
+ const VERB_TAG = "v";
16
+ /**
17
+ * The numerals that count the time or the amount pushed into a 离合词.
18
+ *
19
+ * {@link QUANTITY_CHARACTERS} and the two that ask or halve a count, since
20
+ * 放几天假 and 睡半个小时觉 are as common as any number.
21
+ */
22
+ const INFIX_NUMERALS = `[${[...QUANTITY_CHARACTERS, "几", "幾", "半"].join("")}]`;
23
+ /**
24
+ * What can stand between a 离合词's halves besides a lone 个, as a pattern.
25
+ *
26
+ * The verb half takes an aspect particle or a complement, and the object half a
27
+ * count, in that order and either one alone (睡不着觉, 睡够了觉, 请了假,
28
+ * 睡了十个小时觉, 放三天假, 睡一会儿觉, 睡了个好觉). Spelled out rather than
29
+ * left to the tags, because the tags are what the 个 rule found too loose. 下
30
+ * and 年 count only behind a numeral (睡一下觉), which keeps out the
31
+ * directional 下 the `CLASSIFIER` note in `split-rule.ts` describes. 天 and 会儿 count
32
+ * bare, since 请了天假 and 睡会儿觉 are how both are said.
33
+ *
34
+ * The count is the object's and the complement the verb's, so 好 comes in
35
+ * twice. 睡好觉 completes the sleeping, and 睡了个好觉 describes the sleep.
36
+ */
37
+ const INFIX = new RegExp("^(?=.)" +
38
+ // What the verb takes: aspect, a potential complement, or a result.
39
+ "(?:[了过過]|[不得][着著好了成够夠完饱飽上]|[够夠好完饱飽足]了?)?" +
40
+ // What the object takes: a count, with 个 and a 好 the sleep can be.
41
+ "(?:" +
42
+ `${INFIX_NUMERALS}*[个個]好?` +
43
+ `|${INFIX_NUMERALS}*[个個]?(?:小时|小時|钟头|鐘頭|天|夜|晚上|会儿|會兒)` +
44
+ `|${INFIX_NUMERALS}+(?:下|年|周|週|星期|个月|個月)` +
45
+ `|一?[点點][儿兒]?` +
46
+ ")?$", "u");
47
+ /**
48
+ * How far back the head of a widely separated 离合词 is looked for.
49
+ *
50
+ * 睡了十个小时觉 holds five characters between its halves, the longest the
51
+ * pattern above admits short of a count in the hundreds.
52
+ */
53
+ const WIDEST_INFIX = 6;
54
+ /**
55
+ * The tag prefix jieba gives a noun.
56
+ */
57
+ const NOUN_TAG = "n";
58
+ /**
59
+ * Whether the tail at a position goes on into a noun it could be modifying.
60
+ *
61
+ * 他请了假,要回乡下 ends the compound at the comma. 放了假钱 would not: the 假
62
+ * there says what the money is, and 假钱 is no word the dictionary holds for
63
+ * anything to find. A noun, or the 的 that marks an attributive,
64
+ * in the next place is the shape of that reading, and the rule stands back from
65
+ * it. 假花 gets past this, since 花 is tagged as the verb, and is the one known
66
+ * gap.
67
+ */
68
+ function modifiesWhatFollows(context, at) {
69
+ const next = context.characters[at + 1];
70
+ return next === "的" || tagOf(context, next).startsWith(NOUN_TAG);
71
+ }
72
+ /**
73
+ * The directional complements the dictionary tags as verbs, and reads neutral
74
+ * behind the verb they complete.
75
+ */
76
+ const DIRECTIONS = new Set(["来", "來", "去"]);
77
+ /**
78
+ * Whether the tail at a position can be the object a verb is parted from.
79
+ *
80
+ * The object of a 离合词 is a noun or a verb made into one (觉 is tagged `v`), so
81
+ * the tail has to be tagged as one of those. Both wrong firings the corpus and
82
+ * the ChineseBoost library offered were of another kind. 干吗 is tagged a verb,
83
+ * and 我的袜子已经干了吗 read its 吗 as `má` across the 了. 坐下 is a verb with
84
+ * 下 tagged `f`, and 伊莉雅坐了下一班飞机 read the 下 of 下一班 as `xia`. 来
85
+ * and 去 are tagged verbs and are named, because a verb and the direction it
86
+ * goes in are no verb and its object, and both read neutral behind it.
87
+ */
88
+ function isObject(context, at) {
89
+ /* c8 ignore next -- the tail is a position of the run itself */
90
+ const tail = context.characters[at] ?? "";
91
+ const tag = tagOf(context, tail);
92
+ return (!DIRECTIONS.has(tail) &&
93
+ (tag.startsWith(NOUN_TAG) || tag.startsWith(VERB_TAG)));
94
+ }
95
+ /**
96
+ * The syllable a 离合词 separated by more than a 个 gives its tail, or
97
+ * undefined.
98
+ *
99
+ * The nearest head the {@link INFIX} pattern reaches is the one asked about,
100
+ * so 我还没睡够觉 finds 睡觉 and never gets as far as the 还. The pair has to
101
+ * be tagged a verb itself, which is what a 离合词 is, and 打了场硬仗 found the
102
+ * 打场 of threshing, a noun, behind a 场 that was counting. That stands in for
103
+ * the 个 shape's verb in front, which the dictionary leaves untagged on 休, 流
104
+ * and 理, so 休一天假, 流了血 and 理了发 are read through it. The tail has to be
105
+ * an object, for the reason {@link isObject} gives, and must not run on into a
106
+ * noun, for the reason {@link modifiesWhatFollows} gives.
107
+ *
108
+ * The 个 shape's `opensTaggedWord` is left out, because it changed
109
+ * nothing over either corpus. Forcing the tail's own edge leaves a longer word
110
+ * starting at it to the decode, so 我睡了觉得好多了 still reads 觉得 whole.
111
+ *
112
+ * Only the tail is settled. A head reached across a complement can be an
113
+ * adverb the tags call a verb, and 还不够钱 would read its 还 as `huán` off
114
+ * 还钱.
115
+ */
116
+ export function widelySeparatedSyllableAt(context, at) {
117
+ const { characters } = context;
118
+ for (let head = at - 2; head >= 0 && head >= at - 1 - WIDEST_INFIX; head--) {
119
+ if (!INFIX.test(characters.slice(head + 1, at).join(""))) {
120
+ continue;
121
+ }
122
+ /* c8 ignore next -- both positions are inside the run just measured */
123
+ const word = `${characters[head] ?? ""}${characters[at] ?? ""}`;
124
+ const entry = context.dictionary.lookup(word);
125
+ if (entry?.reading.length !== 2 ||
126
+ !entry.partOfSpeech.startsWith(VERB_TAG) ||
127
+ !isObject(context, at)) {
128
+ continue;
129
+ }
130
+ return modifiesWhatFollows(context, at) ? undefined : entry.reading[1];
131
+ }
132
+ return undefined;
133
+ }
134
+ //# sourceMappingURL=split-infix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-infix.js","sourceRoot":"","sources":["../../src/decode/split-infix.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,17 @@ import { type EdgeRule } from "./rules.js";
38
38
  * default, and they are led by 认为, 获得, 关系 and 告诉, none of which any 个
39
39
  * can be pushed into. The rule never reaches them, since it fires on a 个 that
40
40
  * is written rather than on a pair that exists.
41
+ *
42
+ * The halves come apart around more than a 个, and 睡不着觉, 睡了八个小时觉,
43
+ * 放三天假 and 请了假 all read their tail by its character default the way
44
+ * 请个假 did. {@link widelySeparatedSyllableAt} reads the tail across those,
45
+ * through an infix spelled out in `split-infix.ts` and under tighter conditions,
46
+ * since a head that far back is more often an accident. Over the 88,866 lines
47
+ * and both CPP splits, 241,680 Han runs, it changes 35 decodes and all 35 are
48
+ * corrections. 24 are 觉 to `jiào`, 7 假 to `jià`, 3 血 to `xiě` (流了血, 吐了血)
49
+ * and one the 肚 of 下過肚 to `dù`. Over the 例句 library ChineseBoost publishes it
50
+ * changes 27, all corrections, 25 of them 觉 and 假, and the other two 理了发
51
+ * and 咳出了血. CPP's labelled polyphones hold at 91.86%.
41
52
  */
42
53
  export declare const SEPARATED_COMPOUND: EdgeRule;
43
54
  //# sourceMappingURL=split-rule.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"split-rule.d.ts","sourceRoot":"","sources":["../../src/decode/split-rule.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,QAAQ,EAGd,MAAM,YAAY,CAAC;AA+HpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAehC,CAAC"}
1
+ {"version":3,"file":"split-rule.d.ts","sourceRoot":"","sources":["../../src/decode/split-rule.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,QAAQ,EAGd,MAAM,YAAY,CAAC;AAgIpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAehC,CAAC"}
@@ -1,12 +1,14 @@
1
1
  /**
2
- * How a 离合词 is read once a 量词 has been pushed into the middle of it.
2
+ * How a 离合词 is read once something has been pushed into the middle of it.
3
3
  *
4
- * 请假 is one word and carries one reading. 请个假 is the same word with a
5
- * classifier inside it, and the halves are left standing on their own.
4
+ * 请假 is one word and carries one reading. 请个假, 请了假 and 请了三天假 are
5
+ * the same word with a classifier, an aspect particle or a count inside it, and
6
+ * the halves are left standing on their own.
6
7
  */
7
8
  import { isSameSyllable } from "../dictionary/entry.js";
8
9
  import { toCharacters } from "../script/characters.js";
9
10
  import { tagOf, wordsStartingAt, } from "./rules.js";
11
+ import { widelySeparatedSyllableAt } from "./split-infix.js";
10
12
  /**
11
13
  * The classifier that separates the halves, in both scripts.
12
14
  *
@@ -83,7 +85,7 @@ function opensTaggedWord(context, at) {
83
85
  function separatedSyllableAt(context, at) {
84
86
  const separated = separatedAt(context, at);
85
87
  if (separated === undefined) {
86
- return undefined;
88
+ return widelySeparatedSyllableAt(context, at);
87
89
  }
88
90
  const { word, offset } = separated;
89
91
  const entry = context.dictionary.lookup(word);
@@ -154,6 +156,17 @@ function carriesReading(context, edge) {
154
156
  * default, and they are led by 认为, 获得, 关系 and 告诉, none of which any 个
155
157
  * can be pushed into. The rule never reaches them, since it fires on a 个 that
156
158
  * is written rather than on a pair that exists.
159
+ *
160
+ * The halves come apart around more than a 个, and 睡不着觉, 睡了八个小时觉,
161
+ * 放三天假 and 请了假 all read their tail by its character default the way
162
+ * 请个假 did. {@link widelySeparatedSyllableAt} reads the tail across those,
163
+ * through an infix spelled out in `split-infix.ts` and under tighter conditions,
164
+ * since a head that far back is more often an accident. Over the 88,866 lines
165
+ * and both CPP splits, 241,680 Han runs, it changes 35 decodes and all 35 are
166
+ * corrections. 24 are 觉 to `jiào`, 7 假 to `jià`, 3 血 to `xiě` (流了血, 吐了血)
167
+ * and one the 肚 of 下過肚 to `dù`. Over the 例句 library ChineseBoost publishes it
168
+ * changes 27, all corrections, 25 of them 觉 and 假, and the other two 理了发
169
+ * and 咳出了血. CPP's labelled polyphones hold at 91.86%.
157
170
  */
158
171
  export const SEPARATED_COMPOUND = {
159
172
  name: "separated-compound",
@@ -1 +1 @@
1
- {"version":3,"file":"split-rule.js","sourceRoot":"","sources":["../../src/decode/split-rule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"split-rule.js","sourceRoot":"","sources":["../../src/decode/split-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type VerbalFrame } from "./verbal-frame.js";
2
+ /**
3
+ * 调 read `tiáo` where it is adjusting or mixing.
4
+ */
5
+ export declare const TIAO_FRAME: VerbalFrame;
6
+ //# sourceMappingURL=tiao-frames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiao-frames.d.ts","sourceRoot":"","sources":["../../src/decode/tiao-frames.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAwD3B;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,WAMxB,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { isBareAt, startsWithAny, syllableOf, } from "./verbal-frame.js";
2
+ /**
3
+ * The complements that say which way something was adjusted.
4
+ *
5
+ * 把音量调低, 把冷气调高, 把灯调亮, 把钟调快, 把火调小. Every one of them is a
6
+ * degree of something a dial or a knob sets.
7
+ *
8
+ * 低 stands bare in 调低价格 even though 低价 is a word, so the complement is
9
+ * read as a character and not asked whether it opens one.
10
+ */
11
+ const WHICH_WAY = new Set([
12
+ "高",
13
+ "低",
14
+ "大",
15
+ "小",
16
+ "快",
17
+ "慢",
18
+ "亮",
19
+ "暗",
20
+ "准",
21
+ "匀",
22
+ "淡",
23
+ "浓",
24
+ "松",
25
+ "紧",
26
+ "强",
27
+ "弱",
28
+ ]);
29
+ /**
30
+ * What a 调 is followed by where it is tuning an instrument, with aspect in
31
+ * between: 这台琴好多年没调过音了.
32
+ *
33
+ * 调音 is a word and reads `tiáo` through it. Taken apart, the 调 is left to
34
+ * stand alone.
35
+ */
36
+ const ASPECT = new Set(["过", "過", "了", "好"]);
37
+ /**
38
+ * What a 调 that is mixing a drink is followed by: 调杯热饮料, 调一杯鸡尾酒.
39
+ */
40
+ const MIXED = ["杯", "一杯", "两杯"];
41
+ /**
42
+ * Whether the 调 at a position is adjusting or mixing.
43
+ */
44
+ function isAdjustingAt(context, at) {
45
+ const { characters } = context;
46
+ return (WHICH_WAY.has(characters[at + 1] ?? "") ||
47
+ (isBareAt(context, at + 1, ASPECT) && characters[at + 2] === "音") ||
48
+ startsWithAny(context, at + 1, MIXED));
49
+ }
50
+ /**
51
+ * 调 read `tiáo` where it is adjusting or mixing.
52
+ */
53
+ export const TIAO_FRAME = {
54
+ characters: new Set(["调", "調"]),
55
+ reading: syllableOf("tiáo"),
56
+ boundBefore: new Set(),
57
+ boundAfter: new Set(),
58
+ isVerbalAt: isAdjustingAt,
59
+ };
60
+ //# sourceMappingURL=tiao-frames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiao-frames.js","sourceRoot":"","sources":["../../src/decode/tiao-frames.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,QAAQ,EACR,aAAa,EACb,UAAU,GAEX,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;GAQG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;CACJ,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAE7C;;GAEG;AACH,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEhC;;GAEG;AACH,SAAS,aAAa,CAAC,OAAoB,EAAE,EAAU;IACrD,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC/B,OAAO,CACL,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,IAAI,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC;QACjE,aAAa,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CACtC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAgB;IACrC,UAAU,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;IAC3B,WAAW,EAAE,IAAI,GAAG,EAAE;IACtB,UAAU,EAAE,IAAI,GAAG,EAAE;IACrB,UAAU,EAAE,aAAa;CAC1B,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { type Syllable } from "../syllable/syllable.js";
2
+ import { type EdgeContext } from "./rules.js";
3
+ /**
4
+ * One character whose verb has a reading of its own, and when the verb is the
5
+ * one meant.
6
+ *
7
+ * `characters` holds the character in each script where both scripts read it
8
+ * the same way. `isVerbalAt` is asked about a position holding one of them,
9
+ * and answers from the words around it.
10
+ *
11
+ * `boundBefore` and `boundAfter` are the characters that make a compound with
12
+ * it, on that side, reading it the other way: the 联 of 联系 and the 果 of
13
+ * 结果. The full tier holds those compounds and decides them through the word.
14
+ * The core tier holds few of them, and a frame asking what stands beside the
15
+ * character would otherwise take 我们联系上他们 for tying something.
16
+ */
17
+ export interface VerbalFrame {
18
+ readonly characters: ReadonlySet<string>;
19
+ readonly reading: Syllable;
20
+ readonly boundBefore: ReadonlySet<string>;
21
+ readonly boundAfter: ReadonlySet<string>;
22
+ readonly isVerbalAt: (context: EdgeContext, at: number) => boolean;
23
+ }
24
+ /**
25
+ * Whether the character at a position is bound into a compound by its
26
+ * neighbour on either side.
27
+ */
28
+ export declare function isBoundAt(context: EdgeContext, at: number, frame: VerbalFrame): boolean;
29
+ /**
30
+ * A set of the characters of a string, for a frame's bound characters.
31
+ */
32
+ export declare function charactersOf(text: string): ReadonlySet<string>;
33
+ /**
34
+ * A syllable written out in tone marks, for a frame's reading.
35
+ */
36
+ export declare function syllableOf(text: string): Syllable;
37
+ /**
38
+ * Whether a tagged word of more than one character starts at a position.
39
+ *
40
+ * The test a frame puts to the character after the verb. 系在 is tying, and
41
+ * 系在于 would be no such thing, since 在于 is a word. Untagged keys are left
42
+ * out, since the full tier holds pairs such as 进地 with no part of speech.
43
+ */
44
+ export declare function opensTaggedWord(context: EdgeContext, at: number): boolean;
45
+ /**
46
+ * Whether a tagged word of more than one character ends at a position.
47
+ */
48
+ export declare function closesTaggedWord(context: EdgeContext, at: number): boolean;
49
+ /**
50
+ * Whether the character at a position is one of a set and starts no tagged
51
+ * word of its own.
52
+ */
53
+ export declare function isBareAt(context: EdgeContext, at: number, characters: ReadonlySet<string>): boolean;
54
+ /**
55
+ * Whether the text starting at a position is one of a set of words.
56
+ *
57
+ * Asked of the characters rather than of the dictionary, because what follows
58
+ * a verb is often a word the decode would join to something else: 一下 is a
59
+ * word, and 一下子 is a longer one starting at the same place.
60
+ */
61
+ export declare function startsWithAny(context: EdgeContext, at: number, words: readonly string[]): boolean;
62
+ /**
63
+ * Whether a position is the end of the run.
64
+ *
65
+ * A run stops at punctuation, so the end of the run is the end of the clause.
66
+ */
67
+ export declare function isRunEnd(context: EdgeContext, at: number): boolean;
68
+ //# sourceMappingURL=verbal-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbal-frame.d.ts","sourceRoot":"","sources":["../../src/decode/verbal-frame.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,KAAK,WAAW,EAIjB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;CACpE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,WAAW,GACjB,OAAO,CAKT;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAOjD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAIzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAI1E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,GAC9B,OAAO,CAKT;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAGT;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAElE"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * What every frame of {@link import("./verbal-rule.js").VERBAL_READING} is made
3
+ * of, and the questions about neighbouring words the frames share.
4
+ */
5
+ import { toCharacters } from "../script/characters.js";
6
+ import { readSyllable } from "../syllable/syllable.js";
7
+ import { tagOf, wordsEndingAt, wordsStartingAt, } from "./rules.js";
8
+ /**
9
+ * Whether the character at a position is bound into a compound by its
10
+ * neighbour on either side.
11
+ */
12
+ export function isBoundAt(context, at, frame) {
13
+ return (frame.boundBefore.has(context.characters[at - 1] ?? "") ||
14
+ frame.boundAfter.has(context.characters[at + 1] ?? ""));
15
+ }
16
+ /**
17
+ * A set of the characters of a string, for a frame's bound characters.
18
+ */
19
+ export function charactersOf(text) {
20
+ return new Set(toCharacters(text));
21
+ }
22
+ /**
23
+ * A syllable written out in tone marks, for a frame's reading.
24
+ */
25
+ export function syllableOf(text) {
26
+ const syllable = readSyllable(text);
27
+ /* c8 ignore next 3 -- every frame names a syllable */
28
+ if (syllable === undefined) {
29
+ throw new Error(`${text} is not a syllable`);
30
+ }
31
+ return syllable;
32
+ }
33
+ /**
34
+ * Whether a tagged word of more than one character starts at a position.
35
+ *
36
+ * The test a frame puts to the character after the verb. 系在 is tying, and
37
+ * 系在于 would be no such thing, since 在于 is a word. Untagged keys are left
38
+ * out, since the full tier holds pairs such as 进地 with no part of speech.
39
+ */
40
+ export function opensTaggedWord(context, at) {
41
+ return wordsStartingAt(context, at).some((word) => toCharacters(word).length > 1 && tagOf(context, word) !== "");
42
+ }
43
+ /**
44
+ * Whether a tagged word of more than one character ends at a position.
45
+ */
46
+ export function closesTaggedWord(context, at) {
47
+ return wordsEndingAt(context, at).some((word) => toCharacters(word).length > 1 && tagOf(context, word) !== "");
48
+ }
49
+ /**
50
+ * Whether the character at a position is one of a set and starts no tagged
51
+ * word of its own.
52
+ */
53
+ export function isBareAt(context, at, characters) {
54
+ return (characters.has(context.characters[at] ?? "") &&
55
+ !opensTaggedWord(context, at));
56
+ }
57
+ /**
58
+ * Whether the text starting at a position is one of a set of words.
59
+ *
60
+ * Asked of the characters rather than of the dictionary, because what follows
61
+ * a verb is often a word the decode would join to something else: 一下 is a
62
+ * word, and 一下子 is a longer one starting at the same place.
63
+ */
64
+ export function startsWithAny(context, at, words) {
65
+ const rest = context.characters.slice(at, at + 4).join("");
66
+ return words.some((word) => rest.startsWith(word));
67
+ }
68
+ /**
69
+ * Whether a position is the end of the run.
70
+ *
71
+ * A run stops at punctuation, so the end of the run is the end of the clause.
72
+ */
73
+ export function isRunEnd(context, at) {
74
+ return at >= context.characters.length;
75
+ }
76
+ //# sourceMappingURL=verbal-frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbal-frame.js","sourceRoot":"","sources":["../../src/decode/verbal-frame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAiB,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAEL,KAAK,EACL,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC;AAwBpB;;;GAGG;AACH,MAAM,UAAU,SAAS,CACvB,OAAoB,EACpB,EAAU,EACV,KAAkB;IAElB,OAAO,CACL,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CACvD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,sDAAsD;IACtD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,OAAoB,EAAE,EAAU;IAC9D,OAAO,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CACtC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,CACvE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAoB,EAAE,EAAU;IAC/D,OAAO,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CACpC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,CACvE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAoB,EACpB,EAAU,EACV,UAA+B;IAE/B,OAAO,CACL,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5C,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAoB,EACpB,EAAU,EACV,KAAwB;IAExB,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAoB,EAAE,EAAU;IACvD,OAAO,EAAE,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;AACzC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Syllable } from "../syllable/syllable.js";
2
+ import { type EdgeContext } from "./rules.js";
3
+ /**
4
+ * Whether a tagged word of more than one character holds the position and
5
+ * reads it some other way.
6
+ *
7
+ * A frame is about a character standing as a word of its own. 词汇量 and 数量
8
+ * are words, and whatever stands after them is no evidence about their 量. A
9
+ * word another word crosses is left out (see {@link isCrossed}).
10
+ */
11
+ export declare function isHeldAgainst(context: EdgeContext, at: number, reading: Syllable): boolean;
12
+ //# sourceMappingURL=verbal-held.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbal-held.d.ts","sourceRoot":"","sources":["../../src/decode/verbal-held.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,KAAK,WAAW,EAA0B,MAAM,YAAY,CAAC;AAuCtE;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,QAAQ,GAChB,OAAO,CAgBT"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Whether a word the dictionary holds has a claim on a frame's character.
3
+ */
4
+ import { isSameSyllable } from "../dictionary/entry.js";
5
+ import { toCharacters } from "../script/characters.js";
6
+ import { tagOf, wordsStartingAt } from "./rules.js";
7
+ /**
8
+ * The tagged words of more than one character starting at a position.
9
+ */
10
+ function taggedWordsAt(context, from) {
11
+ return wordsStartingAt(context, from).filter((word) => toCharacters(word).length > 1 && tagOf(context, word) !== "");
12
+ }
13
+ /**
14
+ * Whether a commoner tagged word crosses a word, taking its first or its last
15
+ * character into a word of its own.
16
+ *
17
+ * 冷气调高 holds 气调 as well as 冷气, and the decode takes 冷气, the commoner
18
+ * of the two, every time. A word crossed like that is no claim on the
19
+ * characters it covers. The commoner word has to win: 关系上 holds 系上 too,
20
+ * and 关系 is the word there.
21
+ */
22
+ function isCrossed(context, from, word) {
23
+ const to = from + toCharacters(word).length;
24
+ /* c8 ignore next -- the word came out of the dictionary */
25
+ const own = context.dictionary.frequencyOf(word) ?? 0;
26
+ for (let start = Math.max(0, from - 3); start < to; start++) {
27
+ for (const rival of taggedWordsAt(context, start)) {
28
+ const end = start + toCharacters(rival).length;
29
+ const left = start < from && end > from && end < to;
30
+ const right = start > from && end > to;
31
+ /* c8 ignore next -- the rival came out of the dictionary */
32
+ const commoner = (context.dictionary.frequencyOf(rival) ?? 0) > own;
33
+ if ((left || right) && commoner) {
34
+ return true;
35
+ }
36
+ }
37
+ }
38
+ return false;
39
+ }
40
+ /**
41
+ * Whether a tagged word of more than one character holds the position and
42
+ * reads it some other way.
43
+ *
44
+ * A frame is about a character standing as a word of its own. 词汇量 and 数量
45
+ * are words, and whatever stands after them is no evidence about their 量. A
46
+ * word another word crosses is left out (see {@link isCrossed}).
47
+ */
48
+ export function isHeldAgainst(context, at, reading) {
49
+ for (let from = Math.max(0, at - 3); from <= at; from++) {
50
+ for (const word of taggedWordsAt(context, from)) {
51
+ if (from + toCharacters(word).length <= at ||
52
+ isCrossed(context, from, word)) {
53
+ continue;
54
+ }
55
+ const held = context.dictionary.lookup(word)?.reading[at - from];
56
+ if (held !== undefined && !isSameSyllable(held, reading)) {
57
+ return true;
58
+ }
59
+ }
60
+ }
61
+ return false;
62
+ }
63
+ //# sourceMappingURL=verbal-held.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbal-held.js","sourceRoot":"","sources":["../../src/decode/verbal-held.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAoB,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtE;;GAEG;AACH,SAAS,aAAa,CAAC,OAAoB,EAAE,IAAY;IACvD,OAAO,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,CAC1C,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,CACvE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,SAAS,CAAC,OAAoB,EAAE,IAAY,EAAE,IAAY;IACjE,MAAM,EAAE,GAAG,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAC5C,2DAA2D;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5D,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,GAAG,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;YAC/C,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;YACvC,4DAA4D;YAC5D,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;YACpE,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAoB,EACpB,EAAU,EACV,OAAiB;IAEjB,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YAChD,IACE,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE;gBACtC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAC9B,CAAC;gBACD,SAAS;YACX,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;YACjE,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;gBACzD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { EdgeRule } from "./rules.js";
2
+ import { type VerbalFrame } from "./verbal-frame.js";
3
+ /**
4
+ * Every frame, one to a character.
5
+ */
6
+ export declare const VERBAL_FRAMES: readonly VerbalFrame[];
7
+ /**
8
+ * The verb's reading for nine characters where the sentence uses the verb.
9
+ *
10
+ * Each of them is stored with another reading first, and for the same reason:
11
+ * the commoner reading in a corpus is the one inside words. 量 is `liàng` in
12
+ * 数量, 质量 and 词汇量, 数 is `shù` in 数字 and 数十, 调 is `diào` in 调查, 系
13
+ * is `xì` in 关系, and so on. A word carries its own reading, so what the
14
+ * default decides is the character standing on its own, and in running text
15
+ * that is as often the verb as anything. 我妈妈量了我的体温 came out with
16
+ * `liàng`, 你能数到十吗 with `shù` and 请把音量调低一点 with `diào`.
17
+ *
18
+ * The verb is told apart by its neighbours, a different set for each
19
+ * character, so each has a frame of its own in a file of its own. They share
20
+ * how the verdict is given, which is the way {@link import("./zhi-rule.js").COUNTING_ZHI}
21
+ * gives it: where a frame holds, the edge of the character alone reading the
22
+ * verb is forced, and an edge of several characters reading it some other way
23
+ * is forbidden. A tagged word holding the character with another reading is
24
+ * left alone, since 词汇量 and 关系 decide their own.
25
+ *
26
+ * The reading the frame names has to be among the character's readings for
27
+ * the rule to do anything. Unihan gives 繫 and 釘 no `jì` and no `dìng`, so
28
+ * those two forms are left out until the data has them.
29
+ */
30
+ export declare const VERBAL_READING: EdgeRule;
31
+ //# sourceMappingURL=verbal-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verbal-rule.d.ts","sourceRoot":"","sources":["../../src/decode/verbal-rule.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAe,QAAQ,EAAe,MAAM,YAAY,CAAC;AAGrE,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKhE;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAU/C,CAAC;AA4BF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,cAAc,EAAE,QA2B5B,CAAC"}