@kensio/pinyinjs 1.9.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/de-rule.d.ts +1 -0
- package/dist/decode/de-rule.d.ts.map +1 -1
- package/dist/decode/de-rule.js +1 -0
- package/dist/decode/de-rule.js.map +1 -1
- 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/hua-rule.d.ts +17 -0
- package/dist/decode/hua-rule.d.ts.map +1 -0
- package/dist/decode/hua-rule.js +83 -0
- package/dist/decode/hua-rule.js.map +1 -0
- package/dist/decode/hua-speaking.d.ts +29 -0
- package/dist/decode/hua-speaking.d.ts.map +1 -0
- package/dist/decode/hua-speaking.js +79 -0
- package/dist/decode/hua-speaking.js.map +1 -0
- package/dist/decode/hua-words.d.ts +73 -0
- package/dist/decode/hua-words.d.ts.map +1 -0
- package/dist/decode/hua-words.js +161 -0
- package/dist/decode/hua-words.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/measure-rule.d.ts +31 -0
- package/dist/decode/measure-rule.d.ts.map +1 -0
- package/dist/decode/measure-rule.js +87 -0
- package/dist/decode/measure-rule.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 +6 -32
- package/dist/decode/reading-rules.d.ts.map +1 -1
- package/dist/decode/reading-rules.js +14 -90
- 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,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a 数 is counting or is a number.
|
|
3
|
+
*
|
|
4
|
+
* The verb is `shǔ` and the noun `shù`. A 数 standing on its own is most often
|
|
5
|
+
* "several" in front of a number or a measure word (数十人, 数千人, 数个小时),
|
|
6
|
+
* or the tail of a compound the dictionary lacks (里程数, 网民数). The verb
|
|
7
|
+
* counts up to something, or takes 了 or 一下.
|
|
8
|
+
*/
|
|
9
|
+
import { QUANTITY_CHARACTERS } from "../numerals/characters.js";
|
|
10
|
+
import { tagOf, wordEndingAt, wordStartingAt, } from "./rules.js";
|
|
11
|
+
import { isBareAt, isRunEnd, startsWithAny, syllableOf, charactersOf, } from "./verbal-frame.js";
|
|
12
|
+
/**
|
|
13
|
+
* The 到 of 数到十, which only counting is followed by.
|
|
14
|
+
*/
|
|
15
|
+
const UP_TO = new Set(["到"]);
|
|
16
|
+
/**
|
|
17
|
+
* Aspect after the verb: 我数了一下, 汤姆数了他的钱, 你有试过数星星吗.
|
|
18
|
+
*/
|
|
19
|
+
const ASPECT = new Set(["了", "着", "过", "過"]);
|
|
20
|
+
/**
|
|
21
|
+
* How many times, which only a verb is followed by.
|
|
22
|
+
*/
|
|
23
|
+
const TIMES = ["一下", "一遍", "一数"];
|
|
24
|
+
/**
|
|
25
|
+
* What can come straight before a 数 that is counting.
|
|
26
|
+
*
|
|
27
|
+
* 开始数羊, 这孩子能数到二十. 在 is left out, since 在数分钟内 is "within a few
|
|
28
|
+
* minutes".
|
|
29
|
+
*/
|
|
30
|
+
const BEFORE = new Set(["开始", "会", "能", "可以", "请", "再", "一起", "帮"]);
|
|
31
|
+
/**
|
|
32
|
+
* The tags of what a counting 数 can be followed by after {@link BEFORE}.
|
|
33
|
+
*
|
|
34
|
+
* Nouns of every kind and pronouns. The spans of time in {@link TIME} are
|
|
35
|
+
* nouns too, and are kept out before the tag is asked.
|
|
36
|
+
*/
|
|
37
|
+
function isCountedTag(tag) {
|
|
38
|
+
return tag.startsWith("n") || tag === "r";
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The spans of time 数 counts as "several": 数小时, 数日, 数年.
|
|
42
|
+
*/
|
|
43
|
+
const TIME = [
|
|
44
|
+
"小时",
|
|
45
|
+
"年",
|
|
46
|
+
"天",
|
|
47
|
+
"日",
|
|
48
|
+
"月",
|
|
49
|
+
"周",
|
|
50
|
+
"星期",
|
|
51
|
+
"世纪",
|
|
52
|
+
"分钟",
|
|
53
|
+
"秒",
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Whether the 数 at a position is counting.
|
|
57
|
+
*
|
|
58
|
+
* A numeral in front of it makes it part of a number, as in 十数人.
|
|
59
|
+
*/
|
|
60
|
+
function isCountingAt(context, at) {
|
|
61
|
+
const { characters } = context;
|
|
62
|
+
if (QUANTITY_CHARACTERS.has(characters[at - 1] ?? "")) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (isBareAt(context, at + 1, UP_TO) ||
|
|
66
|
+
startsWithAny(context, at + 1, TIMES) ||
|
|
67
|
+
isBareAt(context, at + 1, ASPECT)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const before = wordEndingAt(context, at);
|
|
71
|
+
if (before === undefined || !BEFORE.has(before)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (isRunEnd(context, at + 1)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return (!startsWithAny(context, at + 1, TIME) &&
|
|
78
|
+
isCountedTag(tagOf(context, wordStartingAt(context, at + 1))));
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The characters that bind it into a compound reading it otherwise.
|
|
82
|
+
*
|
|
83
|
+
* Bound before it: 岁数, 多数, 人数, 次数, 分数 and the other nouns ending in
|
|
84
|
+
* it, so 你多大岁数了 is not read as counting. 倒数 is left out, since it
|
|
85
|
+
* counts too.
|
|
86
|
+
*/
|
|
87
|
+
const BOUND_BEFORE = charactersOf("岁歲多少人次倍分无無函指常变變参參级級总總页頁字步票件户戶名头頭号號礼禮算整基奇偶正负負复複小半单單双雙实實虚虛质質素回场場");
|
|
88
|
+
/**
|
|
89
|
+
* The characters after it that bind it into such a compound.
|
|
90
|
+
*/
|
|
91
|
+
const BOUND_AFTER = new Set();
|
|
92
|
+
/**
|
|
93
|
+
* 数 read `shǔ` where it is counting.
|
|
94
|
+
*/
|
|
95
|
+
export const SHU_FRAME = {
|
|
96
|
+
characters: new Set(["数", "數"]),
|
|
97
|
+
reading: syllableOf("shǔ"),
|
|
98
|
+
boundBefore: BOUND_BEFORE,
|
|
99
|
+
boundAfter: BOUND_AFTER,
|
|
100
|
+
isVerbalAt: isCountingAt,
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=shu-frames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shu-frames.js","sourceRoot":"","sources":["../../src/decode/shu-frames.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Syllable } from "../syllable/syllable.js";
|
|
2
|
+
import { type EdgeContext } from "./rules.js";
|
|
3
|
+
/**
|
|
4
|
+
* The syllable a 离合词 separated by more than a 个 gives its tail, or
|
|
5
|
+
* undefined.
|
|
6
|
+
*
|
|
7
|
+
* The nearest head the {@link INFIX} pattern reaches is the one asked about,
|
|
8
|
+
* so 我还没睡够觉 finds 睡觉 and never gets as far as the 还. The pair has to
|
|
9
|
+
* be tagged a verb itself, which is what a 离合词 is, and 打了场硬仗 found the
|
|
10
|
+
* 打场 of threshing, a noun, behind a 场 that was counting. That stands in for
|
|
11
|
+
* the 个 shape's verb in front, which the dictionary leaves untagged on 休, 流
|
|
12
|
+
* and 理, so 休一天假, 流了血 and 理了发 are read through it. The tail has to be
|
|
13
|
+
* an object, for the reason {@link isObject} gives, and must not run on into a
|
|
14
|
+
* noun, for the reason {@link modifiesWhatFollows} gives.
|
|
15
|
+
*
|
|
16
|
+
* The 个 shape's `opensTaggedWord` is left out, because it changed
|
|
17
|
+
* nothing over either corpus. Forcing the tail's own edge leaves a longer word
|
|
18
|
+
* starting at it to the decode, so 我睡了觉得好多了 still reads 觉得 whole.
|
|
19
|
+
*
|
|
20
|
+
* Only the tail is settled. A head reached across a complement can be an
|
|
21
|
+
* adverb the tags call a verb, and 还不够钱 would read its 还 as `huán` off
|
|
22
|
+
* 还钱.
|
|
23
|
+
*/
|
|
24
|
+
export declare function widelySeparatedSyllableAt(context: EdgeContext, at: number): Syllable | undefined;
|
|
25
|
+
//# sourceMappingURL=split-infix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split-infix.d.ts","sourceRoot":"","sources":["../../src/decode/split-infix.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,KAAK,WAAW,EAAS,MAAM,YAAY,CAAC;AAoGrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,GACT,QAAQ,GAAG,SAAS,CAmBtB"}
|
|
@@ -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"}
|