public override State PushChar (char c, IParseContext context, ref string rollback)
		{
			if (context.CurrentStateLength == 0)
				context.StateTag = 0;
			
			if (c == '<') {
				if (context.StateTag == 0) {
					context.StateTag++;
					return null;
				}
			}
			if (context.StateTag > 0) {
				if (CLOSE[context.StateTag] == c) {
					context.StateTag++;
					if (context.StateTag == CLOSE.Length) {
						var el = (XElement) context.Nodes.Pop ();
						var closing = new XClosingTag (new XName ("script"), context.LocationMinus (CLOSE.Length));
						closing.End (context.Location);
						el.Close (closing);
						return Parent;
					}
				} else {
					context.StateTag = 0;
				}
			}
			return null;
		}
Esempio n. 2
0
        public override XmlParserState PushChar(char c, IXmlParserContext context, ref string rollback)
        {
            if (context.CurrentStateLength == 0)
            {
                context.StateTag = 0;
            }

            if (c == '<')
            {
                if (context.StateTag == 0)
                {
                    context.StateTag++;
                    return(null);
                }
            }
            if (context.StateTag > 0)
            {
                if (CLOSE[context.StateTag] == c)
                {
                    context.StateTag++;
                    if (context.StateTag == CLOSE.Length)
                    {
                        var el      = (XElement)context.Nodes.Pop();
                        var closing = new XClosingTag(new XName("script"), context.LocationMinus(CLOSE.Length));
                        closing.End(context.Location);
                        el.Close(closing);
                        rollback = string.Empty;
                        return(Parent);
                    }
                }
                else
                {
                    context.StateTag = 0;
                }
            }
            return(null);
        }
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            //NOTE: This is (mostly) duplicated in HtmlTagState
            //handle inline tags implicitly closed by block-level elements
            if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState)
            {
                XClosingTag ct = (XClosingTag)context.Nodes.Peek();
                if (!ct.Name.HasPrefix && ct.Name.IsValid)
                {
                    //Note: the node stack will always be at least 1 deep due to the XDocument
                    var parent = context.Nodes.Peek(1) as XElement;
                    //if it's not a matching closing tag
                    if (parent != null && !string.Equals(ct.Name.Name, parent.Name.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        //attempt to implicitly close the parents
                        while (parent != null && parent.ValidAndNoPrefix() && parent.IsImplicitlyClosedBy(ct))
                        {
                            context.Nodes.Pop();
                            context.Nodes.Pop();
                            if (warnAutoClose)
                            {
                                context.LogWarning(string.Format("Tag '{0}' implicitly closed by closing tag '{1}'.",
                                                                 parent.Name.Name, ct.Name.Name), parent.Region);
                            }
                            //parent.Region.End = element.Region.Start;
                            //parent.Region.EndColumn = Math.Max (parent.Region.EndColumn - 1, 1);
                            parent.Close(parent);
                            context.Nodes.Push(ct);

                            parent = context.Nodes.Peek(1) as XElement;
                        }
                    }
                }
            }

            return(base.PushChar(c, context, ref rollback));
        }
        public override State PushChar(char c, MonoDevelop.Xml.StateEngine.IParseContext context, ref string rollback)
        {
            //NOTE: This is (mostly) duplicated in HtmlTagState
            //handle "paragraph" tags implicitly closed by block-level elements
            if (context.CurrentStateLength == 1 && context.PreviousState is XmlNameState)
            {
                XClosingTag ct = (XClosingTag)context.Nodes.Peek();
                //Note: the node stack will always be at least 1 deep due to the XDocument
                XElement parent = context.Nodes.Peek(1) as XElement;


                while (parent != null && parent.Name.IsValid && !parent.Name.HasPrefix && !ct.Name.HasPrefix &&
                       ct.Name.IsValid &&
                       string.Compare(ct.Name.Name, parent.Name.Name, StringComparison.OrdinalIgnoreCase) != 0 &&
                       !ElementTypes.IsInline(ct.Name.Name) &&
                       (ElementTypes.IsInline(parent.Name.Name) || ElementTypes.IsParagraph(parent.Name.Name))
                       )
                {
                    context.Nodes.Pop();
                    context.Nodes.Pop();
                    if (warnAutoClose)
                    {
                        context.LogWarning(string.Format("Tag '{0}' implicitly closed by closing tag '{1}'.",
                                                         parent.Name.Name, ct.Name.Name), parent.Region);
                    }
                    //parent.Region.End = element.Region.Start;
                    //parent.Region.End.Column = Math.Max (parent.Region.End.Column - 1, 1);
                    parent.Close(parent);
                    context.Nodes.Push(ct);

                    parent = context.Nodes.Peek(1) as XElement;
                }
            }

            return(base.PushChar(c, context, ref rollback));
        }
Esempio n. 5
0
        public override XmlParserState PushChar(char c, IXmlParserContext context, ref string rollback)
        {
            var ct = context.Nodes.Peek() as XClosingTag;

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

                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.",
                            ct.Region
                            );
                    }
                }
                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;
            context.LogError("Unexpected character '" + c + "' in closing tag.");
            return(Parent);
        }
		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.Start.Line, el.Region.Start.Column),
								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;
		}
Esempio n. 7
0
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            var ct = context.Nodes.Peek() as XClosingTag;

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

                ct = new XClosingTag(context.Position - STARTOFFSET);
                context.Nodes.Push(ct);
            }

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

                if (ct.IsNamed)
                {
                    ct.End(context.Position + 1);

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

                    //clear the stack of intermediate unclosed tags
                    while (popCount > 1)
                    {
                        if (context.Nodes.Pop() is XElement el)
                        {
                            context.Diagnostics?.LogError(string.Format("Unclosed tag '{0}'", el.Name.FullName), el.Span);
                        }
                        popCount--;
                    }

                    //close the start tag, if we found it
                    if (popCount > 0)
                    {
                        // close it even if not in tree mode, as some spines may want to know whether an element was closed after advancing the parser
                        ((XElement)context.Nodes.Pop()).Close(ct);
                    }
                    else
                    {
                        if (context.BuildTree)
                        {
                            context.Diagnostics?.LogError(
                                $"Closing tag '{ct.Name.FullName}' does not match any currently open tag.",
                                ct.Span
                                );
                            // add it into the tree anyway so it's accessible
                            var parent = context.Nodes.Peek() as XContainer;
                            if (parent != null)
                            {
                                if (!parent.IsEnded)
                                {
                                    parent = context.Nodes.Count > 1? context.Nodes.Peek(1) as XContainer : null;
                                }
                                if (parent != null)
                                {
                                    parent.AddChildNode(ct);
                                }
                            }
                        }
                    }
                }
                else
                {
                    context.Diagnostics?.LogError("Closing tag ended prematurely.", context.Position);
                }
                return(Parent);
            }

            if (c == '<')
            {
                context.Diagnostics?.LogError("Unexpected '<' in tag.", context.Position - 1);
                context.Nodes.Pop();
                rollback = string.Empty;
                return(Parent);
            }

            if (XmlChar.IsWhitespace(c))
            {
                return(null);
            }

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

            rollback = string.Empty;
            context.Diagnostics?.LogError("Unexpected character '" + c + "' in closing tag.", context.Position - 1);
            context.Nodes.Pop();
            return(Parent);
        }