コード例 #1
0
        /// <summary>
        /// Internal implemention of the message reference and interpolation token
        /// Parsing used by tokenizeInterpolation() and replaceMessageReferences().
        /// </summary>
        public static List <string> TokenizeInterpolation(string message, bool parseInterpolationTokens = true)
        {
            var tokens = new List <string>();
            var chars  = message.ToCharArray().ToList();
            // Parse the message with a finite state machine.
            // 0 - Base case.
            // 1 - % found
            // 2 - Digit found.
            // 3 - Message ref found
            var    state  = 0;
            var    buffer = new List <string>();
            string number = "";

            for (var i = 0; i < chars.Count + 1; i++)
            {
                var c = i == chars.Count ? ' ' : chars[i];
                if (state == 0 && i != chars.Count)
                {
                    if (c == '%')
                    {
                        var text = string.Join("", buffer.ToArray());
                        if (!string.IsNullOrEmpty(text))
                        {
                            tokens.Add(text);
                        }
                        buffer.Clear();
                        state = 1; // Start escape.
                    }
                    else
                    {
                        buffer.Add(c.ToString()); // Regular char
                    }
                }
                else if (state == 1)
                {
                    if (c == '%')
                    {
                        buffer.Add(c.ToString()); // Escaped %: %%
                        state = 0;
                    }
                    else if (parseInterpolationTokens && '0' <= c && c <= '9')
                    {
                        state  = 2;
                        number = c.ToString();
                        buffer.Add("");
                        var text = string.Join("", buffer.ToArray());
                        if (!string.IsNullOrEmpty(text))
                        {
                            tokens.Add(text);
                        }
                        buffer.Clear();
                    }
                    else if (c == '{')
                    {
                        state = 3;
                    }
                    else
                    {
                        buffer.Add("%"); // Not recognized. Return as literal.
                        if (i != chars.Count)
                        {
                            buffer.Add(c.ToString());
                        }
                        state = 0; // add parse as string literl
                    }
                }
                else if (state == 2)
                {
                    if ('0' <= c && c <= '9')
                    {
                        number += c; // Multi-digit number.
                    }
                    else
                    {
                        tokens.Add(int.Parse(number).ToString());
                        i--; // Parse this char agian.
                        state = 0;
                    }
                }
                else if (state == 3)
                {
                    if (i == chars.Count)
                    {
                        // Premature end before closing '}'
                        buffer.Insert(0, "%{"); // Re-insert leading delimiter
                        i--;                    // Parse this char again.
                        state = 0;              // add parse as string literal.
                    }
                    else if (c != '}')
                    {
                        buffer.Add(c.ToString());
                    }
                    else
                    {
                        var rawKey = string.Join("", buffer.ToArray());
                        if (new Regex("[a-zA-Z][a-zAZ0-9_]").Match(rawKey).Success) // Strict matching
                        {
                            // Found a valied string key. Attempt case insensitive match.
                            var keyUpper = rawKey.ToUpper();

                            // BKY_ is the prefix used to namespace the string s used in Blockly
                            // core files adn the predefined blocks in ../blocks/. These strings
                            // are defined in ../msgs/ files.
                            var bklyKey = keyUpper.StartsWith("BKY_") ? keyUpper.Substring(4) : null;
                            if (!string.IsNullOrEmpty(bklyKey) && I18n.Contains(bklyKey))
                            {
                                var rawValue = I18n.Get(bklyKey);
                                tokens.AddRange(TokenizeInterpolation(rawValue));
                            }
                            else
                            {
                                tokens.Add("%{" + rawKey + "}");
                            }

                            buffer.Clear(); // Clear the array
                            state = 0;
                        }
                        else
                        {
                            tokens.Add("%{" + rawKey + "}");
                            buffer.Clear();
                            state = 0; // and parse as string literal.
                        }
                    }
                }
            }

            var text1 = string.Join("", buffer.ToArray());

            if (!string.IsNullOrEmpty(text1))
            {
                tokens.Add(text1);
            }

            // Merge adjacent text tokens into a single string.
            var mergedTokens = new List <string>();

            buffer.Clear();
            for (int i = 0; i < tokens.Count; i++)
            {
                int tokenNum = 0;

                if (int.TryParse(tokens[i], out tokenNum))
                {
                    text1 = string.Join("", buffer.ToArray());
                    if (!string.IsNullOrEmpty(text1))
                    {
                        mergedTokens.Add(text1);
                    }
                    buffer.Clear();
                    mergedTokens.Add(tokens[i]);
                }
                else
                {
                    buffer.Add(tokens[i]);
                }
            }

            text1 = string.Join("", buffer.ToArray());

            if (!string.IsNullOrEmpty(text1))
            {
                mergedTokens.Add(text1);
            }
            buffer.Clear();

            // remove last
            return(mergedTokens);
        }