/// <summary>
        /// 오토마타 스코프 글자에서 만약 <paramref name="castChar"/>이 모음이거나 이중 자음이지만,
        /// <para>한 글자에 있는 것이 불가능한 경우, 마지막 문자를 가져와 다음 오토마타를 만들어 붙이고 탈출합니다.</para>
        /// </summary>
        /// <param name="castChar">다음 오토마타에 붙일 새 문자</param>
        private static void EscapeGlyph(char castChar)
        {
            //if (characterHistory.Count <= 2) return;

            if (Vowel.ContainsKey(castChar))
            {
                char lastIndex = characterHistory[characterHistory.Count - 1];
                if (UndoAutomata())
                {
                    GlyphInfo data = Consonant[characterHistory[characterHistory.Count - 1]];

                    lastIndex = data.constructGlyphs[(int)Consonant[lastIndex].index - (int)data.index - 1];
                }

                EscapeGlyph();
                characterHistory.Add(lastIndex);

                scopeHistory.Add(currentScope = AutomataScope.first);
            }
            else
            {
                EscapeGlyph();
                scopeHistory.Add(currentScope = AutomataScope.idle);
            }
            PushAutomata(castChar);
        }
        /// <summary>
        /// 오토마타로 만들어지는 글리프를 되돌리거나 텍스트에서 문자를 제거합니다.
        /// </summary>
        public static bool UndoAutomata()
        {
            buildResult = UNDERBAR_IDLE;
            if (characterHistory.Count > 0)
            {
                if (Consonant.ContainsKey(characterHistory[characterHistory.Count - 1]))
                {
                    uint      glyph = characterHistory[characterHistory.Count - 1];
                    GlyphInfo data  = Consonant[Convert.ToChar(glyph)];
                    if (data.constructGlyphs == null &&
                        data.endUpStyle != EndUpStyle.alone)
                    {
                        while (data.constructGlyphs == null)
                        {
                            data = Consonant[Convert.ToChar(--glyph)];
                        }

                        characterHistory[characterHistory.Count - 1] = Convert.ToChar(glyph);

                        buildResult = BuildGlyph(characterHistory);

                        return(true);
                    }
                }
                else if (Vowel.ContainsKey(characterHistory[characterHistory.Count - 1]))
                {
                    uint      glyph = characterHistory[characterHistory.Count - 1];
                    GlyphInfo data  = Vowel[Convert.ToChar(glyph)];
                    if (data.constructGlyphs == null)
                    {
                        while (data.constructGlyphs == null ||
                               (data.constructGlyphs != null && data.constructGlyphs.Length <= 1))
                        {
                            data = Vowel[Convert.ToChar(--glyph)];
                        }

                        characterHistory[characterHistory.Count - 1] = Convert.ToChar(glyph);

                        buildResult = BuildGlyph(characterHistory);

                        return(true);
                    }
                }

                characterHistory.RemoveAt(characterHistory.Count - 1);
                scopeHistory.RemoveAt(scopeHistory.Count - 1);
                currentScope = scopeHistory.Count > 0 ? scopeHistory[scopeHistory.Count - 1] : AutomataScope.idle;
                buildResult  = BuildGlyph(characterHistory);
            }
            else if (currentText.Length > 1)
            {
                currentText = currentText.Remove(currentText.Length - 1);
            }
            else
            {
                currentText = "";
            }

            return(false);
        }
        /// <summary>
        /// 오토마타 스코프에 잡힌 문자에서 탈출합니다.
        /// </summary>
        public static void EscapeGlyph()
        {
            char build = BuildGlyph(characterHistory);

            if (build != '\0')
            {
                currentText += build;
            }
            characterHistory.Clear();
            scopeHistory.Clear();
            scopeHistory.Add(currentScope = AutomataScope.idle);

            buildResult = UNDERBAR_IDLE;
        }
        /// <summary>
        /// 자음 또는 모음인 글자를 오토마타에 적용합니다.
        /// </summary>
        /// <param name="glyph">자음 또는 모음인 글자</param>
        /// <exception cref="Exception">글자가 자음/모음이 아닌 문자</exception>
        public static void PushAutomata(char glyph)
        {
            if (glyph == ' ' || glyph == '_' || glyph == '_')
            {
                if (characterHistory.Count != 0)
                {
                    EscapeGlyph();
                }
                else
                {
                    currentText += " ";
                }
                return;
            }

            uint scope = Convert.ToUInt32(glyph);

            if (scope < 0x3131 || scope > 0x3163)
            {
                throw new Exception("악");
            }

            scope -= 0x3131;

            uint cacheGlyph;

            switch (currentScope)
            {
            default:
            case AutomataScope.idle:
                if (Consonant.ContainsKey(glyph))
                {
                    characterHistory.Clear();
                    scopeHistory.Clear();
                    characterHistory.Add(glyph);
                    scopeHistory.Add(currentScope = AutomataScope.first);
                }
                break;

            case AutomataScope.first:
                if (characterHistory.Count != 1)
                {
                    goto default;
                }

                if (Vowel.ContainsKey(glyph))
                {
                    characterHistory.Add(glyph);
                    scopeHistory.Add(currentScope = AutomataScope.second);
                }
                else if (Consonant.ContainsKey(glyph))
                {
                    if (Consonant[characterHistory[0]]
                        .constructGlyphs == null)
                    {
                        EscapeGlyph(glyph);
                    }
                    else if (Consonant[characterHistory[0]]
                             .constructGlyphs.Contains(glyph))
                    {
                        cacheGlyph = Convert.ToUInt32(characterHistory[0])
                                     + (uint)Consonant[characterHistory[0]]
                                     .constructGlyphs.IndexOf(glyph)
                                     + 1;

                        characterHistory[0] = Convert.ToChar(cacheGlyph);
                    }
                    else
                    {
                        EscapeGlyph(glyph);
                    }
                }
                else
                {
                    EscapeGlyph(glyph);
                }

                break;

            case AutomataScope.second:
                if (characterHistory.Count != 2)
                {
                    goto default;
                }

                if (Consonant.ContainsKey(glyph))
                {
                    characterHistory.Add(glyph);
                    scopeHistory.Add(currentScope = AutomataScope.last);
                }
                else if (Vowel.ContainsKey(glyph))
                {
                    if (Vowel[characterHistory[1]]
                        .constructGlyphs == null)
                    {
                        EscapeGlyph();
                    }
                    else if (Vowel[characterHistory[1]]
                             .constructGlyphs.Contains(glyph))
                    {
                        cacheGlyph = Convert.ToUInt32(characterHistory[1])
                                     + (uint)Vowel[characterHistory[1]]
                                     .constructGlyphs.IndexOf(glyph)
                                     + 1;

                        characterHistory[1] = Convert.ToChar(cacheGlyph);
                    }
                    else
                    {
                        EscapeGlyph();
                    }
                }
                else
                {
                    EscapeGlyph();
                }

                break;

            case AutomataScope.last:
                if (characterHistory.Count != 3)
                {
                    goto default;
                }

                if (Vowel.ContainsKey(glyph))
                {
                    EscapeGlyph(glyph);
                }
                else if (Consonant.ContainsKey(glyph))
                {
                    if (Consonant[characterHistory[2]]
                        .constructGlyphs == null)
                    {
                        EscapeGlyph(glyph);
                    }
                    else if (Consonant[characterHistory[2]]
                             .constructGlyphs.Contains(glyph))
                    {
                        cacheGlyph = Convert.ToUInt32(characterHistory[2])
                                     + (uint)Consonant[characterHistory[2]]
                                     .constructGlyphs.IndexOf(glyph)
                                     + 1;

                        if (Consonant[Convert.ToChar(cacheGlyph)].endUpStyle
                            == EndUpStyle.endUp)
                        {
                            UndoAutomata();
                            EscapeGlyph();

                            characterHistory.Clear();
                            characterHistory.Add(Convert.ToChar(cacheGlyph));
                            scopeHistory.Clear();
                            scopeHistory.Add(currentScope = AutomataScope.first);
                        }
                        else
                        {
                            characterHistory[2] = Convert.ToChar(cacheGlyph);
                        }
                    }
                    else
                    {
                        EscapeGlyph(glyph);
                    }
                }
                break;
            }

            buildResult = BuildGlyph(characterHistory);
        }