Beispiel #1
0
        protected XmlParser(XmlRootState rootState)
        {
            RootState = rootState;

            Context = new XmlParserContext {
                CurrentStateLength = 0,
                CurrentState       = rootState,
                PreviousState      = rootState,
                KeywordBuilder     = new StringBuilder(),
                Nodes = new NodeStack()
            };

            Context.Nodes.Push(RootState.CreateDocument());
        }
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            System.Diagnostics.Debug.Assert(((XAttribute)context.Nodes.Peek()).Value == null);

            if (c == '<')
            {
                //the parent state should report the error
                rollback = string.Empty;
                return(Parent);
            }

            if (context.CurrentStateLength == 0)
            {
                if (c == '"')
                {
                    context.StateTag = DOUBLEQUOTE;
                    return(null);
                }
                if (c == '\'')
                {
                    context.StateTag = SINGLEQUOTE;
                    return(null);
                }
                context.StateTag = UNQUOTED;
            }

            int maskedTag = context.StateTag & TagMask;

            if (maskedTag == UNQUOTED)
            {
                return(BuildUnquotedValue(c, context, ref rollback));
            }

            if ((c == '"' && maskedTag == DOUBLEQUOTE) || c == '\'' && maskedTag == SINGLEQUOTE)
            {
                //ending the value
                var att = (XAttribute)context.Nodes.Peek();
                att.Value = context.KeywordBuilder.ToString();
                return(Parent);
            }

            context.KeywordBuilder.Append(c);
            return(null);
        }
        XmlParserState BuildUnquotedValue(char c, XmlParserContext context, ref string rollback)
        {
            if (char.IsLetterOrDigit(c) || c == '_' || c == '.')
            {
                context.KeywordBuilder.Append(c);
                return(null);
            }

            if (context.KeywordBuilder.Length == 0)
            {
                context.Diagnostics?.LogError($"The value of attribute '{(string)((XAttribute)context.Nodes.Peek ()).Name.FullName}' ended unexpectedly.", context.Position);
                rollback = string.Empty;
                return(Parent);
            }

            var att = (XAttribute)context.Nodes.Peek();

            att.Value = context.KeywordBuilder.ToString();
            rollback  = string.Empty;
            return(Parent);
        }
Beispiel #4
0
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            if (context.CurrentStateLength == 0)
            {
                context.Nodes.Push(new XCData(context.Position - STARTOFFSET));
            }

            if (c == ']')
            {
                //make sure we know when there are two ']' chars together
                if (context.StateTag == NOMATCH)
                {
                    context.StateTag = SINGLE_BRACKET;
                }
                else
                {
                    context.StateTag = DOUBLE_BRACKET;
                }
            }
            else if (c == '>' && context.StateTag == DOUBLE_BRACKET)
            {
                // if the ']]' is followed by a '>', the state has ended
                // so attach a node to the DOM and end the state
                var cdata = (XCData)context.Nodes.Pop();
                cdata.End(context.Position + 1);

                if (context.BuildTree)
                {
                    ((XContainer)context.Nodes.Peek()).AddChildNode(cdata);
                }
                return(Parent);
            }
            else
            {
                // not any part of a ']]>', so make sure matching is reset
                context.StateTag = NOMATCH;
            }

            return(null);
        }
Beispiel #5
0
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            if (context.CurrentStateLength == 0)
            {
                context.Nodes.Push(new XProcessingInstruction(context.Position - QUESTION));
            }

            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
                var xpi = (XProcessingInstruction)context.Nodes.Pop();

                // at this point the position isn't incremented to include the '>' yet
                // so make sure to include the closing '>' in the span
                xpi.End(context.Position + 1);

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

            return(null);
        }
 public static char?GetDelimiterChar(XmlParserContext context)
 => context.CurrentState is XmlAttributeValueState
                 ? (context.StateTag & TagMask) switch
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            var doc = context.Nodes.Peek() as XDocType;

            if (doc == null)
            {
                doc = new XDocType(context.Position - STARTOFFSET);
                context.Nodes.Push(doc);
            }

            if (!doc.RootElement.IsValid)
            {
                if (XmlChar.IsWhitespace(c))
                {
                    return(null);
                }
                else if (XmlChar.IsFirstNameChar(c))
                {
                    rollback = "";
                    return(nameState);
                }
            }
            else if (doc.PublicFpi == null)
            {
                if (context.StateTag == 0)
                {
                    if (c == 's' || c == 'S')
                    {
                        context.StateTag = 1;
                        return(null);
                    }
                    else if (c == 'p' || c == 'P')
                    {
                        context.StateTag = -1;
                        return(null);
                    }
                    if (XmlChar.IsWhitespace(c))
                    {
                        return(null);
                    }
                }
                else if (Math.Abs(context.StateTag) < 6)
                {
                    if (context.StateTag > 0)
                    {
                        if ("YSTEM"[context.StateTag - 1] == c || "ystem"[context.StateTag - 1] == c)
                        {
                            context.StateTag++;
                            if (context.StateTag == 6)
                            {
                                context.StateTag = 0;
                                doc.PublicFpi    = "";
                            }
                            return(null);
                        }
                    }
                    else
                    {
                        int absState = Math.Abs(context.StateTag) - 1;
                        if ("UBLIC"[absState] == c || "ublic"[absState] == c)
                        {
                            context.StateTag--;
                            return(null);
                        }
                    }
                }
                else
                {
                    if (context.KeywordBuilder.Length == 0)
                    {
                        if (XmlChar.IsWhitespace(c))
                        {
                            return(null);
                        }
                        else if (c == '"')
                        {
                            context.KeywordBuilder.Append(c);
                            return(null);
                        }
                    }
                    else
                    {
                        if (c == '"')
                        {
                            context.KeywordBuilder.Remove(0, 1);
                            doc.PublicFpi = context.KeywordBuilder.ToString();
                            context.KeywordBuilder.Length = 0;
                            context.StateTag = 0;
                        }
                        else
                        {
                            context.KeywordBuilder.Append(c);
                        }
                        return(null);
                    }
                }
            }
            else if (doc.Uri == null)
            {
                if (context.KeywordBuilder.Length == 0)
                {
                    if (XmlChar.IsWhitespace(c))
                    {
                        return(null);
                    }
                    else if (c == '"')
                    {
                        context.KeywordBuilder.Append(c);
                        return(null);
                    }
                }
                else
                {
                    if (c == '"')
                    {
                        context.KeywordBuilder.Remove(0, 1);
                        doc.Uri = context.KeywordBuilder.ToString();
                        context.KeywordBuilder.Length = 0;
                    }
                    else
                    {
                        context.KeywordBuilder.Append(c);
                    }
                    return(null);
                }
            }
            else if (doc.InternalDeclarationRegion.Length == 0)
            {
                if (XmlChar.IsWhitespace(c))
                {
                    return(null);
                }
                switch (context.StateTag)
                {
                case 0:
                    if (c == '[')
                    {
                        doc.InternalDeclarationRegion = new TextSpan(context.Position + 1, 0);
                        context.StateTag = 1;
                        return(null);
                    }
                    break;

                case 1:
                    if (c == '<')
                    {
                        context.StateTag = 2;
                        return(null);
                    }
                    else if (c == ']')
                    {
                        context.StateTag = 0;
                        doc.InternalDeclarationRegion = TextSpan.FromBounds(doc.InternalDeclarationRegion.Start, context.Position);
                        return(null);
                    }
                    break;

                case 2:
                    if (c == '>')
                    {
                        context.StateTag = 1;
                    }
                    return(null);

                default:
                    throw new InvalidOperationException();
                }
            }

            doc = (XDocType)context.Nodes.Pop();
            if (c == '<')
            {
                rollback = string.Empty;
                context.Diagnostics?.LogError("Doctype ended prematurely.", context.Position);
            }
            else if (c != '>')
            {
                context.Diagnostics?.LogError("Unexpected character '" + c + "' in doctype.", context.Position);
            }

            doc.End(context.Position);
            if (context.BuildTree)
            {
                ((XContainer)context.Nodes.Peek()).AddChildNode(doc);
            }
            return(Parent);
        }
