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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
//! # korean-regex
//!
//! 한글은 초성, 중성, 종성의 조합이기에 각각을 분리해 분석하거나 사용하는 것이 때때로 유용합니다.
//!
//! korean-regex는 한글을 초성, 중성, 종성의 조합으로 사용할 수 있도록 합니다.
//!
//! ## Syntax
//!
//! 기본적으로 korean-regex는 한 글자 OR 문법의 확장입니다. 정규표현식의 다른 문법은 건드리지 않습니다.
//!
//! 우선 초성, 중성, 종성은 각각 `[]`로 둘러싸인 뒤 `:`으로 분리됩니다.
//! 예를 들어 아래의 예시처럼 `[ㄱ:ㅏ:ㄱ]`일 경우 초성에 `ㄱ`, 중성에 `ㅏ`, 종성에 `ㄱ`이 각각 들어가 `각`이 됩니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[각]", compile("[ㄱ:ㅏ:ㄱ]", order).unwrap().to_string());
//! ```
//!
//! 한 파트에 두 개 이상의 문자를 적으면 각 가능한 경우의 수로 변환됩니다.
//! 예를 들어 아래처럼 `[ㄱㄴ:ㅏㅣ:ㄴ]`일 경우 모든 경우의 수인 `간긴난닌`로 대체됩니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[간긴난닌]", compile("[ㄱㄴ:ㅏㅣ:ㄴ]", order).unwrap().to_string());
//! ```
//!
//! 만약 해당 칸은 비워놓는다면 해당 자리는 어떤 것이든 받아들이겠다는 의미입니다.
//! 예를 들어 `[::ㅎ]`은 '종성이 `ㅎ`인 모든 음소'를 의미합니다.
//!
//! ```no_run
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[갛갷걓걯...흏흫힇힣]", compile("[::ㅎ]", order).unwrap().to_string());
//! ```
//!
//! `-`을 통해 연속되는 음소를 대체할 수 있습니다.
//!
//! 이때 기본적으로 `ㄱㄴㄷㄹ...`가 *아닌* `ㄱㄲㄴㄷㄸㄹ...`와 같은 사전순으로 match된다는 점을 주의해 주세요.
//! 이는 중성과 종성도 동일합니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[간깐난단딴란]", compile("[ㄱ-ㄹ:ㅏ:ㄴ]", order).unwrap().to_string());
//! assert_eq!("[간갠갼걘건겐견곈곤관괜괸굔군권궨귄균근긘긴]", compile("[ㄱ:ㅏ-ㅣ:ㄴ]", order).unwrap().to_string());
//! assert_eq!("[간-갈]", compile("[ㄱ:ㅏ:ㄴ-ㄹ]", order).unwrap().to_string());
//! ```
//!
//! `0`은 해당 자리에 음소가 없다는 것을 의미합니다. 기본적으로 종성에 사용됩니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[가각간나낙난다닥단]", compile("[ㄱㄴㄷ:ㅏ:0ㄱㄴ]", order).unwrap().to_string());
//! ```
//!
//! 하지만 특수하게 `[*:0:0]`이나 `[0:*:0]`과 같은 형태도 사용될 수 있습니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[ㄱㄲㄴㄷㄸㄹ]", compile("[ㄱ-ㄹ:0:0]", order).unwrap().to_string());
//! assert_eq!("[ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ]", compile("[0:ㅏ-ㅣ:0]", order).unwrap().to_string());
//! ```
//!
//! `^`을 이용하면 해당 음소에 match하고 싶은 문자 대신 match하기 싫은 문자를 지정할 수 있습니다.
//! 예를 들어 초성이 `ㄱ`이고 중성이 `ㅏ`이면서 받침이 `ㄹ`이 아닌 모든 음소는 `[ㄱ:ㅏ:^ㄹ]`로 표현할 수 있습니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[가-갇갉-갛]", compile("[ㄱ:ㅏ:^ㄹ]", order).unwrap().to_string());
//! ```
//!
//! 만약 종성이 없는 문자를 match하고 싶다면 `[*:*:0]` 대신 `[*:*]` 문법을 사용할 수도 있습니다.
//! 예를 들어 `[ㄱㄴㄷ:ㅏㅣ:0]`는 `[ㄱㄴㄷ:ㅏㅣ]`로 대체될 수 있습니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[가기나니다디]", compile("[ㄱㄴㄷ:ㅏㅣ:0]", order).unwrap().to_string());
//! assert_eq!("[가기나니다디]", compile("[ㄱㄴㄷ:ㅏㅣ]", order).unwrap().to_string());
//! ```
//!
//! 만약 별개로 몇 개의 글자를 match에 추가하고 싶다면 `|`를 그 뒤에 추가하면 됩니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[과구놔누돠두한abc]", compile("[ㄱㄴㄷ:ㅜㅘ|한abc]", order).unwrap().to_string());
//! ```
//!
//! 한글에는 두 개 이상의 글자가 합쳐서 생성된 문자들이 있습니다. `ㄲ`이나 `ㄼ`, `ㅢ` 등이 그 예입니다.
//! 만약 글자 입력기가 `ㄺ`같은 문자를 입력하는 것을 지원하지 않거나, 미관상의 이유로 코드에서 피하고 싶다면
//! 괄호를 사용해서 문자를 합칠 수 있습니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[곿괇궧궯뽟뽧쀇쀏]", compile("[ㄱ(ㅂㅂ):(ㅗㅏ)(ㅜㅔ):(ㄹㅂ)(ㄱㅅ)]", order).unwrap().to_string());
//! ```
//!
//! 이 고유 문법이 적용되는 범위를 넘어서면 기본 정규 표현식과 같이 섞어 사용할 수 있습니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
// ! // ㅇ이 초성인 글자로 단어가 시작하는 세 글자 이하의 모든 단어를 찾음.
//! let pattern = compile(r"\b([아-잏][^ ]{0,2})\b", order).unwrap();
//! let input = "저기 양을 잡아먹는 이리 때가 오르막길을 타고 간다!";
//! let result: Vec<_> = pattern.find_iter(input).map(|m| m.as_str()).collect();
//! assert_eq!(vec!["양을", "이리"], result);
//! ```
//!
//! ## Example
//!
//! 다른 문법과 합치면 다음과 같이 사용할 수 있습니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! // 초성이 ㄱ이 아니고 그 뒤에 종성이 `ㅇ`인 모든 글자가 오며 그 다음 글자 바운더리 혹은 종성이 없는 문자가 있는 경우
//! let pattern = compile(r"[^ㄱ::][::ㅇ](\b|[:])", order).unwrap();
//! let result: Vec<_> = pattern
//! .captures_iter("한글은 초성, 중성, 종성의 조합이기에 각각을 분리해 분석하거나 사용하는 것이 때때로 유용합니다.")
//! .map(|captures| captures[0].to_string())
//! .collect();
//! assert_eq!(vec!["초성", "중성", "종성의", "사용하"], result)
//! ```
//!
//! ## Hyphen replacing
//!
//! 정규표현식의 `[]` 문법에는 연속되는 문자를 대체하는 `-` 문법이 있습니다.
//!
//! 만약 연속되는 문자가 세 개 이상 있다면 korean-regex에서도 `-`문법이 이용됩니다.
//!
//! ```rust
//! use korean_regex::*;
//!
//! let order = Order::Default;
//! assert_eq!("[가-깋라-맇]", compile("[ㄱㄹ::]", order).unwrap().to_string());
//! ```
use Regex;
pub use substitute;
type CompiledOrders<'a> = ;
const CHOSUNGS: = ;
const JUNGSUNGS: = ;
const JONGSUNGS: = ;
const CHOSUNGS_REGFIRST: = ;
const JUNGSUNGS_REGFIRST: = ;
const JONSGSUNGS_REGFIRST: = ;
/// korean-regex에서 나올 수 있는 모든 오류를 모아놓은 enum입니다.
/// 하이픈 구성 시 사용할 순서를 결정합니다.
///
/// 이 라이브러리와 유니코드, 한국의 글자 체계는 기본적으로 다음과 같은 글자 순서를 사용합니다.
///
/// ```raw
/// 초성: ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
/// 중성: ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
/// 종성: 0ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ
/// ```
///
/// 이 순서에는 장점도 있지만 단점도 있습니다 대표적으로는 `-`을 사용할 때 나타납니다.
///
/// `[ㄱ-ㄹ:0:0]`의 결과값은 `[ㄱㄲㄴㄷㄸㄹ]`입니다. 하지만 `ㄱ`부터
/// `ㄹ`의 결과값으로 `[ㄱㄴㄷㄹ]`를 얻는 것이 필요한 경우도 존재합니다.
/// 이때 `[ㄱㄴㄷㄹ]`로 적는 것 또한 좋지만 이를 `[ㄱ-ㄹ]`로 줄이는 것을
/// 더 선호할 수도 있습니다.
///
/// 이러한 경우 Order를 고쳐서 순서를 변경해 문제를 해결할 수 있습니다.
///
/// `Order::RegularFirst`를 순서로 사용하면 각각의 순서는 다음과 같이 변경됩니다.
///
/// ```raw
/// 초성: ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㄲㄸㅃㅆㅉ
/// 중성: ㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣㅐㅒㅔㅖㅘㅙㅚㅝㅞㅟㅢ
/// 종성: 0ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㄲㄳㄵㄶㄺㄻㄼㄽㄾㄿㅀㅄㅆ
/// ```
///
/// 이는 `[ㄱ-ㄹ:0:0]`의 결과값이 `[ㄱㄴㄷㄹ]`가 되도록 만듭니다.
///
/// 하지만 하이픈 대체에 영향을 줄 수 있어 이는 결과값의 순서에 영향을 주진 않습니다.
/// 예를 들어 `[ㄲㄴ:0:0]`의 결과는 `Order::Default`에서는
/// `[ㄲㄴ]`가 되고 `Order::RegularFirst`에서도 `[ㄲㄴ]`가 됩니다.
///
/// 하이픈 사용 시 두 순서 중에서 어느 것이 자신의 필요에 맞는지 확인하고 사용하시면 됩니다.
/// 컴파일 결과를 Regex로 컴파일하는 대신 String 값으로 받습니다.
///
/// `compile`은 단순히 `compilestr`의 결과를 `Regex::new`로 감싸는 함수일 뿐입니다.
///
/// ```rust
/// use korean_regex::*;
/// use regex::Regex;
///
/// let order = Order::Default;
/// assert_eq!(
/// compilestr("[ㄱ::]", order).unwrap(),
/// compile("[ㄱ::]", order).unwrap().to_string()
/// );
/// ```
///
/// 만약 다른 정규표현식 크레이트를 이용하고 싶은 경우에
/// compilestr을 이용해 다른 정규표현식 크레이트를 사용할 수 있습니다.
///
/// ```pass
/// use fancy_regex::Regex;
/// use korean_regex::*;
///
/// let pattern = compilestr(r"(?<![ㅎ:ㅏ:])[^ㄱ::][::ㅇ]", Order::Default);
/// let re = Regex::new(&pattern.unwrap()).unwrap();
/// ```
/// 한국어 regex가 담긴 패턴을 받아 Regex로 컴파일합니다.