private bool ExitTableBody(Token t, HtmlTreeBuilder tb)
            {
                if (!(tb.InTableScope("tbody") ||
                      tb.InTableScope("thead") ||
                      tb.InScope("tfoot")))
                {
                    // frag case
                    tb.Error(this);
                    return(false);
                }

                tb.ClearStackToTableBodyContext();
                tb.Process(new Token.EndTag(tb.CurrentElement.NodeName)); // tbody, tfoot, thead
                return(tb.Process(t));
            }
            public override bool Process(Token t, HtmlTreeBuilder tb)
            {
                switch (t.Type)
                {
                case TokenType.StartTag:
                    Token.StartTag startTag = t.AsStartTag();
                    string         name     = startTag.Name;

                    if (name.Equals("tr"))
                    {
                        tb.ClearStackToTableBodyContext();
                        tb.Insert(startTag);
                        tb.Transition(InRow);
                    }
                    else if (StringUtil.In(name, "th", "td"))
                    {
                        tb.Error(this);
                        tb.Process(new Token.StartTag("tr"));
                        return(tb.Process(startTag));
                    }
                    else if (StringSet.Create("caption col colgroup tbody tfoot thead").Contains(name))
                    {
                        return(ExitTableBody(t, tb));
                    }
                    else
                    {
                        return(AnythingElse(t, tb));
                    }

                    break;

                case TokenType.EndTag:
                    Token.EndTag endTag = t.AsEndTag();
                    name = endTag.Name;

                    if (StringUtil.In(name, "tbody", "tfoot", "thead"))
                    {
                        if (!tb.InTableScope(name))
                        {
                            tb.Error(this);
                            return(false);
                        }
                        else
                        {
                            tb.ClearStackToTableBodyContext();
                            tb.Pop();
                            tb.Transition(InTable);
                        }
                    }
                    else if (name.Equals("table"))
                    {
                        return(ExitTableBody(t, tb));
                    }
                    else if (StringSet.Create("body caption col colgroup html td th tr").Contains(name))
                    {
                        tb.Error(this);
                        return(false);
                    }
                    else
                    {
                        return(AnythingElse(t, tb));
                    }

                    break;

                default:
                    return(AnythingElse(t, tb));
                }
                return(true);
            }