public override bool Equals(object obj)
        {
            MarkupExtensionToken other = obj as MarkupExtensionToken;

            if (other == null)
            {
                return(false);
            }
            return(this.Kind == other.Kind && this.Value == other.Value);
        }
        static MarkupExtensionInfo Parse(string text, int offset)
        {
            var    info         = new MarkupExtensionInfo();
            string argumentName = null;
            MarkupExtensionTokenizer tokenizer = new MarkupExtensionTokenizer(text);

            MarkupExtensionToken token = null;

            try {
                token = tokenizer.NextToken();

                while (token.Kind != MarkupExtensionTokenKind.EndOfFile)
                {
                    switch (token.Kind)
                    {
                    case MarkupExtensionTokenKind.OpenBrace:
                        info.StartOffset = token.StartOffset + offset;
                        break;

                    case MarkupExtensionTokenKind.CloseBrace:
                        info.EndOffset = token.EndOffset + offset;
                        break;

                    case MarkupExtensionTokenKind.TypeName:
                        info.ExtensionType = token.Value;
                        break;

                    case MarkupExtensionTokenKind.MemberName:
                        // if there is an open member without a value add the member name
                        if (argumentName != null)
                        {
                            info.TryAddNamedArgument(argumentName, ParseValue("", token.EndOffset + offset));
                        }
                        argumentName = token.Value;
                        break;

                    case MarkupExtensionTokenKind.String:
                        if (argumentName != null)
                        {
                            info.TryAddNamedArgument(argumentName, ParseValue(token.Value, token.StartOffset + offset));
                            argumentName = null;
                        }
                        else
                        {
                            info.PositionalArguments.Add(ParseValue(token.Value, token.StartOffset + offset));
                        }
                        break;
                    }

                    token = tokenizer.NextToken();
                }
            } catch (MarkupExtensionParseException) {
                // ignore parser errors
            } finally {
                if (token != null && argumentName != null)
                {
                    info.TryAddNamedArgument(argumentName, ParseValue(token.Value, token.StartOffset + offset));
                }
            }

            return(info);
        }