bool Complex_Selector::is_superselector_of(Complex_Selector* rhs) { Complex_Selector* lhs = this; To_String to_string; // check for selectors with leading or trailing combinators if (!lhs->head() || !rhs->head()) { return false; } Complex_Selector* l_innermost = lhs->innermost(); if (l_innermost->combinator() != Complex_Selector::ANCESTOR_OF && !l_innermost->tail()) { return false; } Complex_Selector* r_innermost = rhs->innermost(); if (r_innermost->combinator() != Complex_Selector::ANCESTOR_OF && !r_innermost->tail()) { return false; } // more complex (i.e., longer) selectors are always more specific size_t l_len = lhs->length(), r_len = rhs->length(); if (l_len > r_len) { return false; } if (l_len == 1) { return lhs->head()->is_superselector_of(rhs->base()); } bool found = false; Complex_Selector* marker = rhs; for (size_t i = 0, L = rhs->length(); i < L; ++i) { if (i == L-1) { return false; } if (lhs->head()->is_superselector_of(marker->head())) { found = true; break; } marker = marker->tail(); } if (!found) { return false; } /* Hmm, I hope I have the logic right: if lhs has a combinator: if !(marker has a combinator) return false if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) return false return lhs.tail-without-innermost.is_superselector_of(marker.tail-without-innermost) else if marker has a combinator: if !(marker.combinator == ">") return false return lhs.tail.is_superselector_of(marker.tail) else return lhs.tail.is_superselector_of(marker.tail) */ if (lhs->combinator() != Complex_Selector::ANCESTOR_OF) { if (marker->combinator() == Complex_Selector::ANCESTOR_OF) { return false; } if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator())) { return false; } return lhs->tail()->is_superselector_of(marker->tail()); } else if (marker->combinator() != Complex_Selector::ANCESTOR_OF) { if (marker->combinator() != Complex_Selector::PARENT_OF) { return false; } return lhs->tail()->is_superselector_of(marker->tail()); } else { return lhs->tail()->is_superselector_of(marker->tail()); } // catch-all return false; }