/// <summary>
        /// Initializes the <see cref="PinglishConverter"/> class.
        /// </summary>
        public PinglishConverter()
        {
            #region Preprocess Replacements

            //TODO: It's better to load them from a file --> In progress -> DONE

            PreprocessElementInfo entryInfo = null;
            ///////////////////////////////////////////////////////////////
            entryInfo = new PreprocessElementInfo("U", true);
            entryInfo.Equivalents.Add("too");
            this.m_preprocessReplacements.Add(entryInfo.PinglishString, entryInfo);
            ///////////////////////////////////////////////////////////////
            entryInfo = new PreprocessElementInfo("I", true);
            entryInfo.Equivalents.Add("man");
            this.m_preprocessReplacements.Add(entryInfo.PinglishString, entryInfo);
            /////////////////////////////////////////////////////////////////
            entryInfo = new PreprocessElementInfo(QuotationMark.RightSingleQuotationMark.ToString(), false);
            entryInfo.Equivalents.Add(QuotationMark.SingleQuotationMark.ToString());
            this.m_preprocessReplacements.Add(entryInfo.PinglishString, entryInfo);
            /////////////////////////////////////////////////////////////////
            entryInfo = new PreprocessElementInfo(QuotationMark.Prime.ToString(), false);
            entryInfo.Equivalents.Add(QuotationMark.SingleQuotationMark.ToString());
            this.m_preprocessReplacements.Add(entryInfo.PinglishString, entryInfo);
            /////////////////////////////////////////////////////////////////
            entryInfo = new PreprocessElementInfo(QuotationMark.SingleHighReveresed9QuotationMark.ToString(), false);
            entryInfo.Equivalents.Add(QuotationMark.SingleQuotationMark.ToString());
            this.m_preprocessReplacements.Add(entryInfo.PinglishString, entryInfo);
            /////////////////////////////////////////////////////////////////
            entryInfo = new PreprocessElementInfo("k", true);
            entryInfo.Equivalents.Add("kei");
            this.m_preprocessReplacements.Add(entryInfo.PinglishString, entryInfo);
            /////////////////////////////////////////////////////////////////

            #region m_bigLettersAtBeginOrEnd

            this.m_bigLettersAtBeginOrEnd.Add('B', new[] { "b", "bi" });
            this.m_bigLettersAtBeginOrEnd.Add('C', new[] { "c", "si" });
            this.m_bigLettersAtBeginOrEnd.Add('D', new[] { "d", "di" });
            this.m_bigLettersAtBeginOrEnd.Add('E', new[] { "e", "ee" });
            this.m_bigLettersAtBeginOrEnd.Add('F', new[] { "f", "ef" });
            this.m_bigLettersAtBeginOrEnd.Add('G', new[] { "g", "ji" });
            this.m_bigLettersAtBeginOrEnd.Add('K', new [] { "k", "kei" });
            this.m_bigLettersAtBeginOrEnd.Add('M', new [] { "m", "em" });
            this.m_bigLettersAtBeginOrEnd.Add('N', new [] { "n", "en" });
            this.m_bigLettersAtBeginOrEnd.Add('P', new [] { "p", "pi" });
            this.m_bigLettersAtBeginOrEnd.Add('Q', new [] { "q", "kioo" });
            this.m_bigLettersAtBeginOrEnd.Add('S', new [] { "s", "es" });
            this.m_bigLettersAtBeginOrEnd.Add('T', new [] { "t", "ti" });
            this.m_bigLettersAtBeginOrEnd.Add('U', new [] { "u", "yoo" });
            this.m_bigLettersAtBeginOrEnd.Add('V', new [] { "v", "vi", });
            this.m_bigLettersAtBeginOrEnd.Add('Y', new [] { "y", "vay" });
            this.m_bigLettersAtBeginOrEnd.Add('Z', new [] { "z", "zed" });

            #endregion

            #region m_oneLetterWords

            m_oneLetterWords.Add('4', new string[] { "baraye" });
            m_oneLetterWords.Add('K', new string[] { "kei" });
            m_oneLetterWords.Add('U', new string[] { "to" });

            /*m_oneLetterWords.Add('', new string[] { "" });
            *  m_oneLetterWords.Add('', new string[] { "" });
            *  m_oneLetterWords.Add('', new string[] { "" });
            *  m_oneLetterWords.Add('', new string[] { "" });
            *  m_oneLetterWords.Add('', new string[] { "" });
            *  m_oneLetterWords.Add('', new string[] { "" });
            *  m_oneLetterWords.Add('', new string[] { "" });*/

            foreach (char key in m_oneLetterWords.Keys)
            {
                Debug.Assert(StringUtil.OneLetterPinglishWords.Contains(char.ToLower(key)));
            }

            #endregion

            #endregion
        }
        /// <summary>
        /// Loads Pinglish preprocess elements from a file.
        /// </summary>
        public static List <PreprocessElementInfo> LoadPreprocessElements(string filePath)
        {
            string[] elementWithInfos;

            var preprocessElementInfos = new List <PreprocessElementInfo>();

            PreprocessElementInfo elementInfo;

            if (File.Exists(filePath))
            {
                StreamReader reader = null;
                try
                {
                    reader = new StreamReader(filePath);
                    string line;
                    while (!reader.EndOfStream)
                    {
                        line = reader.ReadLine();
                        if (string.IsNullOrEmpty(line) || line.StartsWith("#")) // It's for comments
                        {
                            continue;
                        }

                        elementWithInfos = line.Split(PreprocessElementInfoSeparators, StringSplitOptions.RemoveEmptyEntries);
                        if (elementWithInfos.Length <= 1)
                        {
                            continue;
                        }

                        string pinglishStr = elementWithInfos[0];
                        bool   isWholeWord = false;
                        bool   isExactWord = false;
                        var    position    = TokenPosition.None;
                        var    equivalents = new List <string>();

                        for (int i = 1; i < elementWithInfos.Length; i++)
                        {
                            if (!elementWithInfos[i].StartsWith("#"))
                            {
                                equivalents.Add(elementWithInfos[i]);
                            }
                            else
                            {
                                string info = elementWithInfos[i].TrimStart('#');
                                switch (info.ToLower())
                                {
                                case "start":
                                    position = position.Set(TokenPosition.StartOfWord);
                                    break;

                                case "middle":
                                    position = position.Set(TokenPosition.MiddleOfWord);
                                    break;

                                case "end":
                                    position = position.Set(TokenPosition.EndOfWord);
                                    break;

                                case "wholeword":
                                    isWholeWord = true;
                                    break;

                                case "exact":
                                    isExactWord = true;
                                    break;
                                }
                            }
                        }
                        if (position == TokenPosition.None || isWholeWord)
                        {
                            position = TokenPosition.Any;
                        }

                        elementInfo = new PreprocessElementInfo(pinglishStr, isWholeWord, isExactWord, position);
                        elementInfo.Equivalents.AddRange(equivalents);
                        preprocessElementInfos.Add(elementInfo);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                }
                finally
                {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                }
            }

            return(preprocessElementInfos);
        }