Skip to content

Instantly share code, notes, and snippets.

@RanolP
Created August 23, 2020 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RanolP/bd277b8aae7d2567ca59ef45eeb3488e to your computer and use it in GitHub Desktop.
Save RanolP/bd277b8aae7d2567ca59ef45eeb3488e to your computer and use it in GitHub Desktop.
조사를 조사하세요
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