Beispiel #8
0
 protected XmlParser(XmlParserContext context, XmlRootState rootState)
 {
     Context   = context;
     RootState = rootState;
 }
Beispiel #9
0
        public override XmlParserState PushChar(char c, XmlParserContext context, ref string rollback)
        {
            var element = context.Nodes.Peek() as XElement;

            if (element == null || element.IsEnded)
            {
                var parent = element;
                element = new XElement(context.Position - STARTOFFSET)
                {
                    Parent = parent
                };
                context.Nodes.Push(element);
                if (context.BuildTree)
                {
                    var parentContainer = (XContainer)context.Nodes.Peek(element.IsClosed ? 0 : 1);
                    parentContainer.AddChildNode(element);
                }
            }

            if (c == '<')
            {
                if (element.IsNamed)
                {
                    context.Diagnostics?.LogError("Unexpected '<' in tag '" + element.Name.FullName + "'.", context.Position);
                    Close(element, context, context.Position);
                }
                else
                {
                    context.Diagnostics?.LogError("Tag has no name.", element.Span.Start);
                }

                rollback = string.Empty;
                return(Parent);
            }

            Debug.Assert(!element.IsEnded);

            if (element.IsClosed && c != '>')
            {
                if (char.IsWhiteSpace(c))
                {
                    context.Diagnostics?.LogWarning("Unexpected whitespace after '/' in self-closing tag.", context.Position);
                    return(null);
                }
                context.Diagnostics?.LogError("Unexpected character '" + c + "' after '/' in self-closing tag.", context.Position);
                context.Nodes.Pop();
                return(Parent);
            }

            //if tag closed
            if (c == '>')
            {
                element.HasEndBracket = true;
                if (context.StateTag == MAYBE_SELF_CLOSING)
                {
                    element.Close(element);
                }
                if (!element.IsNamed)
                {
                    context.Diagnostics?.LogError("Tag closed prematurely.", context.Position);
                    element.End(context.Position + 1);
                }
                else
                {
                    Close(element, context, context.Position + 1);
                }
                return(Parent);
            }

            if (c == '/')
            {
                context.StateTag = MAYBE_SELF_CLOSING;
                return(null);
            }

            if (context.StateTag == ATTEMPT_RECOVERY)
            {
                if (XmlChar.IsWhitespace(c))
                {
                    context.StateTag = RECOVERY_FOUND_WHITESPACE;
                }
                return(null);
            }

            if (context.StateTag == RECOVERY_FOUND_WHITESPACE)
            {
                if (!XmlChar.IsFirstNameChar(c))
                {
                    return(null);
                }
            }

            context.StateTag = FREE;

            if (context.CurrentStateLength > 0 && XmlChar.IsFirstNameChar(c))
            {
                rollback = string.Empty;
                return(AttributeState);
            }

            if (!element.IsNamed && XmlChar.IsFirstNameChar(c))
            {
                rollback = string.Empty;
                return(NameState);
            }

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

            context.Diagnostics?.LogError($"Unexpected character '{c}' in tag.", context.Position - 1);
            context.StateTag = ATTEMPT_RECOVERY;
            return(null);
        }
Beispiel #10
0
 public static bool IsFree(XmlParserContext context) => context.CurrentState is XmlTagState && context.StateTag == FREE;