// ParseSelection returns a parsed Article.
// If the Article is not valid (e.g., Author profile), it returns error.
774704
func ParseSelection(s *goquery.Selection) (a *Article, err error) {
	a = &Article{}

	a.Title = parseH3(s)
	a.Year = parseGreenLine(s)
	a.ClusterId, a.NumCite, a.NumVer, a.InfoId = parseBottom(s)
	a.Link = parseSideBar(s)

	if a.InfoId != "" {
		time.Sleep(1.0 * time.Second) // TODO: make 1.0 parameter
		a.BibTeX, err = getBibTeX(generateBibTeXLink(a.InfoId))
		if err != nil {
			return nil, err
		}
	}

	if a.BibTeX != "" {
		bibmap, err := gobibtex.Decode(a.BibTeX)
		if err != nil {
			return nil, err
		}

		if author, ok := bibmap["author"]; ok {
			a.Author = author.([]string)
		}
		if journal, ok := bibmap["journal"]; ok {
			a.Journal = journal.(string)
		}
		if booktitle, ok := bibmap["booktitle"]; ok {
			a.Booktitle = booktitle.(string)
		}
		if volume, ok := bibmap["volume"]; ok {
			a.Volume = volume.(string)
		}
		if number, ok := bibmap["number"]; ok {
			a.Number = number.(string)
		}
		if pages, ok := bibmap["pages"]; ok {
			a.Pages = pages.(string)
		}
		if publisher, ok := bibmap["publisher"]; ok {
			a.Publisher = publisher.(string)
		}
	}

	if !a.isValid() {
		return nil, errors.New(fmt.Sprintf("\"%v\" is not a valid article", a.Title.Name))
	}

	return a, nil
}
4479
func inSelectIM(p *parser) bool {
	switch p.tok.Type {
	case ErrorToken:
		// Stop parsing.
		return true
	case TextToken:
		p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
	case StartTagToken:
		switch p.tok.DataAtom {
		case a.Html:
			return inBodyIM(p)
		case a.Option:
			if p.top().DataAtom == a.Option {
				p.oe.pop()
			}
			p.addElement()
		case a.Optgroup:
			if p.top().DataAtom == a.Option {
				p.oe.pop()
			}
			if p.top().DataAtom == a.Optgroup {
				p.oe.pop()
			}
			p.addElement()
		case a.Select:
			p.tok.Type = EndTagToken
			return false
		case a.Input, a.Keygen, a.Textarea:
			if p.elementInScope(selectScope, a.Select) {
				p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
				return false
			}
			// In order to properly ignore <textarea>, we need to change the tokenizer mode.
			p.tokenizer.NextIsNotRawText()
			// Ignore the token.
			return true
		case a.Script:
			return inHeadIM(p)
		}
	case EndTagToken:
		switch p.tok.DataAtom {
		case a.Option:
			if p.top().DataAtom == a.Option {
				p.oe.pop()
			}
		case a.Optgroup:
			i := len(p.oe) - 1
			if p.oe[i].DataAtom == a.Option {
				i--
			}
			if p.oe[i].DataAtom == a.Optgroup {
				p.oe = p.oe[:i]
			}
		case a.Select:
			if p.popUntil(selectScope, a.Select) {
				p.resetInsertionMode()
			}
		}
	case CommentToken:
		p.addChild(&Node{
			Type: CommentNode,
			Data: p.tok.Data,
		})
	case DoctypeToken:
		// Ignore the token.
		return true
	}

	return true
}
903778
func (p *parser) parsePseudoclassSelector() (Selector, error) {
	if p.i >= len(p.s) {
		return nil, fmt.Errorf("expected pseudoclass selector (:pseudoclass), found EOF instead")
	}
	if p.s[p.i] != ':' {
		return nil, fmt.Errorf("expected attribute selector (:pseudoclass), found '%c' instead", p.s[p.i])
	}

	p.i++
	name, err := p.parseIdentifier()
	if err != nil {
		return nil, err
	}
	name = toLowerASCII(name)

	switch name {
	case "not", "has", "haschild":
		if !p.consumeParenthesis() {
			return nil, expectedParenthesis
		}
		sel, err := p.parseSelectorGroup()
		if err != nil {
			return nil, err
		}
		if !p.consumeClosingParenthesis() {
			return nil, expectedClosingParenthesis
		}

		switch name {
		case "not":
			return negatedSelector(sel), nil
		case "has":
			return hasDescendantSelector(sel), nil
		case "haschild":
			return hasChildSelector(sel), nil
		}

	case "contains", "containsown":
		if !p.consumeParenthesis() {
			return nil, expectedParenthesis
		}
		var val string
		switch p.s[p.i] {
		case '\'', '"':
			val, err = p.parseString()
		default:
			val, err = p.parseIdentifier()
		}
		if err != nil {
			return nil, err
		}
		val = strings.ToLower(val)
		p.skipWhitespace()
		if p.i >= len(p.s) {
			return nil, errors.New("unexpected EOF in pseudo selector")
		}
		if !p.consumeClosingParenthesis() {
			return nil, expectedClosingParenthesis
		}

		switch name {
		case "contains":
			return textSubstrSelector(val), nil
		case "containsown":
			return ownTextSubstrSelector(val), nil
		}

	case "matches", "matchesown":
		if !p.consumeParenthesis() {
			return nil, expectedParenthesis
		}
		rx, err := p.parseRegex()
		if err != nil {
			return nil, err
		}
		if p.i >= len(p.s) {
			return nil, errors.New("unexpected EOF in pseudo selector")
		}
		if !p.consumeClosingParenthesis() {
			return nil, expectedClosingParenthesis
		}

		switch name {
		case "matches":
			return textRegexSelector(rx), nil
		case "matchesown":
			return ownTextRegexSelector(rx), nil
		}

	case "nth-child", "nth-last-child", "nth-of-type", "nth-last-of-type":
		if !p.consumeParenthesis() {
			return nil, expectedParenthesis
		}
		a, b, err := p.parseNth()
		if err != nil {
			return nil, err
		}
		if !p.consumeClosingParenthesis() {
			return nil, expectedClosingParenthesis
		}
		return nthChildSelector(a, b,
				name == "nth-last-child" || name == "nth-last-of-type",
				name == "nth-of-type" || name == "nth-last-of-type"),
			nil

	case "first-child":
		return nthChildSelector(0, 1, false, false), nil
	case "last-child":
		return nthChildSelector(0, 1, true, false), nil
	case "first-of-type":
		return nthChildSelector(0, 1, false, true), nil
	case "last-of-type":
		return nthChildSelector(0, 1, true, true), nil
	case "only-child":
		return onlyChildSelector(false), nil
	case "only-of-type":
		return onlyChildSelector(true), nil
	case "empty":
		return emptyElementSelector, nil
	}

	return nil, fmt.Errorf("unknown pseudoclass :%s", name)
}
937244
func parseExpression(expr string) (node ast.ExprNode, err error) {
	expr = fmt.Sprintf("select %s", expr)
	charset, collation := charset.GetDefaultCharsetAndCollate()
	stmts, _, err := parser.New().Parse(expr, charset, collation)
	if err == nil {
		node = stmts[0].(*ast.SelectStmt).Fields.Fields[0].Expr
	}
	return node, util.SyntaxError(err)
}
986743
func (g *generatorContext) parseOptional(slexer *structLexer) (node, error) {
	_, _ = slexer.Next() // [
	disj, err := g.parseDisjunction(slexer)
	if err != nil {
		return nil, err
	}
	n := &group{expr: disj, mode: groupMatchZeroOrOne}
	next, err := slexer.Next()
	if err != nil {
		return nil, err
	}
	if next.Type != ']' {
		return nil, fmt.Errorf("expected ] but got %q", next)
	}
	return n, nil
}
782201
func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
	if sel == nil {
		return s.Parents()
	}
	return s.ParentsUntilNodes(sel.Nodes...)
}
808987
func (s *Selection) IndexOfSelection(sel *Selection) int {
	if sel != nil && len(sel.Nodes) > 0 {
		return indexInSlice(s.Nodes, sel.Nodes[0])
	}
	return -1
}
1197842
func (s OptionSelector) Select(data []byte, options []Option) ([]Option, bool) {
	var current Option
	var has bool
	index := -1

	alloc := s.Alloc
	if alloc == nil {
		alloc = defaultAlloc
	}
	check := s.Check
	if check == nil {
		check = defaultCheck
	}

	ok := ScanOptions(data, func(idx int, name, attr, val []byte) Control {
		if idx != index {
			if has && check(current) {
				if s.Flags&SelectCopy != 0 {
					current = current.Copy(alloc(current.Size()))
				}
				options = append(options, current)
				has = false
			}
			if s.Flags&SelectUnique != 0 {
				for i := len(options) - 1; i >= 0; i-- {
					if bytes.Equal(options[i].Name, name) {
						return ControlSkip
					}
				}
			}
			index = idx
			current = Option{Name: name}
			has = true
		}
		if attr != nil {
			current.Parameters.Set(attr, val)
		}

		return ControlContinue
	})
	if has && check(current) {
		if s.Flags&SelectCopy != 0 {
			current = current.Copy(alloc(current.Size()))
		}
		options = append(options, current)
	}

	return options, ok
}
601436
func parseAnnotationSelector(s string) (map[string]string, error) {
	if len(s) == 0 {
		return nil, nil
	}
	stringReader := strings.NewReader(s)
	csvReader := csv.NewReader(stringReader)
	annotations, err := csvReader.Read()
	if err != nil {
		return nil, err
	}
	parsed := map[string]string{}
	for _, annotation := range annotations {
		parts := strings.SplitN(annotation, "=", 2)
		if len(parts) != 2 {
			return nil, fmt.Errorf("Malformed annotation selector, expected %q: %s", "key=value", annotation)
		}
		parsed[parts[0]] = parts[1]
	}
	return parsed, nil
}
1146831
func selectString(s, spec string) bool {
	if spec == "*" {
		return true
	}
	if !strings.Contains(spec, "*") {
		return s == spec
	}

	pos := 0
	match := true
	parts := strings.Split(spec, "*")
	for i, part := range parts {
		if len(part) == 0 {
			continue
		}
		next := strings.Index(s[pos:], part)
		switch {
		// next part not in string
		case next < pos:
			fallthrough
		// first part does not match start of string
		case i == 0 && pos != 0:
			fallthrough
		// last part does not exactly match remaining part of string
		case i == (len(parts)-1) && len(s) != (len(part)+next):
			match = false
			break
		default:
			pos = next
		}
	}
	return match
}
542203
func descendantSelector(a, d Selector) Selector {
	return func(n *html.Node) bool {
		if !d(n) {
			return false
		}

		for p := n.Parent; p != nil; p = p.Parent {
			if a(p) {
				return true
			}
		}

		return false
	}
}
154852
func (p *parser) parseSelectorGroup() (result Selector, err error) {
	result, err = p.parseSelector()
	if err != nil {
		return
	}

	for p.i < len(p.s) {
		if p.s[p.i] != ',' {
			return result, nil
		}
		p.i++
		c, err := p.parseSelector()
		if err != nil {
			return nil, err
		}
		result = unionSelector(result, c)
	}

	return
}
1145693
func parseOptionParams(value string) (option, params string) {
	// Strip off the first component; use this as the option name.
	idx := strings.IndexRune(value, ',')

	if idx == -1 {
		option, params = value, ""
	} else {
		option, params = value[:idx], value[(idx+1):]
	}
	return
}
997159
func (s *Selection) IndexSelector(selector string) int {
	if len(s.Nodes) > 0 {
		sel := s.document.Find(selector)
		return indexInSlice(sel.Nodes, s.Nodes[0])
	}
	return -1
}
1338715
func NewSelector(keys []string) selector.SelectOption {
	return selector.WithStrategy(func(services []*registry.Service) selector.Next {
		return Next(keys, services)
	})
}
1151132
func Selector(s selector.Selector) Option {
	return func(o *Options) {
		o.Client.Init(client.Selector(s))
	}
}
271348
func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace string, selector labels.Selector, export bool) *Selector {
	return &Selector{
		Client:    client,
		Mapping:   mapping,
		Namespace: namespace,
		Selector:  selector,
		Export:    export,
	}
}