Нашел оставленную на память регуляшку. Описание скобок:
( 1 - Запятая или комбинатор слева - ошибка если заполнено)?
(
2 - литерал ИД или КЛАССА (чтобы понимать для кого скобка 3)
3 - значение ИД или КЛАССА
ИЛИ
(4 - Пространство имен селектора ТИПА)?
5 - Значение селектора типа
ИЛИ
( 6 - Пространство имен селектора атрибута )?
7 - имя атрибута
(8 - тип сравнения значения аттрибута с переданной строкой
9 или 10 или 11 - значение аттрибута)?
ИЛИ
12 - псевдокласс
(13 - аргумент псевокласса)?
ИЛИ
14 - ошибка
)
(
15 - запятая или комбинатор (если нет его, то далее будет сова прстой селектор)
)?
var GRINDER = /\s*([,>+~])?\s*(?:([#\.])(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)|(?:(-?(?:\\[\s\S]|[a-zA-Z_\u00C0-\uFFFF])(?:\\[\s\S]|[\-\w\u00C0-\uFFFF])*|\*)?\|)?(-?(?:\\[\s\S]|[a-zA-Z_\u00C0-\uFFFF])(?:\\[\s\S]|[\-\w\u00C0-\uFFFF])*|\*)|\[\s*(?:(-?(?:\\[\s\S]|[a-zA-Z_\u00C0-\uFFFF])(?:\\[\s\S]|[\-\w\u00C0-\uFFFF])*|\*)?\|)?(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)(?:\s*(\S|)=\s*(?:'((?:\\[\s\S]|[^'\n\r\f])*)'|"((?:\\[\s\S]|[^"\n\r\f])*)"|(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)))?\s*\]|:(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)(?:\(((?:'(?:\\[\s\S]|[^'\n\r\f])*'|"(?:\\[\s\S]|[^"\n\r\f])*"|\((?:\\[\s\S]|[^()])*\)|\\[\s\S]|[^()])*)\))?|([^,>+~\s]+))(?:\s*(?:$|([\s,>+~])\s*))?/g;
Если это погонять в цикле,
while ( m = GRINDER.exec(selectror) )
то из
var selector = " NS|TYPE#ID.CLASS + :PSEUDO(ARG)[NS|ATTR='VAL'] "
можно собрать что-то типа
[ [ ["TYPE", "NS"], ["ID"], ["CLASS"] ], [ ["PSEUDO", "ARG"], ["ATTR", "=", "VAL", "NS"] ] ]
Каждую итерацию по номеру заполненных скобок мы можем узнавать какого типа простой селектор и сразу брать его, уже разобранного на части. Когда появлялся m[15], я по содержимому, определял что будет дальше, следующая последовательность (комбинатор + последовательность простых) или вообще следующий одиночный селектор (если там запятая)
Чтобы понимать в коде выборок к какому типу простого селектора относятся эти распарсенные куски, можно определить константы для разных типов и записывать значения например свойством массива (в котором кусочки простого селектора). Так же для оберток этих простых селекторов (последовательностей простых селекторов) и комбинаторов. Потом можно будет эти sequense сортировать, чтобы применять в том порядке в каком лучше. Ну это я так думаю, регулярное выражение писал давно, мне лень тестировать его производительность, но теоретически оно не шибко шустрое, 15 скобок, хотя я не исследовал производительность регекспов.
За парсер, код которого к сожалению не сохранился, могу только одно сказать, что синтаксис селекторов полностью соответствовал спецификации и нельзя было передать не правильный селектор, 100% было бы SyntaxError