Created
August 23, 2020 13:00
-
-
Save RanolP/bd277b8aae7d2567ca59ef45eeb3488e to your computer and use it in GitHub Desktop.
조사를 조사하세요
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type TailId = -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27; | |
function tailIdOf(word: string): TailId { | |
if (word.length === 0) { | |
return -1; | |
} | |
const last = word[word.length - 1]; | |
if (last < '가' || '힣' < last) { | |
return -1; | |
} | |
// 위의 if 문에서 가 <= last이므로 해당 값은 양의 정수고 | |
// 28로 나눈 나머지이므로 0 ~ 27 범위입니다. | |
// 따라서 TailId라고 단언할 수 있습니다. | |
return (last.charCodeAt(0) - 44032) % 28 as TailId; | |
} | |
export interface Josa<HaveTail extends string, NotHaveTail extends string> { | |
aliases: string[]; | |
bothForm?: string; | |
haveTail: HaveTail; | |
notHaveTail: NotHaveTail; | |
useNotHaveTailWhen: TailId[]; | |
} | |
function createJosa< | |
HaveTail extends string, | |
NotHaveTail extends string | |
>( | |
haveTail: HaveTail, | |
notHaveTail: NotHaveTail, | |
bothForm?: string, | |
useNotHaveTailWhen: TailId[] = [0] | |
): Josa<HaveTail, NotHaveTail> { | |
return { | |
aliases: [haveTail, notHaveTail], | |
bothForm, | |
haveTail, | |
notHaveTail, | |
useNotHaveTailWhen, | |
}; | |
} | |
const enum NotKoreanStrategy { | |
Ignore, | |
ShowBoth, | |
} | |
const StandardJosa = [ | |
createJosa('이', '가'), | |
createJosa('을', '를'), | |
createJosa('과', '와'), | |
createJosa('아', '야'), | |
createJosa('으로', '로', '(으)로', [0, 8]), | |
createJosa('으로서', '로서', '(으)로서', [0, 8]), | |
createJosa('으로써', '로써', '(으)로써', [0, 8]), | |
createJosa('으로부터', '로부터', '(으)로부터', [0, 8]), | |
createJosa('이라고', '라고', '(이)라고'), | |
createJosa('이서', '서', '(이)서'), | |
createJosa('이다', '다', '(이)다'), | |
createJosa('이여', '여', '(이)여'), | |
createJosa('이며', '며', '(이)며'), | |
createJosa('이랑', '랑', '(이)랑'), | |
createJosa('이나', '나', '(이)나'), | |
createJosa('이란', '란', '(이)란'), | |
createJosa('이든가', '든가', '(이)든가'), | |
createJosa('이든지', '든지', '(이)든지'), | |
createJosa('이나마', '나마', '(이)나마'), | |
createJosa('이야', '야', '(이)야'), | |
createJosa('이야말로', '야말로', '(이)야말로'), | |
] as const; | |
type DigJosa<T> = T extends Josa<infer A, infer B> ? A | B : never; | |
type AllJosaKeySet = DigJosa<typeof StandardJosa[number]>; | |
type JosaAttachedString = string & { noTailFirst: string }; | |
declare global { | |
interface Object extends Record<AllJosaKeySet, JosaAttachedString> { } | |
} | |
function patchJosa(notKoreanStrategy: NotKoreanStrategy = NotKoreanStrategy.ShowBoth) { | |
const duplicatedAlias = [] as string[]; | |
const aliasHaveSeen = [] as string[]; | |
for (const josa of StandardJosa) { | |
for (const alias of josa.aliases) { | |
if (aliasHaveSeen.includes(alias)) { | |
duplicatedAlias.push(alias); | |
} else { | |
aliasHaveSeen.push(alias) | |
} | |
} | |
} | |
for (const josa of StandardJosa) { | |
function get(this: unknown): JosaAttachedString { | |
const thisString = String(this); | |
const tail = tailIdOf(thisString); | |
function process(noTailFirst: boolean): string { | |
if (tail == -1) { | |
switch (notKoreanStrategy) { | |
case NotKoreanStrategy.Ignore: { | |
return thisString; | |
} | |
case NotKoreanStrategy.ShowBoth: { | |
return thisString + (josa.bothForm ?? (noTailFirst ? `(${josa.notHaveTail})${josa.haveTail}` : `(${josa.haveTail})${josa.notHaveTail}`)); | |
} | |
} | |
} | |
return thisString + (josa.useNotHaveTailWhen.includes(tail) ? josa.notHaveTail : josa.haveTail); | |
} | |
return Object.assign(process(true), { noTailFirst: process(false) }); | |
} | |
for (const alias of josa.aliases) { | |
if (duplicatedAlias.includes(alias)) { | |
continue; | |
} | |
Object.defineProperty(Object.prototype, alias, { get }); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment