package css_parser

import (
	
	
)

Parse the first selector
	.eat(css_lexer.TWhitespace)
	,  := .parseComplexSelector()
	if ! {
		return
	}
	 = append(, )
Parse the remaining selectors
	for {
		.eat(css_lexer.TWhitespace)
		if !.eat(css_lexer.TComma) {
			break
		}
		.eat(css_lexer.TWhitespace)
		,  := .parseComplexSelector()
		if ! {
			return
		}
		 = append(, )
	}

	 = true
	return
}

Parent
	,  := .parseCompoundSelector()
	if ! {
		return
	}
	.Selectors = append(.Selectors, )

	for {
		.eat(css_lexer.TWhitespace)
		if .peek(css_lexer.TEndOfFile) || .peek(css_lexer.TComma) || .peek(css_lexer.TOpenBrace) {
			break
		}
Optional combinator
		 := .parseCombinator()
		if  != "" {
			.eat(css_lexer.TWhitespace)
		}
Child
		,  := .parseCompoundSelector()
		if ! {
			return
		}
		.Combinator = 
		.Selectors = append(.Selectors, )
	}

	 = true
	return
}

func ( *parser) () css_ast.NameToken {
	return css_ast.NameToken{
		Kind: .current().Kind,
		Text: .decoded(),
	}
}

This is an extension: https://drafts.csswg.org/css-nesting-1/
Parse the type selector
Hack: Create an empty "identifier" to represent this
			.Name.Kind = css_lexer.TIdent
		}
		if .eat(css_lexer.TDelimBar) {
			if !.peek(css_lexer.TIdent) && !.peek(css_lexer.TDelimAsterisk) {
				.expect(css_lexer.TIdent)
				return
			}
			 := .Name
			.NamespacePrefix = &
			.Name = .nameToken()
			.advance()
		}
		.TypeSelector = &
	}
Parse the subclass selectors
:
	for {
		switch .current().Kind {
		case css_lexer.THash:
			if !.current().IsID {
				break 
			}
			 := .decoded()
			.SubclassSelectors = append(.SubclassSelectors, &css_ast.SSHash{Name: })
			.advance()

		case css_lexer.TDelimDot:
			.advance()
			 := .decoded()
			.SubclassSelectors = append(.SubclassSelectors, &css_ast.SSClass{Name: })
			.expect(css_lexer.TIdent)

		case css_lexer.TOpenBracket:
			.advance()
			,  := .parseAttributeSelector()
			if ! {
				return
			}
			.SubclassSelectors = append(.SubclassSelectors, &)

		case css_lexer.TColon:
Stop if this is the start of the pseudo-element selector section
				break 
			}
			 := .parsePseudoElementSelector()
			.SubclassSelectors = append(.SubclassSelectors, &)

		default:
			break 
		}
	}
Parse the pseudo-element selectors
The compound selector must be non-empty
	if !.HasNestPrefix && .TypeSelector == nil && len(.SubclassSelectors) == 0 && len(.PseudoClassSelectors) == 0 {
		.unexpected()
		return
	}

	 = true
	return
}

Parse the namespaced name
	switch .current().Kind {
"[|x]" "[*|x]"
		if .peek(css_lexer.TDelimAsterisk) {
			 := .nameToken()
			.advance()
			.NamespacedName.NamespacePrefix = &
"[|attr]" is equivalent to "[attr]". From the specification: "In keeping with the Namespaces in the XML recommendation, default namespaces do not apply to attributes, therefore attribute selectors without a namespace component apply only to attributes that have no namespace (equivalent to |attr)."
		}
		if !.expect(css_lexer.TDelimBar) {
			return
		}
		.NamespacedName.Name = .nameToken()
		if !.expect(css_lexer.TIdent) {
			return
		}

"[x]" "[x|y]"
		.NamespacedName.Name = .nameToken()
		if !.expect(css_lexer.TIdent) {
			return
		}
		if .next().Kind != css_lexer.TDelimEquals && .eat(css_lexer.TDelimBar) {
			 := .NamespacedName.Name
			.NamespacedName.NamespacePrefix = &
			.NamespacedName.Name = .nameToken()
			if !.expect(css_lexer.TIdent) {
				return
			}
		}
	}
Parse the optional matcher operator
	.eat(css_lexer.TWhitespace)
	if .eat(css_lexer.TDelimEquals) {
		.MatcherOp = "="
	} else {
		switch .current().Kind {
		case css_lexer.TDelimTilde:
			.MatcherOp = "~="
		case css_lexer.TDelimBar:
			.MatcherOp = "|="
		case css_lexer.TDelimCaret:
			.MatcherOp = "^="
		case css_lexer.TDelimDollar:
			.MatcherOp = "$="
		case css_lexer.TDelimAsterisk:
			.MatcherOp = "*="
		}
		if .MatcherOp != "" {
			.advance()
			.expect(css_lexer.TDelimEquals)
		}
	}
Parse the optional matcher value
	if .MatcherOp != "" {
		.eat(css_lexer.TWhitespace)
		if !.peek(css_lexer.TString) && !.peek(css_lexer.TIdent) {
			.unexpected()
		}
		.MatcherValue = .decoded()
		.advance()
		.eat(css_lexer.TWhitespace)
		if .peek(css_lexer.TIdent) {
			if  := .decoded(); len() == 1 {
				if  := [0];  == 'i' ||  == 'I' {
					.MatcherModifier = 
					.advance()
				}
			}
		}
	}

	.expect(css_lexer.TCloseBracket)
	 = true
	return
}

func ( *parser) () css_ast.SSPseudoClass {
	.advance()

	if .peek(css_lexer.TFunction) {
		 := .decoded()
		.advance()
		 := .convertTokens(.parseAnyValue())
		.expect(css_lexer.TCloseParen)
		return css_ast.SSPseudoClass{Name: , Args: }
	}

	 := .decoded()
	 := css_ast.SSPseudoClass{}
	if .expect(css_lexer.TIdent) {
		.Name = 
	}
	return 
}

Reference: https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value

	.stack = .stack[:0] // Reuse allocated memory
	 := .index

:
	for {
		switch .current().Kind {
		case css_lexer.TCloseParen, css_lexer.TCloseBracket, css_lexer.TCloseBrace:
			 := len(.stack) - 1
			if  < 0 || !.peek(.stack[]) {
				break 
			}
			.stack = .stack[:]

		case css_lexer.TSemicolon, css_lexer.TDelimExclamation:
			if len(.stack) == 0 {
				break 
			}

		case css_lexer.TOpenParen, css_lexer.TFunction:
			.stack = append(.stack, css_lexer.TCloseParen)

		case css_lexer.TOpenBracket:
			.stack = append(.stack, css_lexer.TCloseBracket)

		case css_lexer.TOpenBrace:
			.stack = append(.stack, css_lexer.TCloseBrace)
		}

		.advance()
	}

	 := .tokens[:.index]
	if len() == 0 {
		.unexpected()
	}
	return 
}

func ( *parser) () string {
	switch .current().Kind {
	case css_lexer.TDelimGreaterThan:
		.advance()
		return ">"

	case css_lexer.TDelimPlus:
		.advance()
		return "+"

	case css_lexer.TDelimTilde:
		.advance()
		return "~"

	default:
		return ""
	}