/// <summary>
        /// 從堆疊中讀取字元,並轉成點字。只處理中文字和中文標點符號。
        /// </summary>
        /// <param name="charStack">字元堆疊。</param>
        /// <param name="context">情境物件。</param>
        /// <returns>傳回轉換後的點字物件串列,若串列為空串列,表示沒有成功轉換的字元。</returns>
        public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context)
        {
            if (charStack.Count < 1)
            {
                throw new ArgumentException("傳入空的字元堆疊!");
            }

            bool               done = false;
            char               ch;
            string             text;
            bool               isExtracted; // 目前處理的字元是否已從堆疊中移出。
            BrailleWord        brWord;
            List <BrailleWord> brWordList = null;
            int idx             = 0;
            int chineseStartIdx = -1;
            int chineseEndIdx   = -1;

            while (!done && charStack.Count > 0)
            {
                ch          = charStack.Peek(); // 只讀取但不從堆疊移走。
                isExtracted = false;

                // 小於跟大於符號是情境標籤,不處理(交由 ControlTagConverter 負責)。
                if (ch == '<' || ch == '>')
                {
                    break;
                }

                // 全形英文字母要轉成半形,並且由英文點字元件處理。
                if (CharHelper.IsFullShapeLetter(ch))
                {
                    charStack.Pop();
                    ch = CharHelper.FullShapeToAsciiLetter(ch);
                    charStack.Push(ch);
                    break;
                }

                // 全形數字要轉成半形,並且由英文點字元件處理。
                if (CharHelper.IsFullShapeDigit(ch))
                {
                    charStack.Pop();
                    ch = CharHelper.FullShapeToAsciiDigit(ch);
                    charStack.Push(ch);
                    break;
                }

                text = ch.ToString();

                // 處理雙字元的標點符號。
                if (ch == '…' || ch == '-' || ch == '─' || ch == '╴' || ch == '﹏')
                {
                    // 讀下一個字元,若是相同符號,則可略過;若不同,則下次迴圈仍需處理。
                    if (charStack.Count >= 2)
                    {
                        charStack.Pop();
                        char ch2 = charStack.Pop();
                        if (ch2 == ch)  // 如果是連續兩個刪節號或破折號。
                        {
                            text        = text + text;
                            isExtracted = true;
                        }
                        else
                        {
                            // 不是連續符號,把之前取出的字元放回堆疊。
                            charStack.Push(ch2);
                            charStack.Push(ch);
                            isExtracted = false;
                        }
                    }
                }
                else if (ch == '[')     // 處理以半形中括號包住的特殊符號.
                {
                    if (charStack.Count >= 3)
                    {
                        charStack.Pop();
                        char ch2 = charStack.Pop();
                        char ch3 = charStack.Pop();
                        if (ch3 == ']' && (ch2 == '↗' || ch2 == '↘'))
                        {
                            text        = text + ch2.ToString() + ch3.ToString();
                            isExtracted = true;
                        }
                        else
                        {
                            // 不是中括號包住的特殊符號,把之前取出的字元放回堆疊。
                            charStack.Push(ch3);
                            charStack.Push(ch2);
                            charStack.Push(ch);
                            isExtracted = false;
                        }
                    }
                }

                /* 特殊數字編號【1】已經改成直接定義在 xml 檔案 (2009-6-22).
                 *              else if (ch == '【')
                 *              {   // 特殊數字編號,用於選擇題的答案編號,例如: 【1】,見 ChineseBrailleTable.xml。
                 *                  if (charStack.Count >= 3)
                 *                  {
                 *                      charStack.Pop();
                 *                      char ch2 = charStack.Pop();
                 *                      char ch3 = charStack.Pop();
                 *                      if (Char.IsDigit(ch2) && ch3 == '】')   // 無論是半形或全形數字,Char.IsDigit 都會傳回 true。
                 *                      {
                 *                          isExtracted = true;
                 *                          if (CharHelper.IsFullShapeDigit(ch2))
                 *                          {
                 *                              ch2 = CharHelper.FullShapeToAsciiDigit(ch2);
                 *                          }
                 *                          text = ch.ToString() + ch2.ToString() + ch3.ToString();
                 *                      }
                 *                      else
                 *                      {
                 *                          charStack.Push(ch3);
                 *                          charStack.Push(ch2);
                 *                          charStack.Push(ch);
                 *                          isExtracted = false;
                 *                      }
                 *                  }
                 *              }
                 */
                brWord = InternalConvert(text);
                if (brWord == null)
                {
                    break;
                }

                if (!isExtracted)
                {
                    charStack.Pop();
                }

                if (!StrHelper.IsEmpty(text))   // 避免將空白字元也列入 Chinese。
                {
                    brWord.Language = BrailleLanguage.Chinese;
                }

                ApplyBrailleConfig(brWord); // 根據組態檔的設定調整點字轉換結果。

                if (brWordList == null)
                {
                    brWordList = new List <BrailleWord>();
                }
                brWordList.Add(brWord);

                // 記錄連續中文字元,以修正破音字的注音字根。
                if (brWord.Text.IsCJK())   // 如果是中文字元,要記錄連續的中文字元區間
                {
                    if (chineseStartIdx < 0)
                    {
                        chineseStartIdx = idx;
                        chineseEndIdx   = idx;
                    }
                    else
                    {
                        chineseEndIdx = idx;
                    }
                }
                else  // 不是中文字,則把之前紀錄的連續中文字取出,並修正其注音字根
                {
                    FixPhoneticCodes(brWordList, chineseStartIdx, chineseEndIdx);
                    chineseStartIdx = -1;
                    chineseEndIdx   = -1;
                }
                idx++;
            }

            // 處理這段中文字的最後一段連續中文字。
            if (chineseStartIdx >= 0)
            {
                FixPhoneticCodes(brWordList, chineseStartIdx, chineseEndIdx);
            }

            return(brWordList);
        }