Ejemplo n.º 1
0
        /// <summary>
        /// Parse a start tag
        /// </summary>
        protected ParsedToken ParseStartTag()
        {
            _StartTagPosition = _CurrentPosition;
            _TagBuffer        = SourceReader.OpenBuffer();
            CharInfo c = ReadChar();

            // Comments ?
            if (c == '!')
            {
                // Expect '--' or 'DOCTYPE'
                c = ReadChar();
                if (Char.IsLetter(c.AsChar))
                {
                    SaveChar(c);
                    return(ParseDoctype());
                }
                else if (c == '-')
                {
                    if (ReadChar() != '-')
                    {
                        throw new ParseError("Comments need to start with '<!--'.", ReadPosition);
                    }
                    return(ParseComment());
                }
                throw new ParseError("Comment or DOCTYPE expected.", ReadPosition);
            }
            // Process instruction ?
            if (c == '?')
            {
                _State = ParseState.ProcessInstruction;
                c      = ReadChar(false);
                // Pass whitespace
                while (c != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar))
                {
                    c = ReadChar(false);
                }
            }
            else if (c == '/')
            {
                _State = ParseState.EndTag;
                c      = ReadChar(false);
                if (c == CharInfo.EOF || !Char.IsLetterOrDigit(c.AsChar))
                {
                    SaveChar(c);
                    throw new ParseError("Invalid tag name. Need to start with an alphanumeric", ReadPosition);
                }
            }
            else
            {
                _State = ParseState.Tag;
            }
            // Tagname
            if (c == CharInfo.EOF || !Char.IsLetterOrDigit(c.AsChar))
            {
                throw new ParseError("Invalid tag name. Need to start with an alphanumeric", ReadPosition);
            }
            // Loop tag name
            _CurrentRead = null;
            AddToCurrentRead(c);
            while ((c = ReadChar(false)) != CharInfo.EOF && (Char.IsLetterOrDigit(c.AsChar) || c == '.' || c == ':' || c == '-'))
            {
                AddToCurrentRead(c);
            }
            // If EndTag
            if (_State == ParseState.EndTag)
            {
                _CurrentToken          = ParsedTag.EndTag(GetCurrentRead(true));
                _CurrentToken.Position = _StartTagPosition;

                // Pass whitespace
                while (c != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar))
                {
                    c = ReadChar(false);
                }
                try
                {
                    if (c == CharInfo.EOF)
                    {
                        throw new ParseError("Unexpected end of stream.", ReadPosition);
                    }
                    if (IsAttributeNameChar(c.AsChar))
                    {
                        throw new ParseError("End tag can't contains attribute.", ReadPosition);
                    }
                    if (c != '>')
                    {
                        throw new ParseError("Unexpected char. End tag not closed.", ReadPosition);
                    }
                }
                catch
                {
                    // Reset steam
                    while (c != CharInfo.EOF && c != '<' && c != '>')
                    {
                        c = ReadChar(false);
                    }
                    if (c == '<')
                    {
                        SaveChar(c);
                    }
                    throw;
                }
                _State = ParseState.Content;
                ResetTagBuffer();
                var result = _CurrentToken;
                _CurrentToken = null;
                return(result);
            }
            // Create the tag
            if (c != CharInfo.EOF)
            {
                SaveChar(c);
            }
            _CurrentToken          = _State == ParseState.Tag ? ParsedTag.OpenTag(GetCurrentRead(true)) : ParsedTag.OpenProcessInstruction(GetCurrentRead(true));
            _CurrentToken.Position = _StartTagPosition;
            return(_CurrentToken);
        }