function pseudoNodeToVElementMatcher(selector) {
  const pseudo = selector.value
  switch (pseudo) {
    case ':not': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:not
      const selectors = selectorsToVElementMatcher(selector.nodes)
      return (element, subject) => !selectors(element, subject)
    }
    case ':is':
    case ':where': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:is
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:where
      return selectorsToVElementMatcher(selector.nodes)
    }
    case ':has': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:has
      return pseudoHasSelectorsToVElementMatcher(selector.nodes)
    }
    case ':empty': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:empty
      return (element) =>
        element.children.every(
          (child) => child.type === 'VText' && !child.value.trim()
        )
    }
    case ':nth-child': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
      const nth = parseNth(selector)
      return buildPseudoNthVElementMatcher(nth)
    }
    case ':nth-last-child': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-child
      const nth = parseNth(selector)
      return buildPseudoNthVElementMatcher((index, length) =>
        nth(length - index - 1)
      )
    }
    case ':first-child': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child
      return buildPseudoNthVElementMatcher((index) => index === 0)
    }
    case ':last-child': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child
      return buildPseudoNthVElementMatcher(
        (index, length) => index === length - 1
      )
    }
    case ':only-child': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child
      return buildPseudoNthVElementMatcher(
        (index, length) => index === 0 && length === 1
      )
    }
    case ':nth-of-type': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type
      const nth = parseNth(selector)
      return buildPseudoNthOfTypeVElementMatcher(nth)
    }
    case ':nth-last-of-type': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type
      const nth = parseNth(selector)
      return buildPseudoNthOfTypeVElementMatcher((index, length) =>
        nth(length - index - 1)
      )
    }
    case ':first-of-type': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type
      return buildPseudoNthOfTypeVElementMatcher((index) => index === 0)
    }
    case ':last-of-type': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type
      return buildPseudoNthOfTypeVElementMatcher(
        (index, length) => index === length - 1
      )
    }
    case ':only-of-type': {
      // https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type
      return buildPseudoNthOfTypeVElementMatcher(
        (index, length) => index === 0 && length === 1
      )
    }
    default: {
      throw new SelectorError(`Unsupported pseudo selector: ${pseudo}.`)
    }
  }
}
Convert Pseudo node to VElementMatcher
@param {parser.Pseudo} selector
@returns {VElementMatcher}