Beispiel #1
0
        protected override void ShallowCopyFrom(XObject copyFrom)
        {
            base.ShallowCopyFrom(copyFrom);
            XClosingTag copyFromAtt = (XClosingTag)copyFrom;

            //immutable types
            name = copyFromAtt.name;
        }
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            XClosingTag ct = context.Nodes.Peek() as XClosingTag;

            if (ct == null)
            {
                Debug.Assert(context.CurrentStateLength == 1,
                             "IncompleteNode must not be an XClosingTag when CurrentStateLength is 1");
                Debug.Assert(context.Nodes.Peek() is XElement);

                ct = new XClosingTag(context.LocationMinus(3)); //3 = </ and the current char
                context.Nodes.Push(ct);
            }

            //if tag closed
            if (c == '>')
            {
                context.Nodes.Pop();

                if (ct.IsNamed)
                {
                    ct.End(context.Location);

                    // walk up tree of parents looking for matching tag
                    int  popCount = 0;
                    bool found    = false;
                    foreach (XObject node in context.Nodes)
                    {
                        popCount++;
                        XElement element = node as XElement;
                        if (element != null && element.Name == ct.Name)
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        popCount = 0;
                    }

                    //clear the stack of intermediate unclosed tags
                    while (popCount > 1)
                    {
                        XElement el = context.Nodes.Pop() as XElement;
                        if (el != null)
                        {
                            context.LogError(string.Format(
                                                 "Unclosed tag '{0}' at line {1}, column {2}.", el.Name.FullName, el.Region.BeginLine, el.Region.BeginColumn),
                                             ct.Region);
                        }
                        popCount--;
                    }

                    //close the start tag, if we found it
                    if (popCount > 0)
                    {
                        if (context.BuildTree)
                        {
                            ((XElement)context.Nodes.Pop()).Close(ct);
                        }
                        else
                        {
                            context.Nodes.Pop();
                        }
                    }
                    else
                    {
                        context.LogError(
                            "Closing tag '" + ct.Name.FullName + "' does not match any currently open tag.");
                    }
                }
                else
                {
                    context.LogError("Closing tag ended prematurely.");
                }
                return(Parent);
            }

            if (c == '<')
            {
                context.LogError("Unexpected '<' in tag.");
                rollback = string.Empty;
                return(Parent);
            }

            if (!ct.IsNamed && (char.IsLetter(c) || c == '_'))
            {
                rollback = string.Empty;
                return(NameState);
            }

            rollback = string.Empty;
            //note: MalformedTagState logs an error, so skip this
            //context.LogError ("Unexpected character '" + c + "' in closing tag.");
            return(MalformedTagState);
        }