public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            if (context.CurrentStateLength == 1)
            {
                context.Nodes.Push(new XProcessingInstruction(context.LocationMinus("<?".Length)));
            }

            if (c == '?')
            {
                if (context.StateTag == NOMATCH)
                {
                    context.StateTag = QUESTION;
                    return(null);
                }
            }
            else if (c == '>' && context.StateTag == QUESTION)
            {
                // if the '?' is followed by a '>', the state has ended
                // so attach a node to the DOM and end the state
                XProcessingInstruction xpi = (XProcessingInstruction)context.Nodes.Pop();

                if (context.BuildTree)
                {
                    xpi.End(context.Location);
                    ((XContainer)context.Nodes.Peek()).AddChildNode(xpi);
                }
                return(Parent);
            }
            else
            {
                context.StateTag = NOMATCH;
            }

            return(null);
        }
        protected override int Dispatch(char c)
        {
            switch (CurrentXState)
            {
            case XState.Free:
                switch (c)
                {
                case '<':
                    return((int)XState.OpeningBracket);

//				case '&': return (int) XState.Entity;
                default:
                    return((int)XState.Free);
                }

            case XState.Malformed:
                if (StateLength == 0)
                {
                    if (BuildTree)
                    {
                        ConnectAll();
                    }
                    EndAll(true);
                }
                switch (c)
                {
                case '>':
                    return((int)XState.Free);

                case '<':
                    return((int)XState.OpeningBracket);

                default:
                    return((int)XState.Malformed);
                }

            case XState.OpeningBracket:
                if (StateLength == 0)
                {
                    switch (c)
                    {
                    case '!':
                        return((int)XState.OpeningBracket);

                    case '?':
                        Nodes.Push(new XProcessingInstruction(this.Position - 2));
                        return((int)XState.ProcessingInstruction);

                    case '/':
                        Nodes.Push(new XClosingTag(this.Position - 2));
                        return((int)XState.ClosingTagName);

                        if (char.IsLetter(c) || c == '_')
                        {
                            Nodes.Push(new XElement(this.Position - 2));
                            KeywordBuilder.Append(c);
                            return((int)XState.TagName);
                        }
                    }
                }
                else if (StateLength == 1)
                {
                    switch (c)
                    {
                    case '-':
                        return((int)XState.CommentOpening);

                    case '[':
                        return((int)XState.CDataOpening);
                    }
                }
                LogError("Malformed tag start.");
                if (c == '>')
                {
                    return((int)XState.Free);
                }
                else if (c == '<')
                {
                    return((int)XState.OpeningBracket);
                }
                else
                {
                    return((int)XState.Malformed);
                }

            case XState.TagName:
                return((int)XState.TagName);

            /*
             *                          if (char.IsLetterOrDigit (c) || c == '_') {
             *                                  KeywordBuilder.Append (c);
             *                                  return (int)XState.TagName;
             *                          }
             *
             *                          if (c == ':') {
             *                                  XElement el = Nodes.Peek () as INamedXObject;
             *                                  if (namedObject.Name.Name != null || KeywordBuilder.Length == 0) {
             *                                          LogError ("Unexpected ':' in name.");
             *                                          return GetStateForCurrentObject ();
             *                                  } else {
             *                                          namedObject.Name = new XName (context.KeywordBuilder.ToString ());
             *                                          context.KeywordBuilder.Length = 0;
             *                                  }
             *                          }
             *
             *                          else if (char.IsWhiteSpace (c)) return (int)XState.Tag;
             *                          else if (c == '>') return (int)XState.Free;
             *                          else if (c == '/') return (int)XState.SelfClosing;
             *                          else break;
             *
             *                  case XState.Tag:
             *                          if (char.IsWhiteSpace (c)) return (int)XState.Tag;
             *                          else if (char.IsLetter (c)) return PushCurrent (XState.AttributeName);
             *                          else if (c == '>') return (int)XState.Free;
             *                          else if (c == '/') return (int)XState.SelfClosing;
             *                          else break;
             *
             *                  case XState.SelfClosing:
             *                          if (c == '>') return (int)XState.Free;
             *                          else break;
             *
             *                  case XState.AttributeName:
             *                          if (char.IsWhiteSpace (c))
             *                                  return (int)XState.AttributeNamed;
             *                          else if (char.IsLetterOrDigit (c) | c == ':')
             *                                  return (int)XState.AttributeName;
             *                          else if (c == '=')
             *                                  return (int)XState.AttributeValue;
             *                          else return (int)XState.Malformed;
             *
             *                  case XState.AttributeNamed:
             *                          if (c == '=') return (int)XState.AttributeValue;
             *                          else if (char.IsWhiteSpace (c)) return (int)XState.AttributeNamed;
             *                          else return (int)XState.Malformed;
             *
             *                  case XState.AttributeValue:
             *                          if (c == '\'') return (int)XState.AttributeQuotes;
             *                          else if (c == '"') return (int)XState.AttributeDoubleQuotes;
             *                          else if (c == '<') break;
             *                          else if (char.IsWhiteSpace (c)) return (int)XState.AttributeValue;
             *                          else if (char.IsLetterOrDigit (c)) {
             *                                  LogWarning ("Unquoted attribute value.");
             *                                  return (int)XState.AttributeUnquoted;
             *                          } else {
             *                                  LogWarning ("Incomplete attribute.");
             *                                  return PopState ();
             *                          }
             *
             *                  case XState.AttributeQuotes:
             *                          switch (c) {
             *                          case '\'': return PopState ();
             *                          case '<': return UnexpectedOpeningTag;
             *                          case '&': return PushCurrent (XState.Entity);
             *                          default: return (int)XState.AttributeQuotes;
             *                          }
             *
             *                  case XState.AttributeDoubleQuotes:
             *                          switch (c) {
             *                          case '"': return PopState ();
             *                          case '<': return UnexpectedOpeningTag;
             *                          case '&': return PushCurrent (XState.Entity);
             *                          default: return (int)XState.AttributeDoubleQuotes;
             *                          }
             *
             *                  case XState.AttributeUnquoted:
             *                          switch (c) {
             *                          case '<': return UnexpectedOpeningTag;
             *                          case '&': return PushCurrent (XState.Entity);
             *                          case '.': case '_': case ':': case ';': return CurrentState;
             *                          case '>': return (int)XState.Free;
             *                          }
             *                          if (char.IsLetterOrDigit (c)) return CurrentState;
             *                          else if (char.IsWhiteSpace (c)) return PopState ();
             *                          break;
             */
            case XState.CData:
                return((int)((c == ']')? XState.CDataClosing: XState.CData));

            case XState.CDataOpening:
                if (StateLength < "CDATA[".Length)
                {
                    if ("CDATA["[StateLength] == c)
                    {
                        return((int)XState.CDataOpening);
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    Nodes.Push(new XCData(Position - "<![CDATA[".Length));
                    return((int)XState.CData);
                }

            case XState.CDataClosing:
                if ("]>"[StateLength] == c)
                {
                    if (StateLength == 1)
                    {
                        XCData n = (XCData)Nodes.Pop();
                        n.End(Position);
                        ((XContainer)Nodes.Peek()).AddChildNode(n);
                        return((int)XState.Free);
                    }
                    else
                    {
                        return((int)XState.CDataClosing);
                    }
                }
                else
                {
                    return((int)XState.CData);
                }

            /*
             *                  case XState.Entity:
             *                          if ((StateLength == 0 && c == '#') || char.IsLetterOrDigit (c))
             *                                  return (int)XState.Entity;
             *                          else if (c == ';') return PopState ();
             *                          else LogWarning ("Malformed entity");
             *                          break;
             */
            case XState.ProcessingInstruction:
                switch (c)
                {
                case '<':
                    break;

                case '?':
                    return((int)XState.ProcessingInstructionClosing);

                default:
                    return((int)XState.ProcessingInstruction);
                }
                break;

            case XState.ProcessingInstructionClosing:
                switch (c)
                {
                case '<':
                    break;

                case '?':
                    return((int)XState.ProcessingInstructionClosing);

                case '>':
                {
                    XProcessingInstruction n = (XProcessingInstruction)Nodes.Pop();
                    n.End(Position);
                    if (BuildTree)
                    {
                        ((XContainer)Nodes.Peek()).AddChildNode(n);
                    }
                    return((int)XState.Free);
                }

                default:
                    return((int)XState.ProcessingInstruction);
                }
                break;

            case XState.CommentOpening:
                if (c == '-')
                {
                    Nodes.Push(new XComment(Position - "<!--".Length));
                    return((int)XState.Comment);
                }
                else
                {
                    break;
                }

            case XState.Comment:
                if (c == '-')
                {
                    return((int)XState.CommentClosing);
                }
                else
                {
                    return((int)XState.Comment);
                }

            case XState.CommentClosing:
                if (StateLength == 0)
                {
                    if (c == '-')
                    {
                        return((int)XState.CommentClosing);
                    }
                    else
                    {
                        return((int)XState.Comment);
                    }
                }
                else if (StateLength > 0)
                {
                    if (c == '>')
                    {
                        XComment n = (XComment)Nodes.Pop();
                        n.End(Position);
                        if (BuildTree)
                        {
                            ((XContainer)Nodes.Peek()).AddChildNode(n);
                        }
                    }
                    else
                    {
                        LogWarning("The string '--' should not appear in comments.");
                    }
                    if (c == '-')
                    {
                        return((int)XState.CommentClosing);
                    }
                    else
                    {
                        return((int)XState.Comment);
                    }
                }
                else
                {
                    break;
                }
            }

            if (c == '<')
            {
                return(UnexpectedOpeningTag);
            }
            return((int)XState.Malformed);
        }