@kensio/pinyinjs 1.9.0 → 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.
- package/dist/decode/chang-context.d.ts +4 -0
- package/dist/decode/chang-context.d.ts.map +1 -1
- package/dist/decode/chang-context.js +16 -2
- package/dist/decode/chang-context.js.map +1 -1
- package/dist/decode/chang-rule.d.ts.map +1 -1
- package/dist/decode/chang-rule.js +6 -0
- package/dist/decode/chang-rule.js.map +1 -1
- package/dist/decode/chang-span.d.ts +37 -0
- package/dist/decode/chang-span.d.ts.map +1 -0
- package/dist/decode/chang-span.js +100 -0
- package/dist/decode/chang-span.js.map +1 -0
- package/dist/decode/chong-frames.d.ts +9 -0
- package/dist/decode/chong-frames.d.ts.map +1 -0
- package/dist/decode/chong-frames.js +58 -0
- package/dist/decode/chong-frames.js.map +1 -0
- package/dist/decode/ding-frames.d.ts +8 -0
- package/dist/decode/ding-frames.d.ts.map +1 -0
- package/dist/decode/ding-frames.js +54 -0
- package/dist/decode/ding-frames.js.map +1 -0
- package/dist/decode/dominant-readings.d.ts +55 -0
- package/dist/decode/dominant-readings.d.ts.map +1 -0
- package/dist/decode/dominant-readings.js +67 -0
- package/dist/decode/dominant-readings.js.map +1 -0
- package/dist/decode/dominant-rule.d.ts +24 -0
- package/dist/decode/dominant-rule.d.ts.map +1 -0
- package/dist/decode/dominant-rule.js +122 -0
- package/dist/decode/dominant-rule.js.map +1 -0
- package/dist/decode/guo-rule.d.ts.map +1 -1
- package/dist/decode/guo-rule.js +12 -0
- package/dist/decode/guo-rule.js.map +1 -1
- package/dist/decode/hao-rule.d.ts +16 -0
- package/dist/decode/hao-rule.d.ts.map +1 -0
- package/dist/decode/hao-rule.js +61 -0
- package/dist/decode/hao-rule.js.map +1 -0
- package/dist/decode/ji-frames.d.ts +9 -0
- package/dist/decode/ji-frames.d.ts.map +1 -0
- package/dist/decode/ji-frames.js +71 -0
- package/dist/decode/ji-frames.js.map +1 -0
- package/dist/decode/jiao-rule.d.ts +5 -6
- package/dist/decode/jiao-rule.d.ts.map +1 -1
- package/dist/decode/jiao-rule.js +39 -3
- package/dist/decode/jiao-rule.js.map +1 -1
- package/dist/decode/jie-frames.d.ts +6 -0
- package/dist/decode/jie-frames.d.ts.map +1 -0
- package/dist/decode/jie-frames.js +94 -0
- package/dist/decode/jie-frames.js.map +1 -0
- package/dist/decode/liang-frames.d.ts +6 -0
- package/dist/decode/liang-frames.d.ts.map +1 -0
- package/dist/decode/liang-frames.js +112 -0
- package/dist/decode/liang-frames.js.map +1 -0
- package/dist/decode/polyphone-rules.d.ts +2 -1
- package/dist/decode/polyphone-rules.d.ts.map +1 -1
- package/dist/decode/polyphone-rules.js +2 -1
- package/dist/decode/polyphone-rules.js.map +1 -1
- package/dist/decode/reading-rules.d.ts +3 -1
- package/dist/decode/reading-rules.d.ts.map +1 -1
- package/dist/decode/reading-rules.js +9 -2
- package/dist/decode/reading-rules.js.map +1 -1
- package/dist/decode/reduplication-readings.d.ts +26 -0
- package/dist/decode/reduplication-readings.d.ts.map +1 -0
- package/dist/decode/reduplication-readings.js +48 -0
- package/dist/decode/reduplication-readings.js.map +1 -0
- package/dist/decode/reduplication-rule.d.ts +1 -1
- package/dist/decode/reduplication-rule.d.ts.map +1 -1
- package/dist/decode/reduplication-rule.js +2 -41
- package/dist/decode/reduplication-rule.js.map +1 -1
- package/dist/decode/shu-frames.d.ts +6 -0
- package/dist/decode/shu-frames.d.ts.map +1 -0
- package/dist/decode/shu-frames.js +102 -0
- package/dist/decode/shu-frames.js.map +1 -0
- package/dist/decode/split-infix.d.ts +25 -0
- package/dist/decode/split-infix.d.ts.map +1 -0
- package/dist/decode/split-infix.js +134 -0
- package/dist/decode/split-infix.js.map +1 -0
- package/dist/decode/split-rule.d.ts +11 -0
- package/dist/decode/split-rule.d.ts.map +1 -1
- package/dist/decode/split-rule.js +17 -4
- package/dist/decode/split-rule.js.map +1 -1
- package/dist/decode/tiao-frames.d.ts +6 -0
- package/dist/decode/tiao-frames.d.ts.map +1 -0
- package/dist/decode/tiao-frames.js +60 -0
- package/dist/decode/tiao-frames.js.map +1 -0
- package/dist/decode/verbal-frame.d.ts +68 -0
- package/dist/decode/verbal-frame.d.ts.map +1 -0
- package/dist/decode/verbal-frame.js +76 -0
- package/dist/decode/verbal-frame.js.map +1 -0
- package/dist/decode/verbal-held.d.ts +12 -0
- package/dist/decode/verbal-held.d.ts.map +1 -0
- package/dist/decode/verbal-held.js +63 -0
- package/dist/decode/verbal-held.js.map +1 -0
- package/dist/decode/verbal-rule.d.ts +31 -0
- package/dist/decode/verbal-rule.d.ts.map +1 -0
- package/dist/decode/verbal-rule.js +100 -0
- package/dist/decode/verbal-rule.js.map +1 -0
- package/dist/decode/xiang-frames.d.ts +6 -0
- package/dist/decode/xiang-frames.d.ts.map +1 -0
- package/dist/decode/xiang-frames.js +65 -0
- package/dist/decode/xiang-frames.js.map +1 -0
- package/dist/decode/zhuan-frames.d.ts +6 -0
- package/dist/decode/zhuan-frames.d.ts.map +1 -0
- package/dist/decode/zhuan-frames.js +97 -0
- package/dist/decode/zhuan-frames.js.map +1 -0
- package/dist/dictionary/frequency-table.d.ts +8 -0
- package/dist/dictionary/frequency-table.d.ts.map +1 -1
- package/dist/dictionary/frequency-table.js +11 -1
- package/dist/dictionary/frequency-table.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- 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":"
|
|
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
|
|
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.
|
|
5
|
-
*
|
|
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
|
|
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":"AAAA
|
|
1
|
+
{"version":3,"file":"split-rule.js","sourceRoot":"","sources":["../../src/decode/split-rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|